linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/19] mt76: improve runtime-pm support
@ 2021-04-18 16:45 Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 01/19] mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl Lorenzo Bianconi
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

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(-)

-- 
2.30.2


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/19] mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 02/19] mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl Lorenzo Bianconi
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

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

Fixes: 1d8efc741df8 ("mt76: mt7921: introduce Runtime PM support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index b811f3c410a1..2b31c9794e92 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -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;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index eab6e2dcdb96..0b8a5a7f4362 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 14ba856de0b6..ea00f6b6af56 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -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
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/19] mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 01/19] mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 03/19] mt76: connac: introduce wake counter for fw_pmctrl synchronization Lorenzo Bianconi
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce 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

Fixes: 1f549009b5b2 ("mt76: mt7615: do not request {driver,fw}_own if already granted")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7615/init.c  |  1 +
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 20 +++++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index d84662fb0304..5429536e8d43 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 364daef4b0be..7081bb4a28bd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -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;
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/19] mt76: connac: introduce wake counter for fw_pmctrl synchronization
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 01/19] mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 02/19] mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 04/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path Lorenzo Bianconi
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce wake counter and related spinlock in order to synchronize
tx/rx path and fw_pmctrl request.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt76_connac.h  | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 2b31c9794e92..85846eab8d7d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -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)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 03/19] mt76: connac: introduce wake counter for fw_pmctrl synchronization Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 05/19] mt76: mt7663: " Lorenzo Bianconi
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 0b8a5a7f4362..ce0e231ab772 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 25591e2c510c..95e1775c5c00 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 3780a7f4cb16..a794c074867e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -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);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/19] mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 04/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 06/19] mt76: dma: add the capability to define a custom rx napi poll routine Lorenzo Bianconi
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 289f195a7951..0660b708156d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 5429536e8d43..3ef6bcdf38c4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 8313bf468db2..a3e53d3aec02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 5262b84a28c7..4c533b8ffa47 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 04e47259ea5f..cfc7229aa7b0 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -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)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/19] mt76: dma: add the capability to define a custom rx napi poll routine
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 05/19] mt76: mt7663: " Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 07/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi Lorenzo Bianconi
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Add 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 6ea58aecca41..72b1cc0ecfda 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -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]);
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h
index e7c27697ef04..fdf786f975ea 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.h
+++ b/drivers/net/wireless/mediatek/mt76/dma.h
@@ -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);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 0660b708156d..49f3e5985422 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -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__)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
index 2b6244116842..415ea17b9be6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
index 642b4eab0d8b..d658555f5965 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index ce1e9ad23fec..b50084bbe83d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
index 9fe09870f8f0..11d0b760abd7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index 992faf82ad09..b056ac15f09a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -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;
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 06/19] mt76: dma: add the capability to define a custom rx napi poll routine Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 08/19] mt76: mt7663: " Lorenzo Bianconi
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce mt7921_poll_rx rx napi callback for mt7921.
Do not access device registers in tx/rx napi if the device is not awake.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index b056ac15f09a..c26979614113 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index c8819e78cea3..def00b255495 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index a794c074867e..c9687c57cbe7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -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,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/19] mt76: mt7663: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (6 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 07/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 09/19] mt76: connac: unschedule ps_work in mt76_connac_pm_wake Lorenzo Bianconi
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce mt7615_poll_rx rx napi callback for mt7663.
Do not access device registers in tx/rx napi if the device is not awake.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7615/dma.c   | 30 +++++++++++++++++--
 .../net/wireless/mediatek/mt76/mt7615/mac.c   | 10 +++++--
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
index d658555f5965..8004ae5c16a9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 0b386030dbd8..e81c7d322811 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -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);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/19] mt76: connac: unschedule ps_work in mt76_connac_pm_wake
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (7 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 08/19] mt76: mt7663: " Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 10/19] mt76: connac: check wake refcount in mcu_fw_pmctrl Lorenzo Bianconi
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

In order to avoid synchronization issues between wake and ps works,
cancel ps_work in mt76_connac_pm_wake routine

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 7081bb4a28bd..5890fee98d97 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -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;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index c5f5037f5757..32d664ac1e35 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -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;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index ea00f6b6af56..44f02cbf9cc7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -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)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/19] mt76: connac: check wake refcount in mcu_fw_pmctrl
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (8 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 09/19] mt76: connac: unschedule ps_work in mt76_connac_pm_wake Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 11/19] mt76: connac: remove MT76_STATE_PM in mac_tx_free Lorenzo Bianconi
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

In 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 5890fee98d97..45c6fb5832b8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 85846eab8d7d..116d800c9f9d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -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)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 44f02cbf9cc7..1204f5d324f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -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++) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/19] mt76: connac: remove MT76_STATE_PM in mac_tx_free
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (9 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 10/19] mt76: connac: check wake refcount in mcu_fw_pmctrl Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 12/19] mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work Lorenzo Bianconi
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Get 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 4 ----
 drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 ------
 2 files changed, 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index e81c7d322811..ad1e236727cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -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);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index def00b255495..a8247a6d5bc7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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);
 }
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/19] mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (10 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 11/19] mt76: connac: remove MT76_STATE_PM in mac_tx_free Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 13/19] mt76: connac: alaways wake the device before scanning Lorenzo Bianconi
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Remove useless MT76_STATE_PM check in mt7921_mac_work since
mt7921_mutex_acquire will wake up the device if necessary

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index a8247a6d5bc7..5dcb574a2768 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/19] mt76: connac: alaways wake the device before scanning
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (11 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 12/19] mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 14/19] mt76: mt7615: rely on pm refcounting in mt7615_led_set_config Lorenzo Bianconi
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

