mt7663s: enable runtime-pm support
Subsystems (2)
Lorenzo Bianconi
maintainercover mt7663s: enable runtime-pm support
As already done for mt7663e, introduce runtime-pm support for mt7663s
Lorenzo Bianconi (5):
mt76: sdio: do not run mt76_txq_schedule directly
mt76: mt7663s: rely on pm reference counting
mt76: mt7663s: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx
path
mt76: mt7663s: enable runtime-pm
mt76: mt7615: set macwork timeout according to runtime-pm
.../wireless/mediatek/mt76/mt7615/debugfs.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 29 ++++++++++---- .../net/wireless/mediatek/mt76/mt7615/main.c | 18 +++++---- .../wireless/mediatek/mt76/mt7615/mt7615.h | 7 +++- .../wireless/mediatek/mt76/mt7615/pci_mac.c | 7 ++-- .../wireless/mediatek/mt76/mt7615/sdio_mcu.c | 39 +++++++++++++------ .../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 16 ++++++-- .../wireless/mediatek/mt76/mt76_connac_mac.c | 4 +- drivers/net/wireless/mediatek/mt76/sdio.c | 16 +++++--- 9 files changed, 95 insertions(+), 43 deletions(-)
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH 1/5 mt76: sdio: do not run mt76_txq_schedule directly
In order to support runtime-pm for sdio, do not run mt76_txq_schedule directly, but schedule tx_worker instead
--- drivers/net/wireless/mediatek/mt76/sdio.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/sdio.c +11 -5
@@ -184,9 +184,6 @@ static int mt76s_process_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)if (!q->queued)wake_up (&dev->tx_wait); -if (!mcu) -mt76_txq_schedule (&dev->phy, q->qid); -return nframes; }
@@ -195,19 +192,28 @@ static void mt76s_status_worker(struct mt76_worker *w) struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, status_worker); struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); +bool resched = false;int i, nframes;do { +int ndata_frames =0 ; + nframes =mt76s_process_tx_queue (dev, dev->q_mcu[MT_MCUQ_WM ]);for (i =0 ; i <=MT_TXQ_PSD ; i++) - nframes +=mt76s_process_tx_queue (dev, - dev->phy.q_tx[i]); + ndata_frames +=mt76s_process_tx_queue (dev, + dev->phy.q_tx[i]); + nframes += ndata_frames; +if (ndata_frames >0 ) + resched = true;if (dev->drv->tx_status_data && !test_and_set_bit (MT76_READING_STATS , &dev->phy.state))queue_work (dev->wq, &dev->sdio.stat_work); }while (nframes >0 ); + +if (resched) +mt76_worker_schedule (&dev->sdio.txrx_worker); }static void mt76s_tx_status_data (struct work_struct *work)
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH 2/5 mt76: mt7663s: rely on pm reference counting
In reply to Lorenzo BianconiAs already done for mt7921 and mt7663e, rely on pm reference counting in drv/fw_own
--- .../wireless/mediatek/mt76/mt7615/sdio_mcu.c | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c +22 -14
@@ -55,6 +55,7 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev) {struct sdio_func *func = dev->mt76.sdio.func;struct mt76_phy *mphy = &dev->mt76.phy; +struct mt76_connac_pm *pm = &dev->pm;u32 status;int ret;
@@ -64,39 +65,44 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev) ret =readx_poll_timeout (mt7663s_read_pcr, dev, status, status &WHLPCR_IS_DRIVER_OWN ,2000 ,1000000 ); -if (ret <0 ) { +if (ret <0 )dev_err (dev->mt76.dev,"Cannot get ownership from device" ); -set_bit (MT76_STATE_PM , &mphy->state); -sdio_release_host (func); - -return ret; - } +else +clear_bit (MT76_STATE_PM , &mphy->state);sdio_release_host (func); - dev->pm.last_activity = jiffies; + pm->last_activity = jiffies; -return 0 ; +return ret; }static int mt7663s_mcu_drv_pmctrl (struct mt7615_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy; +int ret =0 ; -if (test_and_clear_bit (MT76_STATE_PM , &mphy->state)) -return __mt7663s_mcu_drv_pmctrl (dev); +mutex_lock (&dev->pm.mutex); -return 0 ; +if (test_bit (MT76_STATE_PM , &mphy->state)) + ret =__mt7663s_mcu_drv_pmctrl (dev); + +mutex_unlock (&dev->pm.mutex); + +return ret; }static int mt7663s_mcu_fw_pmctrl (struct mt7615_dev *dev) {struct sdio_func *func = dev->mt76.sdio.func;struct mt76_phy *mphy = &dev->mt76.phy; +struct mt76_connac_pm *pm = &dev->pm; +int ret =0 ;u32 status; -int ret; -if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) -return 0 ; +mutex_lock (&pm->mutex); + +if (mt76_connac_skip_fw_pmctrl (mphy, pm)) + goto out;sdio_claim_host (func);
@@ -110,6 +116,8 @@ static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev) }sdio_release_host (func); +out: +mutex_unlock (&pm->mutex);return ret; }
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH 3/5 mt76: mt7663s: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path
In reply to Lorenzo BianconiSimilar to mt7663e, rely on mt76_connac_pm_ref/mt76_connac_pm_unref to check PM state and increment/decrement wake counter
--- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 14 ++++++++++---- .../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +10 -4
@@ -1906,12 +1906,18 @@ void mt7615_pm_wake_work(struct work_struct *work) mphy = dev->phy.mt76;if (!mt7615_mcu_set_drv_ctrl (dev)) { +struct mt76_dev *mdev = &dev->mt76;int i; -mt76_for_each_q_rx (&dev->mt76, i) -napi_schedule (&dev->mt76.napi[i]); -mt76_connac_pm_dequeue_skbs (mphy, &dev->pm); -mt76_queue_tx_cleanup (dev, dev->mt76.q_mcu[MT_MCUQ_WM ], false); +if (mt76_is_sdio (mdev)) { +mt76_worker_schedule (&mdev->sdio.txrx_worker); + }else { +mt76_for_each_q_rx (mdev, i) +napi_schedule (&mdev->napi[i]); +mt76_connac_pm_dequeue_skbs (mphy, &dev->pm); +mt76_queue_tx_cleanup (dev, mdev->q_mcu[MT_MCUQ_WM ], + false); + }if (test_bit (MT76_STATE_RUNNING , &mphy->state))ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work,MT7615_WATCHDOG_TIME );
drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +12 -4
@@ -283,9 +283,15 @@ void mt7663s_txrx_worker(struct mt76_worker *w) { struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, txrx_worker); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); + struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio); + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);int i, nframes, ret; +if (!mt76_connac_pm_ref (&dev->mphy, &dev->pm)) { +queue_work (mdev->wq, &dev->pm.wake_work); +return ; + } +/* disable interrupt */ sdio_claim_host (sdio->func);sdio_writel (sdio->func,WHLPCR_INT_EN_CLR ,MCR_WHLPCR ,NULL );
@@ -295,16 +301,16 @@ void mt7663s_txrx_worker(struct mt76_worker *w)/* tx */ for (i =0 ; i <=MT_TXQ_PSD ; i++) { - ret =mt7663s_tx_run_queue (dev, dev->phy.q_tx[i]); + ret =mt7663s_tx_run_queue (mdev, mdev->phy.q_tx[i]);if (ret >0 ) nframes += ret; } - ret =mt7663s_tx_run_queue (dev, dev->q_mcu[MT_MCUQ_WM ]); + ret =mt7663s_tx_run_queue (mdev, mdev->q_mcu[MT_MCUQ_WM ]);if (ret >0 ) nframes += ret;/* rx */ - ret =mt7663s_rx_handler (dev); + ret =mt7663s_rx_handler (mdev);if (ret >0 ) nframes += ret; }while (nframes >0 );
@@ -312,6 +318,8 @@ void mt7663s_txrx_worker(struct mt76_worker *w)/* enable interrupt */ sdio_writel (sdio->func,WHLPCR_INT_EN_SET ,MCR_WHLPCR ,NULL );sdio_release_host (sdio->func); + +mt76_connac_pm_unref (&dev->pm); }void mt7663s_sdio_irq (struct sdio_func *func)
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH 4/5 mt76: mt7663s: enable runtime-pm
In reply to Lorenzo BianconiAllow the user to enable runtime-pm for mt7663s driver
--- drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/sdio_mcu.c | 13 ++++++++++--- .../net/wireless/mediatek/mt76/mt76_connac_mac.c | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +1 -1
@@ -75,7 +75,7 @@ mt7615_pm_set(void *data, u64 val)if (!mt7615_wait_for_mcu_init (dev))return 0 ; -if (!mt7615_firmware_offload (dev) || !mt76_is_mmio (&dev->mt76)) +if (!mt7615_firmware_offload (dev) ||mt76_is_usb (&dev->mt76))return -EOPNOTSUPP ;if (val == pm->enable)
drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c +10 -3
@@ -65,13 +65,16 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev) ret =readx_poll_timeout (mt7663s_read_pcr, dev, status, status &WHLPCR_IS_DRIVER_OWN ,2000 ,1000000 ); -if (ret <0 ) +if (ret <0 ) {dev_err (dev->mt76.dev,"Cannot get ownership from device" ); -else + }else {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; + }sdio_release_host (func); - pm->last_activity = jiffies;return ret; }
@@ -113,6 +116,10 @@ static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)if (ret <0 ) {dev_err (dev->mt76.dev,"Cannot set ownership to device" );clear_bit (MT76_STATE_PM , &mphy->state); + }else { + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; }sdio_release_host (func);
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +2 -2
@@ -10,7 +10,7 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)if (!pm->enable)return 0 ; -if (!mt76_is_mmio (dev)) +if (mt76_is_usb (dev))return 0 ;cancel_delayed_work_sync (&pm->ps_work);
@@ -34,7 +34,7 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy, {struct mt76_dev *dev = phy->dev; -if (!mt76_is_mmio (dev)) +if (mt76_is_usb (dev))return ;if (!pm->enable)
Signature · 1 line
2.31.1
Lorenzo Bianconi
maintainerPATCH 5/5 mt76: mt7615: set macwork timeout according to runtime-pm
In reply to Lorenzo BianconiSet macwork timeout value according to runtime-pm in order to reduce power consumption
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 15 +++++++++++---- .../net/wireless/mediatek/mt76/mt7615/main.c | 18 +++++++++++------- .../net/wireless/mediatek/mt76/mt7615/mt7615.h | 7 ++++++- .../wireless/mediatek/mt76/mt7615/pci_mac.c | 7 ++++--- 4 files changed, 32 insertions(+), 15 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +11 -4
@@ -1918,9 +1918,14 @@ void mt7615_pm_wake_work(struct work_struct *work)mt76_queue_tx_cleanup (dev, mdev->q_mcu[MT_MCUQ_WM ], false); } -if (test_bit (MT76_STATE_RUNNING , &mphy->state)) + +if (test_bit (MT76_STATE_RUNNING , &mphy->state)) { +unsigned long timeout; + + timeout =mt7615_get_macwork_timeout (dev);ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work, -MT7615_WATCHDOG_TIME ); + timeout); + } }ieee80211_wake_queues (mphy->hw);
@@ -1955,6 +1960,7 @@ void mt7615_mac_work(struct work_struct *work) {struct mt7615_phy *phy;struct mt76_phy *mphy; +unsigned long timeout; mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, mac_work.work);
@@ -1973,8 +1979,9 @@ void mt7615_mac_work(struct work_struct *work)mt7615_mutex_release (phy->dev);mt76_tx_status_check (mphy->dev,NULL , false); -ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work, -MT7615_WATCHDOG_TIME ); + + timeout =mt7615_get_macwork_timeout (phy->dev); +ieee80211_queue_delayed_work (mphy->hw, &mphy->mac_work, timeout); }void mt7615_tx_token_put (struct mt7615_dev *dev)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +11 -7
@@ -28,6 +28,7 @@ static int mt7615_start(struct ieee80211_hw *hw) {struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt7615_phy *phy =mt7615_hw_phy (hw); +unsigned long timeout;bool running;int ret;
@@ -78,8 +79,8 @@ static int mt7615_start(struct ieee80211_hw *hw)set_bit (MT76_STATE_RUNNING , &phy->mt76->state); -ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, -MT7615_WATCHDOG_TIME ); + timeout =mt7615_get_macwork_timeout (dev); +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, timeout);if (!running)mt7615_mac_reset_counters (dev);
@@ -352,10 +353,12 @@ int mt7615_set_channel(struct mt7615_phy *phy)mt7615_mutex_release (dev);mt76_worker_schedule (&dev->mt76.tx_worker); -if (!mt76_testmode_enabled (phy->mt76)) +if (!mt76_testmode_enabled (phy->mt76)) { +unsigned long timeout =mt7615_get_macwork_timeout (dev); +ieee80211_queue_delayed_work (phy->mt76->hw, - &phy->mt76->mac_work, -MT7615_WATCHDOG_TIME ); + &phy->mt76->mac_work, timeout); + }return ret; }
@@ -1200,6 +1203,7 @@ static int mt7615_resume(struct ieee80211_hw *hw) {struct mt7615_phy *phy =mt7615_hw_phy (hw);struct mt7615_dev *dev =mt7615_hw_dev (hw); +unsigned long timeout;bool running;mt7615_mutex_acquire (dev);
@@ -1223,8 +1227,8 @@ static int mt7615_resume(struct ieee80211_hw *hw) mt76_connac_mcu_set_suspend_iter, phy->mt76); -ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, -MT7615_WATCHDOG_TIME ); + timeout =mt7615_get_macwork_timeout (dev); +ieee80211_queue_delayed_work (hw, &phy->mt76->mac_work, timeout);mt7615_mutex_release (dev);
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +6 -1
@@ -20,7 +20,6 @@ MT7615_MAX_INTERFACES)#define MT7615_PM_TIMEOUT (HZ / 12) -#define MT7615_WATCHDOG_TIME (HZ / 10)#define MT7615_HW_SCAN_TIMEOUT (HZ / 10)#define MT7615_RESET_TIMEOUT (30 * HZ)#define MT7615_RATE_RETRY 2
@@ -460,6 +459,12 @@ static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev)return MT_INT_TX_DONE (dev->mt76.q_mcu[MT_MCUQ_WM ]->hw_idx); } +static inline unsigned long +mt7615_get_macwork_timeout (struct mt7615_dev *dev) +{ +return dev->pm.enable ?HZ /3 :HZ /10 ; +} +void mt7615_dma_reset (struct mt7615_dev *dev);void mt7615_scan_work (struct work_struct *work);void mt7615_roc_work (struct work_struct *work);
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +4 -3
@@ -268,6 +268,7 @@ void mt7615_mac_reset_work(struct work_struct *work)struct mt7615_phy *phy2;struct mt76_phy *ext_phy;struct mt7615_dev *dev; +unsigned long timeout; dev = container_of(work, struct mt7615_dev, reset_work); ext_phy = dev->mt76.phy2;
@@ -345,11 +346,11 @@ void mt7615_mac_reset_work(struct work_struct *work)mt7615_mutex_release (dev); + timeout =mt7615_get_macwork_timeout (dev);ieee80211_queue_delayed_work (mt76_hw (dev), &dev->mphy.mac_work, -MT7615_WATCHDOG_TIME ); + timeout);if (phy2)ieee80211_queue_delayed_work (ext_phy->hw, - &phy2->mt76->mac_work, -MT7615_WATCHDOG_TIME ); + &phy2->mt76->mac_work, timeout); }
Signature · 1 line
2.31.1