Commit 6ce34ec1 authored by Sujith's avatar Sujith Committed by John W. Linville

ath9k_htc: Handle WMI timeouts properly

If a WMI command has timed out for some reason,
a late WMI response would end up updating the
response region of a new WMI request that has been
issued in the meantime.

Fix this race condition by dropping a WMI response
if a new WMI command has been issued.
Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent eac8e385
...@@ -204,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, ...@@ -204,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
return; return;
} }
/* Check if there has been a timeout. */
spin_lock(&wmi->wmi_lock);
if (cmd_id != wmi->last_cmd_id) {
spin_unlock(&wmi->wmi_lock);
goto free_skb;
}
spin_unlock(&wmi->wmi_lock);
/* WMI command response */ /* WMI command response */
ath9k_wmi_rsp_callback(wmi, skb); ath9k_wmi_rsp_callback(wmi, skb);
...@@ -266,6 +274,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, ...@@ -266,6 +274,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
struct sk_buff *skb; struct sk_buff *skb;
u8 *data; u8 *data;
int time_left, ret = 0; int time_left, ret = 0;
unsigned long flags;
if (!wmi) if (!wmi)
return -EINVAL; return -EINVAL;
...@@ -297,6 +306,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, ...@@ -297,6 +306,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (ret) if (ret)
goto out; goto out;
spin_lock_irqsave(&wmi->wmi_lock, flags);
wmi->last_cmd_id = cmd_id;
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
if (!time_left) { if (!time_left) {
ath_print(common, ATH_DBG_WMI, ath_print(common, ATH_DBG_WMI,
......
...@@ -97,6 +97,7 @@ struct wmi { ...@@ -97,6 +97,7 @@ struct wmi {
enum htc_endpoint_id ctrl_epid; enum htc_endpoint_id ctrl_epid;
struct mutex op_mutex; struct mutex op_mutex;
struct completion cmd_wait; struct completion cmd_wait;
enum wmi_cmd_id last_cmd_id;
u16 tx_seq_id; u16 tx_seq_id;
u8 *cmd_rsp_buf; u8 *cmd_rsp_buf;
u32 cmd_rsp_len; u32 cmd_rsp_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment