ath11k: suspend support for QCA6390 PCI
cover ath11k: suspend support for QCA6390 PCI
Here is suspend support for QCA6390 PCI devices. For suspend we switch firmware to WoW mode and keep the firmware running. At the moment we are not able to shutdown and fully power off the device due to bugs in MHI subsystem, so WoW mode is a workaround for the time being.
This patchset depends on patchset:
ath11k: QCA6390 stability fixes
https://patchwork.kernel.org/project/linux-wireless/list/?series=399797
Please review.
Kalle
Carl Huang (9):
ath11k: mhi: hook suspend and resume
ath11k: hif: implement suspend and resume functions
ath11k: pci: read select_window register to ensure write is finished
ath11k: htc: implement suspend handling
ath11k: dp: stop rx pktlog before suspend
ath11k: set credit_update flag for flow controlled ep only
ath11k: implement WoW enable and wakeup commands
ath11k: hif: add ce irq enable and disable functions
ath11k: implement suspend for QCA6390 PCI devices
Kalle Valo (1):
ath11k: htc: remove unused struct ath11k_htc_ops
drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/ce.c | 2 +- drivers/net/wireless/ath/ath11k/ce.h | 2 + drivers/net/wireless/ath/ath11k/core.c | 88 +++++++++++++++++ drivers/net/wireless/ath/ath11k/core.h | 11 +++ drivers/net/wireless/ath/ath11k/dp.c | 2 +- drivers/net/wireless/ath/ath11k/dp.h | 2 + drivers/net/wireless/ath/ath11k/dp_rx.c | 48 +++++++++ drivers/net/wireless/ath/ath11k/dp_rx.h | 3 + drivers/net/wireless/ath/ath11k/hif.h | 32 ++++++ drivers/net/wireless/ath/ath11k/htc.c | 31 +++++- drivers/net/wireless/ath/ath11k/htc.h | 10 +- drivers/net/wireless/ath/ath11k/hw.h | 1 + drivers/net/wireless/ath/ath11k/mac.c | 4 + drivers/net/wireless/ath/ath11k/mhi.c | 11 +++ drivers/net/wireless/ath/ath11k/mhi.h | 3 + drivers/net/wireless/ath/ath11k/pci.c | 71 ++++++++++++- drivers/net/wireless/ath/ath11k/wmi.c | 99 +++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 165 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wow.c | 73 ++++++++++++++ drivers/net/wireless/ath/ath11k/wow.h | 10 ++ 21 files changed, 656 insertions(+), 15 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/wow.c create mode 100644 drivers/net/wireless/ath/ath11k/wow.h
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 1/10 ath11k: mhi: hook suspend and resume
From: Carl Huang <[email protected]>
MHI suspend and resume isn't hooked in ath11k yet, so hook these functions needed for suspend support.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/mhi.c | 11 +++++++++++ drivers/net/wireless/ath/ath11k/mhi.h | 3 +++ 2 files changed, 14 insertions(+)
drivers/net/wireless/ath/ath11k/mhi.c +11 -0
@@ -418,8 +418,10 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, ret =0 ;break ;case ATH11K_MHI_SUSPEND : + ret =mhi_pm_suspend (ab_pci->mhi_ctrl);break ;case ATH11K_MHI_RESUME : + ret =mhi_pm_resume (ab_pci->mhi_ctrl);break ;case ATH11K_MHI_TRIGGER_RDDM : ret =mhi_force_rddm_mode (ab_pci->mhi_ctrl);
@@ -470,3 +472,12 @@ void ath11k_mhi_stop(struct ath11k_pci *ab_pci)ath11k_mhi_set_state (ab_pci,ATH11K_MHI_DEINIT ); } +void ath11k_mhi_suspend (struct ath11k_pci *ab_pci) +{ +ath11k_mhi_set_state (ab_pci,ATH11K_MHI_SUSPEND ); +} + +void ath11k_mhi_resume (struct ath11k_pci *ab_pci) +{ +ath11k_mhi_set_state (ab_pci,ATH11K_MHI_RESUME ); +}
drivers/net/wireless/ath/ath11k/mhi.h +3 -0
@@ -36,4 +36,7 @@ void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);void ath11k_mhi_set_mhictrl_reset (struct ath11k_base *ab);void ath11k_mhi_clear_vector (struct ath11k_base *ab); +void ath11k_mhi_suspend (struct ath11k_pci *ar_pci); +void ath11k_mhi_resume (struct ath11k_pci *ar_pci); +#endif
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
Re: [PATCH 01/10] ath11k: mhi: hook suspend and resume
Quoted 7 lines · Kalle Valo
MHI suspend and resume isn't hooked in ath11k yet, so hook these functions needed for suspend support.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Signed-off-by Carl Huang <[email protected]>Signed-off-by Kalle Valo <[email protected]>
10 patches applied to ath-next branch of ath.git, thanks.
34fb81e4eb92 ath11k: mhi: hook suspend and resumefa5917e44ee8 ath11k: hif: implement suspend and resume functions f6fa37a4928f ath11k: pci: read select_window register to ensure write is finished d50370c953bc ath11k: htc: remove unused struct ath11k_htc_ops 8733d835ec43 ath11k: htc: implement suspend handling840c36fa727a ath11k: dp: stop rx pktlog before suspend2151ffde188a ath11k: set credit_update flag for flow controlled ep only 79802b13a492 ath11k: implement WoW enable and wakeup commands d578ec2a0d5c ath11k: hif: add ce irq enable and disable functions d1b0c33850d2 ath11k: implement suspend for QCA6390 PCI devices
Signature · 9 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
Re: [PATCH 01/10] ath11k: mhi: hook suspend and resume
In reply to Kalle ValoQuoted 7 lines · Kalle Valo
MHI suspend and resume isn't hooked in ath11k yet, so hook these functions needed for suspend support.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Signed-off-by Carl Huang <[email protected]>Signed-off-by Kalle Valo <[email protected]>
10 patches applied to ath-next branch of ath.git, thanks.
34fb81e4eb92 ath11k: mhi: hook suspend and resumefa5917e44ee8 ath11k: hif: implement suspend and resume functions f6fa37a4928f ath11k: pci: read select_window register to ensure write is finished d50370c953bc ath11k: htc: remove unused struct ath11k_htc_ops 8733d835ec43 ath11k: htc: implement suspend handling840c36fa727a ath11k: dp: stop rx pktlog before suspend2151ffde188a ath11k: set credit_update flag for flow controlled ep only 79802b13a492 ath11k: implement WoW enable and wakeup commands d578ec2a0d5c ath11k: hif: add ce irq enable and disable functions d1b0c33850d2 ath11k: implement suspend for QCA6390 PCI devices
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
PATCH 2/10 ath11k: hif: implement suspend and resume functions
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
For suspend support add suspend and resume to HIF layer. These ops are optional and, for example, AHB bus driver does not need to implement these.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/hif.h | 18 ++++++++++++++++++ drivers/net/wireless/ath/ath11k/pci.c | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+)
drivers/net/wireless/ath/ath11k/hif.h +18 -0
@@ -17,6 +17,8 @@ struct ath11k_hif_ops {void (*stop)(struct ath11k_base *sc);int (*power_up)(struct ath11k_base *sc);void (*power_down)(struct ath11k_base *sc); +int (*suspend)(struct ath11k_base *ab); +int (*resume)(struct ath11k_base *ab);int (*map_service_to_pipe)(struct ath11k_base *sc,u16 service_id,u8 *ul_pipe,u8 *dl_pipe); int (*get_user_msi_vector)(struct ath11k_base *ab, char *user_name,
@@ -56,6 +58,22 @@ static inline void ath11k_hif_power_down(struct ath11k_base *sc) sc->hif.ops->power_down (sc); } +static inline int ath11k_hif_suspend (struct ath11k_base *ab) +{ +if (ab->hif.ops->suspend) +return ab->hif.ops->suspend (ab); + +return 0 ; +} + +static inline int ath11k_hif_resume (struct ath11k_base *ab) +{ +if (ab->hif.ops->resume) +return ab->hif.ops->resume (ab); + +return 0 ; +} +static inline u32 ath11k_hif_read32 (struct ath11k_base *sc,u32 address) {return sc->hif.ops->read32 (sc, address);
drivers/net/wireless/ath/ath11k/pci.c +20 -0
@@ -913,6 +913,24 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)ath11k_pci_sw_reset (ab_pci->ab, false); } +static int ath11k_pci_hif_suspend (struct ath11k_base *ab) +{ +struct ath11k_pci *ar_pci =ath11k_pci_priv (ab); + +ath11k_mhi_suspend (ar_pci); + +return 0 ; +} + +static int ath11k_pci_hif_resume (struct ath11k_base *ab) +{ +struct ath11k_pci *ar_pci =ath11k_pci_priv (ab); + +ath11k_mhi_resume (ar_pci); + +return 0 ; +} +static void ath11k_pci_kill_tasklets (struct ath11k_base *ab) {int i;
@@ -997,6 +1015,8 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = { .write32 = ath11k_pci_write32, .power_down = ath11k_pci_power_down, .power_up = ath11k_pci_power_up, + .suspend = ath11k_pci_hif_suspend, + .resume = ath11k_pci_hif_resume, .irq_enable = ath11k_pci_ext_irq_enable, .irq_disable = ath11k_pci_ext_irq_disable, .get_msi_address = ath11k_pci_get_msi_address,
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 3/10 ath11k: pci: read select_window register to ensure write is finished
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Just when resume from WoW, the write to select_window doesn't take effect immediately, so read the register again to ensure the write operation is finished.
Another change is to reset select_window to ZERO because this register isn't restored after WoW, so the content of this register becomes ZERO too.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/pci.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/ath/ath11k/pci.c +1 -0
@@ -126,6 +126,7 @@ static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offseif (window != ab_pci->register_window) {iowrite32 (WINDOW_ENABLE_BIT | window, ab->mem +WINDOW_REG_ADDRESS ); +ioread32 (ab->mem +WINDOW_REG_ADDRESS ); ab_pci->register_window = window; } }
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 4/10 ath11k: htc: remove unused struct ath11k_htc_ops
In reply to Kalle ValoNo need for it so remove. Compile tested only.
--- drivers/net/wireless/ath/ath11k/htc.h | 6 ------ 1 file changed, 6 deletions(-)
drivers/net/wireless/ath/ath11k/htc.h +0 -6
@@ -221,10 +221,6 @@ enum ath11k_htc_ep_id { ATH11K_HTC_EP_COUNT, }; -struct ath11k_htc_ops { -void (*target_send_suspend_complete)(struct ath11k_base *ar); -}; -struct ath11k_htc_ep_ops {void (*ep_tx_complete)(struct ath11k_base *,struct sk_buff *);void (*ep_rx_complete)(struct ath11k_base *,struct sk_buff *);
@@ -284,8 +280,6 @@ struct ath11k_htc {/* protects endpoints */ spinlock_t tx_lock; -struct ath11k_htc_ops htc_ops; -u8 control_resp_buffer[ATH11K_HTC_MAX_CTRL_MSG_LEN ];int control_resp_len;
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 5/10 ath11k: htc: implement suspend handling
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
When ath11k sends suspend command to firmware, firmware will return suspend_complete events and add handlers for those.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/core.c | 2 ++ drivers/net/wireless/ath/ath11k/core.h | 4 ++++ drivers/net/wireless/ath/ath11k/htc.c | 23 ++++++++++++++++++++++- drivers/net/wireless/ath/ath11k/htc.h | 4 +++- 4 files changed, 31 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/core.c +2 -0
@@ -968,6 +968,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,init_waitqueue_head (&ab->qmi.cold_boot_waitq);INIT_WORK (&ab->restart_work, ath11k_core_restart);timer_setup (&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry,0 ); +init_completion (&ab->htc_suspend); + ab->dev = dev; ab->bus_params = *bus_params; ab->hif.bus = bus;
drivers/net/wireless/ath/ath11k/core.h +4 -0
@@ -186,6 +186,7 @@ enum ath11k_dev_flags {ATH11K_FLAG_UNREGISTERING ,ATH11K_FLAG_REGISTERED ,ATH11K_FLAG_QMI_FAIL , + ATH11K_FLAG_HTC_SUSPEND_COMPLETE, }; enum ath11k_monitor_flags {
@@ -732,6 +733,9 @@ struct ath11k_base {u32 num_db_cap;struct timer_list mon_reap_timer; + +struct completion htc_suspend; +/* must be last */ u8 drv_priv[0 ]__aligned(sizeof(void *)) ; };
drivers/net/wireless/ath/ath11k/htc.c +22 -1
@@ -231,6 +231,18 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc,return status; } +static void ath11k_htc_suspend_complete (struct ath11k_base *ab,bool ack) +{ +ath11k_dbg (ab,ATH11K_DBG_BOOT ,"boot suspend complete %d\n" , ack); + +if (ack) +set_bit (ATH11K_FLAG_HTC_SUSPEND_COMPLETE , &ab->dev_flags); +else +clear_bit (ATH11K_FLAG_HTC_SUSPEND_COMPLETE , &ab->dev_flags); + +complete (&ab->htc_suspend); +} +void ath11k_htc_rx_completion_handler (struct ath11k_base *ab,struct sk_buff *skb) {
@@ -328,8 +340,17 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,complete (&htc->ctl_resp);break ; +case ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE : +ath11k_htc_suspend_complete (ab, true); +break ; +case ATH11K_HTC_MSG_NACK_SUSPEND : +ath11k_htc_suspend_complete (ab, false); +break ; +case ATH11K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID : +break ;default : -ath11k_warn (ab,"ignoring unsolicited htc ep0 event\n" ); +ath11k_warn (ab,"ignoring unsolicited htc ep0 event %ld\n" , +FIELD_GET (HTC_MSG_MESSAGEID , msg->msg_svc_id));break ; } goto out;
drivers/net/wireless/ath/ath11k/htc.h +3 -1
@@ -65,7 +65,9 @@ enum ath11k_htc_msg_id {ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID =3 ,ATH11K_HTC_MSG_SETUP_COMPLETE_ID =4 ,ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID =5 , -ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE =6 +ATH11K_HTC_MSG_SEND_SUSPEND_COMPLETE =6 , +ATH11K_HTC_MSG_NACK_SUSPEND =7 , + ATH11K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID = 8, }; enum ath11k_htc_version {
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 6/10 ath11k: dp: stop rx pktlog before suspend
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Stop dp rx pktlog when entering suspend and reap the mon_status buffer to keep it empty. During resume restart the reap timer.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/dp.h | 1 + drivers/net/wireless/ath/ath11k/dp_rx.c | 48 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/dp_rx.h | 3 +++ drivers/net/wireless/ath/ath11k/mac.c | 4 +++ 4 files changed, 56 insertions(+)
drivers/net/wireless/ath/ath11k/dp.h +1 -0
@@ -40,6 +40,7 @@ struct dp_rx_tid {#define DP_REO_DESC_FREE_THRESHOLD 64#define DP_REO_DESC_FREE_TIMEOUT_MS 1000 +#define DP_MON_PURGE_TIMEOUT_MS 100#define DP_MON_SERVICE_BUDGET 128struct dp_reo_cache_flush_elem {
drivers/net/wireless/ath/ath11k/dp_rx.c +48 -0
57 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/dp_rx.h +3 -0
@@ -91,4 +91,7 @@ int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);int ath11k_dp_rx_pdev_mon_attach (struct ath11k *ar);int ath11k_peer_rx_frag_setup (struct ath11k *ar,const u8 *peer_mac,int vdev_id); +int ath11k_dp_rx_pktlog_start (struct ath11k_base *ab); +int ath11k_dp_rx_pktlog_stop (struct ath11k_base *ab,bool stop_timer); +#endif /* ATH11K_DP_RX_H */
drivers/net/wireless/ath/ath11k/mac.c +4 -0
@@ -4146,6 +4146,10 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable) &tlv_filter); } +if (enable && !ar->ab->hw_params.rxdma1_enable) +mod_timer (&ar->ab->mon_reap_timer, jiffies + +msecs_to_jiffies (ATH11K_MON_TIMER_INTERVAL )); +return ret; }
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 7/10 ath11k: set credit_update flag for flow controlled ep only
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Firmware will check all the pipes before entering WoW mode during suspend. If ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE is set, firmware treats this pipe needed to return credit even though it's actually not required. If any pipe needs to return credit, the suspend_complete message doesn't send to host but is dropped. So host gets time out and WoW suspend failed.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/htc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath11k/htc.c +5 -3
@@ -60,9 +60,11 @@ static void ath11k_htc_prepare_tx_skb(struct ath11k_htc_ep *ep,memset (hdr,0 ,sizeof (*hdr)); hdr->htc_info =FIELD_PREP (HTC_HDR_ENDPOINTID , ep->eid) |FIELD_PREP (HTC_HDR_PAYLOADLEN , - (skb->len -sizeof (*hdr))) | -FIELD_PREP (HTC_HDR_FLAGS , -ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE ); + (skb->len -sizeof (*hdr))); + +if (ep->tx_credit_flow_enabled) + hdr->htc_info |=FIELD_PREP (HTC_HDR_FLAGS , +ATH11K_HTC_FLAG_NEED_CREDIT_UPDATE );spin_lock_bh (&ep->htc->tx_lock); hdr->ctrl_info =FIELD_PREP (HTC_HDR_CONTROLBYTES1 , ep->seq_no++);
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 8/10 ath11k: implement WoW enable and wakeup commands
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Implement wow enable ane wow wakeup commands which are needed for suspend.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/core.c | 1 + drivers/net/wireless/ath/ath11k/core.h | 5 + drivers/net/wireless/ath/ath11k/wmi.c | 99 +++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 165 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wow.c | 73 ++++++++++++++ drivers/net/wireless/ath/ath11k/wow.h | 10 ++ 7 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath11k/wow.c create mode 100644 drivers/net/wireless/ath/ath11k/wow.h
drivers/net/wireless/ath/ath11k/Makefile +2 -1
@@ -16,7 +16,8 @@ ath11k-y += core.o \ ce.o \ peer.o \ dbring.o \ - hw.o + hw.o \ + wow.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
drivers/net/wireless/ath/ath11k/core.c +1 -0
@@ -969,6 +969,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,INIT_WORK (&ab->restart_work, ath11k_core_restart);timer_setup (&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry,0 );init_completion (&ab->htc_suspend); +init_completion (&ab->wow.wakeup_completed); ab->dev = dev; ab->bus_params = *bus_params;
drivers/net/wireless/ath/ath11k/core.h +5 -0
@@ -466,6 +466,7 @@ struct ath11k {struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS ][NUM_NL80211_IFTYPES ]; } mac; +unsigned long dev_flags;unsigned int filter_flags;unsigned long monitor_flags;
@@ -672,6 +673,10 @@ struct ath11k_base {const struct ath11k_hif_ops *ops; } hif; +struct { +struct completion wakeup_completed; + } wow; +struct ath11k_ce ce;struct timer_list rx_replenish_retry;struct ath11k_hal hal;
drivers/net/wireless/ath/ath11k/wmi.c +99 -0
114 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wmi.h +165 -0
176 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wow.c new file +73 -0
73 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wow.h new file +10 -0
@@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* +* Copyright (c) 2020 The Linux Foundation. All rights reserved. +*/ + +#define ATH11K_WOW_RETRY_NUM 3 +#define ATH11K_WOW_RETRY_WAIT_MS 200 + +int ath11k_wow_enable (struct ath11k_base *ab); +int ath11k_wow_wakeup (struct ath11k_base *ab);
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 9/10 ath11k: hif: add ce irq enable and disable functions
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Add ce irq enable and disable hif layer functions, so core module can enable enable them without cleaning pipe and refilling pipe. Needed for suspend.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/hif.h | 14 ++++++++++++++ drivers/net/wireless/ath/ath11k/pci.c | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ath11k/hif.h +14 -0
@@ -26,8 +26,22 @@ struct ath11k_hif_ops { u32 *base_vector);void (*get_msi_address)(struct ath11k_base *ab,u32 *msi_addr_lo,u32 *msi_addr_hi); +void (*ce_irq_enable)(struct ath11k_base *ab); +void (*ce_irq_disable)(struct ath11k_base *ab); }; +static inline void ath11k_hif_ce_irq_enable (struct ath11k_base *ab) +{ +if (ab->hif.ops->ce_irq_enable) + ab->hif.ops->ce_irq_enable (ab); +} + +static inline void ath11k_hif_ce_irq_disable (struct ath11k_base *ab) +{ +if (ab->hif.ops->ce_irq_disable) + ab->hif.ops->ce_irq_disable (ab); +} +static inline int ath11k_hif_start (struct ath11k_base *sc) {return sc->hif.ops->start (sc);
drivers/net/wireless/ath/ath11k/pci.c +18 -1
@@ -946,11 +946,16 @@ static void ath11k_pci_kill_tasklets(struct ath11k_base *ab) } } -static void ath11k_pci_stop (struct ath11k_base *ab) +static void ath11k_pci_ce_irq_disable_sync (struct ath11k_base *ab) {ath11k_pci_ce_irqs_disable (ab);ath11k_pci_sync_ce_irqs (ab);ath11k_pci_kill_tasklets (ab); +} + +static void ath11k_pci_stop (struct ath11k_base *ab) +{ +ath11k_pci_ce_irq_disable_sync (ab);ath11k_ce_cleanup_pipes (ab); }
@@ -966,6 +971,16 @@ static int ath11k_pci_start(struct ath11k_base *ab)return 0 ; } +static void ath11k_pci_hif_ce_irq_enable (struct ath11k_base *ab) +{ +ath11k_pci_ce_irqs_enable (ab); +} + +static void ath11k_pci_hif_ce_irq_disable (struct ath11k_base *ab) +{ +ath11k_pci_ce_irq_disable_sync (ab); +} +static int ath11k_pci_map_service_to_pipe (struct ath11k_base *ab,u16 service_id,u8 *ul_pipe,u8 *dl_pipe) {
@@ -1023,6 +1038,8 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = { .get_msi_address = ath11k_pci_get_msi_address, .get_user_msi_vector = ath11k_get_user_msi_assignment, .map_service_to_pipe = ath11k_pci_map_service_to_pipe, + .ce_irq_enable = ath11k_pci_hif_ce_irq_enable, + .ce_irq_disable = ath11k_pci_hif_ce_irq_disable, }; static int ath11k_pci_probe(struct pci_dev *pdev,
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k
PATCH 10/10 ath11k: implement suspend for QCA6390 PCI devices
In reply to Kalle ValoFrom: Carl Huang <[email protected]>
Now that all the needed pieces are in place implement suspend support QCA6390 PCI devices. All other devices will return -EOPNOTSUPP during suspend. The suspend is implemented by switching the firmware to WoW mode during suspend, so the firmware will be running on low power mode while host is in suspend.
At the moment we are not able to shutdown and fully power off the device due to bugs in MHI subsystem, so WoW mode is a workaround for the time being.
During suspend we enable WoW mode, disable CE irq and DP irq, then put MHI to suspend state. During resume, driver resumes MHI firstly, then enables CE irq and dp IRQ, and sends WoW wakeup command to firmware.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/ce.c | 2 +- drivers/net/wireless/ath/ath11k/ce.h | 2 + drivers/net/wireless/ath/ath11k/core.c | 85 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/core.h | 2 + drivers/net/wireless/ath/ath11k/dp.c | 2 +- drivers/net/wireless/ath/ath11k/dp.h | 1 + drivers/net/wireless/ath/ath11k/hw.h | 1 + drivers/net/wireless/ath/ath11k/pci.c | 31 +++++++++++++ 8 files changed, 124 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/ce.c +1 -1
@@ -195,7 +195,7 @@ static bool ath11k_ce_need_shadow_fix(int ce_id)return false; } -static void ath11k_ce_stop_shadow_timers (struct ath11k_base *ab) +void ath11k_ce_stop_shadow_timers (struct ath11k_base *ab) {int i;
drivers/net/wireless/ath/ath11k/ce.h +2 -0
@@ -190,4 +190,6 @@ int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,int ath11k_ce_attr_attach (struct ath11k_base *ab);void ath11k_ce_get_shadow_config (struct ath11k_base *ab,u32 **shadow_cfg,u32 *shadow_cfg_len); +void ath11k_ce_stop_shadow_timers (struct ath11k_base *ab); +#endif
drivers/net/wireless/ath/ath11k/core.c +85 -0
112 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/core.h +2 -0
@@ -897,6 +897,8 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);int ath11k_core_check_dt (struct ath11k_base *ath11k);void ath11k_core_halt (struct ath11k *ar); +int ath11k_core_resume (struct ath11k_base *ab); +int ath11k_core_suspend (struct ath11k_base *ab);const struct firmware *ath11k_core_firmware_request (struct ath11k_base *ab,const char *filename);
drivers/net/wireless/ath/ath11k/dp.c +1 -1
@@ -304,7 +304,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,return 0 ; } -static void ath11k_dp_stop_shadow_timers (struct ath11k_base *ab) +void ath11k_dp_stop_shadow_timers (struct ath11k_base *ab) {int i;
drivers/net/wireless/ath/ath11k/dp.h +1 -0
@@ -1641,5 +1641,6 @@ void ath11k_dp_shadow_stop_timer(struct ath11k_base *ab,void ath11k_dp_shadow_init_timer (struct ath11k_base *ab,struct ath11k_hp_update_timer *update_timer,u32 interval,u32 ring_id); +void ath11k_dp_stop_shadow_timers (struct ath11k_base *ab);#endif
drivers/net/wireless/ath/ath11k/hw.h +1 -0
@@ -156,6 +156,7 @@ struct ath11k_hw_params {bool supports_shadow_regs;bool idle_ps;bool cold_boot_calib; +bool supports_suspend; };struct ath11k_hw_ops {
drivers/net/wireless/ath/ath11k/pci.c +31 -0
@@ -1204,12 +1204,43 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)ath11k_pci_power_down (ab); } +static __maybe_unused int ath11k_pci_pm_suspend (struct device *dev) +{ +struct ath11k_base *ab =dev_get_drvdata (dev); +int ret; + + ret =ath11k_core_suspend (ab); +if (ret) +ath11k_warn (ab,"failed to suspend core: %d\n" , ret); + +return ret; +} + +static __maybe_unused int ath11k_pci_pm_resume (struct device *dev) +{ +struct ath11k_base *ab =dev_get_drvdata (dev); +int ret; + + ret =ath11k_core_resume (ab); +if (ret) +ath11k_warn (ab,"failed to resume core: %d\n" , ret); + +return ret; +} + +static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops, + ath11k_pci_pm_suspend, + ath11k_pci_pm_resume); +static struct pci_driver ath11k_pci_driver = { .name ="ath11k_pci" , .id_table = ath11k_pci_id_table, .probe = ath11k_pci_probe, .remove = ath11k_pci_remove, .shutdown = ath11k_pci_shutdown, +#ifdef CONFIG_PM + .driver.pm = &ath11k_pci_pm_ops, +#endif };static int ath11k_pci_init (void )
Signature · 7 lines
2.7.4 -- ath11k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath11k