| From 0b72cc45e045cfc62698fc620cf590f14c9cbafa Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 6 Mar 2024 07:15:14 +0200 |
| Subject: wifi: ath10k: poll service ready message before failing |
| |
| From: Baochen Qiang <quic_bqiang@quicinc.com> |
| |
| [ Upstream commit e57b7d62a1b2f496caf0beba81cec3c90fad80d5 ] |
| |
| Currently host relies on CE interrupts to get notified that |
| the service ready message is ready. This results in timeout |
| issue if the interrupt is not fired, due to some unknown |
| reasons. See below logs: |
| |
| [76321.937866] ath10k_pci 0000:02:00.0: wmi service ready event not received |
| ... |
| [76322.016738] ath10k_pci 0000:02:00.0: Could not init core: -110 |
| |
| And finally it causes WLAN interface bring up failure. |
| |
| Change to give it one more chance here by polling CE rings, |
| before failing directly. |
| |
| Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00157-QCARMSWPZ-1 |
| |
| Fixes: 5e3dd157d7e7 ("ath10k: mac80211 driver for Qualcomm Atheros 802.11ac CQA98xx devices") |
| Reported-by: James Prestwood <prestwoj@gmail.com> |
| Tested-By: James Prestwood <prestwoj@gmail.com> # on QCA6174 hw3.2 |
| Link: https://lore.kernel.org/linux-wireless/304ce305-fbe6-420e-ac2a-d61ae5e6ca1a@gmail.com/ |
| Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> |
| Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> |
| Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> |
| Link: https://msgid.link/20240227030409.89702-1-quic_bqiang@quicinc.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/wireless/ath/ath10k/wmi.c | 26 +++++++++++++++++++++++--- |
| 1 file changed, 23 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c |
| index 85fe855ece097..9cfd35dc87ba3 100644 |
| --- a/drivers/net/wireless/ath/ath10k/wmi.c |
| +++ b/drivers/net/wireless/ath/ath10k/wmi.c |
| @@ -1762,12 +1762,32 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch, |
| |
| int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) |
| { |
| - unsigned long time_left; |
| + unsigned long time_left, i; |
| |
| time_left = wait_for_completion_timeout(&ar->wmi.service_ready, |
| WMI_SERVICE_READY_TIMEOUT_HZ); |
| - if (!time_left) |
| - return -ETIMEDOUT; |
| + if (!time_left) { |
| + /* Sometimes the PCI HIF doesn't receive interrupt |
| + * for the service ready message even if the buffer |
| + * was completed. PCIe sniffer shows that it's |
| + * because the corresponding CE ring doesn't fires |
| + * it. Workaround here by polling CE rings once. |
| + */ |
| + ath10k_warn(ar, "failed to receive service ready completion, polling..\n"); |
| + |
| + for (i = 0; i < CE_COUNT; i++) |
| + ath10k_hif_send_complete_check(ar, i, 1); |
| + |
| + time_left = wait_for_completion_timeout(&ar->wmi.service_ready, |
| + WMI_SERVICE_READY_TIMEOUT_HZ); |
| + if (!time_left) { |
| + ath10k_warn(ar, "polling timed out\n"); |
| + return -ETIMEDOUT; |
| + } |
| + |
| + ath10k_warn(ar, "service ready completion received, continuing normally\n"); |
| + } |
| + |
| return 0; |
| } |
| |
| -- |
| 2.43.0 |
| |