mt76 fixes for 6.16

-----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCaGws0wAKCRDXfRQdAqdu
 9cxcAKCKrKFhB8TKyWHwfiH8QEC86XyyMQCeJ6T0seeKLXopyvdb3s120ehCcdY=
 =4/7B
 -----END PGP SIGNATURE-----

Merge tag 'mt76-fixes-2025-07-07' of https://github.com/nbd168/wireless

Felix Fietkau says:
===================
mt76 fixes for 6.16
===================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2025-07-08 09:22:40 +02:00
commit 5300e5e24b
27 changed files with 301 additions and 197 deletions

View File

@ -1224,6 +1224,16 @@ static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
#define mt76_dereference(p, dev) \
rcu_dereference_protected(p, lockdep_is_held(&(dev)->mutex))
static inline struct mt76_wcid *
__mt76_wcid_ptr(struct mt76_dev *dev, u16 idx)
{
if (idx >= ARRAY_SIZE(dev->wcid))
return NULL;
return rcu_dereference(dev->wcid[idx]);
}
#define mt76_wcid_ptr(dev, idx) __mt76_wcid_ptr(&(dev)->mt76, idx)
struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
const struct mt76_driver_ops *drv_ops);

View File

@ -44,7 +44,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
if (idx >= MT7603_WTBL_STA - 1)
goto free;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (!wcid)
goto free;

View File

@ -487,10 +487,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
struct mt7603_sta *sta;
struct mt76_wcid *wcid;
if (idx >= MT7603_WTBL_SIZE)
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (unicast || !wcid)
return wcid;
@ -1266,12 +1263,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
if (pid == MT_PACKET_ID_NO_ACK)
return;
if (wcidx >= MT7603_WTBL_SIZE)
return;
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;

View File

@ -90,10 +90,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
struct mt7615_sta *sta;
struct mt76_wcid *wcid;
if (idx >= MT7615_WTBL_SIZE)
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (unicast || !wcid)
return wcid;
@ -1504,7 +1501,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;

View File

@ -1172,7 +1172,7 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
wcid_idx = wcid->idx;
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid = rcu_dereference(dev->wcid[wcid_idx]);
wcid = __mt76_wcid_ptr(dev, wcid_idx);
if (wcid && wcid->sta) {
sta = container_of((void *)wcid, struct ieee80211_sta,

View File

@ -287,7 +287,7 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif
mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,
&hdr.wlan_idx_hi);
skb = mt76_mcu_msg_alloc(dev, NULL, len);
skb = __mt76_mcu_msg_alloc(dev, NULL, len, len, GFP_ATOMIC);
if (!skb)
return ERR_PTR(-ENOMEM);
@ -1740,8 +1740,8 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
if (!sreq->ssids[i].ssid_len)
continue;
req->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
memcpy(req->ssids[i].ssid, sreq->ssids[i].ssid,
req->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
memcpy(req->ssids[n_ssids].ssid, sreq->ssids[i].ssid,
sreq->ssids[i].ssid_len);
n_ssids++;
}

View File

@ -262,10 +262,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
{
struct mt76_wcid *wcid;
if (idx >= MT76x02_N_WCIDS)
return NULL;
wcid = rcu_dereference(dev->wcid[idx]);
wcid = __mt76_wcid_ptr(dev, idx);
if (!wcid)
return NULL;

View File

@ -564,9 +564,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
rcu_read_lock();
if (stat->wcid < MT76x02_N_WCIDS)
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
wcid = mt76_wcid_ptr(dev, stat->wcid);
if (wcid && wcid->sta) {
void *priv;

View File

@ -56,10 +56,7 @@ static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev,
struct mt7915_sta *sta;
struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (unicast || !wcid)
return wcid;
@ -917,7 +914,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
u16 idx;
idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info);
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
sta = wcid_to_sta(wcid);
if (!sta)
continue;
@ -1013,12 +1010,9 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
if (pid < MT_PACKET_ID_WED)
return;
if (wcidx >= mt7915_wtbl_size(dev))
return;
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;

View File

@ -3986,7 +3986,7 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
wcid = mt76_wcid_ptr(dev, wlan_idx);
if (wcid)
wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
else

View File

@ -587,12 +587,9 @@ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed,
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
if (idx >= mt7915_wtbl_size(dev))
return;
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (wcid) {
wcid->stats.rx_bytes += le32_to_cpu(stats->rx_byte_cnt);
wcid->stats.rx_packets += le32_to_cpu(stats->rx_pkt_cnt);

View File

@ -465,7 +465,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data)
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;
@ -516,7 +516,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
count++;
idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info);
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
sta = wcid_to_sta(wcid);
if (!sta)
continue;
@ -816,7 +816,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
u16 idx;
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid = rcu_dereference(mdev->wcid[idx]);
wcid = __mt76_wcid_ptr(mdev, idx);
sta = wcid_to_sta(wcid);
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))

