diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921/mac.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 193 |
1 files changed, 40 insertions, 153 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index b507f3917830..214bd1859792 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -785,20 +785,6 @@ mt7921_write_hw_txp(struct mt7921_dev *dev, struct mt76_tx_info *tx_info, } } -static void mt7921_set_tx_blocked(struct mt7921_dev *dev, bool blocked) -{ - struct mt76_phy *mphy = &dev->mphy; - struct mt76_queue *q; - - q = mphy->q_tx[0]; - if (blocked == q->blocked) - return; - - q->blocked = blocked; - if (!blocked) - mt76_worker_schedule(&dev->mt76.tx_worker); -} - int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, @@ -824,15 +810,7 @@ int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; - spin_lock_bh(&dev->token_lock); - id = idr_alloc(&dev->token, t, 0, MT7921_TOKEN_SIZE, GFP_ATOMIC); - if (id >= 0) - dev->token_count++; - - if (dev->token_count >= MT7921_TOKEN_SIZE - MT7921_TOKEN_FREE_THR) - mt7921_set_tx_blocked(dev, true); - spin_unlock_bh(&dev->token_lock); - + id = mt76_token_consume(mdev, &t); if (id < 0) return id; @@ -994,15 +972,7 @@ void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb) msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); stat = FIELD_GET(MT_TX_FREE_STATUS, info); - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, msdu); - if (txwi) - dev->token_count--; - if (dev->token_count < MT7921_TOKEN_SIZE - MT7921_TOKEN_FREE_THR && - dev->mphy.q_tx[0]->blocked) - wake = true; - spin_unlock_bh(&dev->token_lock); - + txwi = mt76_token_release(mdev, msdu, &wake); if (!txwi) continue; @@ -1030,11 +1000,8 @@ void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb) mt76_put_txwi(mdev, txwi); } - if (wake) { - spin_lock_bh(&dev->token_lock); - mt7921_set_tx_blocked(dev, false); - spin_unlock_bh(&dev->token_lock); - } + if (wake) + mt76_set_tx_blocked(&dev->mt76, false); napi_consume_skb(skb, 1); @@ -1043,13 +1010,7 @@ void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb) napi_consume_skb(skb, 1); } - if (test_bit(MT76_STATE_PM, &dev->phy.mt76->state)) - return; - mt7921_mac_sta_poll(dev); - - mt76_connac_power_save_sched(&dev->mphy, &dev->pm); - mt76_worker_schedule(&dev->mt76.tx_worker); } @@ -1071,11 +1032,8 @@ void mt7921_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) u16 token; txp = mt7921_txwi_to_txp(mdev, e->txwi); - token = le16_to_cpu(txp->hw.msdu_id[0]) & ~MT_MSDU_ID_VALID; - spin_lock_bh(&dev->token_lock); - t = idr_remove(&dev->token, token); - spin_unlock_bh(&dev->token_lock); + t = mt76_token_put(mdev, token); e->skb = t ? t->skb : NULL; } @@ -1210,85 +1168,13 @@ void mt7921_update_channel(struct mt76_dev *mdev) mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } -int mt7921_wfsys_reset(struct mt7921_dev *dev) -{ - mt76_set(dev, 0x70002600, BIT(0)); - msleep(200); - mt76_clear(dev, 0x70002600, BIT(0)); - - return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B, - WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500); -} - -static void -mt7921_dma_reset(struct mt7921_dev *dev) -{ - int i; - - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST); - - /* disable WFDMA0 */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - mt76_poll(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000); - - /* reset hw queues */ - for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_reset(dev, dev->mphy.q_tx[i]); - - for (i = 0; i < __MT_MCUQ_MAX; i++) - mt76_queue_reset(dev, dev->mt76.q_mcu[i]); - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_reset(dev, &dev->mt76.q_rx[i]); - - /* configure perfetch settings */ - mt7921_dma_prefetch(dev); - - /* reset dma idx */ - mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); - - /* configure delay interrupt */ - mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); - - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_WB_DDONE | - MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN | - MT_WFDMA0_GLO_CFG_CLK_GAT_DIS | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); - - /* enable interrupts for TX/RX rings */ - mt7921_irq_enable(dev, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); -} - void mt7921_tx_token_put(struct mt7921_dev *dev) { struct mt76_txwi_cache *txwi; int id; - spin_lock_bh(&dev->token_lock); - idr_for_each_entry(&dev->token, txwi, id) { + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { mt7921_txp_skb_unmap(&dev->mt76, txwi); if (txwi->skb) { struct ieee80211_hw *hw; @@ -1297,10 +1183,10 @@ void mt7921_tx_token_put(struct mt7921_dev *dev) ieee80211_free_txskb(hw, txwi->skb); } mt76_put_txwi(&dev->mt76, txwi); - dev->token_count--; + dev->mt76.token_count--; } - spin_unlock_bh(&dev->token_lock); - idr_destroy(&dev->token); + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); } static void @@ -1339,23 +1225,13 @@ mt7921_mac_reset(struct mt7921_dev *dev) napi_disable(&dev->mt76.tx_napi); mt7921_tx_token_put(dev); - idr_init(&dev->token); - - /* clean up hw queues */ - for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++) - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); - - mt76_for_each_q_rx(&dev->mt76, i) - mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); + idr_init(&dev->mt76.token); - mt7921_wfsys_reset(dev); - mt7921_dma_reset(dev); + err = mt7921_wpdma_reset(dev, true); + if (err) + return err; mt76_for_each_q_rx(&dev->mt76, i) { - mt76_queue_rx_reset(dev, i); napi_enable(&dev->mt76.napi[i]); napi_schedule(&dev->mt76.napi[i]); } @@ -1365,12 +1241,10 @@ mt7921_mac_reset(struct mt7921_dev *dev) mt76_worker_enable(&dev->mt76.tx_worker); clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_STATE_PM, &dev->mphy.state); mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - mt7921_irq_enable(dev, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); err = mt7921_run_firmware(dev); if (err) @@ -1411,10 +1285,18 @@ void mt7921_mac_reset_work(struct work_struct *work) if (i == 10) dev_err(dev->mt76.dev, "chip reset failed\n"); + if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state)) { + struct cfg80211_scan_info info = { + .aborted = true, + }; + + ieee80211_scan_completed(dev->mphy.hw, &info); + } + ieee80211_wake_queues(hw); ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, - mt7921_vif_connect_iter, 0); + mt7921_vif_connect_iter, NULL); } void mt7921_reset(struct mt76_dev *mdev) @@ -1488,25 +1370,20 @@ void mt7921_mac_work(struct work_struct *work) mac_work.work); phy = mphy->priv; - if (test_bit(MT76_STATE_PM, &mphy->state)) - goto out; - mt7921_mutex_acquire(phy->dev); mt76_update_survey(mphy->dev); - if (++mphy->mac_work_count == 5) { + if (++mphy->mac_work_count == 2) { mphy->mac_work_count = 0; mt7921_mac_update_mib_stats(phy); } - if (++phy->sta_work_count == 10) { + if (++phy->sta_work_count == 4) { phy->sta_work_count = 0; mt7921_mac_sta_stats_work(phy); } mt7921_mutex_release(phy->dev); - -out: ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, MT7921_WATCHDOG_TIME); } @@ -1520,13 +1397,19 @@ void mt7921_pm_wake_work(struct work_struct *work) pm.wake_work); mphy = dev->phy.mt76; - if (!mt7921_mcu_drv_pmctrl(dev)) + if (!mt7921_mcu_drv_pmctrl(dev)) { + int i; + + mt76_for_each_q_rx(&dev->mt76, i) + napi_schedule(&dev->mt76.napi[i]); mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - else - dev_err(mphy->dev->dev, "failed to wake device\n"); + mt7921_tx_cleanup(dev); + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT7921_WATCHDOG_TIME); + } ieee80211_wake_queues(mphy->hw); - complete_all(&dev->pm.wake_cmpl); + wake_up(&dev->pm.wait); } void mt7921_pm_power_save_work(struct work_struct *work) @@ -1538,6 +1421,10 @@ void mt7921_pm_power_save_work(struct work_struct *work) pm.ps_work.work); delta = dev->pm.idle_timeout; + if (test_bit(MT76_HW_SCANNING, &dev->mphy.state) || + test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state)) + goto out; + if (time_is_after_jiffies(dev->pm.last_activity + delta)) { delta = dev->pm.last_activity + delta - jiffies; goto out; |