mt76: improve runtime-pm support
Subsystems (2)
Lorenzo Bianconi
maintainercover mt76: improve runtime-pm support
Rework runtime-pm support introduce pm refcounting in order to fix some leftover races between fw_own and tx/rx path. Introduce awake/doze time accounting.
This is a preliminary series to enable 'deep sleep' support in mt7921 firmware.
Lorenzo Bianconi (19):
mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and
mt7921_mcu_fw_pmctrl
mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and
mt7615_mcu_fw_pmctrl mt76: connac: introduce wake counter for fw_pmctrl synchronization
mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx
path
mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx
path
mt76: dma: add the capability to define a custom rx napi poll routine
mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx
napi
mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx
napi
mt76: connac: unschedule ps_work in mt76_connac_pm_wake
mt76: connac: check wake refcount in mcu_fw_pmctrl
mt76: connac: remove MT76_STATE_PM in mac_tx_free
mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work
mt76: connac: alaways wake the device before scanning
mt76: mt7615: rely on pm refcounting in mt7615_led_set_config
mt76: connac: do not run mt76_txq_schedule_all directly
mt76: connac: use waitqueue for runtime-pm
mt76: remove MT76_STATE_PM in tx path
mt76: mt7921: add awake and doze time accounting
mt76: mt7921: enable sw interrupts
drivers/net/wireless/mediatek/mt76/dma.c | 10 ++-- drivers/net/wireless/mediatek/mt76/dma.h | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 6 ++- .../net/wireless/mediatek/mt76/mt7603/dma.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/dma.c | 30 +++++++++-- .../net/wireless/mediatek/mt76/mt7615/init.c | 5 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 20 ++++--- .../net/wireless/mediatek/mt76/mt7615/main.c | 30 +++++------ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 23 +++++--- .../wireless/mediatek/mt76/mt7615/mt7615.h | 1 + .../wireless/mediatek/mt76/mt7615/pci_init.c | 4 +- .../net/wireless/mediatek/mt76/mt76_connac.h | 52 ++++++++++++++++++- .../wireless/mediatek/mt76/mt76_connac_mac.c | 17 ++---- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 +- .../net/wireless/mediatek/mt76/mt7915/dma.c | 2 +- .../wireless/mediatek/mt76/mt7921/debugfs.c | 32 +++++++++++- .../net/wireless/mediatek/mt76/mt7921/dma.c | 34 ++++++++++-- .../net/wireless/mediatek/mt76/mt7921/init.c | 10 +++- .../net/wireless/mediatek/mt76/mt7921/mac.c | 29 +++++------ .../net/wireless/mediatek/mt76/mt7921/main.c | 26 ++++------ .../net/wireless/mediatek/mt76/mt7921/mcu.c | 46 +++++++++++----- .../wireless/mediatek/mt76/mt7921/mt7921.h | 3 ++ .../net/wireless/mediatek/mt76/mt7921/pci.c | 13 +++++ .../net/wireless/mediatek/mt76/mt7921/regs.h | 17 +++--- drivers/net/wireless/mediatek/mt76/tx.c | 18 ++++--- 25 files changed, 307 insertions(+), 126 deletions(-)
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 1/19 mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl
Introduce a mutex in order to avoid a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl routines since they are run two independent works
--- .../net/wireless/mediatek/mt76/mt76_connac.h | 1 + .../net/wireless/mediatek/mt76/mt7921/init.c | 1 + .../net/wireless/mediatek/mt76/mt7921/mcu.c | 34 +++++++++++++------ 3 files changed, 26 insertions(+), 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac.h +1 -0
@@ -54,6 +54,7 @@ struct mt76_connac_pm {struct work_struct wake_work;struct completion wake_cmpl; +struct mutex mutex;struct delayed_work ps_work;unsigned long last_activity;
drivers/net/wireless/mediatek/mt76/mt7921/init.c +1 -0
@@ -222,6 +222,7 @@ int mt7921_register_device(struct mt7921_dev *dev)INIT_DELAYED_WORK (&dev->pm.ps_work, mt7921_pm_power_save_work);INIT_WORK (&dev->pm.wake_work, mt7921_pm_wake_work); +mutex_init (&dev->pm.mutex);init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state);
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +24 -10
@@ -1267,9 +1267,11 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,int mt7921_mcu_drv_pmctrl (struct mt7921_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; -int i; +int i, err =0 ; -if (!test_and_clear_bit (MT76_STATE_PM , &mphy->state)) +mutex_lock (&dev->pm.mutex); + +if (!test_bit (MT76_STATE_PM , &mphy->state)) goto out;for (i =0 ; i <MT7921_DRV_OWN_RETRY_COUNT ; i++) {
@@ -1281,23 +1283,30 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)if (i ==MT7921_DRV_OWN_RETRY_COUNT ) {dev_err (dev->mt76.dev,"driver own failed\n" ); -mt7921_reset (&dev->mt76); -return -EIO ; + err = -EIO ; + goto out; } +clear_bit (MT76_STATE_PM , &mphy->state); out: dev->pm.last_activity = jiffies; +mutex_unlock (&dev->pm.mutex); -return 0 ; +if (err) +mt7921_reset (&dev->mt76); + +return err; }int mt7921_mcu_fw_pmctrl (struct mt7921_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; -int i; +int i, err =0 ; + +mutex_lock (&dev->pm.mutex);if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) -return 0 ; + goto out;for (i =0 ; i <MT7921_DRV_OWN_RETRY_COUNT ; i++) {mt76_wr (dev,MT_CONN_ON_LPCTL ,PCIE_LPCR_HOST_SET_OWN );
@@ -1308,11 +1317,16 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)if (i ==MT7921_DRV_OWN_RETRY_COUNT ) {dev_err (dev->mt76.dev,"firmware own failed\n" ); -mt7921_reset (&dev->mt76); -return -EIO ; +clear_bit (MT76_STATE_PM , &mphy->state); + err = -EIO ; } +out: +mutex_unlock (&dev->pm.mutex); -return 0 ; +if (err) +mt7921_reset (&dev->mt76); + +return err; }void
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 2/19 mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl
In reply to Lorenzo BianconiIntroduce a mutex in order to avoid a race between mt7615_mcu_lp_drv_pmctrl and mt7615_mcu_fw_pmctrl routines since they are run two independent works
--- .../net/wireless/mediatek/mt76/mt7615/init.c | 1 + .../net/wireless/mediatek/mt76/mt7615/mcu.c | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -0
@@ -505,6 +505,7 @@ void mt7615_init_device(struct mt7615_dev *dev)INIT_DELAYED_WORK (&dev->pm.ps_work, mt7615_pm_power_save_work);INIT_WORK (&dev->pm.wake_work, mt7615_pm_wake_work); +mutex_init (&dev->pm.mutex);init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +14 -6
@@ -323,9 +323,11 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)static int mt7615_mcu_lp_drv_pmctrl (struct mt7615_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; -int i; +int i, err =0 ; + +mutex_lock (&dev->pm.mutex); -if (!test_and_clear_bit (MT76_STATE_PM , &mphy->state)) +if (!test_bit (MT76_STATE_PM , &mphy->state)) goto out;for (i =0 ; i <MT7615_DRV_OWN_RETRY_COUNT ; i++) {
@@ -337,14 +339,16 @@ static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)if (i ==MT7615_DRV_OWN_RETRY_COUNT ) {dev_err (dev->mt76.dev,"driver own failed\n" ); -set_bit (MT76_STATE_PM , &mphy->state); -return -EIO ; + err = -EIO ; + goto out; } +clear_bit (MT76_STATE_PM , &mphy->state); out: dev->pm.last_activity = jiffies; +mutex_unlock (&dev->pm.mutex); -return 0 ; +return err; }static int mt7615_mcu_fw_pmctrl (struct mt7615_dev *dev)
@@ -353,8 +357,10 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)int err =0 ;u32 addr; +mutex_lock (&dev->pm.mutex); +if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) -return 0 ; + goto out;mt7622_trigger_hif_int (dev, true);
@@ -370,6 +376,8 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) }mt7622_trigger_hif_int (dev, false); +out: +mutex_unlock (&dev->pm.mutex);return err; }
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 3/19 mt76: connac: introduce wake counter for fw_pmctrl synchronization
In reply to Lorenzo BianconiIntroduce wake counter and related spinlock in order to synchronize tx/rx path and fw_pmctrl request.
--- .../net/wireless/mediatek/mt76/mt76_connac.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+)
drivers/net/wireless/mediatek/mt76/mt76_connac.h +31 -0
@@ -54,6 +54,11 @@ struct mt76_connac_pm {struct work_struct wake_work;struct completion wake_cmpl; + +struct { +spinlock_t lock; +u32 count; + } wake;struct mutex mutex;struct delayed_work ps_work;
@@ -85,6 +90,32 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy,void mt76_connac_free_pending_tx_skbs (struct mt76_connac_pm *pm,struct mt76_wcid *wcid); +static inline bool +mt76_connac_pm_ref (struct mt76_phy *phy,struct mt76_connac_pm *pm) +{ +bool ret = false; + +spin_lock_bh (&pm->wake.lock); +if (test_bit (MT76_STATE_PM , &phy->state)) + goto out; + + pm->wake.count++; + ret = true; +out: +spin_unlock_bh (&pm->wake.lock); + +return ret; +} + +static inline void +mt76_connac_pm_unref (struct mt76_connac_pm *pm) +{ +spin_lock_bh (&pm->wake.lock); + pm->wake.count--; + pm->last_activity = jiffies; +spin_unlock_bh (&pm->wake.lock); +} + static inline void mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm) __acquires(&dev->mutex)
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 4/19 mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path
In reply to Lorenzo BianconiIntroduce mt7921_tx_worker routine as mt76 tx worker callback for mt7921.
Rely on mt76_connac_pm_ref/mt76_connac_pm_unref to check PM state and increment/decrement wake counter
--- .../net/wireless/mediatek/mt76/mt7921/init.c | 2 ++ .../net/wireless/mediatek/mt76/mt7921/main.c | 23 ++++++++----------- .../wireless/mediatek/mt76/mt7921/mt7921.h | 2 ++ 3 files changed, 13 insertions(+), 14 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/init.c +2 -0
@@ -219,9 +219,11 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; + dev->mt76.tx_worker.fn = mt7921_tx_worker;INIT_DELAYED_WORK (&dev->pm.ps_work, mt7921_pm_power_save_work);INIT_WORK (&dev->pm.wake_work, mt7921_pm_wake_work); +spin_lock_init (&dev->pm.wake.lock);mutex_init (&dev->pm.mutex);init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);
drivers/net/wireless/mediatek/mt76/mt7921/main.c +9 -14
@@ -725,23 +725,18 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,mt76_connac_power_save_sched (&dev->mphy, &dev->pm); } -static void -mt7921_wake_tx_queue (struct ieee80211_hw *hw,struct ieee80211_txq *txq) +void mt7921_tx_worker (struct mt76_worker *w) { -struct mt7921_dev *dev =mt7921_hw_dev (hw); -struct mt7921_phy *phy =mt7921_hw_phy (hw); -struct mt76_phy *mphy = phy->mt76; - -if (!test_bit (MT76_STATE_RUNNING , &mphy->state)) -return ; + struct mt7921_dev *dev = container_of(w, struct mt7921_dev, + mt76.tx_worker); -if (test_bit (MT76_STATE_PM , &mphy->state)) { +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) {queue_work (dev->mt76.wq, &dev->pm.wake_work);return ; } - dev->pm.last_activity = jiffies; -mt76_worker_schedule (&dev->mt76.tx_worker); +mt76_txq_schedule_all (&dev->mphy); +mt76_connac_pm_unref (&dev->pm); } static void mt7921_tx(struct ieee80211_hw *hw,
@@ -769,9 +764,9 @@ static void mt7921_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } -if (!test_bit (MT76_STATE_PM , &mphy->state)) { - dev->pm.last_activity = jiffies; +if (mt76_connac_pm_ref (mphy, &dev->pm)) {mt76_tx (mphy, control->sta, wcid, skb); +mt76_connac_pm_unref (&dev->pm);return ; }
@@ -1200,7 +1195,7 @@ const struct ieee80211_ops mt7921_ops = { .set_key = mt7921_set_key, .ampdu_action = mt7921_ampdu_action, .set_rts_threshold = mt7921_set_rts_threshold, - .wake_tx_queue = mt7921_wake_tx_queue, + .wake_tx_queue = mt76_wake_tx_queue, .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, .get_stats = mt7921_get_stats,
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +2 -0
@@ -336,6 +336,8 @@ 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, struct mt76_tx_info *tx_info); + +void mt7921_tx_worker (struct mt76_worker *w);void mt7921_tx_complete_skb (struct mt76_dev *mdev,struct mt76_queue_entry *e);int mt7921_init_tx_queues (struct mt7921_phy *phy,int idx,int n_desc);void mt7921_tx_token_put (struct mt7921_dev *dev);
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 5/19 mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path
In reply to Lorenzo BianconiIntroduce mt7615_tx_worker routine as mt76 tx worker callback for mt7663.
Rely on mt76_connac_pm_ref/mt76_connac_pm_unref to check PM state and increment/decrement wake counter
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/init.c | 2 ++ .../net/wireless/mediatek/mt76/mt7615/main.c | 27 +++++++++---------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 1 + drivers/net/wireless/mediatek/mt76/tx.c | 12 ++++++--- 5 files changed, 25 insertions(+), 18 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -1015,6 +1015,7 @@ void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta,void mt76_tx_check_agg_ssn (struct ieee80211_sta *sta,struct sk_buff *skb);void mt76_txq_schedule (struct mt76_phy *phy,enum mt76_txq_id qid);void mt76_txq_schedule_all (struct mt76_phy *phy); +void mt76_tx_worker_run (struct mt76_dev *dev);void mt76_tx_worker (struct mt76_worker *w); void mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
drivers/net/wireless/mediatek/mt76/mt7615/init.c +2 -0
@@ -502,9 +502,11 @@ void mt7615_init_device(struct mt7615_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; + dev->mt76.tx_worker.fn = mt7615_tx_worker;INIT_DELAYED_WORK (&dev->pm.ps_work, mt7615_pm_power_save_work);INIT_WORK (&dev->pm.wake_work, mt7615_pm_wake_work); +spin_lock_init (&dev->pm.wake.lock);mutex_init (&dev->pm.mutex);init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock);
drivers/net/wireless/mediatek/mt76/mt7615/main.c +12 -15
@@ -694,28 +694,25 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,break ; } msta->n_rates = i; -if (!test_bit (MT76_STATE_PM , &phy->mt76->state)) +if (mt76_connac_pm_ref (phy->mt76, &dev->pm)) {mt7615_mac_set_rates (phy, msta,NULL , msta->rates); +mt76_connac_pm_unref (&dev->pm); + }spin_unlock_bh (&dev->mt76.lock); } -static void -mt7615_wake_tx_queue (struct ieee80211_hw *hw,struct ieee80211_txq *txq) +void mt7615_tx_worker (struct mt76_worker *w) { -struct mt7615_dev *dev =mt7615_hw_dev (hw); -struct mt7615_phy *phy =mt7615_hw_phy (hw); -struct mt76_phy *mphy = phy->mt76; - -if (!test_bit (MT76_STATE_RUNNING , &mphy->state)) -return ; + struct mt7615_dev *dev = container_of(w, struct mt7615_dev, + mt76.tx_worker); -if (test_bit (MT76_STATE_PM , &mphy->state)) { +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) {queue_work (dev->mt76.wq, &dev->pm.wake_work);return ; } - dev->pm.last_activity = jiffies; -mt76_worker_schedule (&dev->mt76.tx_worker); +mt76_tx_worker_run (&dev->mt76); +mt76_connac_pm_unref (&dev->pm); } static void mt7615_tx(struct ieee80211_hw *hw,
@@ -743,9 +740,9 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &msta->wcid; } -if (!test_bit (MT76_STATE_PM , &mphy->state)) { - dev->pm.last_activity = jiffies; +if (mt76_connac_pm_ref (mphy, &dev->pm)) {mt76_tx (mphy, control->sta, wcid, skb); +mt76_connac_pm_unref (&dev->pm);return ; }
@@ -1272,7 +1269,7 @@ const struct ieee80211_ops mt7615_ops = { .sta_set_decap_offload = mt7615_sta_set_decap_offload, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, - .wake_tx_queue = mt7615_wake_tx_queue, + .wake_tx_queue = mt76_wake_tx_queue, .sta_rate_tbl_update = mt7615_sta_rate_tbl_update, .sw_scan_start = mt76_sw_scan, .sw_scan_complete = mt76_sw_scan_complete,
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +1 -0
@@ -508,6 +508,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); +void mt7615_tx_worker (struct mt76_worker *w);void mt7615_tx_complete_skb (struct mt76_dev *mdev,struct mt76_queue_entry *e);void mt7615_tx_token_put (struct mt7615_dev *dev); void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
drivers/net/wireless/mediatek/mt76/tx.c +9 -3
@@ -540,10 +540,8 @@ void mt76_txq_schedule_all(struct mt76_phy *phy) }EXPORT_SYMBOL_GPL (mt76_txq_schedule_all); -void mt76_tx_worker (struct mt76_worker *w) +void mt76_tx_worker_run (struct mt76_dev *dev) { - struct mt76_dev *dev = container_of(w, struct mt76_dev, tx_worker); -mt76_txq_schedule_all (&dev->phy);if (dev->phy2)mt76_txq_schedule_all (dev->phy2);
@@ -555,6 +553,14 @@ void mt76_tx_worker(struct mt76_worker *w)mt76_testmode_tx_pending (dev->phy2);#endif } +EXPORT_SYMBOL_GPL (mt76_tx_worker_run); + +void mt76_tx_worker (struct mt76_worker *w) +{ + struct mt76_dev *dev = container_of(w, struct mt76_dev, tx_worker); + +mt76_tx_worker_run (dev); +}void mt76_stop_tx_queues (struct mt76_phy *phy,struct ieee80211_sta *sta,bool send_bar)
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 6/19 mt76: dma: add the capability to define a custom rx napi poll routine
In reply to Lorenzo BianconiAdd the capability to define a custom rx napi callback for each driver. This is a preliminary patch to properly support runtime-pm on rx side
--- drivers/net/wireless/mediatek/mt76/dma.c | 10 +++++----- drivers/net/wireless/mediatek/mt76/dma.h | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 5 +++-- drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +5 -5
@@ -602,8 +602,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)return done; } -static int -mt76_dma_rx_poll (struct napi_struct *napi,int budget) +int mt76_dma_rx_poll (struct napi_struct *napi,int budget) {struct mt76_dev *dev;int qid, done =0 , cur;
@@ -626,9 +625,11 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)return done; } +EXPORT_SYMBOL_GPL (mt76_dma_rx_poll);static int -mt76_dma_init (struct mt76_dev *dev) +mt76_dma_init (struct mt76_dev *dev, +int (*poll)(struct napi_struct *napi,int budget)) {int i;
@@ -639,8 +640,7 @@ mt76_dma_init(struct mt76_dev *dev) dev->napi_dev.threaded =1 ;mt76_for_each_q_rx (dev, i) { -netif_napi_add (&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, -64 ); +netif_napi_add (&dev->napi_dev, &dev->napi[i], poll,64 );mt76_dma_rx_fill (dev, &dev->q_rx[i]);napi_enable (&dev->napi[i]); }
drivers/net/wireless/mediatek/mt76/dma.h +1 -0
@@ -45,6 +45,7 @@ enum mt76_mcu_evt_type { EVT_EVENT_DFS_DETECT_RSP, }; +int mt76_dma_rx_poll (struct napi_struct *napi,int budget);void mt76_dma_attach (struct mt76_dev *dev);void mt76_dma_cleanup (struct mt76_dev *dev);
drivers/net/wireless/mediatek/mt76/mt76.h +3 -2
@@ -170,7 +170,8 @@ struct mt76_mcu_ops { };struct mt76_queue_ops { -int (*init)(struct mt76_dev *dev); +int (*init)(struct mt76_dev *dev, +int (*poll)(struct napi_struct *napi,int budget)); int (*alloc)(struct mt76_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize,
@@ -802,7 +803,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev)#define mt76xx_chip (dev) mt76_chip(&((dev)->mt76))#define mt76xx_rev (dev) mt76_rev(&((dev)->mt76)) -#define mt76_init_queues (dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) +#define mt76_init_queues (dev, ...) (dev)->mt76.queue_ops->init(&((dev)->mt76), __VA_ARGS__)#define mt76_queue_alloc (dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__)#define mt76_tx_queue_skb_raw (dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)#define mt76_tx_queue_skb (dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)
drivers/net/wireless/mediatek/mt76/mt7603/dma.c +1 -1
@@ -219,7 +219,7 @@ int mt7603_dma_init(struct mt7603_dev *dev)return ret;mt76_wr (dev,MT_DELAY_INT_CFG ,0 ); - ret =mt76_init_queues (dev); + ret =mt76_init_queues (dev, mt76_dma_rx_poll);if (ret)return ret;
drivers/net/wireless/mediatek/mt76/mt7615/dma.c +1 -1
@@ -261,7 +261,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)mt76_wr (dev,MT_DELAY_INT_CFG ,0 ); - ret =mt76_init_queues (dev); + ret =mt76_init_queues (dev, mt76_dma_rx_poll);if (ret <0 )return ret;
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +1 -1
@@ -226,7 +226,7 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)if (ret)return ret; - ret =mt76_init_queues (dev); + ret =mt76_init_queues (dev, mt76_dma_rx_poll);if (ret)return ret;
drivers/net/wireless/mediatek/mt76/mt7915/dma.c +1 -1
@@ -213,7 +213,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)return ret; } - ret =mt76_init_queues (dev); + ret =mt76_init_queues (dev, mt76_dma_rx_poll);if (ret <0 )return ret;
drivers/net/wireless/mediatek/mt76/mt7921/dma.c +1 -1
@@ -295,7 +295,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)if (ret)return ret; - ret =mt76_init_queues (dev); + ret =mt76_init_queues (dev, mt76_dma_rx_poll);if (ret <0 )return ret;
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 7/19 mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi
In reply to Lorenzo BianconiIntroduce mt7921_poll_rx rx napi callback for mt7921.
Do not access device registers in tx/rx napi if the device is not awake.
--- .../net/wireless/mediatek/mt76/mt7921/dma.c | 33 ++++++++++++++++--- .../net/wireless/mediatek/mt76/mt7921/mac.c | 11 +++++-- .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 3 files changed, 37 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/dma.c +28 -5
@@ -53,8 +53,7 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } -static void -mt7921_tx_cleanup (struct mt7921_dev *dev) +void mt7921_tx_cleanup (struct mt7921_dev *dev) {mt76_queue_tx_cleanup (dev, dev->mt76.q_mcu[MT_MCUQ_WM ], false);mt76_queue_tx_cleanup (dev, dev->mt76.q_mcu[MT_MCUQ_WA ], false);
@@ -66,14 +65,38 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget) dev = container_of(napi, struct mt7921_dev, mt76.tx_napi); -mt7921_tx_cleanup (dev); +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) { +napi_complete (napi); +queue_work (dev->mt76.wq, &dev->pm.wake_work); +return 0 ; + } -if (napi_complete_done (napi,0 )) +mt7921_tx_cleanup (dev); +if (napi_complete (napi))mt7921_irq_enable (dev,MT_INT_TX_DONE_ALL ); +mt76_connac_pm_unref (&dev->pm);return 0 ; } +static int mt7921_poll_rx (struct napi_struct *napi,int budget) +{ +struct mt7921_dev *dev; +int done; + + dev = container_of(napi->dev, struct mt7921_dev, mt76.napi_dev); + +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) { +napi_complete (napi); +queue_work (dev->mt76.wq, &dev->pm.wake_work); +return 0 ; + } + done =mt76_dma_rx_poll (napi, budget); +mt76_connac_pm_unref (&dev->pm); + +return done; +} +void mt7921_dma_prefetch (struct mt7921_dev *dev) {#define PREFETCH (base, depth) ((base) << 16 | (depth))
@@ -295,7 +318,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)if (ret)return ret; - ret =mt76_init_queues (dev, mt76_dma_rx_poll); + ret =mt76_init_queues (dev, mt7921_poll_rx);if (ret <0 )return ret;
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +8 -3
@@ -1367,6 +1367,7 @@ 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 );
@@ -1530,10 +1531,14 @@ 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_wake_queues (mphy->hw);complete_all (&dev->pm.wake_cmpl);
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +1 -0
@@ -332,6 +332,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,void mt7921_mac_work (struct work_struct *work);void mt7921_mac_reset_work (struct work_struct *work);void mt7921_reset (struct mt76_dev *mdev); +void mt7921_tx_cleanup (struct mt7921_dev *dev); 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,
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 8/19 mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi
In reply to Lorenzo BianconiIntroduce mt7615_poll_rx rx napi callback for mt7663.
Do not access device registers in tx/rx napi if the device is not awake.
--- .../net/wireless/mediatek/mt76/mt7615/dma.c | 30 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 10 +++++-- 2 files changed, 34 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/dma.c +27 -3
@@ -71,15 +71,39 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)struct mt7615_dev *dev; dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) { +napi_complete (napi); +queue_work (dev->mt76.wq, &dev->pm.wake_work); +return 0 ; + }mt76_queue_tx_cleanup (dev, dev->mt76.q_mcu[MT_MCUQ_WM ], false); - -if (napi_complete_done (napi,0 )) +if (napi_complete (napi))mt7615_irq_enable (dev,mt7615_tx_mcu_int_mask (dev)); +mt76_connac_pm_unref (&dev->pm); +return 0 ; } +static int mt7615_poll_rx (struct napi_struct *napi,int budget) +{ +struct mt7615_dev *dev; +int done; + + dev = container_of(napi->dev, struct mt7615_dev, mt76.napi_dev); + +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) { +napi_complete (napi); +queue_work (dev->mt76.wq, &dev->pm.wake_work); +return 0 ; + } + done =mt76_dma_rx_poll (napi, budget); +mt76_connac_pm_unref (&dev->pm); + +return done; +} +int mt7615_wait_pdma_busy (struct mt7615_dev *dev) {struct mt76_dev *mdev = &dev->mt76;
@@ -261,7 +285,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)mt76_wr (dev,MT_DELAY_INT_CFG ,0 ); - ret =mt76_init_queues (dev, mt76_dma_rx_poll); + ret =mt76_init_queues (dev, mt7615_poll_rx);if (ret <0 )return ret;
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +7 -3
@@ -1913,10 +1913,14 @@ void mt7615_pm_wake_work(struct work_struct *work) pm.wake_work); mphy = dev->phy.mt76; -if (!mt7615_mcu_set_drv_ctrl (dev)) +if (!mt7615_mcu_set_drv_ctrl (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" ); +mt76_queue_tx_cleanup (dev, dev->mt76.q_mcu[MT_MCUQ_WM ], false); + }ieee80211_wake_queues (mphy->hw);complete_all (&dev->pm.wake_cmpl);
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 9/19 mt76: connac: unschedule ps_work in mt76_connac_pm_wake
In reply to Lorenzo BianconiIn order to avoid synchronization issues between wake and ps works, cancel ps_work in mt76_connac_pm_wake routine
--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 1 - drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 1 - 3 files changed, 1 insertion(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +0 -1
@@ -345,7 +345,6 @@ static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)clear_bit (MT76_STATE_PM , &mphy->state); out: - dev->pm.last_activity = jiffies;mutex_unlock (&dev->pm.mutex);return err;
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +1 -0
@@ -13,6 +13,7 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)if (!mt76_is_mmio (dev))return 0 ; +cancel_delayed_work_sync (&pm->ps_work);if (!test_bit (MT76_STATE_PM , &phy->state))return 0 ;
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +0 -1
@@ -1289,7 +1289,6 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)clear_bit (MT76_STATE_PM , &mphy->state); out: - dev->pm.last_activity = jiffies;mutex_unlock (&dev->pm.mutex);if (err)
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 10/19 mt76: connac: check wake refcount in mcu_fw_pmctrl
In reply to Lorenzo BianconiIn order to avoid synchronization races between tx and rx path, rely on mt76_connac_skip_fw_pmctrl putting the chip in sleep mode for mt7921 and mt7663 devices
--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 12 ++++++++++++ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +1 -1
@@ -358,7 +358,7 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)mutex_lock (&dev->pm.mutex); -if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) +if (mt76_connac_skip_fw_pmctrl (mphy, &dev->pm)) goto out;mt7622_trigger_hif_int (dev, true);
drivers/net/wireless/mediatek/mt76/mt76_connac.h +12 -0
@@ -116,6 +116,18 @@ mt76_connac_pm_unref(struct mt76_connac_pm *pm)spin_unlock_bh (&pm->wake.lock); } +static inline bool +mt76_connac_skip_fw_pmctrl (struct mt76_phy *phy,struct mt76_connac_pm *pm) +{ +bool ret; + +spin_lock_bh (&pm->wake.lock); + ret = pm->wake.count ||test_and_set_bit (MT76_STATE_PM , &phy->state); +spin_unlock_bh (&pm->wake.lock); + +return ret; +} + static inline void mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm) __acquires(&dev->mutex)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +1 -1
@@ -1304,7 +1304,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)mutex_lock (&dev->pm.mutex); -if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) +if (mt76_connac_skip_fw_pmctrl (mphy, &dev->pm)) goto out;for (i =0 ; i <MT7921_DRV_OWN_RETRY_COUNT ; i++) {
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 11/19 mt76: connac: remove MT76_STATE_PM in mac_tx_free
In reply to Lorenzo BianconiGet rid of MT76_STATE_PM chec in mt7615_mac_tx_free and mt7921_mac_tx_free since we already rely on mt76_connac_pm_unref in the NAPI callback.
Remove mt76_connac_power_save_sched calls in mt7615_mac_tx_free and mt7921_mac_tx_free
--- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 4 ---- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 ------ 2 files changed, 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +0 -4
@@ -1514,14 +1514,10 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)dev_kfree_skb (skb); -if (test_bit (MT76_STATE_PM , &dev->phy.mt76->state)) -return ; -rcu_read_lock ();mt7615_mac_sta_poll (dev);rcu_read_unlock (); -mt76_connac_power_save_sched (&dev->mphy, &dev->pm);mt76_worker_schedule (&dev->mt76.tx_worker); }
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +0 -6
@@ -1043,13 +1043,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); }
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 12/19 mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work
In reply to Lorenzo BianconiRemove useless MT76_STATE_PM check in mt7921_mac_work since mt7921_mutex_acquire will wake up the device if necessary
--- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +0 -5
@@ -1493,9 +1493,6 @@ 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);
@@ -1510,8 +1507,6 @@ void mt7921_mac_work(struct work_struct *work) }mt7921_mutex_release (phy->dev); - -out:ieee80211_queue_delayed_work (phy->mt76->hw, &mphy->mac_work,MT7921_WATCHDOG_TIME ); }
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 13/19 mt76: connac: alaways wake the device before scanning
In reply to Lorenzo Bianconimove scanning check from mt76_connac_power_save_sched routine to mt7921_pm_power_save_work/mt7615_pm_power_save_work ones
--- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 8 -------- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 4 ++++ 3 files changed, 8 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +4 -0
@@ -1931,6 +1931,10 @@ void mt7615_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;
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +0 -8
@@ -17,10 +17,6 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)if (!test_bit (MT76_STATE_PM , &phy->state))return 0 ; -if (test_bit (MT76_HW_SCANNING , &phy->state) || -test_bit (MT76_HW_SCHED_SCANNING , &phy->state)) -return 0 ; -if (queue_work (dev->wq, &pm->wake_work))reinit_completion (&pm->wake_cmpl);
@@ -46,10 +42,6 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy, pm->last_activity = jiffies; -if (test_bit (MT76_HW_SCANNING , &phy->state) || -test_bit (MT76_HW_SCHED_SCANNING , &phy->state)) -return ; -if (!test_bit (MT76_STATE_PM , &phy->state))queue_delayed_work (dev->wq, &pm->ps_work, pm->idle_timeout); }
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +4 -0
@@ -1542,6 +1542,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;
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 14/19 mt76: mt7615: rely on pm refcounting in mt7615_led_set_config
In reply to Lorenzo BianconiRely on mt76_connac_pm_ref/mt76_connac_pm_unref utility routines in mt7615_led_set_config
--- drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +3 -1
@@ -82,7 +82,7 @@ mt7615_led_set_config(struct led_classdev *led_cdev, mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); dev = container_of(mt76, struct mt7615_dev, mt76); -if (test_bit (MT76_STATE_PM , &mt76->phy.state)) +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm))return ; val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) |
@@ -100,6 +100,8 @@ mt7615_led_set_config(struct led_classdev *led_cdev, val |=MT_LED_CTRL_POLARITY (mt76->led_pin); addr =mt7615_reg_map (dev,MT_LED_CTRL );mt76_wr (dev, addr, val); + +mt76_connac_pm_unref (&dev->pm); } static int
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 15/19 mt76: connac: do not run mt76_txq_schedule_all directly
In reply to Lorenzo BianconiIn order to not break runtime-pm, do run mt76_txq_schedule_all in mt7615_set_channel/mt7921_set_channel but rely on mt76_worker_schedule
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +1 -2
@@ -351,8 +351,7 @@ int mt7615_set_channel(struct mt7615_phy *phy)mt7615_mutex_release (dev); -mt76_txq_schedule_all (phy->mt76); - +mt76_worker_schedule (&dev->mt76.tx_worker);if (!mt76_testmode_enabled (phy->mt76)) ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work,
drivers/net/wireless/mediatek/mt76/mt7921/main.c +1 -2
@@ -395,8 +395,7 @@ int mt7921_set_channel(struct mt7921_phy *phy)clear_bit (MT76_RESET , &phy->mt76->state);mt7921_mutex_release (dev); -mt76_txq_schedule_all (phy->mt76); - +mt76_worker_schedule (&dev->mt76.tx_worker);ieee80211_queue_delayed_work (phy->mt76->hw, &phy->mt76->mac_work,MT7921_WATCHDOG_TIME );
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 16/19 mt76: connac: use waitqueue for runtime-pm
In reply to Lorenzo BianconiSimplify the code using a wait_queue_head_t instead of a completion to wait the chip is fully awake in mt76_connac_pm_wake routine
--- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 8 ++++---- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -1
@@ -508,7 +508,7 @@ void mt7615_init_device(struct mt7615_dev *dev)INIT_WORK (&dev->pm.wake_work, mt7615_pm_wake_work);spin_lock_init (&dev->pm.wake.lock);mutex_init (&dev->pm.mutex); -init_completion (&dev->pm.wake_cmpl); +init_waitqueue_head (&dev->pm.wait);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state);INIT_DELAYED_WORK (&dev->mphy.mac_work, mt7615_mac_work);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +1 -1
@@ -1919,7 +1919,7 @@ void mt7615_pm_wake_work(struct work_struct *work) }ieee80211_wake_queues (mphy->hw); -complete_all (&dev->pm.wake_cmpl); +wake_up (&dev->pm.wait); }void mt7615_pm_power_save_work (struct work_struct *work)
drivers/net/wireless/mediatek/mt76/mt76_connac.h +1 -1
@@ -53,7 +53,7 @@ struct mt76_connac_pm { } tx_q[IEEE80211_NUM_ACS ];struct work_struct wake_work; -struct completion wake_cmpl; +wait_queue_head_t wait;struct {spinlock_t lock;
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +4 -4
@@ -17,10 +17,10 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)if (!test_bit (MT76_STATE_PM , &phy->state))return 0 ; -if (queue_work (dev->wq, &pm->wake_work)) -reinit_completion (&pm->wake_cmpl); - -if (!wait_for_completion_timeout (&pm->wake_cmpl,3 *HZ )) { +queue_work (dev->wq, &pm->wake_work); +if (!wait_event_timeout (pm->wait, + !test_bit (MT76_STATE_PM , &phy->state), +3 *HZ )) {ieee80211_wake_queues (phy->hw);return -ETIMEDOUT ; }
drivers/net/wireless/mediatek/mt76/mt7921/init.c +1 -1
@@ -225,7 +225,7 @@ int mt7921_register_device(struct mt7921_dev *dev)INIT_WORK (&dev->pm.wake_work, mt7921_pm_wake_work);spin_lock_init (&dev->pm.wake.lock);mutex_init (&dev->pm.mutex); -init_completion (&dev->pm.wake_cmpl); +init_waitqueue_head (&dev->pm.wait);spin_lock_init (&dev->pm.txq_lock);set_bit (MT76_STATE_PM , &dev->mphy.state);INIT_LIST_HEAD (&dev->phy.stats_list);
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +1 -1
@@ -1530,7 +1530,7 @@ void mt7921_pm_wake_work(struct work_struct *work) }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)
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 17/19 mt76: remove MT76_STATE_PM in tx path
In reply to Lorenzo Bianconisince tx/rx path is now relying pm ref counting, get rid of MT76_STATE_PM check in the tx path
--- drivers/net/wireless/mediatek/mt76/tx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/tx.c +2 -4
@@ -422,8 +422,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,return idx; do { - if (test_bit(MT76_STATE_PM, &phy->state) || - test_bit(MT76_RESET, &phy->state)) + if (test_bit(MT76_RESET, &phy->state)) return -EBUSY; if (stop || mt76_txq_stopped(q))
@@ -463,8 +462,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)while (1 ) {int n_frames =0 ; -if (test_bit (MT76_STATE_PM , &phy->state) || -test_bit (MT76_RESET , &phy->state)) +if (test_bit (MT76_RESET , &phy->state))return -EBUSY ; if (dev->queue_ops->tx_cleanup &&
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 18/19 mt76: mt7921: add awake and doze time accounting
In reply to Lorenzo BianconiIntroduce awake and doze time accounting for runtime pm.
--- .../net/wireless/mediatek/mt76/mt76_connac.h | 6 ++++ .../wireless/mediatek/mt76/mt7921/debugfs.c | 32 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7921/init.c | 5 ++- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 19 ++++++++--- 4 files changed, 55 insertions(+), 7 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac.h +6 -0
@@ -64,6 +64,12 @@ struct mt76_connac_pm {struct delayed_work ps_work;unsigned long last_activity;unsigned long idle_timeout; +struct { +unsigned long last_wake_event; +unsigned long awake_time; +unsigned long last_doze_event; +unsigned long doze_time; + } stats; };struct mt76_connac_coredump {
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +31 -1
@@ -230,11 +230,19 @@ static int mt7921_pm_set(void *data, u64 val) {struct mt7921_dev *dev = data; +struct mt76_connac_pm *pm = &dev->pm;struct mt76_phy *mphy = dev->phy.mt76; +if (val == pm->enable) +return 0 ; +mt7921_mutex_acquire (dev); - dev->pm.enable = val; +if (!pm->enable) { + pm->stats.last_wake_event = jiffies; + pm->stats.last_doze_event = jiffies; + } + pm->enable = val; ieee80211_iterate_active_interfaces(mphy->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
@@ -256,6 +264,26 @@ mt7921_pm_get(void *data, u64 *val)DEFINE_DEBUGFS_ATTRIBUTE (fops_pm, mt7921_pm_get, mt7921_pm_set,"%lld\n" ); +static int +mt7921_pm_stats (struct seq_file *s,void *data) +{ +struct mt7921_dev *dev =dev_get_drvdata (s->private); +struct mt76_connac_pm *pm = &dev->pm; +unsigned long awake_time = pm->stats.awake_time; +unsigned long doze_time = pm->stats.doze_time; + +if (!test_bit (MT76_STATE_PM , &dev->mphy.state)) + awake_time += jiffies - pm->stats.last_wake_event; +else + doze_time += jiffies - pm->stats.last_doze_event; + +seq_printf (s,"awake time: %14u\ndoze time: %15u\n" , +jiffies_to_msecs (awake_time), +jiffies_to_msecs (doze_time)); + +return 0 ; +} +static int mt7921_pm_idle_timeout_set (void *data,u64 val) {
@@ -322,6 +350,8 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)debugfs_create_file ("idle-timeout" ,0600 , dir, dev, &fops_pm_idle_timeout);debugfs_create_file ("chip_reset" ,0600 , dir, dev, &fops_reset); +debugfs_create_devm_seqfile (dev->mt76.dev,"runtime_pm_stats" , dir, + mt7921_pm_stats);return 0 ; }
drivers/net/wireless/mediatek/mt76/mt7921/init.c +4 -1
@@ -239,12 +239,15 @@ int mt7921_register_device(struct mt7921_dev *dev)INIT_WORK (&dev->reset_work, mt7921_mac_reset_work); + dev->pm.idle_timeout =MT7921_PM_TIMEOUT ; + dev->pm.stats.last_wake_event = jiffies; + dev->pm.stats.last_doze_event = jiffies; + ret =mt7921_init_hardware (dev);if (ret)return ret;mt7921_init_wiphy (hw); - dev->pm.idle_timeout =MT7921_PM_TIMEOUT ; dev->mphy.sband_2g.sband.ht_cap.cap |=IEEE80211_HT_CAP_LDPC_CODING |IEEE80211_HT_CAP_MAX_AMSDU ;
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +14 -5
@@ -1267,9 +1267,10 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,int mt7921_mcu_drv_pmctrl (struct mt7921_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; +struct mt76_connac_pm *pm = &dev->pm;int i, err =0 ; -mutex_lock (&dev->pm.mutex); +mutex_lock (&pm->mutex);if (!test_bit (MT76_STATE_PM , &mphy->state)) goto out;
@@ -1288,8 +1289,11 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) }clear_bit (MT76_STATE_PM , &mphy->state); + pm->stats.last_wake_event = jiffies; + pm->stats.doze_time += pm->stats.last_wake_event - + pm->stats.last_doze_event; out: -mutex_unlock (&dev->pm.mutex); +mutex_unlock (&pm->mutex);if (err)mt7921_reset (&dev->mt76);
@@ -1300,11 +1304,12 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)int mt7921_mcu_fw_pmctrl (struct mt7921_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; +struct mt76_connac_pm *pm = &dev->pm;int i, err =0 ; -mutex_lock (&dev->pm.mutex); +mutex_lock (&pm->mutex); -if (mt76_connac_skip_fw_pmctrl (mphy, &dev->pm)) +if (mt76_connac_skip_fw_pmctrl (mphy, pm)) goto out;for (i =0 ; i <MT7921_DRV_OWN_RETRY_COUNT ; i++) {
@@ -1319,8 +1324,12 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)clear_bit (MT76_STATE_PM , &mphy->state); err = -EIO ; } + + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; out: -mutex_unlock (&dev->pm.mutex); +mutex_unlock (&pm->mutex);if (err)mt7921_reset (&dev->mt76);
Signature · 1 line
2.30.2
Lorenzo Bianconi
maintainerPATCH 19/19 mt76: mt7921: enable sw interrupts
In reply to Lorenzo BianconiEnable sw interrupts in order to wake the device from deep sleep receiving packets
--- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 1 + drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 13 +++++++++++++ .../net/wireless/mediatek/mt76/mt7921/regs.h | 17 ++++++++++------- 4 files changed, 25 insertions(+), 7 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/dma.c +1 -0
@@ -351,6 +351,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)/* enable interrupts for TX/RX rings */ mt7921_irq_enable (dev,MT_INT_RX_DONE_ALL |MT_INT_TX_DONE_ALL |MT_INT_MCU_CMD ); +mt76_set (dev,MT_MCU2HOST_SW_INT_ENA ,MT_MCU_CMD_WAKE_RX_PCIE );return 0 ; }
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +1 -0
@@ -1276,6 +1276,7 @@ mt7921_dma_reset(struct mt7921_dev *dev)mt7921_irq_enable (dev,MT_INT_RX_DONE_ALL |MT_INT_TX_DONE_ALL |MT_INT_MCU_CMD ); +mt76_set (dev,MT_MCU2HOST_SW_INT_ENA ,MT_MCU_CMD_WAKE_RX_PCIE ); }void mt7921_tx_token_put (struct mt7921_dev *dev)
drivers/net/wireless/mediatek/mt76/mt7921/pci.c +13 -0
@@ -61,6 +61,18 @@ static void mt7921_irq_tasklet(unsigned long data)if (intr &MT_INT_TX_DONE_MCU ) mask |=MT_INT_TX_DONE_MCU ; +if (intr &MT_INT_MCU_CMD ) { +u32 intr_sw; + + intr_sw =mt76_rr (dev,MT_MCU_CMD ); +/* ack MCU2HOST_SW_INT_STA */ +mt76_wr (dev,MT_MCU_CMD , intr_sw); +if (intr_sw &MT_MCU_CMD_WAKE_RX_PCIE ) { + mask |=MT_INT_RX_DONE_DATA ; + intr |=MT_INT_RX_DONE_DATA ; + } + } +mt76_set_irq_mask (&dev->mt76,MT_WFDMA0_HOST_INT_ENA , mask,0 );if (intr &MT_INT_TX_DONE_ALL )
@@ -253,6 +265,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev)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 ); +mt76_set (dev,MT_MCU2HOST_SW_INT_ENA ,MT_MCU_CMD_WAKE_RX_PCIE );/* put dma enabled */ mt76_set(dev, MT_WFDMA0_GLO_CFG,
drivers/net/wireless/mediatek/mt76/mt7921/regs.h +10 -7
@@ -251,13 +251,16 @@#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1)#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) -#define MT_MCU_CMD MT_WFDMA0(0x1f0) -#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) -#define MT_MCU_CMD_STOP_DMA BIT(2) -#define MT_MCU_CMD_RESET_DONE BIT(3) -#define MT_MCU_CMD_RECOVERY_DONE BIT(4) -#define MT_MCU_CMD_NORMAL_STATE BIT(5) -#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) +#define MT_MCU_CMD MT_WFDMA0(0x1f0) +#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0) +#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_DMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) + +#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4)#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200)#define HOST_RX_DONE_INT_STS0 BIT(0)/* Rx mcu */
Signature · 1 line
2.30.2