View File

@ -1180,6 +1180,9 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
struct mt792x_dev *dev = mt792x_hw_dev(hw);
if (!msta->deflink.wcid.sta)
return;
mt792x_mutex_acquire(dev);
if (enabled)

View File

@ -52,6 +52,8 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7925_%s",
wiphy_name(wiphy));
if (!name)
return -ENOMEM;
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7925_hwmon_groups);

View File

@ -1040,7 +1040,7 @@ void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;
@ -1122,7 +1122,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
u16 idx;
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
sta = wcid_to_sta(wcid);
if (!sta)
continue;
@ -1445,7 +1445,7 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
u16 idx;
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
wcid = rcu_dereference(mdev->wcid[idx]);
wcid = __mt76_wcid_ptr(mdev, idx);
sta = wcid_to_sta(wcid);
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))

View File

@ -1481,7 +1481,7 @@ mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt792x_mutex_acquire(dev);
err = mt7925_mcu_sched_scan_req(mphy, vif, req);
err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);
if (err < 0)
goto out;
@ -1603,6 +1603,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
unsigned long valid = mvif->valid_links;
u8 i;
if (!msta->vif)
return;
mt792x_mutex_acquire(dev);
valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);
@ -1617,6 +1620,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
else
clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);
if (!mlink->wcid.sta)
continue;
mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);
}

View File

@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
bool suspend, struct cfg80211_wowlan *wowlan)
{
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
struct ieee80211_scan_ies ies = {};
struct mt76_dev *dev = phy->dev;
struct {
struct {
@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |
UNI_WOW_DETECT_TYPE_BCN_LOST);
if (wowlan->nd_config) {
mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config);
mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies);
req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;
mt7925_mcu_sched_scan_enable(phy, vif, suspend);
}
@ -2818,6 +2819,54 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
return err;
}
static void
mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
struct sk_buff *skb,
struct ieee80211_scan_ies *scan_ies)
{
u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN;
struct scan_ie_tlv *ie;
enum nl80211_band i;
struct tlv *tlv;
const u8 *ies;
u16 ies_len;
for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
if (i == NL80211_BAND_60GHZ)
continue;
ies = scan_ies->ies[i];
ies_len = scan_ies->len[i];
if (!ies || !ies_len)
continue;
if (ies_len > max_len)
return;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
sizeof(*ie) + ies_len);
ie = (struct scan_ie_tlv *)tlv;
memcpy(ie->ies, ies, ies_len);
ie->ies_len = cpu_to_le16(ies_len);
switch (i) {
case NL80211_BAND_2GHZ:
ie->band = 1;
break;
case NL80211_BAND_6GHZ:
ie->band = 3;
break;
default:
ie->band = 2;
break;
}
max_len -= (sizeof(*ie) + ies_len);
}
}
int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_scan_request *scan_req)
{
@ -2843,7 +2892,8 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) +
sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS +
sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie);
sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) +
MT76_CONNAC_SCAN_IE_LEN;
skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
if (!skb)
@ -2869,8 +2919,8 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
if (i > MT7925_RNR_SCAN_MAX_BSSIDS)
break;
ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid,
ssid->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
memcpy(ssid->ssids[n_ssids].ssid, sreq->ssids[i].ssid,
sreq->ssids[i].ssid_len);
n_ssids++;
}
@ -2925,13 +2975,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
}
chan_info->channel_type = sreq->n_channels ? 4 : 0;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
ie = (struct scan_ie_tlv *)tlv;
if (sreq->ie_len > 0) {
memcpy(ie->ies, sreq->ie, sreq->ie_len);
ie->ies_len = cpu_to_le16(sreq->ie_len);
}
req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc));
@ -2942,6 +2985,9 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
req->scan_func |= SCAN_FUNC_RANDOM_MAC;
}
/* Append scan probe IEs as the last tlv */
mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies);
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
true);
if (err < 0)
@ -2953,7 +2999,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan);
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq)
struct cfg80211_sched_scan_request *sreq,
struct ieee80211_scan_ies *ies)
{
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
struct ieee80211_channel **scan_list = sreq->channels;
@ -3041,12 +3088,8 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
}
chan_info->channel_type = sreq->n_channels ? 4 : 0;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
ie = (struct scan_ie_tlv *)tlv;
if (sreq->ie_len > 0) {
memcpy(ie->ies, sreq->ie, sreq->ie_len);
ie->ies_len = cpu_to_le16(sreq->ie_len);
}
/* Append scan probe IEs as the last tlv */
mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies);
return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
true);

