Shengyu Qu <wiagn233@xxxxxxxxxxx> wrote: > @@ -1280,6 +1292,34 @@ static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, > if (!msta->wcid.sta) > return; > > + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && > + !is_mt7915(&dev->mt76) && > + (msta->wcid.idx < min || msta->wcid.idx > max - 1)) { > + pre_sta = kmemdup(sta, sizeof(*sta) + sizeof(*msta), GFP_KERNEL | __GFP_ZERO); Need to check if pre_sta != NULL before using. > + pre_msta = (struct mt7915_sta *)pre_sta->drv_priv; > + > + flags = test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags) ? > + MT76_WED_WDS_ACTIVE : MT76_WED_ACTIVE; > + > + tmp_idx = __mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA, flags); > + if (tmp_idx == -1) At other places, it checks this by 'idx < 0'. > + goto error; > + pre_msta->wcid.idx = (u16)tmp_idx; > + mt7915_mac_sta_add(&dev->mt76, vif, pre_sta); > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], &msta->wcid); > + > + tmp_idx = msta->wcid.idx; > + msta->wcid.idx = pre_msta->wcid.idx; > + pre_msta->wcid.idx = (u16)tmp_idx; > + rcu_assign_pointer(dev->mt76.wcid[tmp_idx], NULL); > + > + synchronize_rcu(); > + mt7915_mac_sta_remove(&dev->mt76, vif, pre_sta); > + > +error: > + kfree(pre_sta); > + } > + > mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); > } > [...] > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > index 9d790f234e82..32c5aa1a361e 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c > @@ -2385,10 +2385,20 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev) > > mt76_connac_mcu_del_wtbl_all(&dev->mt76); > > - if ((mtk_wed_device_active(&dev->mt76.mmio.wed) && > - is_mt7915(&dev->mt76)) || > - !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > - mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0); > +#ifdef CONFIG_NET_MEDIATEK_SOC_WED if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) ... ? > + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { > + if (is_mt7915(&dev->mt76) || > + !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed)) > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), > + 0, 0, 0); > + else > + ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), > + MCU_WA_PARAM_WED_VERSION, > + dev->mt76.mmio.wed.rev_id, 0); > + if (ret) > + return ret; > + } > +#endif > > ret = mt7915_mcu_set_mwds(dev, 1); > if (ret) > diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > index 49476a4182fd..c3dd0cb4a5d3 100644 > --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h > @@ -278,6 +278,7 @@ enum { > MCU_WA_PARAM_PDMA_RX = 0x04, > MCU_WA_PARAM_CPU_UTIL = 0x0b, > MCU_WA_PARAM_RED = 0x0e, > + MCU_WA_PARAM_WED_VERSION = 0x32, > MCU_WA_PARAM_RED_SETTING = 0x40, > }; > > diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c > index 95b3dc96e4c4..7fac9c79ebdf 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.c > +++ b/drivers/net/wireless/mediatek/mt76/util.c > @@ -42,9 +42,11 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, > } > EXPORT_SYMBOL_GPL(____mt76_poll_msec); > > -int mt76_wcid_alloc(u32 *mask, int size) > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flag) > { > int i, idx = 0, cur; > + int min = MT76_WED_WDS_MIN; > + int max = MT76_WED_WDS_MAX; In reverse X'mas tree order? > > for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { > idx = ffs(~mask[i]); > @@ -53,16 +55,45 @@ int mt76_wcid_alloc(u32 *mask, int size) > > idx--; > cur = i * 32 + idx; > - if (cur >= size) > + > + switch (flag) { > + case MT76_WED_ACTIVE: > + if (cur >= min && cur < max) > + continue; > + > + if (cur >= size) { > + u32 end = max - min - 1; > + > + i = min / 32; > + idx = ffs(~mask[i] & GENMASK(end, 0)); > + if (!idx) > + goto error; > + idx--; > + cur = min + idx; > + } > + > break; > + case MT76_WED_WDS_ACTIVE: > + if (cur < min) > + continue; > + if (cur >= max) > + goto error; > + > + break; > + default: > + if (cur >= size) > + goto error; > + break; > + } > > mask[i] |= BIT(idx); > return cur; > } > > +error: > return -1; > } > -EXPORT_SYMBOL_GPL(mt76_wcid_alloc); > +EXPORT_SYMBOL_GPL(__mt76_wcid_alloc); > > int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx) > { > diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h > index 260965dde94c..99b7263c0a20 100644 > --- a/drivers/net/wireless/mediatek/mt76/util.h > +++ b/drivers/net/wireless/mediatek/mt76/util.h > @@ -27,7 +27,12 @@ enum { > #define MT76_INCR(_var, _size) \ > (_var = (((_var) + 1) % (_size))) > > -int mt76_wcid_alloc(u32 *mask, int size); > +int __mt76_wcid_alloc(u32 *mask, int size, u8 flags); > + > +static inline int mt76_wcid_alloc(u32 *mask, int size) > +{ > + return __mt76_wcid_alloc(mask, size, 0); return __mt76_wcid_alloc(mask, size, MT76_WED_DEFAULT); ? > +} > > static inline void > mt76_wcid_mask_set(u32 *mask, int idx) > -- > 2.48.1