move scanning check from mt76_connac_power_save_sched routine
to mt7921_pm_power_save_work/mt7615_pm_power_save_work ones

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index ad1e236727cb..adbc726149a9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -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;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index 32d664ac1e35..a263921d9f42 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -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);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 5dcb574a2768..90ede75cfba8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/19] mt76: mt7615: rely on pm refcounting in mt7615_led_set_config
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (12 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 13/19] mt76: connac: alaways wake the device before scanning Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 15/19] mt76: connac: do not run mt76_txq_schedule_all directly Lorenzo Bianconi
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Rely on mt76_connac_pm_ref/mt76_connac_pm_unref utility routines in
mt7615_led_set_config

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
index 49540b00519d..736d19699a03 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
@@ -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
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 15/19] mt76: connac: do not run mt76_txq_schedule_all directly
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (13 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 14/19] mt76: mt7615: rely on pm refcounting in mt7615_led_set_config Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 16/19] mt76: connac: use waitqueue for runtime-pm Lorenzo Bianconi
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

In 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index a3e53d3aec02..39733b351ac4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 95e1775c5c00..255a931675bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -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);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 16/19] mt76: connac: use waitqueue for runtime-pm
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (14 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 15/19] mt76: connac: do not run mt76_txq_schedule_all directly Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 17/19] mt76: remove MT76_STATE_PM in tx path Lorenzo Bianconi
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Simplify 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

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 3ef6bcdf38c4..894b2588e075 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index adbc726149a9..747bf90f9d8a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -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)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 116d800c9f9d..e3937f6d3640 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -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;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index a263921d9f42..66f1667481e6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -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;
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index ce0e231ab772..2d8dba000d0b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 90ede75cfba8..7b5323181fac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 17/19] mt76: remove MT76_STATE_PM in tx path
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (15 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 16/19] mt76: connac: use waitqueue for runtime-pm Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 18/19] mt76: mt7921: add awake and doze time accounting Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 19/19] mt76: mt7921: enable sw interrupts Lorenzo Bianconi
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

since tx/rx path is now relying pm ref counting, get rid of MT76_STATE_PM
check in the tx path

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/tx.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index cfc7229aa7b0..236eaa351f53 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -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 &&
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 18/19] mt76: mt7921: add awake and doze time accounting
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (16 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 17/19] mt76: remove MT76_STATE_PM in tx path Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  2021-04-18 16:45 ` [PATCH 19/19] mt76: mt7921: enable sw interrupts Lorenzo Bianconi
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Introduce awake and doze time accounting for runtime pm.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index e3937f6d3640..9e61c107c640 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -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 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
index 5a54cd8d2ce4..f3982578cc56 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -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;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 2d8dba000d0b..cec17a249a8c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -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;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 1204f5d324f8..c00295b63ba8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -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);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 19/19] mt76: mt7921: enable sw interrupts
  2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
                   ` (17 preceding siblings ...)
  2021-04-18 16:45 ` [PATCH 18/19] mt76: mt7921: add awake and doze time accounting Lorenzo Bianconi
@ 2021-04-18 16:45 ` Lorenzo Bianconi
  18 siblings, 0 replies; 20+ messages in thread
From: Lorenzo Bianconi @ 2021-04-18 16:45 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sean.wang

Enable sw interrupts in order to wake the device from deep sleep
receiving packets

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 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(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index c26979614113..7ada8339b74f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -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;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 7b5323181fac..8770e0d93f45 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -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)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 40e2086d075c..d5da98d36f63 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -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,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
index 76ecfea21dce..b6944c867a57 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
@@ -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 */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2021-04-18 16:46 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-18 16:45 [PATCH 00/19] mt76: improve runtime-pm support Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 01/19] mt76: mt7921: fix a race between mt7921_mcu_drv_pmctrl and mt7921_mcu_fw_pmctrl Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 02/19] mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 03/19] mt76: connac: introduce wake counter for fw_pmctrl synchronization Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 04/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx path Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 05/19] mt76: mt7663: " Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 06/19] mt76: dma: add the capability to define a custom rx napi poll routine Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 07/19] mt76: mt7921: rely on mt76_connac_pm_ref/mt76_connac_pm_unref in tx/rx napi Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 08/19] mt76: mt7663: " Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 09/19] mt76: connac: unschedule ps_work in mt76_connac_pm_wake Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 10/19] mt76: connac: check wake refcount in mcu_fw_pmctrl Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 11/19] mt76: connac: remove MT76_STATE_PM in mac_tx_free Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 12/19] mt76: mt7921: get rid of useless MT76_STATE_PM in mt7921_mac_work Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 13/19] mt76: connac: alaways wake the device before scanning Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 14/19] mt76: mt7615: rely on pm refcounting in mt7615_led_set_config Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 15/19] mt76: connac: do not run mt76_txq_schedule_all directly Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 16/19] mt76: connac: use waitqueue for runtime-pm Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 17/19] mt76: remove MT76_STATE_PM in tx path Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 18/19] mt76: mt7921: add awake and doze time accounting Lorenzo Bianconi
2021-04-18 16:45 ` [PATCH 19/19] mt76: mt7921: enable sw interrupts Lorenzo Bianconi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).