| From 9b5284be6784cf32222425a9cbbd9622db38aafd Mon Sep 17 00:00:00 2001 |
| From: Shayne Chen <shayne.chen@mediatek.com> |
| Date: Thu, 23 Nov 2023 18:22:11 +0800 |
| Subject: [PATCH 089/116] wifi: mt76: mt7996: support multi-link vif links and |
| MLO bss callbacks |
| |
| Rework add/remove interface functions to add/remove bss_conf functions, |
| and also switch to callbacks for MLO bss. |
| This is a preliminary patch to add MLO support for mt7996 chipsets. |
| |
| Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com> |
| Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com> |
| Signed-off-by: Shayne Chen <shayne.chen@mediatek.com> |
| --- |
| mt7996/main.c | 298 +++++++++++++++++++++++++++++++++++++++--------- |
| mt7996/mcu.c | 29 +++-- |
| mt7996/mt7996.h | 9 ++ |
| 3 files changed, 270 insertions(+), 66 deletions(-) |
| |
| diff --git a/mt7996/main.c b/mt7996/main.c |
| index 4e5ba58..9fbb86c 100644 |
| --- a/mt7996/main.c |
| +++ b/mt7996/main.c |
| @@ -205,6 +205,38 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) |
| return -1; |
| } |
| |
| +static int get_own_mld_idx(u64 mask, bool group_mld) |
| +{ |
| + u8 start, end; |
| + int i; |
| + |
| + if (group_mld) { |
| + start = 0; |
| + end = 15; |
| + } else { |
| + start = 16; |
| + end = 63; |
| + } |
| + |
| + i = get_free_idx(mask, start, end); |
| + if (i) |
| + return i - 1; |
| + |
| + return -1; |
| +} |
| + |
| +static int get_mld_remap_idx(u64 mask) |
| +{ |
| + u8 start = 0, end = 15; |
| + int i; |
| + |
| + i = get_free_idx(mask, start, end); |
| + if (i) |
| + return i - 1; |
| + |
| + return -1; |
| +} |
| + |
| static void mt7996_init_bitrate_mask(struct mt7996_bss_conf *mconf) |
| { |
| int i; |
| @@ -223,48 +255,108 @@ static void mt7996_init_bitrate_mask(struct mt7996_bss_conf *mconf) |
| } |
| } |
| |
| -static int mt7996_add_interface(struct ieee80211_hw *hw, |
| - struct ieee80211_vif *vif) |
| +static void mt7996_remove_bss_conf(struct ieee80211_vif *vif, |
| + struct ieee80211_bss_conf *conf, |
| + struct mt7996_bss_conf *mconf) |
| { |
| - struct ieee80211_bss_conf *conf = &vif->bss_conf; |
| + struct mt7996_phy *phy = mconf->phy; |
| + struct mt7996_dev *dev = phy->dev; |
| struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| - struct mt7996_bss_conf *mconf = &mvif->deflink; |
| - struct mt7996_link_sta *mlink = &mvif->sta.deflink; |
| - struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| - struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| + u8 link_id = conf->link_id; |
| + struct mt7996_link_sta *mlink = |
| + mlink_dereference_protected(&mvif->sta, link_id); |
| + |
| + if (!mlink) |
| + return; |
| + |
| + mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, false, false); |
| + mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, false); |
| + mt7996_mcu_add_dev_info(phy, conf, mconf, false); |
| + |
| + rcu_assign_pointer(dev->mt76.wcid[mlink->wcid.idx], NULL); |
| + rcu_assign_pointer(mvif->link[link_id], NULL); |
| + rcu_assign_pointer(mvif->sta.link[link_id], NULL); |
| + |
| + dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx); |
| + dev->mld_id_mask &= ~BIT_ULL(mconf->own_mld_id); |
| + phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx); |
| + |
| + spin_lock_bh(&dev->mt76.sta_poll_lock); |
| + if (!list_empty(&mlink->wcid.poll_list)) |
| + list_del_init(&mlink->wcid.poll_list); |
| + spin_unlock_bh(&dev->mt76.sta_poll_lock); |
| + |
| + mt76_wcid_cleanup(&dev->mt76, &mlink->wcid); |
| + |
| + if (mlink != &mvif->sta.deflink) |
| + kfree(mlink); |
| + |
| + if (mconf != &mvif->deflink) |
| + kfree(mconf); |
| +} |
| + |
| +static int mt7996_add_bss_conf(struct mt7996_phy *phy, |
| + struct ieee80211_vif *vif, |
| + struct ieee80211_bss_conf *conf) |
| +{ |
| + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| + struct mt7996_dev *dev = phy->dev; |
| + struct mt7996_bss_conf *mconf; |
| + struct mt7996_link_sta *mlink; |
| struct mt76_txq *mtxq; |
| u8 band_idx = phy->mt76->band_idx; |
| - int idx, ret = 0; |
| - |
| - mutex_lock(&dev->mt76.mutex); |
| + u8 link_id = conf->link_id; |
| + int idx, ret; |
| |
| - if (vif->type == NL80211_IFTYPE_MONITOR && |
| - is_zero_ether_addr(vif->addr)) |
| - phy->monitor_vif = vif; |
| + if (conf != &vif->bss_conf) { |
| + mconf = kzalloc(sizeof(*mconf), GFP_KERNEL); |
| + if (!mconf) |
| + return -ENOMEM; |
| + } else { |
| + mconf = &mvif->deflink; |
| + } |
| |
| mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); |
| if (mconf->mt76.idx >= mt7996_max_interface_num(dev)) { |
| ret = -ENOSPC; |
| - goto out; |
| + goto error; |
| } |
| |
| idx = get_omac_idx(vif->type, phy->omac_mask); |
| if (idx < 0) { |
| ret = -ENOSPC; |
| - goto out; |
| + goto error; |
| + } |
| + |
| + mconf->own_mld_id = get_own_mld_idx(dev->mld_id_mask, false); |
| + if (mconf->own_mld_id < 0) { |
| + ret = -ENOSPC; |
| + goto error; |
| } |
| + |
| mconf->mt76.omac_idx = idx; |
| mconf->vif = mvif; |
| mconf->phy = phy; |
| mconf->mt76.band_idx = band_idx; |
| mconf->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; |
| - mvif->dev = dev; |
| + mconf->link_id = link_id; |
| |
| ret = mt7996_mcu_add_dev_info(phy, conf, mconf, true); |
| if (ret) |
| - goto out; |
| + goto error; |
| + |
| + if (ieee80211_vif_is_mld(vif)) { |
| + mlink = kzalloc(sizeof(*mlink), GFP_KERNEL); |
| + if (!mlink) { |
| + ret = -ENOMEM; |
| + goto error; |
| + } |
| + } else { |
| + mlink = &mvif->sta.deflink; |
| + } |
| |
| dev->mt76.vif_mask |= BIT_ULL(mconf->mt76.idx); |
| + dev->mld_id_mask |= BIT_ULL(mconf->own_mld_id); |
| phy->omac_mask |= BIT_ULL(mconf->mt76.omac_idx); |
| |
| idx = MT7996_WTBL_RESERVED - mconf->mt76.idx; |
| @@ -275,6 +367,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, |
| mlink->wcid.phy_idx = band_idx; |
| mlink->wcid.hw_key_idx = -1; |
| mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET; |
| + mlink->wcid.def_wcid = &mvif->sta.deflink.wcid; |
| + mlink->wcid.link_id = link_id; |
| + mlink->wcid.link_valid = ieee80211_vif_is_mld(vif); |
| mlink->sta = &mvif->sta; |
| mlink->sta->vif = mvif; |
| mt76_wcid_init(&mlink->wcid); |
| @@ -296,7 +391,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, |
| mconf->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; |
| else |
| mconf->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL; |
| - |
| mt7996_init_bitrate_mask(mconf); |
| |
| mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, true); |
| @@ -306,10 +400,32 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, |
| if (vif->type != NL80211_IFTYPE_STATION) |
| mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, true, true); |
| rcu_assign_pointer(dev->mt76.wcid[idx], &mlink->wcid); |
| - rcu_assign_pointer(mvif->link[0], mconf); |
| - rcu_assign_pointer(mvif->sta.link[0], mlink); |
| + rcu_assign_pointer(mvif->link[link_id], mconf); |
| + rcu_assign_pointer(mvif->sta.link[link_id], mlink); |
| |
| -out: |
| + return 0; |
| +error: |
| + mt7996_remove_bss_conf(vif, conf, mconf); |
| + return ret; |
| +} |
| + |
| +static int mt7996_add_interface(struct ieee80211_hw *hw, |
| + struct ieee80211_vif *vif) |
| +{ |
| + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| + struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| + struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| + int ret = 0; |
| + |
| + mutex_lock(&dev->mt76.mutex); |
| + if (vif->type == NL80211_IFTYPE_MONITOR && |
| + is_zero_ether_addr(vif->addr)) |
| + phy->monitor_vif = vif; |
| + |
| + mvif->dev = dev; |
| + mvif->sta.vif = mvif; |
| + |
| + ret = mt7996_add_bss_conf(phy, vif, &vif->bss_conf); |
| mutex_unlock(&dev->mt76.mutex); |
| |
| return ret; |
| @@ -321,38 +437,23 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, |
| struct ieee80211_bss_conf *conf; |
| struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| struct mt7996_bss_conf *mconf; |
| - struct mt7996_link_sta *mlink = &mvif->sta.deflink; |
| struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| - int idx = mlink->wcid.idx; |
| |
| cancel_delayed_work_sync(&phy->scan_work); |
| |
| mutex_lock(&dev->mt76.mutex); |
| |
| - conf = link_conf_dereference_protected(vif, 0); |
| - mconf = mconf_dereference_protected(mvif, 0); |
| - mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, false, false); |
| - mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, false); |
| + if (test_bit(MT76_SCANNING, &phy->mt76->state)) |
| + mt7996_scan_complete(phy, true); |
| |
| if (vif == phy->monitor_vif) |
| phy->monitor_vif = NULL; |
| |
| - mt7996_mcu_add_dev_info(phy, conf, mconf, false); |
| - |
| - rcu_assign_pointer(dev->mt76.wcid[idx], NULL); |
| - |
| - dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx); |
| - phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx); |
| - |
| - spin_lock_bh(&dev->mt76.sta_poll_lock); |
| - if (!list_empty(&mlink->wcid.poll_list)) |
| - list_del_init(&mlink->wcid.poll_list); |
| - spin_unlock_bh(&dev->mt76.sta_poll_lock); |
| + conf = link_conf_dereference_protected(vif, 0); |
| + mconf = mconf_dereference_protected(mvif, 0); |
| |
| - mt76_wcid_cleanup(&dev->mt76, &mlink->wcid); |
| - rcu_assign_pointer(mvif->link[0], NULL); |
| - rcu_assign_pointer(mvif->sta.link[0], NULL); |
| + mt7996_remove_bss_conf(vif, conf, mconf); |
| |
| mutex_unlock(&dev->mt76.mutex); |
| } |
| @@ -716,10 +817,31 @@ mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_bss_conf *conf, |
| mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]); |
| } |
| |
| -static void mt7996_bss_info_changed(struct ieee80211_hw *hw, |
| - struct ieee80211_vif *vif, |
| - struct ieee80211_bss_conf *info, |
| - u64 changed) |
| +static void mt7996_vif_cfg_changed(struct ieee80211_hw *hw, |
| + struct ieee80211_vif *vif, u64 changed) |
| +{ |
| + struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| + struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| + |
| + mutex_lock(&dev->mt76.mutex); |
| + |
| + if (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) { |
| + struct ieee80211_bss_conf *conf = &vif->bss_conf; |
| + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| + struct mt7996_bss_conf *mconf = mconf_dereference_protected(mvif, 0); |
| + struct mt7996_link_sta *mlink = mlink_dereference_protected(&mvif->sta, 0); |
| + |
| + mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, true); |
| + mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, true, false); |
| + } |
| + |
| + mutex_unlock(&dev->mt76.mutex); |
| +} |
| + |
| +static void mt7996_link_info_changed(struct ieee80211_hw *hw, |
| + struct ieee80211_vif *vif, |
| + struct ieee80211_bss_conf *info, |
| + u64 changed) |
| { |
| struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| struct mt7996_bss_conf *mconf; |
| @@ -735,7 +857,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, |
| * and then peer references bss_info_rfch to set bandwidth cap. |
| */ |
| if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) || |
| - (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) || |
| (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) { |
| mt7996_mcu_add_bss_info(phy, info, mconf, mlink, true); |
| mt7996_mcu_add_sta(dev, info, mconf, NULL, mlink, true, |
| @@ -1078,7 +1199,7 @@ mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
| u64 ret; |
| |
| mutex_lock(&dev->mt76.mutex); |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, mvif->master_link_id); |
| ret = __mt7996_get_tsf(hw, mconf); |
| mutex_unlock(&dev->mt76.mutex); |
| |
| @@ -1101,7 +1222,7 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| |
| mutex_lock(&dev->mt76.mutex); |
| |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, mvif->master_link_id); |
| n = mconf->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 |
| : mconf->mt76.omac_idx; |
| mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); |
| @@ -1129,7 +1250,7 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| |
| mutex_lock(&dev->mt76.mutex); |
| |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, mvif->master_link_id); |
| n = mconf->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 |
| : mconf->mt76.omac_idx; |
| mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); |
| @@ -1304,7 +1425,7 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; |
| |
| mutex_lock(&dev->mt76.mutex); |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, mvif->master_link_id); |
| mconf->bitrate_mask = *mask; |
| mutex_unlock(&dev->mt76.mutex); |
| |
| @@ -1524,7 +1645,7 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw, |
| int i, ei = 0; |
| |
| mutex_lock(&dev->mt76.mutex); |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, mvif->master_link_id); |
| wi.idx = mconf->mt76.idx, |
| |
| mt7996_mac_update_stats(phy); |
| @@ -1897,6 +2018,8 @@ mt7996_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| struct mt7996_phy *phy = ctx->phy; |
| struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| struct mt7996_bss_conf *mconf; |
| + u8 link_id = link_conf->link_id; |
| + int ret; |
| |
| wiphy_info(hw->wiphy, "Assign VIF (addr: %pM, type: %d, link_id: %d) to channel context: %d MHz\n", |
| vif->addr, vif->type, link_conf->link_id, |
| @@ -1904,10 +2027,24 @@ mt7996_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| |
| mutex_lock(&phy->dev->mt76.mutex); |
| |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + /* remove first */ |
| + if (rcu_access_pointer(mvif->link[link_id])) |
| + mt7996_remove_bss_conf(vif, link_conf, |
| + mconf_dereference_protected(mvif, link_id)); |
| + |
| + ret = mt7996_add_bss_conf(phy, vif, link_conf); |
| + if (ret) { |
| + mutex_unlock(&phy->dev->mt76.mutex); |
| + return ret; |
| + } |
| + |
| + mconf = mconf_dereference_protected(mvif, link_id); |
| mconf->chanctx = ctx; |
| ctx->nbss_assigned++; |
| |
| + if (mt7996_hw_phy(hw) == phy) |
| + mvif->master_link_id = link_id; |
| + |
| mutex_unlock(&phy->dev->mt76.mutex); |
| |
| return 0; |
| @@ -1933,7 +2070,7 @@ mt7996_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| if (test_bit(MT76_SCANNING, &phy->mt76->state)) |
| mt7996_scan_complete(phy, true); |
| |
| - mconf = mconf_dereference_protected(mvif, 0); |
| + mconf = mconf_dereference_protected(mvif, link_conf->link_id); |
| mconf->chanctx = NULL; |
| ctx->nbss_assigned--; |
| |
| @@ -1973,6 +2110,57 @@ mt7996_switch_vif_chanctx(struct ieee80211_hw *hw, |
| return mt7996_set_channel(phy, &new_ctx->chandef); |
| } |
| |
| +static int |
| +mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
| + u16 old_links, u16 new_links, |
| + struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) |
| +{ |
| + struct mt7996_dev *dev = mt7996_hw_dev(hw); |
| + struct mt7996_phy *phy = mt7996_hw_phy(hw); |
| + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| + unsigned long rem = old_links & ~new_links; |
| + unsigned int link_id; |
| + int ret = 0; |
| + |
| + if (old_links == new_links) |
| + return 0; |
| + |
| + mutex_lock(&dev->mt76.mutex); |
| + |
| + /* check if there's legacy bss needed to be removed */ |
| + if (rcu_access_pointer(mvif->link[0]) == &mvif->deflink) |
| + rem |= BIT(0); |
| + /* remove first */ |
| + for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) { |
| + struct mt7996_bss_conf *mconf = |
| + mconf_dereference_protected(mvif, link_id); |
| + |
| + if (!mconf) |
| + continue; |
| + |
| + mt7996_remove_bss_conf(vif, old[link_id], mconf); |
| + } |
| + |
| + if (!old_links) { |
| + mvif->group_mld_id = get_own_mld_idx(dev->mld_id_mask, true); |
| + dev->mld_id_mask |= BIT_ULL(mvif->group_mld_id); |
| + |
| + mvif->mld_remap_id = get_mld_remap_idx(dev->mld_remap_id_mask); |
| + dev->mld_remap_id_mask |= BIT_ULL(mvif->mld_remap_id); |
| + } |
| + |
| + /* fallback to non-MLO interface */ |
| + if (!new_links) { |
| + ret = mt7996_add_bss_conf(phy, vif, &vif->bss_conf); |
| + dev->mld_id_mask &= ~BIT_ULL(mvif->group_mld_id); |
| + dev->mld_remap_id_mask &= ~BIT_ULL(mvif->mld_remap_id); |
| + } |
| + |
| + mutex_unlock(&dev->mt76.mutex); |
| + |
| + return ret; |
| +} |
| + |
| const struct ieee80211_ops mt7996_ops = { |
| .tx = mt7996_tx, |
| .start = mt7996_start, |
| @@ -1982,7 +2170,8 @@ const struct ieee80211_ops mt7996_ops = { |
| .config = mt7996_config, |
| .conf_tx = mt7996_conf_tx, |
| .configure_filter = mt7996_configure_filter, |
| - .bss_info_changed = mt7996_bss_info_changed, |
| + .vif_cfg_changed = mt7996_vif_cfg_changed, |
| + .link_info_changed = mt7996_link_info_changed, |
| .sta_state = mt76_sta_state, |
| .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, |
| .sta_rc_update = mt7996_sta_rc_update, |
| @@ -2028,4 +2217,5 @@ const struct ieee80211_ops mt7996_ops = { |
| .assign_vif_chanctx = mt7996_assign_vif_chanctx, |
| .unassign_vif_chanctx = mt7996_unassign_vif_chanctx, |
| .switch_vif_chanctx = mt7996_switch_vif_chanctx, |
| + .change_vif_links = mt7996_change_vif_links, |
| }; |
| diff --git a/mt7996/mcu.c b/mt7996/mcu.c |
| index cab4a0a..2a17299 100644 |
| --- a/mt7996/mcu.c |
| +++ b/mt7996/mcu.c |
| @@ -1047,15 +1047,23 @@ static void |
| mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, |
| struct mt7996_bss_conf *mconf) |
| { |
| + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; |
| struct bss_mld_tlv *mld; |
| struct tlv *tlv; |
| |
| tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_MLD, sizeof(*mld)); |
| - |
| mld = (struct bss_mld_tlv *)tlv; |
| - mld->group_mld_id = 0xff; |
| - mld->own_mld_id = mconf->mt76.idx; |
| - mld->remap_idx = 0xff; |
| + |
| + if (ieee80211_vif_is_mld(vif)) { |
| + mld->group_mld_id = mvif->group_mld_id; |
| + mld->remap_idx = mvif->mld_remap_id; |
| + memcpy(mld->mac_addr, vif->addr, ETH_ALEN); |
| + } else { |
| + mld->group_mld_id = 0xff; |
| + mld->remap_idx = 0xff; |
| + } |
| + |
| + mld->own_mld_id = mconf->own_mld_id; |
| } |
| |
| static void |
| @@ -1136,13 +1144,11 @@ mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct mt7996_phy *phy) |
| } |
| |
| static int |
| -mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, |
| - struct ieee80211_bss_conf *conf, |
| - struct mt7996_bss_conf *mconf, |
| - struct ieee80211_sta *sta, |
| - struct mt76_phy *phy, u16 wlan_idx, |
| - bool enable) |
| +mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *conf, |
| + struct mt7996_bss_conf *mconf, struct ieee80211_sta *sta, |
| + u16 wlan_idx, bool enable) |
| { |
| + struct mt76_phy *phy = mconf->phy->mt76; |
| struct ieee80211_vif *vif = conf->vif; |
| struct cfg80211_chan_def *chandef = &phy->chandef; |
| struct mt76_connac_bss_basic_tlv *bss; |
| @@ -1254,8 +1260,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, |
| return PTR_ERR(skb); |
| |
| /* bss_basic must be first */ |
| - mt7996_mcu_bss_basic_tlv(skb, conf, mconf, NULL, phy->mt76, |
| - mlink->wcid.idx, enable); |
| + mt7996_mcu_bss_basic_tlv(skb, conf, mconf, NULL, mlink->wcid.idx, enable); |
| mt7996_mcu_bss_sec_tlv(skb, mconf); |
| |
| if (vif->type == NL80211_IFTYPE_MONITOR) |
| diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h |
| index 3701720..ed8c82e 100644 |
| --- a/mt7996/mt7996.h |
| +++ b/mt7996/mt7996.h |
| @@ -340,6 +340,9 @@ struct mt7996_bss_conf { |
| struct cfg80211_bitrate_mask bitrate_mask; |
| |
| struct mt7996_chanctx *chanctx; |
| + |
| + u8 link_id; |
| + u8 own_mld_id; |
| }; |
| |
| struct mt7996_vif { |
| @@ -348,6 +351,10 @@ struct mt7996_vif { |
| |
| struct mt7996_sta sta; |
| struct mt7996_dev *dev; |
| + |
| + u8 master_link_id; |
| + u8 group_mld_id; |
| + u8 mld_remap_id; |
| }; |
| |
| /* crash-dump */ |
| @@ -549,6 +556,8 @@ struct mt7996_dev { |
| u16 chainmask; |
| u8 chainshift[__MT_MAX_BAND]; |
| u32 hif_idx; |
| + u64 mld_id_mask; |
| + u64 mld_remap_id_mask; |
| |
| struct work_struct init_work; |
| struct work_struct rc_work; |
| -- |
| 2.18.0 |
| |