浏览代码

iwlagn: fix race condition when reprogram sta

During reprogram stations, do not send link quality command.
uCode will crash if receive link quality command for invalid station

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Wey-Yi Guy 14 年之前
父节点
当前提交
40b97c2fe9
共有 1 个文件被更改,包括 13 次插入0 次删除
  1. 13 0
      drivers/net/wireless/iwlwifi/iwl-sta.c

+ 13 - 0
drivers/net/wireless/iwlwifi/iwl-sta.c

@@ -647,6 +647,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
 	memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
 
 
 	active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
 	active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
+	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 
 	if (active) {
 	if (active) {
@@ -657,6 +658,10 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 			IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
 			IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
 				priv->stations[sta_id].sta.sta.addr, ret);
 				priv->stations[sta_id].sta.sta.addr, ret);
 	}
 	}
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
 	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 	ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 	if (ret)
 	if (ret)
 		IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
 		IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
@@ -777,6 +782,14 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
 	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
 		return -EINVAL;
 		return -EINVAL;
 
 
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
 	iwl_dump_lq_cmd(priv, lq);
 	iwl_dump_lq_cmd(priv, lq);
 	BUG_ON(init && (cmd.flags & CMD_ASYNC));
 	BUG_ON(init && (cmd.flags & CMD_ASYNC));