diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt792x_core.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt792x_core.c | 111 |
1 files changed, 79 insertions, 32 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c index a405af8d9052..78fe37c2e07b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -59,20 +59,42 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; + u8 link_id; int qid; if (control->sta) { + struct mt792x_link_sta *mlink; struct mt792x_sta *sta; - + link_id = u32_get_bits(info->control.flags, + IEEE80211_TX_CTRL_MLO_LINK); sta = (struct mt792x_sta *)control->sta->drv_priv; - wcid = &sta->wcid; + mlink = mt792x_sta_to_link(sta, link_id); + wcid = &mlink->wcid; } if (vif && !control->sta) { struct mt792x_vif *mvif; mvif = (struct mt792x_vif *)vif->drv_priv; - wcid = &mvif->sta.wcid; + wcid = &mvif->sta.deflink.wcid; + } + + if (vif && control->sta && ieee80211_vif_is_mld(vif)) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_link_sta *link_sta; + struct ieee80211_bss_conf *conf; + + link_id = wcid->link_id; + rcu_read_lock(); + conf = rcu_dereference(vif->link_conf[link_id]); + memcpy(hdr->addr2, conf->addr, ETH_ALEN); + + link_sta = rcu_dereference(control->sta->link[link_id]); + memcpy(hdr->addr1, link_sta->addr, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_STATION) + memcpy(hdr->addr3, conf->bssid, ETH_ALEN); + rcu_read_unlock(); } if (mt76_connac_pm_ref(mphy, &dev->pm)) { @@ -91,7 +113,7 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, } EXPORT_SYMBOL_GPL(mt792x_tx); -void mt792x_stop(struct ieee80211_hw *hw) +void mt792x_stop(struct ieee80211_hw *hw, bool suspend) { struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt792x_phy *phy = mt792x_hw_phy(hw); @@ -113,31 +135,47 @@ void mt792x_stop(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(mt792x_stop); +void mt792x_mac_link_bss_remove(struct mt792x_dev *dev, + struct mt792x_bss_conf *mconf, + struct mt792x_link_sta *mlink) +{ + struct ieee80211_vif *vif = container_of((void *)mconf->vif, + struct ieee80211_vif, drv_priv); + struct ieee80211_bss_conf *link_conf; + int idx = mlink->wcid.idx; + + link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id); + + mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid); + mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mlink->wcid, false); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + + dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx); + mconf->vif->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); +} +EXPORT_SYMBOL_GPL(mt792x_mac_link_bss_remove); + void mt792x_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct mt792x_sta *msta = &mvif->sta; struct mt792x_dev *dev = mt792x_hw_dev(hw); - struct mt792x_phy *phy = mt792x_hw_phy(hw); - int idx = msta->wcid.idx; + struct mt792x_bss_conf *mconf; mt792x_mutex_acquire(dev); - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); - rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + mconf = mt792x_link_conf_to_mconf(&vif->bss_conf); + mt792x_mac_link_bss_remove(dev, mconf, &mvif->sta.deflink); - dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); - phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mt792x_mutex_release(dev); - - spin_lock_bh(&dev->mt76.sta_poll_lock); - if (!list_empty(&msta->wcid.poll_list)) - list_del_init(&msta->wcid.poll_list); - spin_unlock_bh(&dev->mt76.sta_poll_lock); - - mt76_wcid_cleanup(&dev->mt76, &msta->wcid); } EXPORT_SYMBOL_GPL(mt792x_remove_interface); @@ -149,7 +187,7 @@ int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* no need to update right away, we'll get BSS_CHANGED_QOS */ queue = mt76_connac_lmac_mapping(queue); - mvif->queue_params[queue] = *params; + mvif->bss_conf.queue_params[queue] = *params; return 0; } @@ -178,7 +216,7 @@ u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; + u8 omac_idx = mvif->bss_conf.mt76.omac_idx; union { u64 t64; u32 t32[2]; @@ -204,7 +242,7 @@ void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; + u8 omac_idx = mvif->bss_conf.mt76.omac_idx; union { u64 t64; u32 t32[2]; @@ -261,11 +299,13 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->mt76.ctx = ctx; + mvif->bss_conf.mt76.ctx = ctx; + mctx->bss_conf = &mvif->bss_conf; mutex_unlock(&dev->mt76.mutex); return 0; @@ -277,11 +317,13 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf, struct ieee80211_chanctx_conf *ctx) { + struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv; struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt792x_dev *dev = mt792x_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mvif->mt76.ctx = NULL; + mctx->bss_conf = NULL; + mvif->bss_conf.mt76.ctx = NULL; mutex_unlock(&dev->mt76.mutex); } EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx); @@ -405,10 +447,10 @@ mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; struct mt76_ethtool_worker_info *wi = wi_data; - if (msta->vif->mt76.idx != wi->idx) + if (msta->vif->bss_conf.mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->wcid.stats, true); + mt76_ethtool_worker(wi, &msta->deflink.wcid.stats, true); } void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -421,7 +463,7 @@ void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, - .idx = mvif->mt76.idx, + .idx = mvif->bss_conf.mt76.idx, }; int i, ei = 0; @@ -487,7 +529,7 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, struct station_info *sinfo) { struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct rate_info *txrate = &msta->wcid.rate; + struct rate_info *txrate = &msta->deflink.wcid.rate; if (!txrate->legacy && !txrate->flags) return; @@ -502,19 +544,19 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw, sinfo->txrate.he_dcm = txrate->he_dcm; sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; } - sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->tx_failed = msta->deflink.wcid.stats.tx_failed; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->tx_retries = msta->deflink.wcid.stats.tx_retries; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); - sinfo->ack_signal = (s8)msta->ack_signal; + sinfo->ack_signal = (s8)msta->deflink.ack_signal; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); - sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); + sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->deflink.avg_ack_signal); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); } EXPORT_SYMBOL_GPL(mt792x_sta_statistics); @@ -556,6 +598,7 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw) hw->sta_data_size = sizeof(struct mt792x_sta); hw->vif_data_size = sizeof(struct mt792x_vif); + hw->chanctx_data_size = sizeof(struct mt792x_chanctx); if (dev->fw_features & MT792x_FW_CAP_CNM) { wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; @@ -766,6 +809,10 @@ int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); + + if (dev->aspm_supported) + usleep_range(2000, 3000); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) break; |