From: Lorenzo Bianconi <lorenzo@kernel.org>
To: nbd@nbd.name
Cc: linux-mediatek@lists.infradead.org, lorenzo.bianconi@redhat.com,
sean.wang@mediatek.com, linux-wireless@vger.kernel.org,
ryder.lee@mediatek.com
Subject: [PATCH 11/17] mt76: mt7615: wake device before pushing frames in mt7615_tx
Date: Fri, 26 Jun 2020 23:25:11 +0200 [thread overview]
Message-ID: <62ced1be6533f90aba09c0136d8e172812d4778e.1593204577.git.lorenzo@kernel.org> (raw)
In-Reply-To: <cover.1593204577.git.lorenzo@kernel.org>
Queue frames pushed by mac80211 running mt7615_tx if the device is
low-power state. Run wake workqueue in order to swicth to full-power
before transmitting pending frames
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7615/init.c | 1 +
.../net/wireless/mediatek/mt76/mt7615/mac.c | 25 ++++++++-
.../net/wireless/mediatek/mt76/mt7615/main.c | 56 +++++++++++++++++--
.../wireless/mediatek/mt76/mt7615/mt7615.h | 6 ++
4 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index c22878b82540..576c63b2e949 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -448,6 +448,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);
init_completion(&dev->pm.wake_cmpl);
+ spin_lock_init(&dev->pm.txq_lock);
INIT_DELAYED_WORK(&dev->phy.mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7615_scan_work);
skb_queue_head_init(&dev->phy.scan_event_list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 0a16acf40cf8..8616bac97963 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1836,6 +1836,7 @@ void mt7615_pm_wake_work(struct work_struct *work)
{
struct mt7615_dev *dev;
struct mt76_phy *mphy;
+ int i;
dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,
pm.wake_work);
@@ -1846,8 +1847,28 @@ void mt7615_pm_wake_work(struct work_struct *work)
goto out;
}
+ spin_lock_bh(&dev->pm.txq_lock);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ struct mt7615_sta *msta = dev->pm.tx_q[i].msta;
+ struct mt76_wcid *wcid = msta ? &msta->wcid : NULL;
+ struct ieee80211_sta *sta = NULL;
+
+ if (!dev->pm.tx_q[i].skb)
+ continue;
+
+ if (msta && wcid->sta)
+ sta = container_of((void *)msta, struct ieee80211_sta,
+ drv_priv);
+
+ mt76_tx(mphy, sta, wcid, dev->pm.tx_q[i].skb);
+ dev->pm.tx_q[i].skb = NULL;
+ }
+ spin_unlock_bh(&dev->pm.txq_lock);
+
tasklet_schedule(&dev->mt76.tx_tasklet);
+
out:
+ ieee80211_wake_queues(mphy->hw);
complete_all(&dev->pm.wake_cmpl);
}
@@ -1871,8 +1892,10 @@ int mt7615_pm_wake(struct mt7615_dev *dev)
if (queue_work(dev->mt76.wq, &dev->pm.wake_work))
reinit_completion(&dev->pm.wake_cmpl);
- if (!wait_for_completion_timeout(&dev->pm.wake_cmpl, 3 * HZ))
+ if (!wait_for_completion_timeout(&dev->pm.wake_cmpl, 3 * HZ)) {
+ ieee80211_wake_queues(mphy->hw);
return -ETIMEDOUT;
+ }
return 0;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 9c17026c541d..32f060014bb7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -24,6 +24,22 @@ static bool mt7615_dev_running(struct mt7615_dev *dev)
return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
}
+static void mt7615_free_pending_tx_skbs(struct mt7615_dev *dev,
+ struct mt7615_sta *msta)
+{
+ int i;
+
+ spin_lock_bh(&dev->pm.txq_lock);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ if (msta && dev->pm.tx_q[i].msta != msta)
+ continue;
+
+ dev_kfree_skb(dev->pm.tx_q[i].skb);
+ dev->pm.tx_q[i].skb = NULL;
+ }
+ spin_unlock_bh(&dev->pm.txq_lock);
+}
+
static int mt7615_start(struct ieee80211_hw *hw)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
@@ -77,6 +93,8 @@ static void mt7615_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&dev->pm.ps_work);
cancel_work_sync(&dev->pm.wake_work);
+ mt7615_free_pending_tx_skbs(dev, NULL);
+
mt7615_mutex_acquire(dev, &dev->mt76.mutex);
mt76_testmode_reset(&dev->mt76, true);
@@ -215,6 +233,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
if (vif == phy->monitor_vif)
phy->monitor_vif = NULL;
+ mt7615_free_pending_tx_skbs(dev, msta);
+
mt7615_mcu_add_dev_info(dev, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
@@ -592,6 +612,8 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
+ mt7615_free_pending_tx_skbs(dev, msta);
+
mt7615_mcu_sta_add(dev, vif, sta, false);
mt7615_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -662,22 +684,43 @@ static void mt7615_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+ struct mt7615_sta *msta = NULL;
+ int qid;
if (control->sta) {
- struct mt7615_sta *sta;
-
- sta = (struct mt7615_sta *)control->sta->drv_priv;
- wcid = &sta->wcid;
+ msta = (struct mt7615_sta *)control->sta->drv_priv;
+ wcid = &msta->wcid;
}
if (vif && !control->sta) {
struct mt7615_vif *mvif;
mvif = (struct mt7615_vif *)vif->drv_priv;
- wcid = &mvif->sta.wcid;
+ msta = &mvif->sta;
+ wcid = &msta->wcid;
+ }
+
+ if (!test_bit(MT76_STATE_PM, &mphy->state)) {
+ mt76_tx(mphy, control->sta, wcid, skb);
+ return;
+ }
+
+ qid = skb_get_queue_mapping(skb);
+ if (qid >= MT_TXQ_PSD) {
+ qid = IEEE80211_AC_BE;
+ skb_set_queue_mapping(skb, qid);
}
- mt76_tx(mphy, control->sta, wcid, skb);
+ spin_lock_bh(&dev->pm.txq_lock);
+ if (!dev->pm.tx_q[qid].skb) {
+ ieee80211_stop_queues(hw);
+ dev->pm.tx_q[qid].msta = msta;
+ dev->pm.tx_q[qid].skb = skb;
+ queue_work(dev->mt76.wq, &dev->pm.wake_work);
+ } else {
+ dev_kfree_skb(skb);
+ }
+ spin_unlock_bh(&dev->pm.txq_lock);
}
static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
@@ -1026,6 +1069,7 @@ static int mt7615_suspend(struct ieee80211_hw *hw,
int err = 0;
cancel_delayed_work_sync(&dev->pm.ps_work);
+ mt7615_free_pending_tx_skbs(dev, NULL);
mt7615_mutex_acquire(dev, &dev->mt76.mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index a93ddb1a3def..6da0af628c8d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -300,6 +300,12 @@ struct mt7615_dev {
#endif
struct {
+ spinlock_t txq_lock;
+ struct {
+ struct mt7615_sta *msta;
+ struct sk_buff *skb;
+ } tx_q[IEEE80211_NUM_ACS];
+
struct work_struct wake_work;
struct completion wake_cmpl;
--
2.26.2
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
next prev parent reply other threads:[~2020-06-26 21:26 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-26 21:25 [PATCH 00/17] add runtime-pm support to mt7663 driver Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 01/17] mt76: mt7615: avoid polling in fw_own for mt7663 Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 02/17] mt76: move mt76 worqueue in common code Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 03/17] mt76: mt7615: add mt7615_pm_wake utility routine Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 04/17] mt76: mt7615: introduce mt7615_mutex_{acquire, release} utilities Lorenzo Bianconi
2020-07-01 19:26 ` [PATCH 04/17] mt76: mt7615: introduce mt7615_mutex_{acquire,release} utilities Felix Fietkau
2020-06-26 21:25 ` [PATCH 05/17] mt76: mt7615: wake device before accessing regmap in debugfs Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 06/17] mt76: mt7615: wake device before configuring hw keys Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 07/17] mt76: mt7615: introduce pm_power_save delayed work Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 08/17] mt76: mt7615: wake device in mt7615_update_channel before access regmap Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 09/17] mt76: mt7615: acquire driver_own before configuring device for suspend Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 10/17] mt76: mt7615: wake device before pulling packets from mac80211 queues Lorenzo Bianconi
2020-06-26 21:25 ` Lorenzo Bianconi [this message]
2020-06-26 21:25 ` [PATCH 12/17] mt76: mt7615: check MT76_STATE_PM flag before accessing the device Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 13/17] mt76: mt7615: do not request {driver, fw}_own if already granted Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 14/17] mt76: mt7615: add runtime-pm knob in mt7615 debugfs Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 15/17] mt76: mt7615: enable beacon hw filter for runtime-pm Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 16/17] mt76: mt7615: add idle-timeout knob in mt7615 debugfs Lorenzo Bianconi
2020-06-26 21:25 ` [PATCH 17/17] mt76: mt7615: improve mt7615_driver_own reliability Lorenzo Bianconi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=62ced1be6533f90aba09c0136d8e172812d4778e.1593204577.git.lorenzo@kernel.org \
--to=lorenzo@kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-wireless@vger.kernel.org \
--cc=lorenzo.bianconi@redhat.com \
--cc=nbd@nbd.name \
--cc=ryder.lee@mediatek.com \
--cc=sean.wang@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).