--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -259,7 +259,7 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr, struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; __be32 tmpaddr[8]; - __be32 tmpval[8]; + __be32 tmpval[8] = {0}; int i, ret; for (i = 0; i < count; i++) { --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -204,8 +204,13 @@ static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) { skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + if (unlikely(skb->len < wmi->cmd_rsp_len)) + return; + if (wmi->cmd_rsp_buf != NULL && wmi->cmd_rsp_len != 0) memcpy(wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); + else + return; complete(&wmi->cmd_wait); } @@ -221,6 +226,9 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, if (unlikely(wmi->stopped)) goto free_skb; + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) + goto free_skb; + hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); @@ -308,8 +316,11 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, unsigned long time_left; int ret = 0; - if (ah->ah_flags & AH_UNPLUGGED) - return 0; + if (ah->ah_flags & AH_UNPLUGGED) { + ath_dbg(common, WMI, "Device unplugged for WMI command: %s\n", + wmi_cmd_to_name(cmd_id)); + return -ENODEV; + } skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); if (!skb) @@ -342,15 +353,22 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n", wmi_cmd_to_name(cmd_id)); wmi->last_seq_id = 0; + wmi->cmd_rsp_buf = NULL; + wmi->cmd_rsp_len = 0; mutex_unlock(&wmi->op_mutex); return -ETIMEDOUT; } + wmi->cmd_rsp_buf = NULL; + wmi->cmd_rsp_len = 0; + mutex_unlock(&wmi->op_mutex); return 0; out: + wmi->cmd_rsp_buf = NULL; + wmi->cmd_rsp_len = 0; ath_dbg(common, WMI, "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); mutex_unlock(&wmi->op_mutex); kfree_skb(skb);