diff options
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mac80211.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt76.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/main.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/main.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 60 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/main.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/tx.c | 12 |
12 files changed, 124 insertions, 51 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 3afe4c4cd7bb..59adf3312617 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_free_device); +static void mt76_reset_phy(struct mt76_phy *phy) +{ + if (!phy) + return; + + INIT_LIST_HEAD(&phy->tx_list); +} + +void mt76_reset_device(struct mt76_dev *dev) +{ + int i; + + rcu_read_lock(); + for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) { + struct mt76_wcid *wcid; + + wcid = rcu_dereference(dev->wcid[i]); + if (!wcid) + continue; + + wcid->sta = 0; + mt76_wcid_cleanup(dev, wcid); + rcu_assign_pointer(dev->wcid[i], NULL); + } + rcu_read_unlock(); + + INIT_LIST_HEAD(&dev->wcid_list); + INIT_LIST_HEAD(&dev->sta_poll_list); + dev->vif_mask = 0; + memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask)); + + mt76_reset_phy(&dev->phy); + for (i = 0; i < ARRAY_SIZE(dev->phys); i++) + mt76_reset_phy(dev->phys[i]); +} +EXPORT_SYMBOL_GPL(mt76_reset_device); + struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1679,6 +1716,10 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) skb_queue_splice_tail_init(&wcid->tx_pending, &list); spin_unlock(&wcid->tx_pending.lock); + spin_lock(&wcid->tx_offchannel.lock); + skb_queue_splice_tail_init(&wcid->tx_offchannel, &list); + spin_unlock(&wcid->tx_offchannel.lock); + spin_unlock_bh(&phy->tx_lock); while ((skb = __skb_dequeue(&list)) != NULL) { @@ -1690,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup); void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid) { - if (test_bit(MT76_MCU_RESET, &dev->phy.state)) + if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta) return; spin_lock_bh(&dev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8dd5c29fb75b..127637454c82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1243,6 +1243,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); void mt76_free_device(struct mt76_dev *dev); +void mt76_reset_device(struct mt76_dev *dev); void mt76_unregister_phy(struct mt76_phy *phy); struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 6639976afcee..1c0d310146d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1460,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev) if (i == 10) dev_err(dev->mt76.dev, "chip full reset failed\n"); - spin_lock_bh(&dev->mt76.sta_poll_lock); - while (!list_empty(&dev->mt76.sta_poll_list)) - list_del_init(dev->mt76.sta_poll_list.next); - spin_unlock_bh(&dev->mt76.sta_poll_lock); - - memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask)); - dev->mt76.vif_mask = 0; dev->phy.omac_mask = 0; if (phy2) phy2->omac_mask = 0; + mt76_reset_device(&dev->mt76); + + INIT_LIST_HEAD(&dev->sta_rc_list); + INIT_LIST_HEAD(&dev->twt_list); + i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); dev->mt76.global_wcid.idx = i; dev->recovery.hw_full_reset = false; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 40954e64c7fc..5881040ac195 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1459,11 +1459,8 @@ static int mt7921_pre_channel_switch(struct ieee80211_hw *hw, if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) return -EOPNOTSUPP; - /* Avoid beacon loss due to the CAC(Channel Availability Check) time - * of the AP. - */ if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef, - IEEE80211_CHAN_RADAR)) + IEEE80211_CHAN_DISABLED)) return -EOPNOTSUPP; return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c index 75823c9fd3a1..b581ab9427f2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c @@ -1449,7 +1449,7 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, sta = wcid_to_sta(wcid); if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt76_connac2_tx_check_aggr(sta, txwi); + mt7925_tx_check_aggr(sta, e->skb, wcid); skb_pull(e->skb, headroom); mt76_tx_complete_skb(mdev, e->wcid, e->skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index a8d25b7d47d0..b0e053b15227 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -1191,6 +1191,9 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, struct mt792x_bss_conf *mconf; struct mt792x_link_sta *mlink; + if (vif->type == NL80211_IFTYPE_AP) + break; + link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); if (!link_sta) continue; @@ -2069,8 +2072,10 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, GFP_KERNEL); mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), GFP_KERNEL); - if (!mconf || !mlink) + if (!mconf || !mlink) { + mt792x_mutex_release(dev); return -ENOMEM; + } } mconfs[link_id] = mconf; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index 300c863f0e3e..cd457be26523 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -1834,13 +1834,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb, struct tlv *tlv; u16 eml_cap; + if (!ieee80211_vif_is_mld(vif)) + return; + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld)); eht_mld = (struct sta_rec_eht_mld *)tlv; eht_mld->mld_type = 0xff; - if (!ieee80211_vif_is_mld(vif)) - return; - ext_capa = cfg80211_get_iftype_ext_capa(wiphy, ieee80211_vif_type_p2p(vif)); if (!ext_capa) @@ -1912,6 +1912,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, struct mt76_dev *dev = phy->dev; struct mt792x_bss_conf *mconf; struct sk_buff *skb; + int conn_state; mconf = mt792x_vif_to_link(mvif, info->wcid->link_id); @@ -1920,10 +1921,13 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, if (IS_ERR(skb)) return PTR_ERR(skb); + conn_state = info->enable ? CONN_STATE_PORT_SECURE : + CONN_STATE_DISCONNECT; + if (info->enable && info->link_sta) { mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, info->link_sta, - info->enable, info->newly); + conn_state, info->newly); mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta); mt7925_mcu_sta_ht_tlv(skb, info->link_sta); mt7925_mcu_sta_vht_tlv(skb, info->link_sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 226534490792..b3fcca9bbb95 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -62,7 +62,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, int i; wcid = mt76_wcid_ptr(dev, idx); - if (!wcid) + if (!wcid || !wcid->sta) return NULL; if (!mt7996_band_valid(dev, band_idx)) @@ -903,8 +903,12 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, IEEE80211_TX_CTRL_MLO_LINK); mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; - if (mvif) - mlink = rcu_dereference(mvif->mt76.link[link_id]); + if (mvif) { + if (wcid->offchannel) + mlink = rcu_dereference(mvif->mt76.offchannel_link); + if (!mlink) + mlink = rcu_dereference(mvif->mt76.link[link_id]); + } if (mlink) { omac_idx = mlink->omac_idx; @@ -1243,8 +1247,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); wcid = mt76_wcid_ptr(dev, idx); sta = wcid_to_sta(wcid); - if (!sta) + if (!sta) { + link_sta = NULL; goto next; + } link_sta = rcu_dereference(sta->link[wcid->link_id]); if (!link_sta) @@ -1694,43 +1700,53 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state) static void mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct ieee80211_hw *hw = priv; + struct ieee80211_bss_conf *link_conf; + struct mt7996_phy *phy = priv; + struct mt7996_dev *dev = phy->dev; + unsigned int link_id; + switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: - mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf); break; default: - break; + return; + } + + for_each_vif_active_link(vif, link_conf, link_id) { + struct mt7996_vif_link *link; + + link = mt7996_vif_link(dev, vif, link_id); + if (!link || link->phy != phy) + continue; + + mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf); } } +void mt7996_mac_update_beacons(struct mt7996_phy *phy) +{ + ieee80211_iterate_active_interfaces(phy->mt76->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7996_update_vif_beacon, phy); +} + static void mt7996_update_beacons(struct mt7996_dev *dev) { struct mt76_phy *phy2, *phy3; - ieee80211_iterate_active_interfaces(dev->mt76.hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7996_update_vif_beacon, dev->mt76.hw); + mt7996_mac_update_beacons(&dev->phy); phy2 = dev->mt76.phys[MT_BAND1]; - if (!phy2) - return; - - ieee80211_iterate_active_interfaces(phy2->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7996_update_vif_beacon, phy2->hw); + if (phy2) + mt7996_mac_update_beacons(phy2->priv); phy3 = dev->mt76.phys[MT_BAND2]; - if (!phy3) - return; - - ieee80211_iterate_active_interfaces(phy3->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7996_update_vif_beacon, phy3->hw); + if (phy3) + mt7996_mac_update_beacons(phy3->priv); } void mt7996_tx_token_put(struct mt7996_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 92b57bcce749..84f731b387d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -516,6 +516,9 @@ int mt7996_set_channel(struct mt76_phy *mphy) struct mt7996_phy *phy = mphy->priv; int ret; + if (mphy->offchannel) + mt7996_mac_update_beacons(phy); + ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH); if (ret) goto out; @@ -533,6 +536,8 @@ int mt7996_set_channel(struct mt76_phy *mphy) mt7996_mac_reset_counters(phy); phy->noise = 0; + if (!mphy->offchannel) + mt7996_mac_update_beacons(phy); out: ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 3593fd40c51b..0be03eb3cf46 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1879,8 +1879,8 @@ mt7996_mcu_get_mmps_mode(enum ieee80211_smps_mode smps) int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, void *data, u16 version) { + struct uni_header hdr = {}; struct ra_fixed_rate *req; - struct uni_header hdr; struct sk_buff *skb; struct tlv *tlv; int len; @@ -2755,13 +2755,15 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf); + struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf); + struct mt76_vif_link *mlink = link ? &link->mt76 : NULL; struct ieee80211_mutable_offsets offs; struct ieee80211_tx_info *info; struct sk_buff *skb, *rskb; struct tlv *tlv; struct bss_bcn_content_tlv *bcn; int len, extra_len = 0; + bool enabled = link_conf->enable_beacon; if (link_conf->nontransmitted) return 0; @@ -2769,13 +2771,16 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (!mlink) return -EINVAL; + if (link->phy && link->phy->mt76->offchannel) + enabled = false; + rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, MT7996_MAX_BSS_OFFLOAD_SIZE); if (IS_ERR(rskb)) return PTR_ERR(rskb); skb = ieee80211_beacon_get_template(hw, vif, &offs, link_conf->link_id); - if (link_conf->enable_beacon && !skb) { + if (enabled && !skb) { dev_kfree_skb(rskb); return -EINVAL; } @@ -2794,7 +2799,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4); tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len); bcn = (struct bss_bcn_content_tlv *)tlv; - bcn->enable = link_conf->enable_beacon; + bcn->enable = enabled; if (!bcn->enable) goto out; @@ -3372,7 +3377,7 @@ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans) { struct { u8 __rsv[4]; - } __packed hdr; + } __packed hdr = {}; struct hdr_trans_blacklist *req_blacklist; struct hdr_trans_en *req_en; struct sk_buff *skb; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 33ac16b64ef1..8509d508e1e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -732,6 +732,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed); +void mt7996_mac_update_beacons(struct mt7996_phy *phy); void mt7996_mac_set_coverage_class(struct mt7996_phy *phy); void mt7996_mac_work(struct work_struct *work); void mt7996_mac_reset_work(struct work_struct *work); diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index e6cf16706667..8ab5840fee57 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -332,6 +332,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (void *)skb->data; struct sk_buff_head *head; if (mt76_testmode_enabled(phy)) { @@ -349,7 +350,8 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || - (info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) + ((info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK) && + ieee80211_is_probe_req(hdr->frame_control))) head = &wcid->tx_offchannel; else head = &wcid->tx_pending; @@ -644,6 +646,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid, static void mt76_txq_schedule_pending(struct mt76_phy *phy) { LIST_HEAD(tx_list); + int ret = 0; if (list_empty(&phy->tx_list)) return; @@ -655,13 +658,13 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy) list_splice_init(&phy->tx_list, &tx_list); while (!list_empty(&tx_list)) { struct mt76_wcid *wcid; - int ret; wcid = list_first_entry(&tx_list, struct mt76_wcid, tx_list); list_del_init(&wcid->tx_list); spin_unlock(&phy->tx_lock); - ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel); + if (ret >= 0) + ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel); if (ret >= 0 && !phy->offchannel) ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending); spin_lock(&phy->tx_lock); @@ -670,9 +673,6 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy) !skb_queue_empty(&wcid->tx_offchannel) && list_empty(&wcid->tx_list)) list_add_tail(&wcid->tx_list, &phy->tx_list); - - if (ret < 0) - break; } spin_unlock(&phy->tx_lock); |