]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: ath10k: avoid unnecessary wait for service ready message
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Mon, 11 Aug 2025 09:26:45 +0000 (17:26 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Oct 2025 09:56:35 +0000 (11:56 +0200)
[ Upstream commit 51a73f1b2e56b0324b4a3bb8cebc4221b5be4c7a ]

Commit e57b7d62a1b2 ("wifi: ath10k: poll service ready message before
failing") works around the failure in waiting for the service ready
message by active polling. Note the polling is triggered after initial
wait timeout, which means that the wait-till-timeout can not be avoided
even the message is ready.

A possible fix is to do polling once before wait as well, however this
can not handle the race that the message arrives right after polling.
So the solution is to do periodic polling until timeout.

Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1

Fixes: e57b7d62a1b2 ("wifi: ath10k: poll service ready message before failing")
Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Closes: https://lore.kernel.org/all/97a15967-5518-4731-a8ff-d43ff7f437b0@molgen.mpg.de
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250811-ath10k-avoid-unnecessary-wait-v1-1-db2deb87c39b@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/ath/ath10k/wmi.c

index b126ffba480f10bf72e352d9fa9f0a4d30032cc1..2fda5ca3e6ee93b97cfc5e41fc458f692afb7c8e 100644 (file)
@@ -1762,33 +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 timeout = jiffies + WMI_SERVICE_READY_TIMEOUT_HZ;
        unsigned long time_left, i;
 
-       time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
-                                               WMI_SERVICE_READY_TIMEOUT_HZ);
-       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");
-
+       /* 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. Since
+        * the message could arrive at any time, continue
+        * polling until timeout.
+        */
+       do {
                for (i = 0; i < CE_COUNT; i++)
                        ath10k_hif_send_complete_check(ar, i, 1);
 
+               /* The 100 ms granularity is a tradeoff considering scheduler
+                * overhead and response latency
+                */
                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");
-       }
+                                                       msecs_to_jiffies(100));
+               if (time_left)
+                       return 0;
+       } while (time_before(jiffies, timeout));
 
-       return 0;
+       ath10k_warn(ar, "failed to receive service ready completion\n");
+       return -ETIMEDOUT;
 }
 
 int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)