View File

@ -269,7 +269,7 @@ struct scan_ie_tlv {
__le16 ies_len;
u8 band;
u8 pad;
u8 ies[MT76_CONNAC_SCAN_IE_LEN];
u8 ies[];
};
struct scan_misc_tlv {
@ -673,7 +673,8 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
struct ieee80211_vif *vif);
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq);
struct cfg80211_sched_scan_request *sreq,
struct ieee80211_scan_ies *ies);
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
struct ieee80211_vif *vif,
bool enable);

View File

@ -58,7 +58,7 @@
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \
MT_INT_TX_DONE_FWDL)
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU | \
MT_INT_TX_DONE_BAND0 | \
GENMASK(18, 4))

View File

@ -28,7 +28,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
},
};
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
static const struct ieee80211_iface_limit if_limits_chanctx_mcc[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_STATION) |
@ -36,8 +36,23 @@ static const struct ieee80211_iface_limit if_limits_chanctx[] = {
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO)
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
}
};
static const struct ieee80211_iface_limit if_limits_chanctx_scc[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_AP)
},
{
.max = 1,
@ -47,11 +62,18 @@ static const struct ieee80211_iface_limit if_limits_chanctx[] = {
static const struct ieee80211_iface_combination if_comb_chanctx[] = {
{
.limits = if_limits_chanctx,
.n_limits = ARRAY_SIZE(if_limits_chanctx),
.limits = if_limits_chanctx_mcc,
.n_limits = ARRAY_SIZE(if_limits_chanctx_mcc),
.max_interfaces = 3,
.num_different_channels = 2,
.beacon_int_infra_match = false,
},
{
.limits = if_limits_chanctx_scc,
.n_limits = ARRAY_SIZE(if_limits_chanctx_scc),
.max_interfaces = 3,
.num_different_channels = 1,
.beacon_int_infra_match = false,
}
};

View File

@ -142,10 +142,7 @@ struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
struct mt792x_sta *sta;
struct mt76_wcid *wcid;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (unicast || !wcid)
return wcid;

View File

@ -61,10 +61,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
struct mt76_wcid *wcid;
int i;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (!wcid)
return NULL;
@ -1249,7 +1246,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
u16 idx;
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
sta = wcid_to_sta(wcid);
if (!sta)
goto next;
@ -1471,12 +1468,9 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
if (pid < MT_PACKET_ID_NO_SKB)
return;
if (wcidx >= mt7996_wtbl_size(dev))
return;
rcu_read_lock();
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
wcid = mt76_wcid_ptr(dev, wcidx);
if (!wcid)
goto out;
@ -2353,20 +2347,12 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
void mt7996_mac_sta_rc_work(struct work_struct *work)
{
struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
struct mt76_vif_link *mlink;
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct mt7996_sta *msta;
struct mt7996_vif *mvif;
LIST_HEAD(list);
u32 changed;
u8 link_id;
rcu_read_lock();
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
@ -2377,46 +2363,28 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
changed = msta_link->changed;
msta_link->changed = 0;
sta = wcid_to_sta(&msta_link->wcid);
link_id = msta_link->wcid.link_id;
msta = msta_link->sta;
mvif = msta->vif;
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (!mlink)
continue;
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta)
continue;
link_conf = rcu_dereference(vif->link_conf[link_id]);
if (!link_conf)
continue;
mvif = msta_link->sta->vif;
vif = container_of((void *)mvif, struct ieee80211_vif,
drv_priv);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
link = (struct mt7996_vif_link *)mlink;
if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED |
IEEE80211_RC_BW_CHANGED))
mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
link_sta, link, msta_link,
mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif,
msta_link->wcid.link_id,
true);
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7996_mcu_set_fixed_field(dev, link_sta, link,
msta_link, NULL,
mt7996_mcu_set_fixed_field(dev, msta_link->sta, NULL,
msta_link->wcid.link_id,
RATE_PARAM_MMPS_UPDATE);
spin_lock_bh(&dev->mt76.sta_poll_lock);
}
spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_unlock();
}
void mt7996_mac_work(struct work_struct *work)

View File

@ -1112,9 +1112,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
if (err)
return err;
err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
link_sta, link,
msta_link, false);
err = mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif,
link_id, false);
if (err)
return err;

View File

