add runtime-pm support to mt7663 driver
Subsystems (2)
Lorenzo Bianconi
maintainerv2 cover add runtime-pm support to mt7663 driver
This series enable runtime power management support available in mt7663 offload firmware in order to put the device in a reduced power consumption state if idle for a configurable period of time. mt76 driver wakes the chipset up before tx packets, accessing register map or sending mcu messages.
Changes since v1:
- rely only on mt76 mutext in mt7615_acquire/release utility routines
Lorenzo Bianconi (22):
mt76: mt7615: avoid polling in fw_own for mt7663
mt76: move mt76 worqueue in common code
mt76: mt7615: add mt7615_pm_wake utility routine
mt76: mt7615: introduce mt7615_mutex_{acquire,release} utilities
mt76: mt7615: wake device before accessing regmap in debugfs
mt76: mt7615: wake device before configuring hw keys
mt76: mt7615: introduce pm_power_save delayed work
mt76: mt7615: wake device in mt7615_update_channel before access
regmap
mt76: mt7615: acquire driver_own before configuring device for suspend
mt76: mt7615: wake device before performing freq scan
mt76: mt7615: add missing lock in mt7615_regd_notifier
mt76: mt7615: run mt7615_mcu_set_wmm holding mt76 mutex
mt76: mt7615: run mt7615_mcu_set_roc holding mt76 mutex
mt76: mt7615: wake device before pulling packets from mac80211 queues
mt76: mt7615: wake device before pushing frames in mt7615_tx
mt76: mt7615: run mt7615_pm_wake in mt7615_mac_sta_{add,remove}
mt76: mt7615: check MT76_STATE_PM flag before accessing the device
mt76: mt7615: do not request {driver,fw}_own if already granted
mt76: mt7615: add runtime-pm knob in mt7615 debugfs
mt76: mt7615: enable beacon hw filter for runtime-pm
mt76: mt7615: add idle-timeout knob in mt7615 debugfs
mt76: mt7615: improve mt7615_driver_own reliability
drivers/net/wireless/mediatek/mt76/mac80211.c | 17 +- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +- .../wireless/mediatek/mt76/mt7615/debugfs.c | 74 ++++- .../net/wireless/mediatek/mt76/mt7615/init.c | 9 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 186 +++++++++++- .../net/wireless/mediatek/mt76/mt7615/main.c | 271 ++++++++++++++---- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 51 +++- .../wireless/mediatek/mt76/mt7615/mt7615.h | 42 +++ .../net/wireless/mediatek/mt76/mt7615/pci.c | 4 + .../wireless/mediatek/mt76/mt7615/pci_init.c | 4 + .../net/wireless/mediatek/mt76/mt7615/usb.c | 17 +- .../wireless/mediatek/mt76/mt7615/usb_mcu.c | 2 + .../net/wireless/mediatek/mt76/mt76x0/usb.c | 6 +- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 7 +- drivers/net/wireless/mediatek/mt76/usb.c | 20 +- 15 files changed, 587 insertions(+), 129 deletions(-)
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 1/22 mt76: mt7615: avoid polling in fw_own for mt7663
According to the vendor sdk, mt7663 does not need to poll register after firmware own. Since just mt7622 polls status register, set proper timeout value according to the vendor sdk
--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +2 -2
@@ -1945,9 +1945,9 @@ int mt7615_firmware_own(struct mt7615_dev *dev)mt76_wr (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ); -if (!is_mt7615 (&dev->mt76) && +if (is_mt7622 (&dev->mt76) && !mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN , -MT_CFG_LPCR_HOST_FW_OWN ,3000 )) { +MT_CFG_LPCR_HOST_FW_OWN ,300 )) {dev_err (dev->mt76.dev,"Timeout for firmware own\n" );return -EIO ; }
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 2/22 mt76: move mt76 worqueue in common code
In reply to Lorenzo BianconiMove mt76 worqueue from usb to common code in order to be reused adding low-power support for mt7663 chipset
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 13 +++++++++++- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/main.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/usb.c | 6 ++---- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 6 ++---- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 7 ++----- drivers/net/wireless/mediatek/mt76/usb.c | 20 ++++--------------- 8 files changed, 26 insertions(+), 34 deletions(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +12 -1
@@ -437,6 +437,12 @@ mt76_alloc_device(struct device *pdev, unsigned int size,tasklet_init (&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long )dev); + dev->wq =alloc_ordered_workqueue ("mt76" ,0 ); +if (!dev->wq) { +ieee80211_free_hw (hw); +return NULL ; + } +return dev; }EXPORT_SYMBOL_GPL (mt76_alloc_device);
@@ -490,7 +496,12 @@ EXPORT_SYMBOL_GPL(mt76_unregister_device);void mt76_free_device (struct mt76_dev *dev) { -mt76_tx_free (dev); +if (dev->wq) { +destroy_workqueue (dev->wq); + dev->wq =NULL ; + } +if (mt76_is_mmio (dev)) +mt76_tx_free (dev);ieee80211_free_hw (dev->hw); }EXPORT_SYMBOL_GPL (mt76_free_device);
drivers/net/wireless/mediatek/mt76/mt76.h +2 -2
@@ -424,7 +424,6 @@ struct mt76_usb {u16 data_len;struct tasklet_struct rx_tasklet; -struct workqueue_struct *wq;struct work_struct stat_work;u8 out_ep[__MT_EP_OUT_MAX];
@@ -623,6 +622,8 @@ struct mt76_dev {struct mt76_testmode_data test;#endif +struct workqueue_struct *wq; +union {struct mt76_mmio mmio;struct mt76_usb usb;
@@ -1027,7 +1028,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, void *buf, size_t len);void mt76u_single_wr (struct mt76_dev *dev,const u8 req,const u16 offset,const u32 val); -void mt76u_deinit (struct mt76_dev *dev);int mt76u_init (struct mt76_dev *dev,struct usb_interface *intf,bool ext);int mt76u_alloc_mcu_queue (struct mt76_dev *dev);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +1 -1
@@ -927,7 +927,7 @@ mt7615_mac_queue_rate_update(struct mt7615_phy *phy, struct mt7615_sta *sta,mt7615_mac_update_rate_desc (phy, sta, probe_rate, rates, &wd->rate);list_add_tail (&wd->node, &dev->wd_head); -queue_work (dev->mt76.usb.wq, &dev->wtbl_work); +queue_work (dev->mt76.wq, &dev->wtbl_work);return 0 ; }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +1 -1
@@ -319,7 +319,7 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd, wd->key.cmd = cmd;list_add_tail (&wd->node, &dev->wd_head); -queue_work (dev->mt76.usb.wq, &dev->wtbl_work); +queue_work (dev->mt76.wq, &dev->wtbl_work);return 0 ; }
drivers/net/wireless/mediatek/mt76/mt7615/usb.c +2 -4
@@ -349,11 +349,10 @@ static int mt7663u_probe(struct usb_interface *usb_intf, error_freeq:mt76u_queues_deinit (&dev->mt76); error: -mt76u_deinit (&dev->mt76);usb_set_intfdata (usb_intf,NULL );usb_put_dev (interface_to_usbdev (usb_intf)); -ieee80211_free_hw (mdev->hw); +mt76_free_device (&dev->mt76);return ret; }
@@ -371,8 +370,7 @@ static void mt7663u_disconnect(struct usb_interface *usb_intf)usb_set_intfdata (usb_intf,NULL );usb_put_dev (interface_to_usbdev (usb_intf)); -mt76u_deinit (&dev->mt76); -ieee80211_free_hw (dev->mt76.hw); +mt76_free_device (&dev->mt76); }#ifdef CONFIG_PM
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +2 -4
@@ -277,9 +277,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, err:usb_set_intfdata (usb_intf,NULL );usb_put_dev (interface_to_usbdev (usb_intf)); -mt76u_deinit (&dev->mt76); +mt76_free_device (&dev->mt76); -ieee80211_free_hw (mdev->hw);return ret; }
@@ -297,8 +296,7 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf)usb_set_intfdata (usb_intf,NULL );usb_put_dev (interface_to_usbdev (usb_intf)); -mt76u_deinit (&dev->mt76); -ieee80211_free_hw (dev->mt76.hw); +mt76_free_device (&dev->mt76); } static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +2 -5
@@ -75,8 +75,7 @@ static int mt76x2u_probe(struct usb_interface *intf,return 0 ; err: -ieee80211_free_hw (mt76_hw (dev)); -mt76u_deinit (&dev->mt76); +mt76_free_device (&dev->mt76);usb_set_intfdata (intf,NULL );usb_put_dev (udev);
@@ -92,9 +91,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf)set_bit (MT76_REMOVED , &dev->mphy.state);ieee80211_unregister_hw (hw);mt76x2u_cleanup (dev); -mt76u_deinit (&dev->mt76); - -ieee80211_free_hw (hw); +mt76_free_device (&dev->mt76);usb_set_intfdata (intf,NULL );usb_put_dev (udev); }
drivers/net/wireless/mediatek/mt76/usb.c +4 -16
@@ -842,7 +842,7 @@ static void mt76u_tx_tasklet(unsigned long data)if (dev->drv->tx_status_data && !test_and_set_bit (MT76_READING_STATS , &dev->phy.state)) -queue_work (dev->usb.wq, &dev->usb.stat_work); +queue_work (dev->wq, &dev->usb.stat_work);if (wake)ieee80211_wake_queue (dev->hw, i); }
@@ -868,7 +868,7 @@ static void mt76u_tx_status_data(struct work_struct *work) }if (count &&test_bit (MT76_STATE_RUNNING , &dev->phy.state)) -queue_work (usb->wq, &usb->stat_work); +queue_work (dev->wq, &usb->stat_work);else clear_bit (MT76_READING_STATS , &dev->phy.state); }
@@ -1132,15 +1132,6 @@ static const struct mt76_queue_ops usb_queue_ops = { .kick = mt76u_tx_kick, }; -void mt76u_deinit (struct mt76_dev *dev) -{ -if (dev->usb.wq) { -destroy_workqueue (dev->usb.wq); - dev->usb.wq =NULL ; - } -} -EXPORT_SYMBOL_GPL (mt76u_deinit); -int mt76u_init (struct mt76_dev *dev,struct usb_interface *intf,bool ext) {
@@ -1163,10 +1154,6 @@ int mt76u_init(struct mt76_dev *dev,tasklet_init (&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long )dev);INIT_WORK (&usb->stat_work, mt76u_tx_status_data); - usb->wq =alloc_workqueue ("mt76u" ,WQ_UNBOUND ,0 ); -if (!usb->wq) -return -ENOMEM ; - usb->data_len =usb_maxpacket (udev,usb_sndctrlpipe (udev,0 ),1 );if (usb->data_len <32 ) usb->data_len =32 ;
@@ -1190,7 +1177,8 @@ int mt76u_init(struct mt76_dev *dev,return 0 ; error: -mt76u_deinit (dev); +destroy_workqueue (dev->wq); +return err; }EXPORT_SYMBOL_GPL (mt76u_init);
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 3/22 mt76: mt7615: add mt7615_pm_wake utility routine
In reply to Lorenzo BianconiIntroduce mt7615_pm_wake utility routine to wake the device from runtime low-power state (lower-power state is currently supported by offload firmware for pcie devices).
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/init.c | 3 ++ .../net/wireless/mediatek/mt76/mt7615/mac.c | 42 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 2 + .../net/wireless/mediatek/mt76/mt7615/mcu.c | 25 ++++++++--- .../wireless/mediatek/mt76/mt7615/mt7615.h | 8 ++++ 6 files changed, 75 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -291,6 +291,7 @@ enum {MT76_STATE_POWER_OFF ,MT76_STATE_SUSPEND ,MT76_STATE_ROC , + MT76_STATE_PM, }; struct mt76_hw_cap {
drivers/net/wireless/mediatek/mt76/mt7615/init.c +3 -0
@@ -444,6 +444,9 @@ void mt7615_init_device(struct mt7615_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; + +INIT_WORK (&dev->pm.wake_work, mt7615_pm_wake_work); +init_completion (&dev->pm.wake_cmpl);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);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +42 -0
48 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7615/main.c +2 -0
@@ -74,6 +74,8 @@ static void mt7615_stop(struct ieee80211_hw *hw)del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work); +cancel_work_sync (&dev->pm.wake_work); +mutex_lock (&dev->mt76.mutex);mt76_testmode_reset (&dev->mt76, true);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +19 -6
@@ -1916,28 +1916,36 @@ static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)int mt7615_driver_own (struct mt7615_dev *dev) { +struct mt76_phy *mphy = &dev->mt76.phy;struct mt76_dev *mdev = &dev->mt76; +int err =0 ;u32 addr; +mt7622_trigger_hif_int (dev, true); + addr =is_mt7663 (mdev) ?MT_PCIE_DOORBELL_PUSH :MT_CFG_LPCR_HOST ;mt76_wr (dev, addr,MT_CFG_LPCR_HOST_DRV_OWN ); -mt7622_trigger_hif_int (dev, true); - addr =is_mt7663 (mdev) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ;if (!mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ,0 ,3000 )) {dev_err (dev->mt76.dev,"Timeout for driver own\n" ); -return -EIO ; + err = -EIO ; + goto out; } +clear_bit (MT76_STATE_PM , &mphy->state); + +out:mt7622_trigger_hif_int (dev, false); -return 0 ; +return err; }EXPORT_SYMBOL_GPL (mt7615_driver_own);int mt7615_firmware_own (struct mt7615_dev *dev) { +struct mt76_phy *mphy = &dev->mt76.phy; +int err =0 ;u32 addr; addr =is_mt7663 (&dev->mt76) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ;
@@ -1949,11 +1957,16 @@ int mt7615_firmware_own(struct mt7615_dev *dev) !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, MT_CFG_LPCR_HOST_FW_OWN, 300)) {dev_err (dev->mt76.dev,"Timeout for firmware own\n" ); -return -EIO ; + err = -EIO ; + goto out; } + +set_bit (MT76_STATE_PM , &mphy->state); + +out:mt7622_trigger_hif_int (dev, false); -return 0 ; +return err; }EXPORT_SYMBOL_GPL (mt7615_firmware_own);
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +8 -0
@@ -4,6 +4,7 @@#ifndef __MT7615_H#define __MT7615_H +#include <linux/completion.h> #include <linux/interrupt.h> #include <linux/ktime.h> #include <linux/regmap.h>
@@ -296,6 +297,11 @@ struct mt7615_dev {s8 last_wb_rssi; } test;#endif + +struct { +struct work_struct wake_work; +struct completion wake_cmpl; + } pm; }; enum tx_pkt_queue_idx {
@@ -425,6 +431,8 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);void mt7615_mac_set_rates (struct mt7615_phy *phy,struct mt7615_sta *sta,struct ieee80211_tx_rate *probe_rate,struct ieee80211_tx_rate *rates); +void mt7615_pm_wake_work (struct work_struct *work); +int mt7615_pm_wake (struct mt7615_dev *dev);int mt7615_mcu_del_wtbl_all (struct mt7615_dev *dev);int mt7615_mcu_set_chan_info (struct mt7615_phy *phy,int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 4/22 mt76: mt7615: introduce mt7615_mutex_{acquire, release} utilities
In reply to Lorenzo BianconiIntroduce mt7615_mutex_{acquire,release} utility routines in order to switch in full-power/low-power before/after accessing device register-map
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 14 ++-- .../net/wireless/mediatek/mt76/mt7615/main.c | 82 ++++++++++--------- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 1 + .../wireless/mediatek/mt76/mt7615/mt7615.h | 16 ++++ .../net/wireless/mediatek/mt76/mt7615/usb.c | 11 +-- 5 files changed, 72 insertions(+), 52 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +7 -7
@@ -1530,7 +1530,7 @@ void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable)bool ext_phy = phy != &dev->phy;u32 reg, mask; -mutex_lock (&dev->mt76.mutex); +mt7615_mutex_acquire (dev);if (phy->scs_en == enable) goto out;
@@ -1557,7 +1557,7 @@ void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable) phy->scs_en = enable; out: -mutex_unlock (&dev->mt76.mutex); +mt7615_mutex_release (dev); }void mt7615_mac_enable_nf (struct mt7615_dev *dev,bool ext_phy)
@@ -1859,7 +1859,7 @@ void mt7615_mac_work(struct work_struct *work) mac_work.work); mdev = &phy->dev->mt76; -mutex_lock (&mdev->mutex); +mt7615_mutex_acquire (phy->dev);mt76_update_survey (mdev);if (++phy->mac_work_count ==5 ) {
@@ -1869,7 +1869,7 @@ void mt7615_mac_work(struct work_struct *work)mt7615_mac_scs_check (phy); } -mutex_unlock (&mdev->mutex); +mt7615_mutex_release (phy->dev);mt76_tx_status_check (mdev,NULL , false); ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
@@ -1973,7 +1973,7 @@ void mt7615_mac_reset_work(struct work_struct *work)napi_disable (&dev->mt76.napi[1 ]);napi_disable (&dev->mt76.tx_napi); -mutex_lock (&dev->mt76.mutex); +mt7615_mutex_acquire (dev);mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_PDMA_STOPPED );
@@ -2006,10 +2006,10 @@ void mt7615_mac_reset_work(struct work_struct *work)mt76_wr (dev,MT_MCU_INT_EVENT ,MT_MCU_INT_EVENT_RESET_DONE );mt7615_wait_reset_state (dev,MT_MCU_CMD_NORMAL_STATE ); -mutex_unlock (&dev->mt76.mutex); -mt7615_update_beacons (dev); +mt7615_mutex_release (dev); +ieee80211_queue_delayed_work (mt76_hw (dev), &dev->phy.mac_work,MT7615_WATCHDOG_TIME );if (phy2)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +42 -40
288 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +1 -0
@@ -1937,6 +1937,7 @@ int mt7615_driver_own(struct mt7615_dev *dev) out:mt7622_trigger_hif_int (dev, false); + dev->pm.last_activity = jiffies;return err; }
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +16 -0
@@ -301,6 +301,8 @@ struct mt7615_dev {struct {struct work_struct wake_work;struct completion wake_cmpl; + +unsigned long last_activity; } pm; };
@@ -487,6 +489,20 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev)return MT7615_WTBL_SIZE ; } +static inline void mt7615_mutex_acquire (struct mt7615_dev *dev) + __acquires(&dev->mt76.mutex) +{ +mutex_lock (&dev->mt76.mutex); +mt7615_pm_wake (dev); +} + +static inline void mt7615_mutex_release (struct mt7615_dev *dev) + __releases(&dev->mt76.mutex) +{ + dev->pm.last_activity = jiffies; +mutex_unlock (&dev->mt76.mutex); +} +static inline u8 mt7615_lmac_mapping (struct mt7615_dev *dev,u8 ac) {static const u8 lmac_queue_map[] = {
drivers/net/wireless/mediatek/mt76/mt7615/usb.c +6 -5
@@ -201,12 +201,13 @@ void mt7663u_wtbl_work(struct work_struct *work) dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev, wtbl_work); +mt7615_mutex_acquire (dev); +list_for_each_entry_safe (wd, wd_next, &dev->wd_head, node) {spin_lock_bh (&dev->mt76.lock);list_del (&wd->node);spin_unlock_bh (&dev->mt76.lock); -mutex_lock (&dev->mt76.mutex);switch (wd->type) {case MT7615_WTBL_RATE_DESC :__mt7663u_mac_set_rates (dev, wd);
@@ -215,10 +216,10 @@ void mt7663u_wtbl_work(struct work_struct *work)__mt7663u_mac_set_key (dev, wd);break ; } -mutex_unlock (&dev->mt76.mutex); -kfree (wd); } + +mt7615_mutex_release (dev); } static void
@@ -257,9 +258,9 @@ static bool mt7663u_tx_status_data(struct mt76_dev *mdev, u8 *update) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); -mutex_lock (&dev->mt76.mutex); +mt7615_mutex_acquire (dev);mt7615_mac_sta_poll (dev); -mutex_unlock (&dev->mt76.mutex); +mt7615_mutex_release (dev);return 0 ; }
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 5/22 mt76: mt7615: wake device before accessing regmap in debugfs
In reply to Lorenzo BianconiMake sure the device is in full-power before reading regs in debugfs
--- .../wireless/mediatek/mt76/mt7615/debugfs.c | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +24 -1
@@ -6,11 +6,16 @@ static int mt7615_radar_pattern_set(void *data, u64 val) {struct mt7615_dev *dev = data; +int err;if (!mt7615_wait_for_mcu_init (dev))return 0 ; -return mt7615_mcu_rdd_send_pattern (dev); +mt7615_mutex_acquire (dev); + err =mt7615_mcu_rdd_send_pattern (dev); +mt7615_mutex_release (dev); + +return err; } DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,
@@ -84,7 +89,10 @@ mt7615_fw_debug_set(void *data, u64 val)return 0 ; dev->fw_debug = val; + +mt7615_mutex_acquire (dev);mt7615_mcu_fw_log_2_host (dev, dev->fw_debug ?2 :0 ); +mt7615_mutex_release (dev);return 0 ; }
@@ -111,6 +119,8 @@ mt7615_reset_test_set(void *data, u64 val)if (!mt7615_wait_for_mcu_init (dev))return 0 ; +mt7615_mutex_acquire (dev); + skb =alloc_skb (1 ,GFP_KERNEL );if (!skb)return -ENOMEM ;
@@ -118,6 +128,8 @@ mt7615_reset_test_set(void *data, u64 val)skb_put (skb,1 );mt76_tx_queue_skb_raw (dev,0 , skb,0 ); +mt7615_mutex_release (dev); +return 0 ; }
@@ -167,9 +179,13 @@ mt7615_ampdu_stat_read(struct seq_file *file, void *data) {struct mt7615_dev *dev = file->private; +mt7615_mutex_acquire (dev); +mt7615_ampdu_stat_read_phy (&dev->phy, file);mt7615_ampdu_stat_read_phy (mt7615_ext_phy (dev), file); +mt7615_mutex_release (dev); +return 0 ; }
@@ -221,7 +237,10 @@ static int mt7615_read_temperature(struct seq_file *s, void *data)return 0 ;/* cpu */ +mt7615_mutex_acquire (dev); temp =mt7615_mcu_get_temperature (dev,0 ); +mt7615_mutex_release (dev); +seq_printf (s,"Temperature: %d\n" , temp);return 0 ;
@@ -233,6 +252,8 @@ mt7615_queues_acq(struct seq_file *s, void *data)struct mt7615_dev *dev =dev_get_drvdata (s->private);int i; +mt7615_mutex_acquire (dev); +for (i =0 ; i <16 ; i++) {int j, wmm_idx = i %MT7615_MAX_WMM_SETS ;int acs = i /MT7615_MAX_WMM_SETS ;
@@ -253,6 +274,8 @@ mt7615_queues_acq(struct seq_file *s, void *data)seq_printf (s,"AC%d%d: queued=%d\n" , wmm_idx, acs, qlen); } +mt7615_mutex_release (dev); +return 0 ; }
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 6/22 mt76: mt7615: wake device before configuring hw keys
In reply to Lorenzo BianconiMake sure the device is in full-power before uploading keys to the hw
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +9 -3
@@ -336,7 +336,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta;struct mt76_wcid *wcid = &msta->wcid; -int idx = key->keyidx; +int idx = key->keyidx, err;/* The hardware does not support per-STA RX GTK, fallback * to software mode for these.
@@ -366,6 +366,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,return -EOPNOTSUPP ; } +mt7615_mutex_acquire (dev); +if (cmd ==SET_KEY ) { key->hw_key_idx = wcid->idx; wcid->hw_key_idx = idx;
@@ -376,9 +378,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, cmd == SET_KEY ? key : NULL);if (mt76_is_usb (&dev->mt76)) -return mt7615_queue_key_update (dev, cmd, msta, key); + err =mt7615_queue_key_update (dev, cmd, msta, key); +else + err =mt7615_mac_wtbl_set_key (dev, wcid, key, cmd); -return mt7615_mac_wtbl_set_key (dev, wcid, key, cmd); +mt7615_mutex_release (dev); + +return err; }static int mt7615_config (struct ieee80211_hw *hw,u32 changed)
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 7/22 mt76: mt7615: introduce pm_power_save delayed work
In reply to Lorenzo BianconiIntroduce runtime-pm power_save delayed work used to enable low-power after an inactivity period
--- .../net/wireless/mediatek/mt76/mt7615/init.c | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 27 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 3 +++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 6 ++++- 4 files changed, 36 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -0
@@ -445,6 +445,7 @@ void mt7615_init_device(struct mt7615_dev *dev) dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; +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);INIT_DELAYED_WORK (&dev->phy.mac_work, mt7615_mac_work);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +27 -0
@@ -1850,6 +1850,33 @@ int mt7615_pm_wake(struct mt7615_dev *dev) }EXPORT_SYMBOL_GPL (mt7615_pm_wake); +void mt7615_pm_power_save_sched (struct mt7615_dev *dev) +{ +struct mt76_phy *mphy = dev->phy.mt76; + +if (!mt7615_firmware_offload (dev) || !mt76_is_mmio (mphy->dev) || + !test_bit (MT76_STATE_RUNNING , &mphy->state)) +return ; + + dev->pm.last_activity = jiffies; +if (!test_bit (MT76_STATE_PM , &mphy->state)) +queue_delayed_work (dev->mt76.wq, &dev->pm.ps_work, +MT7615_PM_TIMEOUT ); +} +EXPORT_SYMBOL_GPL (mt7615_pm_power_save_sched); + +void mt7615_pm_power_save_work (struct work_struct *work) +{ +struct mt7615_dev *dev; + + dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev, + pm.ps_work.work); + +if (mt7615_firmware_own (dev)) +queue_delayed_work (dev->mt76.wq, &dev->pm.ps_work, +MT7615_PM_TIMEOUT ); +} +void mt7615_mac_work (struct work_struct *work) {struct mt7615_phy *phy;
drivers/net/wireless/mediatek/mt76/mt7615/main.c +3 -0
@@ -74,6 +74,7 @@ static void mt7615_stop(struct ieee80211_hw *hw)del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work); +cancel_delayed_work_sync (&dev->pm.ps_work);cancel_work_sync (&dev->pm.wake_work);mt7615_mutex_acquire (dev);
@@ -1003,6 +1004,8 @@ static int mt7615_suspend(struct ieee80211_hw *hw,bool ext_phy = phy != &dev->phy;int err =0 ; +cancel_delayed_work_sync (&dev->pm.ps_work); +mt7615_mutex_acquire (dev);clear_bit (MT76_STATE_RUNNING , &phy->mt76->state);
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +5 -1
@@ -19,6 +19,7 @@#define MT7615_WTBL_STA (MT7615_WTBL_RESERVED - \ MT7615_MAX_INTERFACES) +#define MT7615_PM_TIMEOUT (HZ / 12)#define MT7615_WATCHDOG_TIME (HZ / 10)#define MT7615_HW_SCAN_TIMEOUT (HZ / 10)#define MT7615_RESET_TIMEOUT (30 * HZ)
@@ -302,6 +303,7 @@ struct mt7615_dev {struct work_struct wake_work;struct completion wake_cmpl; +struct delayed_work ps_work;unsigned long last_activity; } pm; };
@@ -435,6 +437,8 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *rates);void mt7615_pm_wake_work (struct work_struct *work);int mt7615_pm_wake (struct mt7615_dev *dev); +void mt7615_pm_power_save_sched (struct mt7615_dev *dev); +void mt7615_pm_power_save_work (struct work_struct *work);int mt7615_mcu_del_wtbl_all (struct mt7615_dev *dev);int mt7615_mcu_set_chan_info (struct mt7615_phy *phy,int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue,
@@ -499,7 +503,7 @@ static inline void mt7615_mutex_acquire(struct mt7615_dev *dev)static inline void mt7615_mutex_release (struct mt7615_dev *dev) __releases(&dev->mt76.mutex) { - dev->pm.last_activity = jiffies; +mt7615_pm_power_save_sched (dev);mutex_unlock (&dev->mt76.mutex); }
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 8/22 mt76: mt7615: wake device in mt7615_update_channel before access regmap
In reply to Lorenzo BianconiIntroduce mt7615_update_survey utility routine in order to compute survey stats without waking up the device since it runs holding mt76 lock. Run mt7615_pm_wake directly in mt7615_update_channel since it can run with mt76.mutex held if called by mac80211
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 +-- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 30 +++++++++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +2 -2
@@ -560,8 +560,7 @@ mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c)return &msband->chan[idx]; } -static void -mt76_update_survey_active_time (struct mt76_phy *phy,ktime_t time) +void mt76_update_survey_active_time (struct mt76_phy *phy,ktime_t time) {struct mt76_channel_state *state = phy->chan_state;
@@ -569,6 +568,7 @@ mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) phy->survey_time)); phy->survey_time = time; } +EXPORT_SYMBOL_GPL (mt76_update_survey_active_time);void mt76_update_survey (struct mt76_dev *dev) {
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -893,6 +893,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,bool mt76_has_tx_pending (struct mt76_phy *phy);void mt76_set_channel (struct mt76_phy *phy);void mt76_update_survey (struct mt76_dev *dev); +void mt76_update_survey_active_time (struct mt76_phy *phy,ktime_t time);int mt76_get_survey (struct ieee80211_hw *hw,int idx,struct survey_info *survey);void mt76_set_stream_caps (struct mt76_phy *phy,bool vht);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +27 -3
@@ -1747,9 +1747,9 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) state->noise = -(phy->noise >>4 ); } -void mt7615_update_channel (struct mt76_dev *mdev) +static void __mt7615_update_channel (struct mt7615_dev *dev) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); +struct mt76_dev *mdev = &dev->mt76;mt7615_phy_update_channel (&mdev->phy,0 );if (mdev->phy2)
@@ -1758,8 +1758,32 @@ void mt7615_update_channel(struct mt76_dev *mdev)/* reset obss airtime */ mt76_set (dev,MT_WF_RMAC_MIB_TIME0 ,MT_WF_RMAC_MIB_RXTIME_CLR ); } + +void mt7615_update_channel (struct mt76_dev *mdev) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + +if (mt7615_pm_wake (dev)) +return ; + +__mt7615_update_channel (dev); +mt7615_pm_power_save_sched (dev); +}EXPORT_SYMBOL_GPL (mt7615_update_channel); +static void mt7615_update_survey (struct mt7615_dev *dev) +{ +struct mt76_dev *mdev = &dev->mt76; +ktime_t cur_time; + +__mt7615_update_channel (dev); + cur_time =ktime_get_boottime (); + +mt76_update_survey_active_time (&mdev->phy, cur_time); +if (mdev->phy2) +mt76_update_survey_active_time (mdev->phy2, cur_time); +} +static void mt7615_mac_update_mib_stats (struct mt7615_phy *phy) {
@@ -1888,7 +1912,7 @@ void mt7615_mac_work(struct work_struct *work)mt7615_mutex_acquire (phy->dev); -mt76_update_survey (mdev); +mt7615_update_survey (phy->dev);if (++phy->mac_work_count ==5 ) { phy->mac_work_count =0 ;
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 9/22 mt76: mt7615: acquire driver_own before configuring device for suspend
In reply to Lorenzo BianconiMake sure to wake the device in mt7615_pci_suspend in order to properly configure device registers before suspend
--- drivers/net/wireless/mediatek/mt76/mt7615/pci.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7615/pci.c +4 -0
@@ -75,6 +75,10 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)bool hif_suspend;int i, err; + err =mt7615_pm_wake (dev); +if (err <0 ) +return err; + hif_suspend = !test_bit (MT76_STATE_SUSPEND , &dev->mphy.state) &&mt7615_firmware_offload (dev);if (hif_suspend) {
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 10/22 mt76: mt7615: wake device before performing freq scan
In reply to Lorenzo BianconiSet device in full power before performing hw scan or hw scheduled scan
--- .../net/wireless/mediatek/mt76/mt7615/main.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +30 -4
@@ -915,17 +915,26 @@ static int mt7615_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { + struct mt7615_dev *dev = mt7615_hw_dev(hw);struct mt76_phy *mphy = hw->priv; +int err; -return mt7615_mcu_hw_scan (mphy->priv, vif, req); +mt7615_mutex_acquire (dev); + err =mt7615_mcu_hw_scan (mphy->priv, vif, req); +mt7615_mutex_release (dev); + +return err; }static void mt7615_cancel_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif) { +struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt76_phy *mphy = hw->priv; +mt7615_mutex_acquire (dev);mt7615_mcu_cancel_hw_scan (mphy->priv, vif); +mt7615_mutex_release (dev); } static int
@@ -933,22 +942,35 @@ mt7615_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,struct cfg80211_sched_scan_request *req, struct ieee80211_scan_ies *ies) { + struct mt7615_dev *dev = mt7615_hw_dev(hw);struct mt76_phy *mphy = hw->priv;int err; +mt7615_mutex_acquire (dev); + err =mt7615_mcu_sched_scan_req (mphy->priv, vif, req);if (err <0 ) -return err; + goto out; -return mt7615_mcu_sched_scan_enable (mphy->priv, vif, true); + err =mt7615_mcu_sched_scan_enable (mphy->priv, vif, true); +out: +mt7615_mutex_release (dev); + +return err; }static int mt7615_stop_sched_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif) { +struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt76_phy *mphy = hw->priv; +int err; + +mt7615_mutex_acquire (dev); + err =mt7615_mcu_sched_scan_enable (mphy->priv, vif, false); +mt7615_mutex_release (dev); -return mt7615_mcu_sched_scan_enable (mphy->priv, vif, false); +return err; } static int mt7615_remain_on_channel(struct ieee80211_hw *hw,
@@ -1074,7 +1096,11 @@ static void mt7615_set_rekey_data(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) { + struct mt7615_dev *dev = mt7615_hw_dev(hw); + +mt7615_mutex_acquire (dev);mt7615_mcu_update_gtk_rekey (hw, vif, data); +mt7615_mutex_release (dev); }#endif /* CONFIG_PM */
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 11/22 mt76: mt7615: add missing lock in mt7615_regd_notifier
In reply to Lorenzo BianconiMake sure to run mt7615_dfs_init_radar_detector in mt7615_regd_notifier holding mt76 mutex in order to avoid races and set the device in full power
--- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +2 -0
@@ -294,7 +294,9 @@ mt7615_regd_notifier(struct wiphy *wiphy,if (!(chandef->chan->flags &IEEE80211_CHAN_RADAR ))return ; +mt7615_mutex_acquire (dev);mt7615_dfs_init_radar_detector (phy); +mt7615_mutex_release (dev); } static void
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 12/22 mt76: mt7615: run mt7615_mcu_set_wmm holding mt76 mutex
In reply to Lorenzo BianconiMake sure to run mt7615_mcu_set_wmm() holding mt76 mutex in order to wake the device from low power state and avoid races
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +7 -1
@@ -433,11 +433,17 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, {struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;struct mt7615_dev *dev =mt7615_hw_dev (hw); +int err; + +mt7615_mutex_acquire (dev); queue =mt7615_lmac_mapping (dev, queue); queue += mvif->wmm_idx *MT7615_MAX_WMM_SETS ; + err =mt7615_mcu_set_wmm (dev, queue, params); -return mt7615_mcu_set_wmm (dev, queue, params); +mt7615_mutex_release (dev); + +return err; } static void mt7615_configure_filter(struct ieee80211_hw *hw,
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 13/22 mt76: mt7615: run mt7615_mcu_set_roc holding mt76 mutex
In reply to Lorenzo BianconiMake sure to run mt7615_mcu_set_roc() holding mt76 mutex in order to wake the device from low power state and avoid races
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +12 -4
@@ -871,9 +871,11 @@ void mt7615_roc_work(struct work_struct *work)if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state))return ; +mt7615_mutex_acquire (phy->dev);ieee80211_iterate_active_interfaces (phy->mt76->hw,IEEE80211_IFACE_ITER_RESUME_ALL , mt7615_roc_iter, phy); +mt7615_mutex_release (phy->dev);ieee80211_remain_on_channel_expired (phy->mt76->hw); }
@@ -991,20 +993,24 @@ static int mt7615_remain_on_channel(struct ieee80211_hw *hw,if (test_and_set_bit (MT76_STATE_ROC , &phy->mt76->state))return 0 ; +mt7615_mutex_acquire (phy->dev); + err =mt7615_mcu_set_roc (phy, vif, chan, duration);if (err <0 ) {clear_bit (MT76_STATE_ROC , &phy->mt76->state); -return err; + goto out; }if (!wait_event_timeout (phy->roc_wait, phy->roc_grant,HZ )) {mt7615_mcu_set_roc (phy, vif,NULL ,0 );clear_bit (MT76_STATE_ROC , &phy->mt76->state); - -return -ETIMEDOUT ; + err = -ETIMEDOUT ; } -return 0 ; +out: +mt7615_mutex_release (phy->dev); + +return err; } static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
@@ -1018,7 +1024,9 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,del_timer_sync (&phy->roc_timer);cancel_work_sync (&phy->roc_work); +mt7615_mutex_acquire (phy->dev);mt7615_mcu_set_roc (phy, vif,NULL ,0 ); +mt7615_mutex_release (phy->dev);return 0 ; }
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 14/22 mt76: mt7615: wake device before pulling packets from mac80211 queues
In reply to Lorenzo BianconiMake sure the device is in full-power before pulling frames from mac80211 queues
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 6 +++++- .../net/wireless/mediatek/mt76/mt7615/main.c | 20 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +5 -1
@@ -1841,9 +1841,13 @@ void mt7615_pm_wake_work(struct work_struct *work) pm.wake_work); mphy = dev->phy.mt76; -if (mt7615_driver_own (dev)) +if (mt7615_driver_own (dev)) {dev_err (mphy->dev->dev,"failed to wake device\n" ); + goto out; + } +tasklet_schedule (&dev->mt76.tx_tasklet); +out:complete_all (&dev->pm.wake_cmpl); }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +19 -1
@@ -638,6 +638,24 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,spin_unlock_bh (&dev->mt76.lock); } +static void +mt7615_wake_tx_queue (struct ieee80211_hw *hw,struct ieee80211_txq *txq) +{ +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 ; + +if (test_bit (MT76_STATE_PM , &mphy->state)) { +queue_work (dev->mt76.wq, &dev->pm.wake_work); +return ; + } + +tasklet_schedule (&dev->mt76.tx_tasklet); +} +static void mt7615_tx (struct ieee80211_hw *hw,struct ieee80211_tx_control *control,struct sk_buff *skb)
@@ -1134,7 +1152,7 @@ const struct ieee80211_ops mt7615_ops = { .set_key = mt7615_set_key, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, - .wake_tx_queue = mt76_wake_tx_queue, + .wake_tx_queue = mt7615_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,
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 15/22 mt76: mt7615: wake device before pushing frames in mt7615_tx
In reply to Lorenzo BianconiQueue 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
--- .../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(-)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -0
@@ -450,6 +450,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);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +24 -1
@@ -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 ; }
drivers/net/wireless/mediatek/mt76/mt7615/main.c +50 -6
102 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +6 -0
@@ -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;
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 16/22 mt76: mt7615: run mt7615_pm_wake in mt7615_mac_sta_{add, remove}
In reply to Lorenzo BianconiRun mt7615_pm_wake()/mt7615_pm_power_save_sched() directly in order to wake the device from low power state in mt7615_mac_sta_{add,remove} since they run holding mt76 mutex in common mt76 code
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +10 -1
@@ -583,7 +583,7 @@ int mt7615_mac_sta_add(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;struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; -int idx; +int idx, err; idx =mt76_wcid_alloc (dev->mt76.wcid_mask,MT7615_WTBL_STA -1 );if (idx <0 )
@@ -595,6 +595,10 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->wcid.idx = idx; msta->wcid.ext_phy = mvif->band_idx; + err =mt7615_pm_wake (dev); +if (err) +return err; +if (vif->type ==NL80211_IFTYPE_STATION && !sta->tdls) {struct mt7615_phy *phy;
@@ -605,6 +609,8 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);mt7615_mcu_sta_add (dev, vif, sta, true); +mt7615_pm_power_save_sched (dev); +return 0 ; }EXPORT_SYMBOL_GPL (mt7615_mac_sta_add);
@@ -616,6 +622,7 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;mt7615_free_pending_tx_skbs (dev, msta); +mt7615_pm_wake (dev);mt7615_mcu_sta_add (dev, vif, sta, false); mt7615_mac_wtbl_update(dev, msta->wcid.idx,
@@ -632,6 +639,8 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,if (!list_empty (&msta->poll_list))list_del_init (&msta->poll_list);spin_unlock_bh (&dev->sta_poll_lock); + +mt7615_pm_power_save_sched (dev); }EXPORT_SYMBOL_GPL (mt7615_mac_sta_remove);
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 17/22 mt76: mt7615: check MT76_STATE_PM flag before accessing the device
In reply to Lorenzo BianconiDouble-check if the device is in low-power state before accessing registermap in mt7615_sta_rate_tbl_update() and in mt7615_led_set_config()
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 6 ++++-- drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 -2
@@ -664,8 +664,10 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,break ; } msta->n_rates = i; -mt7615_mac_set_rates (phy, msta,NULL , msta->rates); - msta->rate_probe = false; +if (!test_bit (MT76_STATE_PM , &phy->mt76->state)) { +mt7615_mac_set_rates (phy, msta,NULL , msta->rates); + msta->rate_probe = false; + }spin_unlock_bh (&dev->mt76.lock); }
drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +4 -0
@@ -70,6 +70,10 @@ 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)) +return ; + val =FIELD_PREP (MT_LED_STATUS_DURATION ,0xffff ) |FIELD_PREP (MT_LED_STATUS_OFF , delay_off) |FIELD_PREP (MT_LED_STATUS_ON , delay_on);
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 18/22 mt76: mt7615: do not request {driver, fw}_own if already granted
In reply to Lorenzo BianconiCheck MT76_STATE_PM in mt7615_driver_own/mt7615_firmware_own in order to not requested power ownership if it is already granted
--- .../net/wireless/mediatek/mt76/mt7615/init.c | 1 + .../net/wireless/mediatek/mt76/mt7615/mcu.c | 21 ++++++++++--------- .../wireless/mediatek/mt76/mt7615/usb_mcu.c | 2 ++ 3 files changed, 14 insertions(+), 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -0
@@ -451,6 +451,7 @@ void mt7615_init_device(struct mt7615_dev *dev)INIT_WORK (&dev->pm.wake_work, mt7615_pm_wake_work);init_completion (&dev->pm.wake_cmpl);spin_lock_init (&dev->pm.txq_lock); +set_bit (MT76_STATE_PM , &dev->mphy.state);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);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +11 -10
@@ -1921,6 +1921,9 @@ int mt7615_driver_own(struct mt7615_dev *dev)int err =0 ;u32 addr; +if (!test_and_clear_bit (MT76_STATE_PM , &mphy->state)) + goto out; +mt7622_trigger_hif_int (dev, true); addr =is_mt7663 (mdev) ?MT_PCIE_DOORBELL_PUSH :MT_CFG_LPCR_HOST ;
@@ -1928,15 +1931,13 @@ int mt7615_driver_own(struct mt7615_dev *dev) addr =is_mt7663 (mdev) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ;if (!mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ,0 ,3000 )) { -dev_err (dev->mt76.dev,"Timeout for driver own\n" ); +dev_err (mdev->dev,"Timeout for driver own\n" ); +set_bit (MT76_STATE_PM , &mphy->state); err = -EIO ; - goto out; } -clear_bit (MT76_STATE_PM , &mphy->state); - -out:mt7622_trigger_hif_int (dev, false); +out: dev->pm.last_activity = jiffies;return err;
@@ -1949,22 +1950,22 @@ int mt7615_firmware_own(struct mt7615_dev *dev)int err =0 ;u32 addr; - addr =is_mt7663 (&dev->mt76) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ; +if (test_and_set_bit (MT76_STATE_PM , &mphy->state)) +return 0 ; +mt7622_trigger_hif_int (dev, true); + addr =is_mt7663 (&dev->mt76) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ;mt76_wr (dev, addr,MT_CFG_LPCR_HOST_FW_OWN );if (is_mt7622 (&dev->mt76) && !mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ,MT_CFG_LPCR_HOST_FW_OWN ,300 )) {dev_err (dev->mt76.dev,"Timeout for firmware own\n" ); +clear_bit (MT76_STATE_PM , &mphy->state); err = -EIO ; - goto out; } -set_bit (MT76_STATE_PM , &mphy->state); - -out:mt7622_trigger_hif_int (dev, false);return err;
drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c +2 -0
@@ -60,6 +60,8 @@ int mt7663u_mcu_init(struct mt7615_dev *dev) dev->mt76.mcu_ops = &mt7663u_mcu_ops, +/* usb does not support runtime-pm */ +clear_bit (MT76_STATE_PM , &dev->mphy.state);mt76_set (dev,MT_UDMA_TX_QSEL ,MT_FW_DL_EN );if (test_and_clear_bit (MT76_STATE_POWER_OFF , &dev->mphy.state)) {
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 19/22 mt76: mt7615: add runtime-pm knob in mt7615 debugfs
In reply to Lorenzo BianconiIntroduce runtime-pm knob in mt7615 debugfs in order to enable/disable runtime pm available in offload firmware
--- .../wireless/mediatek/mt76/mt7615/debugfs.c | 24 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mac.c | 20 +++++++++++++++- .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 +++ 3 files changed, 46 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +24 -0
@@ -51,6 +51,29 @@ mt7615_scs_get(void *data, u64 *val)DEFINE_DEBUGFS_ATTRIBUTE (fops_scs, mt7615_scs_get, mt7615_scs_set,"%lld\n" ); +static int +mt7615_pm_set (void *data,u64 val) +{ +struct mt7615_dev *dev = data; + +if (!mt7615_wait_for_mcu_init (dev)) +return 0 ; + +return mt7615_pm_set_enable (dev, val); +} + +static int +mt7615_pm_get (void *data,u64 *val) +{ +struct mt7615_dev *dev = data; + + *val = dev->pm.enable; + +return 0 ; +} + +DEFINE_DEBUGFS_ATTRIBUTE (fops_pm, mt7615_pm_get, mt7615_pm_set,"%lld\n" ); +static int mt7615_dbdc_set (void *data,u64 val) {
@@ -351,6 +374,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)debugfs_create_file ("scs" ,0600 , dir, dev, &fops_scs);debugfs_create_file ("dbdc" ,0600 , dir, dev, &fops_dbdc);debugfs_create_file ("fw_debug" ,0600 , dir, dev, &fops_fw_debug); +debugfs_create_file ("runtime-pm" ,0600 , dir, dev, &fops_pm);debugfs_create_devm_seqfile (dev->mt76.dev,"radio" , dir, mt7615_radio_read);debugfs_create_u32 ("dfs_hw_pattern" ,0400 , dir, &dev->hw_pattern);
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +19 -1
@@ -1905,7 +1905,8 @@ void mt7615_pm_power_save_sched(struct mt7615_dev *dev) {struct mt76_phy *mphy = dev->phy.mt76; -if (!mt7615_firmware_offload (dev) || !mt76_is_mmio (mphy->dev) || +if (!mt7615_firmware_offload (dev) || + !dev->pm.enable || !mt76_is_mmio (mphy->dev) || !test_bit (MT76_STATE_RUNNING , &mphy->state))return ;
@@ -1928,6 +1929,23 @@ void mt7615_pm_power_save_work(struct work_struct *work) MT7615_PM_TIMEOUT); } +int mt7615_pm_set_enable (struct mt7615_dev *dev,bool enable) +{ +if (!mt7615_firmware_offload (dev) || !mt76_is_mmio (&dev->mt76)) +return -EOPNOTSUPP ; + +mt7615_mutex_acquire (dev); + +if (dev->pm.enable == enable) + goto out; + + dev->pm.enable = enable; +out: +mt7615_mutex_release (dev); + +return 0 ; +} +void mt7615_mac_work (struct work_struct *work) {struct mt7615_phy *phy;
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +3 -0
@@ -300,6 +300,8 @@ struct mt7615_dev {#endif struct { +bool enable; +spinlock_t txq_lock;struct {struct mt7615_sta *msta;
@@ -441,6 +443,7 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);void mt7615_mac_set_rates (struct mt7615_phy *phy,struct mt7615_sta *sta,struct ieee80211_tx_rate *probe_rate,struct ieee80211_tx_rate *rates); +int mt7615_pm_set_enable (struct mt7615_dev *dev,bool enable);void mt7615_pm_wake_work (struct work_struct *work);int mt7615_pm_wake (struct mt7615_dev *dev);void mt7615_pm_power_save_sched (struct mt7615_dev *dev);
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 20/22 mt76: mt7615: enable beacon hw filter for runtime-pm
In reply to Lorenzo BianconiIn order to reduce number of received interrupts and power consumption, enable hw beacon filter if runtime-pm is enabled
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 26 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 19 ++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 5 ++-- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 ++ 4 files changed, 49 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +26 -0
@@ -1929,8 +1929,31 @@ void mt7615_pm_power_save_work(struct work_struct *work) MT7615_PM_TIMEOUT); } +static void +mt7615_pm_interface_iter (void *priv,u8 *mac,struct ieee80211_vif *vif) +{ +struct mt7615_phy *phy = priv; +struct mt7615_dev *dev = phy->dev; +bool ext_phy = phy != &dev->phy; + +if (mt7615_mcu_set_bss_pm (dev, vif, dev->pm.enable)) +return ; + +if (dev->pm.enable) { + vif->driver_flags |=IEEE80211_VIF_BEACON_FILTER ; +mt76_set (dev,MT_WF_RFCR (ext_phy), +MT_WF_RFCR_DROP_OTHER_BEACON ); + }else { + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER ; +mt76_clear (dev,MT_WF_RFCR (ext_phy), +MT_WF_RFCR_DROP_OTHER_BEACON ); + } +} +int mt7615_pm_set_enable (struct mt7615_dev *dev,bool enable) { +struct mt76_phy *mphy = dev->phy.mt76; +if (!mt7615_firmware_offload (dev) || !mt76_is_mmio (&dev->mt76))return -EOPNOTSUPP ;
@@ -1940,6 +1963,9 @@ int mt7615_pm_set_enable(struct mt7615_dev *dev, bool enable) goto out; dev->pm.enable = enable; +ieee80211_iterate_active_interfaces (mphy->hw, +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7615_pm_interface_iter, mphy->priv); out:mt7615_mutex_release (dev);
drivers/net/wireless/mediatek/mt76/mt7615/main.c +19 -0
@@ -209,6 +209,18 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, } ret =mt7615_mcu_add_dev_info (dev, vif, true); +if (ret) + goto out; + +if (dev->pm.enable) { + ret =mt7615_mcu_set_bss_pm (dev, vif, true); +if (ret) + goto out; + + vif->driver_flags |=IEEE80211_VIF_BEACON_FILTER ; +mt76_set (dev,MT_WF_RFCR (ext_phy), +MT_WF_RFCR_DROP_OTHER_BEACON ); + } out:mt7615_mutex_release (dev);
@@ -234,6 +246,13 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,mt7615_free_pending_tx_skbs (dev, msta); +if (dev->pm.enable) { +bool ext_phy = phy != &dev->phy; + +mt7615_mcu_set_bss_pm (dev, vif, false); +mt76_clear (dev,MT_WF_RFCR (ext_phy), +MT_WF_RFCR_DROP_OTHER_BEACON ); + }mt7615_mcu_add_dev_info (dev, vif, false);rcu_assign_pointer (dev->mt76.wcid[idx],NULL );
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +2 -3
@@ -3581,9 +3581,8 @@ int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend) }EXPORT_SYMBOL_GPL (mt7615_mcu_set_hif_suspend); -static int -mt7615_mcu_set_bss_pm (struct mt7615_dev *dev,struct ieee80211_vif *vif, -bool enable) +int mt7615_mcu_set_bss_pm (struct mt7615_dev *dev,struct ieee80211_vif *vif, +bool enable) {struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;struct {
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 -0
@@ -640,6 +640,8 @@ int mt7615_driver_own(struct mt7615_dev *dev);int mt7615_init_debugfs (struct mt7615_dev *dev);int mt7615_mcu_wait_response (struct mt7615_dev *dev,int cmd,int seq); +int mt7615_mcu_set_bss_pm (struct mt7615_dev *dev,struct ieee80211_vif *vif, +bool enable);int mt7615_mcu_set_hif_suspend (struct mt7615_dev *dev,bool suspend);void mt7615_mcu_set_suspend_iter (void *priv,u8 *mac,struct ieee80211_vif *vif);
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 21/22 mt76: mt7615: add idle-timeout knob in mt7615 debugfs
In reply to Lorenzo BianconiIntroduce idle-timeout knob in mt7615 debugfs in order to configure the idle time to switch to low-power state
--- .../wireless/mediatek/mt76/mt7615/debugfs.c | 25 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/init.c | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 4 +-- .../wireless/mediatek/mt76/mt7615/mt7615.h | 1 + 4 files changed, 29 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +25 -0
@@ -74,6 +74,29 @@ mt7615_pm_get(void *data, u64 *val)DEFINE_DEBUGFS_ATTRIBUTE (fops_pm, mt7615_pm_get, mt7615_pm_set,"%lld\n" ); +static int +mt7615_pm_idle_timeout_set (void *data,u64 val) +{ +struct mt7615_dev *dev = data; + + dev->pm.idle_timeout =msecs_to_jiffies (val); + +return 0 ; +} + +static int +mt7615_pm_idle_timeout_get (void *data,u64 *val) +{ +struct mt7615_dev *dev = data; + + *val =jiffies_to_msecs (dev->pm.idle_timeout); + +return 0 ; +} + +DEFINE_DEBUGFS_ATTRIBUTE (fops_pm_idle_timeout, mt7615_pm_idle_timeout_get, + mt7615_pm_idle_timeout_set,"%lld\n" ); +static int mt7615_dbdc_set (void *data,u64 val) {
@@ -375,6 +398,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)debugfs_create_file ("dbdc" ,0600 , dir, dev, &fops_dbdc);debugfs_create_file ("fw_debug" ,0600 , dir, dev, &fops_fw_debug);debugfs_create_file ("runtime-pm" ,0600 , dir, dev, &fops_pm); +debugfs_create_file ("idle-timeout" ,0600 , dir, dev, + &fops_pm_idle_timeout);debugfs_create_devm_seqfile (dev->mt76.dev,"radio" , dir, mt7615_radio_read);debugfs_create_u32 ("dfs_hw_pattern" ,0400 , dir, &dev->hw_pattern);
drivers/net/wireless/mediatek/mt76/mt7615/init.c +1 -0
@@ -465,6 +465,7 @@ void mt7615_init_device(struct mt7615_dev *dev)timer_setup (&dev->phy.roc_timer, mt7615_roc_timer,0 );mt7615_init_wiphy (hw); + dev->pm.idle_timeout =MT7615_PM_TIMEOUT ; dev->mphy.sband_2g.sband.ht_cap.cap |=IEEE80211_HT_CAP_LDPC_CODING ; dev->mphy.sband_5g.sband.ht_cap.cap |=IEEE80211_HT_CAP_LDPC_CODING ; dev->mphy.sband_5g.sband.vht_cap.cap |=
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +2 -2
@@ -1913,7 +1913,7 @@ void mt7615_pm_power_save_sched(struct mt7615_dev *dev) dev->pm.last_activity = jiffies;if (!test_bit (MT76_STATE_PM , &mphy->state))queue_delayed_work (dev->mt76.wq, &dev->pm.ps_work, -MT7615_PM_TIMEOUT ); + dev->pm.idle_timeout); }EXPORT_SYMBOL_GPL (mt7615_pm_power_save_sched);
@@ -1926,7 +1926,7 @@ void mt7615_pm_power_save_work(struct work_struct *work)if (mt7615_firmware_own (dev))queue_delayed_work (dev->mt76.wq, &dev->pm.ps_work, -MT7615_PM_TIMEOUT ); + dev->pm.idle_timeout); } static void
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +1 -0
@@ -313,6 +313,7 @@ struct mt7615_dev {struct delayed_work ps_work;unsigned long last_activity; +unsigned long idle_timeout; } pm; };
Signature · 1 line
2.26.2
Lorenzo Bianconi
maintainerPATCH v2 22/22 mt76: mt7615: improve mt7615_driver_own reliability
In reply to Lorenzo Bianconimt7615_driver_own can fail if it runs too close to mt7615_fw_own. In order to improve mt7615_driver_own reliability, retry to get runtime-pm ownership if mt7615_driver_own fails
--- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 27 ++++++++++++------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 ++ 2 files changed, 19 insertions(+), 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +17 -10
@@ -1918,29 +1918,36 @@ int mt7615_driver_own(struct mt7615_dev *dev) {struct mt76_phy *mphy = &dev->mt76.phy;struct mt76_dev *mdev = &dev->mt76; -int err =0 ; -u32 addr; +int i;if (!test_and_clear_bit (MT76_STATE_PM , &mphy->state)) goto out;mt7622_trigger_hif_int (dev, true); - addr =is_mt7663 (mdev) ?MT_PCIE_DOORBELL_PUSH :MT_CFG_LPCR_HOST ; -mt76_wr (dev, addr,MT_CFG_LPCR_HOST_DRV_OWN ); +for (i =0 ; i <MT7615_DRV_OWN_RETRY_COUNT ; i++) { +u32 addr; - addr =is_mt7663 (mdev) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ; -if (!mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ,0 ,3000 )) { -dev_err (mdev->dev,"Timeout for driver own\n" ); -set_bit (MT76_STATE_PM , &mphy->state); - err = -EIO ; + addr =is_mt7663 (mdev) ?MT_PCIE_DOORBELL_PUSH :MT_CFG_LPCR_HOST ; +mt76_wr (dev, addr,MT_CFG_LPCR_HOST_DRV_OWN ); + + addr =is_mt7663 (mdev) ?MT_CONN_HIF_ON_LPCTL :MT_CFG_LPCR_HOST ; +if (mt76_poll_msec (dev, addr,MT_CFG_LPCR_HOST_FW_OWN ,0 ,50 )) +break ; }mt7622_trigger_hif_int (dev, false); + +if (i ==MT7615_DRV_OWN_RETRY_COUNT ) { +dev_err (mdev->dev,"driver own failed\n" ); +set_bit (MT76_STATE_PM , &mphy->state); +return -EIO ; + } + out: dev->pm.last_activity = jiffies; -return err; +return 0 ; }EXPORT_SYMBOL_GPL (mt7615_driver_own);
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 -0
@@ -33,6 +33,8 @@#define MT7615_RX_RING_SIZE 1024#define MT7615_RX_MCU_RING_SIZE 512 +#define MT7615_DRV_OWN_RETRY_COUNT 10 +#define MT7615_FIRMWARE_CR4 "mediatek/mt7615_cr4.bin"#define MT7615_FIRMWARE_N9 "mediatek/mt7615_n9.bin"#define MT7615_ROM_PATCH "mediatek/mt7615_rom_patch.bin"
Signature · 1 line
2.26.2