Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -204,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
		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 */
	ath9k_wmi_rsp_callback(wmi, skb);

@@ -266,6 +274,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
	struct sk_buff *skb;
	u8 *data;
	int time_left, ret = 0;
	unsigned long flags;

	if (!wmi)
		return -EINVAL;
@@ -297,6 +306,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
	if (ret)
		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);
	if (!time_left) {
		ath_print(common, ATH_DBG_WMI,
+1 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ struct wmi {
	enum htc_endpoint_id ctrl_epid;
	struct mutex op_mutex;
	struct completion cmd_wait;
	enum wmi_cmd_id last_cmd_id;
	u16 tx_seq_id;
	u8 *cmd_rsp_buf;
	u32 cmd_rsp_len;