@ -555,7 +555,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
switch (le16_to_cpu(res->tag)) {
case UNI_ALL_STA_TXRX_RATE:
wlan_idx = le16_to_cpu(res->rate[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
wcid = mt76_wcid_ptr(dev, wlan_idx);
if (!wcid)
break;
@ -565,7 +565,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
break;
case UNI_ALL_STA_TXRX_ADM_STAT:
wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
wcid = mt76_wcid_ptr(dev, wlan_idx);
if (!wcid)
break;
@ -579,7 +579,7 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
break;
case UNI_ALL_STA_TXRX_MSDU_COUNT:
wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
wcid = mt76_wcid_ptr(dev, wlan_idx);
if (!wcid)
break;
@ -676,10 +676,7 @@ mt7996_mcu_wed_rro_event(struct mt7996_dev *dev, struct sk_buff *skb)
e = (void *)skb->data;
idx = le16_to_cpu(e->wlan_id);
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
break;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
wcid = mt76_wcid_ptr(dev, idx);
if (!wcid || !wcid->sta)
break;
@ -1905,22 +1902,35 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
MCU_WM_UNI_CMD(RA), true);
}
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
void *data, u32 field)
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
void *data, u8 link_id, u32 field)
{
struct sta_phy_uni *phy = data;
struct mt7996_vif *mvif = msta->vif;
struct mt7996_sta_link *msta_link;
struct sta_rec_ra_fixed_uni *ra;
struct sta_phy_uni *phy = data;
struct mt76_vif_link *mlink;
struct sk_buff *skb;
int err = -ENODEV;
struct tlv *tlv;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
rcu_read_lock();
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (!mlink)
goto error_unlock;
msta_link = rcu_dereference(msta->link[link_id]);
if (!msta_link)
goto error_unlock;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mlink,
&msta_link->wcid,
MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
goto error_unlock;
}
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
ra = (struct sta_rec_ra_fixed_uni *)tlv;
@ -1935,106 +1945,149 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
if (phy)
ra->phy = *phy;
break;
case RATE_PARAM_MMPS_UPDATE:
case RATE_PARAM_MMPS_UPDATE: {
struct ieee80211_sta *sta = wcid_to_sta(&msta_link->wcid);
struct ieee80211_link_sta *link_sta;
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta) {
dev_kfree_skb(skb);
goto error_unlock;
}
ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
break;
}
default:
break;
}
ra->field = cpu_to_le32(field);
rcu_read_unlock();
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
error_unlock:
rcu_read_unlock();
return err;
}
static int
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link)
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta,
struct ieee80211_vif *vif, u8 link_id)
{
struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
enum nl80211_band band = chandef->chan->band;
struct ieee80211_link_sta *link_sta;
struct cfg80211_bitrate_mask mask;
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
struct sta_phy_uni phy = {};
int ret, nrates = 0;
struct ieee80211_sta *sta;
int ret, nrates = 0, idx;
enum nl80211_band band;
bool has_he;
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
do { \
u8 i, gi = mask->control[band]._gi; \
u8 i, gi = mask.control[band]._gi; \
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
phy.sgi = gi; \
phy.he_ltf = mask->control[band].he_ltf; \
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
if (!mask->control[band]._mcs[i]) \
phy.he_ltf = mask.control[band].he_ltf; \
for (i = 0; i < ARRAY_SIZE(mask.control[band]._mcs); i++) { \
if (!mask.control[band]._mcs[i]) \
continue; \
nrates += hweight16(mask->control[band]._mcs[i]); \
phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
nrates += hweight16(mask.control[band]._mcs[i]); \
phy.mcs = ffs(mask.control[band]._mcs[i]) - 1; \
if (_ht) \
phy.mcs += 8 * i; \
} \
} while (0)
if (link_sta->he_cap.has_he) {
rcu_read_lock();
link = mt7996_vif_link(dev, vif, link_id);
if (!link)
goto error_unlock;
msta_link = rcu_dereference(msta->link[link_id]);
if (!msta_link)
goto error_unlock;
sta = wcid_to_sta(&msta_link->wcid);
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta)
goto error_unlock;
band = link->phy->mt76->chandef.chan->band;
has_he = link_sta->he_cap.has_he;
mask = link->bitrate_mask;
idx = msta_link->wcid.idx;
if (has_he) {
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
} else if (link_sta->vht_cap.vht_supported) {
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
} else if (link_sta->ht_cap.ht_supported) {
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
} else {
nrates = hweight32(mask->control[band].legacy);
phy.mcs = ffs(mask->control[band].legacy) - 1;
nrates = hweight32(mask.control[band].legacy);
phy.mcs = ffs(mask.control[band].legacy) - 1;
}
rcu_read_unlock();
#undef __sta_phy_bitrate_mask_check
/* fall back to auto rate control */
if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
mask->control[band].he_gi == GENMASK(7, 0) &&
mask->control[band].he_ltf == GENMASK(7, 0) &&
if (mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
mask.control[band].he_gi == GENMASK(7, 0) &&
mask.control[band].he_ltf == GENMASK(7, 0) &&
nrates != 1)
return 0;
/* fixed single rate */
if (nrates == 1) {
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
msta_link, &phy,
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
RATE_PARAM_FIXED_MCS);
if (ret)
return ret;
}
/* fixed GI */
if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
mask->control[band].he_gi != GENMASK(7, 0)) {
if (mask.control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
mask.control[band].he_gi != GENMASK(7, 0)) {
u32 addr;
/* firmware updates only TXCMD but doesn't take WTBL into
* account, so driver should update here to reflect the
* actual txrate hardware sends out.
*/
addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7);
if (link_sta->he_cap.has_he)
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 7);
if (has_he)
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
else
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
msta_link, &phy,
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
RATE_PARAM_FIXED_GI);
if (ret)
return ret;
}
/* fixed HE_LTF */
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
msta_link, &phy,
if (mask.control[band].he_ltf != GENMASK(7, 0)) {
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
RATE_PARAM_FIXED_HE_LTF);
if (ret)
return ret;
}
return 0;
error_unlock:
rcu_read_unlock();
return -ENODEV;
}
static void
@ -2145,21 +2198,44 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
}
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link, bool changed)
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
struct ieee80211_vif *vif, u8 link_id,
bool changed)
{
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
struct ieee80211_sta *sta;
struct sk_buff *skb;
int ret;
int ret = -ENODEV;
rcu_read_lock();
link = mt7996_vif_link(dev, vif, link_id);
if (!link)
goto error_unlock;
msta_link = rcu_dereference(msta->link[link_id]);
if (!msta_link)
goto error_unlock;
sta = wcid_to_sta(&msta_link->wcid);
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta)
goto error_unlock;
link_conf = rcu_dereference(vif->link_conf[link_id]);
if (!link_conf)
goto error_unlock;
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
&msta_link->wcid,
MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
goto error_unlock;
}
/* firmware rc algorithm refers to sta_rec_he for HE control.
* once dev->rc_work changes the settings driver should also
@ -2173,12 +2249,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
*/
mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link);
rcu_read_unlock();
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
if (ret)
return ret;
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link);
return mt7996_mcu_add_rate_ctrl_fixed(dev, msta, vif, link_id);
error_unlock:
rcu_read_unlock();
return ret;
}
static int

