ath10k: fix vdev-start timeout on error
authorBen Greear <greearb@candelatech.com>
Thu, 6 Sep 2018 16:46:20 +0000 (19:46 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 24 Nov 2019 07:22:54 +0000 (08:22 +0100)
[ Upstream commit 833fd34d743c728afe6d127ef7bee67e7d9199a8 ]

The vdev-start-response message should cause the
completion to fire, even in the error case.  Otherwise,
the user still gets no useful information and everything
is blocked until the timeout period.

Add some warning text to print out the invalid status
code to aid debugging, and propagate failure code.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h

index 949ebb3e967bb43f34ac04b21f3938e372ad7e1a..be9ec265dfe55079e2dbec53f4bdc3acdca41cff 100644 (file)
@@ -881,6 +881,7 @@ struct ath10k {
 
        struct completion install_key_done;
 
+       int last_wmi_vdev_start_status;
        struct completion vdev_setup_done;
 
        struct workqueue_struct *workqueue;
index 8c4bb56c262f6b877252b38ae2e46461f2c6a92f..dff34448588f0a0b87cfcd33a121f9d22f4f84ce 100644 (file)
@@ -955,7 +955,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
        if (time_left == 0)
                return -ETIMEDOUT;
 
-       return 0;
+       return ar->last_wmi_vdev_start_status;
 }
 
 static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
index 4d6c2986c40ddfdc1c42bf02ecd3317420ffe868..25f51ca0609341a5e4851269bf3a194dd01d20e6 100644 (file)
@@ -3133,18 +3133,31 @@ void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb)
 {
        struct wmi_vdev_start_ev_arg arg = {};
        int ret;
+       u32 status;
 
        ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n");
 
+       ar->last_wmi_vdev_start_status = 0;
+
        ret = ath10k_wmi_pull_vdev_start(ar, skb, &arg);
        if (ret) {
                ath10k_warn(ar, "failed to parse vdev start event: %d\n", ret);
-               return;
+               ar->last_wmi_vdev_start_status = ret;
+               goto out;
        }
 
-       if (WARN_ON(__le32_to_cpu(arg.status)))
-               return;
+       status = __le32_to_cpu(arg.status);
+       if (WARN_ON_ONCE(status)) {
+               ath10k_warn(ar, "vdev-start-response reports status error: %d (%s)\n",
+                           status, (status == WMI_VDEV_START_CHAN_INVALID) ?
+                           "chan-invalid" : "unknown");
+               /* Setup is done one way or another though, so we should still
+                * do the completion, so don't return here.
+                */
+               ar->last_wmi_vdev_start_status = -EINVAL;
+       }
 
+out:
        complete(&ar->vdev_setup_done);
 }
 
index d0e05aa437e36549515016d72a35f2cf2dd14629..947b74c64fec0ff3eaa8044d7a7c38a67034fb33 100644 (file)
@@ -6480,11 +6480,17 @@ struct wmi_ch_info_ev_arg {
        __le32 rx_frame_count;
 };
 
+/* From 10.4 firmware, not sure all have the same values. */
+enum wmi_vdev_start_status {
+       WMI_VDEV_START_OK = 0,
+       WMI_VDEV_START_CHAN_INVALID,
+};
+
 struct wmi_vdev_start_ev_arg {
        __le32 vdev_id;
        __le32 req_id;
        __le32 resp_type; /* %WMI_VDEV_RESP_ */
-       __le32 status;
+       __le32 status; /* See wmi_vdev_start_status enum above */
 };
 
 struct wmi_peer_kick_ev_arg {