diff options
27 files changed, 335 insertions, 124 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 0278e1b44576..3a5de1d1b121 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -51,7 +51,7 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data) struct mt76_dev *dev = dev_get_drvdata(s->private); int i, queued; - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { struct mt76_queue *q = &dev->q_rx[i]; if (!q->ndesc) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 75e659774e07..f4d6074fe32a 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -576,7 +576,7 @@ mt76_dma_init(struct mt76_dev *dev) init_dummy_netdev(&dev->napi_dev); - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); mt76_dma_rx_fill(dev, &dev->q_rx[i]); @@ -610,7 +610,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) mt76_dma_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { netif_napi_del(&dev->napi[i]); mt76_dma_rx_cleanup(dev, &dev->q_rx[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e6de4a1b8f26..dfe625a53c63 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -288,8 +288,8 @@ enum { MT76_REMOVED, MT76_READING_STATS, MT76_STATE_POWER_OFF, - MT76_STATE_PS, MT76_STATE_SUSPEND, + MT76_STATE_ROC, }; struct mt76_hw_cap { @@ -537,8 +537,8 @@ struct mt76_dev { wait_queue_head_t tx_wait; struct sk_buff_head status_list; - unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; - unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG]; + u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; + u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; @@ -671,6 +671,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) +#define mt76_for_each_q_rx(dev, i) \ + for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \ + (dev)->q_rx[i].ndesc; i++) + struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, const struct mt76_driver_ops *drv_ops); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index f8c0c957ca01..8060c1514396 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -473,7 +473,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) struct mt7603_sta *sta; struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + if (idx >= MT7603_WTBL_SIZE) return NULL; wcid = rcu_dereference(dev->mt76.wcid[idx]); @@ -1238,7 +1238,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) if (pid == MT_PACKET_ID_NO_ACK) return; - if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + if (wcidx >= MT7603_WTBL_SIZE) return; rcu_read_lock(); @@ -1438,8 +1438,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt7603_dma_sched_reset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 6a5ae047c63b..edac37e7847b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -111,6 +111,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) return; } + if (is_mt7611(&dev->mt76)) { + /* 5GHz only */ + dev->mt76.cap.has_5ghz = true; + return; + } + val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, eeprom[MT_EE_WIFI_CONF]); switch (val) { @@ -310,6 +316,7 @@ static void mt7615_cal_free_data(struct mt7615_dev *dev) mt7622_apply_cal_free_data(dev); break; case 0x7615: + case 0x7611: mt7615_apply_cal_free_data(dev); break; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 1d8fdc7e062b..e2d80518e5af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -139,8 +139,10 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev) ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + wiphy->max_remain_on_channel_duration = 5000; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_P2P_GO_OPPPS; } else { @@ -149,6 +151,8 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev) dev->ops->sched_scan_start = NULL; dev->ops->sched_scan_stop = NULL; dev->ops->set_rekey_data = NULL; + dev->ops->remain_on_channel = NULL; + dev->ops->cancel_remain_on_channel = NULL; wiphy->max_sched_scan_plan_interval = 0; wiphy->max_sched_scan_ie_len = 0; @@ -368,12 +372,6 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) if (phy) return 0; - INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work); - INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); - skb_queue_head_init(&phy->scan_event_list); - - INIT_WORK(&phy->ps_work, mt7615_ps_work); - mt7615_cap_dbdc_enable(dev); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); if (!mphy) @@ -386,6 +384,14 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mt7615_init_wiphy(mphy->hw); + INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work); + INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); + skb_queue_head_init(&phy->scan_event_list); + + INIT_WORK(&phy->roc_work, mt7615_roc_work); + timer_setup(&phy->roc_timer, mt7615_roc_timer, 0); + init_waitqueue_head(&phy->roc_wait); + mt7615_mac_set_scs(phy, true); /* @@ -437,9 +443,11 @@ void mt7615_init_device(struct mt7615_dev *dev) INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); + init_waitqueue_head(&dev->phy.roc_wait); INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); - INIT_WORK(&dev->phy.ps_work, mt7615_ps_work); + INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); + timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); mt7615_init_wiphy(hw); dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 7d65a3fb0c23..9f1c6ca7a665 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -61,7 +61,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, struct mt7615_sta *sta; struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + if (idx >= MT7615_WTBL_SIZE) return NULL; wcid = rcu_dereference(dev->mt76.wcid[idx]); @@ -175,7 +175,8 @@ mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy, struct mt76_rx_status *status, u8 chfreq) { if (!test_bit(MT76_HW_SCANNING, &mphy->state) && - !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state)) { + !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) && + !test_bit(MT76_STATE_ROC, &mphy->state)) { status->freq = mphy->chandef.chan->center_freq; status->band = mphy->chandef.chan->band; return; @@ -1302,7 +1303,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (pid == MT_PACKET_ID_NO_ACK) return; - if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + if (wcidx >= MT7615_WTBL_SIZE) return; rcu_read_lock(); @@ -1819,8 +1820,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | @@ -1849,8 +1851,13 @@ void mt7615_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->phy.mac_work); - if (phy2) + del_timer_sync(&dev->phy.roc_timer); + cancel_work_sync(&dev->phy.roc_work); + if (phy2) { cancel_delayed_work_sync(&phy2->mac_work); + del_timer_sync(&phy2->roc_timer); + cancel_work_sync(&phy2->roc_work); + } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 2e9e9d3519d7..c26f99b368d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -71,7 +71,8 @@ static void mt7615_stop(struct ieee80211_hw *hw) struct mt7615_phy *phy = mt7615_hw_phy(hw); cancel_delayed_work_sync(&phy->mac_work); - cancel_work_sync(&phy->ps_work); + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); mutex_lock(&dev->mt76.mutex); @@ -289,12 +290,11 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd, wd->type = MT7615_WTBL_KEY_DESC; wd->sta = msta; - wd->key.key = kzalloc(key->keylen, GFP_KERNEL); + wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL); if (!wd->key.key) { kfree(wd); return -ENOMEM; } - memcpy(wd->key.key, key->key, key->keylen); wd->key.cipher = key->cipher; wd->key.keyidx = key->keyidx; wd->key.keylen = key->keylen; @@ -360,20 +360,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); } -void mt7615_ps_work(struct work_struct *work) -{ - struct mt7615_phy *phy; - - phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, - ps_work); - - mutex_lock(&phy->dev->mt76.mutex); - ieee80211_iterate_active_interfaces(phy->mt76->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - m7615_mcu_set_ps_iter, phy); - mutex_unlock(&phy->dev->mt76.mutex); -} - static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { struct mt7615_dev *dev = mt7615_hw_dev(hw); @@ -399,14 +385,6 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (hw->conf.flags & IEEE80211_CONF_PS) - set_bit(MT76_STATE_PS, &phy->mt76->state); - else - clear_bit(MT76_STATE_PS, &phy->mt76->state); - ieee80211_queue_work(hw, &phy->ps_work); - } - mutex_unlock(&dev->mt76.mutex); return ret; @@ -509,6 +487,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_BEACON_ENABLED)) mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); + if (changed & BSS_CHANGED_PS) + mt7615_mcu_set_vif_ps(dev, vif); + mutex_unlock(&dev->mt76.mutex); } @@ -791,6 +772,37 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) return 0; } +static void mt7615_roc_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt7615_phy *phy = priv; + + mt7615_mcu_set_roc(phy, vif, NULL, 0); +} + +void mt7615_roc_work(struct work_struct *work) +{ + struct mt7615_phy *phy; + + phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, + roc_work); + + if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + return; + + ieee80211_iterate_active_interfaces(phy->mt76->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_roc_iter, phy); + ieee80211_remain_on_channel_expired(phy->mt76->hw); +} + +void mt7615_roc_timer(struct timer_list *timer) +{ + struct mt7615_phy *phy = from_timer(phy, timer, roc_timer); + + ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); +} + void mt7615_scan_work(struct work_struct *work) { struct mt7615_phy *phy; @@ -864,6 +876,50 @@ mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return mt7615_mcu_sched_scan_enable(mphy->priv, vif, false); } +static int mt7615_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum ieee80211_roc_type type) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int err; + + if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state)) + return 0; + + err = mt7615_mcu_set_roc(phy, vif, chan, duration); + if (err < 0) { + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + return err; + } + + if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) { + mt7615_mcu_set_roc(phy, vif, NULL, 0); + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + + return -ETIMEDOUT; + } + + return 0; +} + +static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + return 0; + + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); + + mt7615_mcu_set_roc(phy, vif, NULL, 0); + + return 0; +} + #ifdef CONFIG_PM static int mt7615_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) @@ -978,6 +1034,8 @@ const struct ieee80211_ops mt7615_ops = { .cancel_hw_scan = mt7615_cancel_hw_scan, .sched_scan_start = mt7615_start_sched_scan, .sched_scan_stop = mt7615_stop_sched_scan, + .remain_on_channel = mt7615_remain_on_channel, + .cancel_remain_on_channel = mt7615_cancel_remain_on_channel, #ifdef CONFIG_PM .suspend = mt7615_suspend, .resume = mt7615_resume, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index b944f372738a..6e869b8c5e26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -360,6 +360,33 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb) } static void +mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_roc_tlv *event; + struct mt7615_phy *phy; + struct mt76_phy *mphy; + int duration; + + skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); + event = (struct mt7615_roc_tlv *)skb->data; + + if (event->dbdc_band && dev->mt76.phy2) + mphy = dev->mt76.phy2; + else + mphy = &dev->mt76.phy; + + ieee80211_ready_on_channel(mphy->hw); + + phy = (struct mt7615_phy *)mphy->priv; + phy->roc_grant = true; + wake_up(&phy->roc_wait); + + duration = le32_to_cpu(event->max_interval); + mod_timer(&phy->roc_timer, + round_jiffies_up(jiffies + msecs_to_jiffies(duration))); +} + +static void mt7615_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; @@ -426,6 +453,9 @@ mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb) case MCU_EVENT_BSS_BEACON_LOSS: mt7615_mcu_beacon_loss_event(dev, skb); break; + case MCU_EVENT_ROC: + mt7615_mcu_roc_event(dev, skb); + break; case MCU_EVENT_SCHED_SCAN_DONE: case MCU_EVENT_SCAN_DONE: mt7615_mcu_scan_event(dev, skb); @@ -451,6 +481,7 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb) rxd->eid == MCU_EVENT_SCHED_SCAN_DONE || rxd->eid == MCU_EVENT_BSS_ABSENCE || rxd->eid == MCU_EVENT_SCAN_DONE || + rxd->eid == MCU_EVENT_ROC || !rxd->seq) mt7615_mcu_rx_unsolicited_event(dev, skb); else @@ -2741,11 +2772,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) sizeof(req), true); } -void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_phy *phy = priv; - struct mt76_phy *mphy = phy->mt76; struct { u8 bss_idx; u8 ps_state; /* 0: device awake @@ -2754,12 +2783,14 @@ void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) */ } req = { .bss_idx = mvif->idx, - .ps_state = test_bit(MT76_STATE_PS, &mphy->state) ? 2 : 0, + .ps_state = vif->bss_conf.ps ? 2 : 0, }; - if (vif->type == NL80211_IFTYPE_STATION) - __mt76_mcu_send_msg(&phy->dev->mt76, MCU_CMD_SET_PS_PROFILE, - &req, sizeof(req), false); + if (vif->type != NL80211_IFTYPE_STATION) + return -ENOTSUPP; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE, + &req, sizeof(req), false); } int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) @@ -2867,6 +2898,7 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif, n_ssids++; } req->ssid_type = n_ssids ? BIT(2) : BIT(0); + req->ssid_type_ext = n_ssids ? BIT(0) : 0; req->ssids_num = n_ssids; /* increase channel time for passive scan */ @@ -3601,6 +3633,26 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw, } #endif /* CONFIG_PM */ +int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = phy->dev; + struct mt7615_roc_tlv req = { + .bss_idx = mvif->idx, + .active = !chan, + .max_interval = cpu_to_le32(duration), + .primary_chan = chan ? chan->hw_value : 0, + .band = chan ? chan->band : 0, + .req_type = 2, + }; + + phy->roc_grant = false; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, + sizeof(req), false); +} + int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 348521b0d44c..2314d0b23af1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -82,6 +82,7 @@ enum { MCU_EVENT_ACCESS_REG = 0x02, MCU_EVENT_MT_PATCH_SEM = 0x04, MCU_EVENT_SCAN_DONE = 0x0d, + MCU_EVENT_ROC = 0x10, MCU_EVENT_BSS_ABSENCE = 0x11, MCU_EVENT_BSS_BEACON_LOSS = 0x13, MCU_EVENT_CH_PRIVILEGE = 0x18, @@ -326,7 +327,8 @@ struct mt7615_hw_scan_req { */ u8 ssid_type; /* BIT(0) wildcard SSID * BIT(1) P2P wildcard SSID - * BIT(2) specified SSID + * BIT(2) specified SSID + wildcard SSID + * BIT(2) + ssid_type_ext BIT(0) specified SSID only */ u8 ssids_num; u8 probe_req_num; /* Number of probe request for each SSID */ @@ -361,7 +363,8 @@ struct mt7615_hw_scan_req { struct mt7615_mcu_scan_ssid ext_ssids[6]; u8 bssid[ETH_ALEN]; u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */ - u8 pad[64]; + u8 pad[63]; + u8 ssid_type_ext; } __packed; #define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64 @@ -525,6 +528,23 @@ struct mt7615_gtk_rekey_tlv { u8 reserverd[3]; } __packed; +struct mt7615_roc_tlv { + u8 bss_idx; + u8 token; + u8 active; + u8 primary_chan; + u8 sco; + u8 band; + u8 width; /* To support 80/160MHz bandwidth */ + u8 freq_seg1; /* To support 80/160MHz bandwidth */ + u8 freq_seg2; /* To support 80/160MHz bandwidth */ + u8 req_type; + u8 dbdc_band; + u8 rsv0; + __le32 max_interval; /* ms */ + u8 rsv1[8]; +} __packed; + /* offload mcu commands */ enum { MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03, @@ -533,6 +553,7 @@ enum { MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16, MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17, MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b, + MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1c, MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33, MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61, MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index ebdfca64b079..d6176d316bee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -201,7 +201,10 @@ struct mt7615_phy { struct sk_buff_head scan_event_list; struct delayed_work scan_work; - struct work_struct ps_work; + struct work_struct roc_work; + struct timer_list roc_timer; + wait_queue_head_t roc_wait; + bool roc_grant; }; #define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__) @@ -411,7 +414,7 @@ static inline bool is_mt7622(struct mt76_dev *dev) static inline bool is_mt7615(struct mt76_dev *dev) { - return mt76_chip(dev) == 0x7615; + return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; } static inline bool is_mt7663(struct mt76_dev *dev) @@ -419,6 +422,11 @@ static inline bool is_mt7663(struct mt76_dev *dev) return mt76_chip(dev) == 0x7663; } +static inline bool is_mt7611(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7611; +} + static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, 0, 0, mask); @@ -441,7 +449,8 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev) void mt7615_dma_reset(struct mt7615_dev *dev); void mt7615_scan_work(struct work_struct *work); -void mt7615_ps_work(struct work_struct *work); +void mt7615_roc_work(struct work_struct *work); +void mt7615_roc_timer(struct timer_list *timer); void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband); void mt7615_phy_init(struct mt7615_dev *dev); @@ -527,11 +536,13 @@ int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy); int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy); -void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); +int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif); int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration); int mt7615_firmware_own(struct mt7615_dev *dev); int mt7615_driver_own(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 88ff14564521..ba12f199bce0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -14,6 +14,7 @@ static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, { PCI_DEVICE(0x14c3, 0x7663) }, + { PCI_DEVICE(0x14c3, 0x7611) }, { }, }; @@ -85,8 +86,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) napi_disable(&mdev->tx_napi); tasklet_kill(&mdev->tx_tasklet); - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) + mt76_for_each_q_rx(mdev, i) { napi_disable(&mdev->napi[i]); + } tasklet_kill(&dev->irq_tasklet); mt7615_dma_reset(dev); @@ -119,8 +121,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; restore: - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) + mt76_for_each_q_rx(mdev, i) { napi_enable(&mdev->napi[i]); + } napi_enable(&mdev->tx_napi); if (hif_suspend) mt7615_mcu_set_hif_suspend(dev, false); @@ -155,7 +158,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev) if (pdma_reset) dev_err(mdev->dev, "PDMA engine must be reinitialized\n"); - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) { + mt76_for_each_q_rx(mdev, i) { napi_enable(&mdev->napi[i]); napi_schedule(&mdev->napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index d74253319622..a50077eb24d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -51,7 +51,8 @@ static void mt7663u_stop(struct ieee80211_hw *hw) struct mt7615_dev *dev = hw->priv; clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); - cancel_work_sync(&phy->ps_work); + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mac_work); mt76u_stop_tx(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6ea210bd3f07..4c9bbc7ce023 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -15,6 +15,7 @@ #include "mt76x02_dfs.h" #include "mt76x02_dma.h" +#define MT76x02_N_WCIDS 128 #define MT_CALIBRATE_INTERVAL HZ #define MT_MAC_WORK_INTERVAL (HZ / 10) @@ -246,7 +247,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx) { struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->wcid)) + if (idx >= MT76x02_N_WCIDS) return NULL; wcid = rcu_dereference(dev->wcid[idx]); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index a5a3bcd30d6f..e4e03beabe43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -561,7 +561,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, rcu_read_lock(); - if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) + if (stat->wcid < MT76x02_N_WCIDS) wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); if (wcid && wcid->sta) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 89a8992d84fa..267058086a90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -20,7 +20,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int ret; u8 seq; - if (mt76_is_mmio(&dev->mt76) && dev->mcu_timeout) + if (dev->mcu_timeout) return -EIO; skb = mt76_mcu_msg_alloc(mdev, data, len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 7e389dbccfeb..cbbe986655fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -415,7 +415,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); rcu_read_unlock(); - for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) { + for (i = 0; i < MT76x02_N_WCIDS; i++) { struct ieee80211_sta *sta; struct ieee80211_vif *vif; struct mt76x02_sta *msta; @@ -489,8 +489,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt76x02_mac_start(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 9a2c9afa2fb5..44822a849eb1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -249,7 +249,7 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, memset(msta, 0, sizeof(*msta)); - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT76x02_N_WCIDS); if (idx < 0) return -ENOSPC; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index ee0066fedd04..5278bee812f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -173,14 +173,14 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) /* Tx Beamformee Rx NDPA & Tx feedback report */ cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy)); - seq_printf(s, "Tx Beamformee sucessful feedback frames: %ld\n", + seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n", FIELD_GET(MT_ETBF_TX_FB_CPL, cnt)); - seq_printf(s, "Tx Beamformee feedback triggerd counts: %ld\n", + seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n", FIELD_GET(MT_ETBF_TX_FB_TRI, cnt)); /* Tx SU counters */ cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy)); - seq_printf(s, "Tx single-user sucessful MPDU counts: %d\n", cnt); + seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt); seq_puts(s, "\n"); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 6f200ab3ac28..aadf56e80bae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -592,7 +592,6 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev) if (phy) return 0; - INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); mt7915_cap_dbdc_enable(dev); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); if (!mphy) @@ -605,6 +604,8 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev) mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mt7915_init_wiphy(mphy->hw); + INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); + /* * Make the secondary PHY MAC address local without overlapping with * the usual MAC address allocation scheme on multiple virtual interfaces diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 7ad7c2b7afdc..a264e304a3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -235,9 +235,14 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | HE_BITS(DATA1_DATA_DCM_KNOWN) | HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN), + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN), + HE_BITS(DATA2_TXBF_KNOWN) | + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN), }; struct ieee80211_radiotap_he *he = NULL; __le32 v2 = rxv->v[2]; @@ -248,12 +253,6 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, he = skb_push(skb, sizeof(known)); memcpy(he, &known, sizeof(known)); - he->data1 = HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN); - he->data2 = HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN); - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) | HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2); he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) | @@ -296,10 +295,10 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - he->data4 = HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); mt7915_mac_decode_he_radiotap_ru(status, rxv, he); break; @@ -426,20 +425,26 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) /* RXD Group 3 - P-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { + u32 v0, v1, v2; + memcpy(rxv.v, rxd, sizeof(rxv.v)); rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; - if (rxv.v[0] & MT_PRXV_HT_AD_CODE) + v0 = le32_to_cpu(rxv.v[0]); + v1 = le32_to_cpu(rxv.v[1]); + v2 = le32_to_cpu(rxv.v[2]); + + if (v0 & MT_PRXV_HT_AD_CODE) status->enc_flags |= RX_ENC_FLAG_LDPC; status->chains = mphy->antenna_mask; - status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, rxv.v[1]); - status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, rxv.v[1]); - status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, rxv.v[1]); - status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, rxv.v[1]); + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); + status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1); + status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1); status->signal = status->chain_signal[0]; for (i = 1; i < hweight8(mphy->antenna_mask); i++) { @@ -452,16 +457,16 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) /* RXD Group 5 - C-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { - u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, rxv.v[2]); - u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, rxv.v[2]); + u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); + u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); bool cck = false; rxd += 18; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; - idx = i = FIELD_GET(MT_PRXV_TX_RATE, rxv.v[0]); - rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, rxv.v[2]); + idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); + rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, v2); switch (rxv.phy) { case MT_PHY_TYPE_CCK: @@ -478,7 +483,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) break; case MT_PHY_TYPE_VHT: status->nss = - FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + FIELD_GET(MT_PRXV_NSTS, v0) + 1; status->encoding = RX_ENC_VHT; if (i > 9) return -EINVAL; @@ -490,7 +495,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) case MT_PHY_TYPE_HE_EXT_SU: case MT_PHY_TYPE_HE_TB: status->nss = - FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + FIELD_GET(MT_PRXV_NSTS, v0) + 1; status->encoding = RX_ENC_HE; status->flag |= RX_FLAG_RADIOTAP_HE; i &= GENMASK(3, 0); @@ -506,7 +511,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) } status->rate_idx = i; - switch (FIELD_GET(MT_CRXV_FRAME_MODE, rxv.v[2])) { + switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) { case IEEE80211_STA_RX_BW_20: break; case IEEE80211_STA_RX_BW_40: @@ -612,7 +617,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, skb->priority & IEEE80211_QOS_CTL_TID_MASK) | FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) - val |= cpu_to_le32(MT_TXD1_TGID); + val |= MT_TXD1_TGID; txwi[1] = cpu_to_le32(val); @@ -1141,8 +1146,9 @@ mt7915_dma_reset(struct mt7915_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } /* re-init prefetch settings after reset */ mt7915_dma_prefetch(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 98567374c2c9..0575c259f245 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -437,8 +437,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, mt7915_mcu_add_sta(dev, vif, NULL, join); } - if (changed & BSS_CHANGED_ASSOC) + if (changed & BSS_CHANGED_ASSOC) { mt7915_mcu_add_bss_info(phy, vif, info->assoc); + mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable); + } if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; @@ -458,6 +460,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_set_tx(dev, vif); + if (changed & BSS_CHANGED_HE_OBSS_PD) + mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable); + if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); @@ -790,7 +795,7 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw, rcu_read_unlock(); return; } - rcu_read_lock(); + rcu_read_unlock(); set_bit(changed, &msta->stats.changed); ieee80211_queue_work(hw, &msta->stats_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 99eeea42478f..c8c12c740c1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -220,7 +220,7 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, { struct mt7915_mcu_txd *mcu_txd; u8 seq, pkt_fmt, qidx; - enum mt7915_txq_id txq; + enum mt76_txq_id txq; __le32 *txd; u32 val; @@ -815,8 +815,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, struct mt7915_he_obss_narrow_bw_ru_data *data = _data; const struct element *elem; - elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data, - bss->ies->len); + elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY); if (!elem || elem->datalen < 10 || !(elem->data[10] & @@ -1802,15 +1801,12 @@ static u8 mt7915_mcu_sta_txbf_type(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7915_sta *msta; u8 type = 0; if (vif->type != NL80211_IFTYPE_STATION && vif->type != NL80211_IFTYPE_AP) return 0; - msta = (struct mt7915_sta *)sta->drv_priv; - if (sta->he_cap.has_he) { struct ieee80211_he_cap_elem *pe; const struct ieee80211_he_cap_elem *ve; @@ -1954,7 +1950,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; ra->supp_mode |= MODE_HT; - mcs = hweight32(ra->supp_ht_mcs) - 1; + mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1; ra->af = sta->ht_cap.ampdu_factor; ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); @@ -1972,7 +1968,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, } if (sta->vht_cap.vht_supported) { - __le16 mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); u16 vht_mcs; u8 af, mcs_prev; @@ -2399,7 +2395,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, }; int attr; - if (req.addr == MCU_PATCH_ADDRESS) + if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS)) attr = -MCU_CMD_PATCH_START_REQ; else attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; @@ -2672,7 +2668,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) u16 len; u8 level; u8 rsv[3]; - u32 module_idx; + __le32 module_idx; } data = { .module_idx = cpu_to_le32(module), .level = level, @@ -3159,3 +3155,28 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev) return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, sizeof(req), true); } + +int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ +#define MT_SPR_ENABLE 1 + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct { + u8 action; + u8 arg_num; + u8 band_idx; + u8 status; + u8 drop_tx_idx; + u8 sta_idx; /* 256 sta */ + u8 rsv[2]; + u32 val; + } __packed req = { + .action = MT_SPR_ENABLE, + .arg_num = 1, + .band_idx = mvif->band_idx, + .val = enable, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, + &req, sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 34ace6e672d0..c241dd7c4c36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -212,6 +212,7 @@ enum { MCU_EXT_CMD_RATE_CTRL = 0x87, MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_SET_RDD_TH = 0x9d, + MCU_EXT_CMD_SET_SPR = 0xa8, }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 5392292a838e..85d74ecd0351 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -301,6 +301,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, enum set_key_cmd cmd); int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int enable); +int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, + bool enable); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 07cf71242d9e..ecde87465bf6 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -42,17 +42,17 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, } EXPORT_SYMBOL_GPL(__mt76_poll_msec); -int mt76_wcid_alloc(unsigned long *mask, int size) +int mt76_wcid_alloc(u32 *mask, int size) { int i, idx = 0, cur; - for (i = 0; i < DIV_ROUND_UP(size, BITS_PER_LONG); i++) { + for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { idx = ffs(~mask[i]); if (!idx) continue; idx--; - cur = i * BITS_PER_LONG + idx; + cur = i * 32 + idx; if (cur >= size) break; @@ -74,13 +74,13 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) rcu_read_lock(); for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { - unsigned long mask = dev->wcid_mask[i]; - unsigned long phy_mask = dev->wcid_phy_mask[i]; + u32 mask = dev->wcid_mask[i]; + u32 phy_mask = dev->wcid_phy_mask[i]; if (!mask) continue; - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) { + for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) { if (!(mask & 1)) continue; diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index 48a71e7479e5..fd1a68820e0a 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -14,24 +14,24 @@ #define MT76_INCR(_var, _size) \ (_var = (((_var) + 1) % (_size))) -int mt76_wcid_alloc(unsigned long *mask, int size); +int mt76_wcid_alloc(u32 *mask, int size); static inline bool -mt76_wcid_mask_test(unsigned long *mask, int idx) +mt76_wcid_mask_test(u32 *mask, int idx) { - return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG); + return mask[idx / 32] & BIT(idx % 32); } static inline void -mt76_wcid_mask_set(unsigned long *mask, int idx) +mt76_wcid_mask_set(u32 *mask, int idx) { - mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG); + mask[idx / 32] |= BIT(idx % 32); } static inline void -mt76_wcid_mask_clear(unsigned long *mask, int idx) +mt76_wcid_mask_clear(u32 *mask, int idx) { - mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); + mask[idx / 32] &= ~BIT(idx % 32); } static inline void |