View File

@ -620,23 +620,17 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
struct mt7996_vif_link *link,
struct ieee80211_he_obss_pd *he_obss_pd);
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link, bool changed);
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
struct ieee80211_vif *vif, u8 link_id,
bool changed);
int mt7996_set_channel(struct mt76_phy *mphy);
int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
void *data, u16 version);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
void *data, u32 field);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
void *data, u8 link_id, u32 field);
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);

View File

@ -64,7 +64,7 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
struct mt76_wcid *wcid;
wcid = rcu_dereference(dev->wcid[cb->wcid]);
wcid = __mt76_wcid_ptr(dev, cb->wcid);
if (wcid) {
status.sta = wcid_to_sta(wcid);
if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) {
@ -251,9 +251,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
rcu_read_lock();
if (wcid_idx < ARRAY_SIZE(dev->wcid))
wcid = rcu_dereference(dev->wcid[wcid_idx]);
wcid = __mt76_wcid_ptr(dev, wcid_idx);
mt76_tx_check_non_aql(dev, wcid, skb);
#ifdef CONFIG_NL80211_TESTMODE
@ -538,7 +536,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
break;
mtxq = (struct mt76_txq *)txq->drv_priv;
wcid = rcu_dereference(dev->wcid[mtxq->wcid]);
wcid = __mt76_wcid_ptr(dev, mtxq->wcid);
if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
continue;
@ -617,7 +615,8 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
!ieee80211_is_data(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(skb))
(!ieee80211_is_bufferable_mmpdu(skb) ||
ieee80211_is_deauth(hdr->frame_control)))
qid = MT_TXQ_PSD;
q = phy->q_tx[qid];

View File

@ -83,7 +83,7 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
if (!(mask & 1))
continue;
wcid = rcu_dereference(dev->wcid[j]);
wcid = __mt76_wcid_ptr(dev, j);
if (!wcid || wcid->phy_idx != phy_idx)
continue;