* [PATCH 1/4] mt76: mt7615: defer mcu initialization via workqueue
@ 2019-12-13 21:36 Felix Fietkau
2019-12-13 21:36 ` [PATCH 2/4] mt7615: replace sta_state callback with sta_add/sta_remove Felix Fietkau
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-13 21:36 UTC (permalink / raw)
To: linux-wireless
Loading the mcu firmware and waiting for it to boot takes a long time,
which adds a significant amount to the system boot time.
Fix this by running the mcu init from a workqueue and waiting for it to
complete before starting the phy or issuing mcu commands via debugfs
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
.../wireless/mediatek/mt76/mt7615/debugfs.c | 12 ++++++
.../net/wireless/mediatek/mt76/mt7615/init.c | 37 ++++++++++++++-----
.../net/wireless/mediatek/mt76/mt7615/main.c | 3 ++
.../wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++
4 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
index f75b3f66cdb4..783f145b7d02 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
@@ -7,6 +7,9 @@ mt7615_radar_pattern_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
+ if (!mt7615_wait_for_mcu_init(dev))
+ return 0;
+
return mt7615_mcu_rdd_send_pattern(dev);
}
@@ -18,6 +21,9 @@ mt7615_scs_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
+ if (!mt7615_wait_for_mcu_init(dev))
+ return 0;
+
mt7615_mac_set_scs(dev, val);
return 0;
@@ -41,6 +47,9 @@ mt7615_dbdc_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
+ if (!mt7615_wait_for_mcu_init(dev))
+ return 0;
+
if (val)
mt7615_register_ext_phy(dev);
else
@@ -131,6 +140,9 @@ static int mt7615_read_temperature(struct seq_file *s, void *data)
struct mt7615_dev *dev = dev_get_drvdata(s->private);
int temp;
+ if (!mt7615_wait_for_mcu_init(dev))
+ return 0;
+
/* cpu */
temp = mt7615_mcu_get_temperature(dev, 0);
seq_printf(s, "Temperature: %d\n", temp);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index a37562965f41..c1e437e031b5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -104,12 +104,33 @@ static void mt7615_mac_init(struct mt7615_dev *dev)
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN);
}
+bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)
+{
+ flush_work(&dev->mcu_work);
+
+ return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
+}
+
+static void mt7615_init_work(struct work_struct *work)
+{
+ struct mt7615_dev *dev = container_of(work, struct mt7615_dev, mcu_work);
+
+ if (mt7615_mcu_init(dev))
+ return;
+
+ mt7615_mcu_set_eeprom(dev);
+ mt7615_mac_init(dev);
+ mt7615_phy_init(dev);
+ mt7615_mcu_del_wtbl_all(dev);
+}
+
static int mt7615_init_hardware(struct mt7615_dev *dev)
{
int ret, idx;
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
+ INIT_WORK(&dev->mcu_work, mt7615_init_work);
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);
@@ -123,15 +144,6 @@ static int mt7615_init_hardware(struct mt7615_dev *dev)
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
- ret = mt7615_mcu_init(dev);
- if (ret)
- return ret;
-
- mt7615_mcu_set_eeprom(dev);
- mt7615_mac_init(dev);
- mt7615_phy_init(dev);
- mt7615_mcu_del_wtbl_all(dev);
-
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
if (idx)
@@ -385,6 +397,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
if (ret)
return ret;
+ ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work);
mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband);
@@ -394,11 +407,15 @@ int mt7615_register_device(struct mt7615_dev *dev)
void mt7615_unregister_device(struct mt7615_dev *dev)
{
struct mt76_txwi_cache *txwi;
+ bool mcu_running;
int id;
+ mcu_running = mt7615_wait_for_mcu_init(dev);
+
mt7615_unregister_ext_phy(dev);
mt76_unregister_device(&dev->mt76);
- mt7615_mcu_exit(dev);
+ if (mcu_running)
+ mt7615_mcu_exit(dev);
mt7615_dma_cleanup(dev);
spin_lock_bh(&dev->token_lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index ef14779fdbc4..c6a0ca1034c0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -30,6 +30,9 @@ static int mt7615_start(struct ieee80211_hw *hw)
struct mt7615_phy *phy = mt7615_hw_phy(hw);
bool running;
+ if (!mt7615_wait_for_mcu_init(dev))
+ return -EIO;
+
mutex_lock(&dev->mt76.mutex);
running = mt7615_dev_running(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 32f23f5fdd58..b4d6727cf285 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -117,6 +117,8 @@ struct mt7615_dev {
u16 chainmask;
+ struct work_struct mcu_work;
+
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
@@ -222,6 +224,7 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
int mt7615_dma_init(struct mt7615_dev *dev);
void mt7615_dma_cleanup(struct mt7615_dev *dev);
int mt7615_mcu_init(struct mt7615_dev *dev);
+bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);
int mt7615_mcu_set_dev_info(struct mt7615_dev *dev,
struct ieee80211_vif *vif, bool enable);
int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif,
--
2.24.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/4] mt7615: replace sta_state callback with sta_add/sta_remove
2019-12-13 21:36 [PATCH 1/4] mt76: mt7615: defer mcu initialization via workqueue Felix Fietkau
@ 2019-12-13 21:36 ` Felix Fietkau
2019-12-13 21:36 ` [PATCH 3/4] mt76: fix rx dma ring descriptor state on reset Felix Fietkau
2019-12-13 21:36 ` [PATCH 4/4] mt76: disable bh in mt76_dma_rx_poll Felix Fietkau
2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-13 21:36 UTC (permalink / raw)
To: linux-wireless
The MT7615 firmware needs to know the association id at creation time,
which is unavailable during the transition from notexist to none in
.sta_state.
This can cause a number of issues, probably also breaking powersave
support.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
.../net/wireless/mediatek/mt76/mt7615/main.c | 38 ++++++++++++-------
.../wireless/mediatek/mt76/mt7615/mt7615.h | 8 ++--
.../net/wireless/mediatek/mt76/mt7615/pci.c | 5 +--
3 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index c6a0ca1034c0..d759f009599b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -434,8 +434,8 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw,
mutex_unlock(&dev->mt76.mutex);
}
-int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
@@ -455,21 +455,14 @@ int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7615_mcu_add_wtbl(dev, vif, sta);
mt7615_mcu_set_sta_rec(dev, vif, sta, 1);
+ if (sta->ht_cap.ht_supported)
+ mt7615_mcu_set_ht_cap(dev, vif, sta);
return 0;
}
-void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-
- if (sta->ht_cap.ht_supported)
- mt7615_mcu_set_ht_cap(dev, vif, sta);
-}
-
-void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
+void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
@@ -605,6 +598,22 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return ret;
}
+static int
+mt7615_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
+ IEEE80211_STA_NONE);
+}
+
+static int
+mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
+ IEEE80211_STA_NOTEXIST);
+}
+
const struct ieee80211_ops mt7615_ops = {
.tx = mt7615_tx,
.start = mt7615_start,
@@ -615,7 +624,8 @@ const struct ieee80211_ops mt7615_ops = {
.conf_tx = mt7615_conf_tx,
.configure_filter = mt7615_configure_filter,
.bss_info_changed = mt7615_bss_info_changed,
- .sta_state = mt76_sta_state,
+ .sta_add = mt7615_sta_add,
+ .sta_remove = mt7615_sta_remove,
.set_key = mt7615_set_key,
.ampdu_action = mt7615_ampdu_action,
.set_rts_threshold = mt7615_set_rts_threshold,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index b4d6727cf285..4fe6dc60e0cd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -313,12 +313,10 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
-int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
void mt7615_mac_work(struct work_struct *work);
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
index dd9ee80dbef7..7e3556c3b6eb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
@@ -81,9 +81,8 @@ static int mt7615_pci_probe(struct pci_dev *pdev,
.rx_skb = mt7615_queue_rx_skb,
.rx_poll_complete = mt7615_rx_poll_complete,
.sta_ps = mt7615_sta_ps,
- .sta_add = mt7615_sta_add,
- .sta_assoc = mt7615_sta_assoc,
- .sta_remove = mt7615_sta_remove,
+ .sta_add = mt7615_mac_sta_add,
+ .sta_remove = mt7615_mac_sta_remove,
.update_survey = mt7615_update_channel,
};
struct mt7615_dev *dev;
--
2.24.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/4] mt76: fix rx dma ring descriptor state on reset
2019-12-13 21:36 [PATCH 1/4] mt76: mt7615: defer mcu initialization via workqueue Felix Fietkau
2019-12-13 21:36 ` [PATCH 2/4] mt7615: replace sta_state callback with sta_add/sta_remove Felix Fietkau
@ 2019-12-13 21:36 ` Felix Fietkau
2019-12-13 21:36 ` [PATCH 4/4] mt76: disable bh in mt76_dma_rx_poll Felix Fietkau
2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-13 21:36 UTC (permalink / raw)
To: linux-wireless
To avoid having the hardware potentially write to memory behind stale
descriptors, set the dma-done flag on all of them before cleaning up
allocated rx buffers
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/dma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index f88d017ff987..2298a4e91943 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -437,7 +437,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
int i;
for (i = 0; i < q->ndesc; i++)
- q->desc[i].ctrl &= ~cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+ q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
mt76_dma_rx_cleanup(dev, q);
mt76_dma_sync_idx(dev, q);
--
2.24.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 4/4] mt76: disable bh in mt76_dma_rx_poll
2019-12-13 21:36 [PATCH 1/4] mt76: mt7615: defer mcu initialization via workqueue Felix Fietkau
2019-12-13 21:36 ` [PATCH 2/4] mt7615: replace sta_state callback with sta_add/sta_remove Felix Fietkau
2019-12-13 21:36 ` [PATCH 3/4] mt76: fix rx dma ring descriptor state on reset Felix Fietkau
@ 2019-12-13 21:36 ` Felix Fietkau
2 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2019-12-13 21:36 UTC (permalink / raw)
To: linux-wireless
Fixes potential RCU issues and avoids calling ieee80211_rx_napi with softirq
enabled.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/wireless/mediatek/mt76/dma.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 2298a4e91943..9e03a7871ff4 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -538,6 +538,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
dev = container_of(napi->dev, struct mt76_dev, napi_dev);
qid = napi - dev->napi;
+ local_bh_disable();
rcu_read_lock();
do {
@@ -547,6 +548,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget)
} while (cur && done < budget);
rcu_read_unlock();
+ local_bh_enable();
if (done < budget && napi_complete(napi))
dev->drv->rx_poll_complete(dev, qid);
--
2.24.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-12-13 21:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-13 21:36 [PATCH 1/4] mt76: mt7615: defer mcu initialization via workqueue Felix Fietkau
2019-12-13 21:36 ` [PATCH 2/4] mt7615: replace sta_state callback with sta_add/sta_remove Felix Fietkau
2019-12-13 21:36 ` [PATCH 3/4] mt76: fix rx dma ring descriptor state on reset Felix Fietkau
2019-12-13 21:36 ` [PATCH 4/4] mt76: disable bh in mt76_dma_rx_poll Felix Fietkau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.