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

ath9k_htc: Fix bug in aggregation initiation

Accessing the sta pointer in TX completion without
approprate RCU protection is wrong. Fix this.

Also, RCU protection is needed when the station's
aggregation state is updated. Handle this properly.
Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0995d110
...@@ -412,32 +412,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, ...@@ -412,32 +412,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
if (tid > ATH9K_HTC_MAX_TID) if (tid > ATH9K_HTC_MAX_TID)
return -EINVAL; return -EINVAL;
memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
rcu_read_lock(); rcu_read_lock();
/* Check if we are able to retrieve the station */
sta = ieee80211_find_sta(vif, sta_addr); sta = ieee80211_find_sta(vif, sta_addr);
if (sta) { if (!sta) {
ista = (struct ath9k_htc_sta *) sta->drv_priv;
} else {
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
} }
if (!ista) { ista = (struct ath9k_htc_sta *) sta->drv_priv;
rcu_read_unlock();
return -EINVAL;
}
memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); if (oper)
ista->tid_state[tid] = AGGR_START;
else
ista->tid_state[tid] = AGGR_STOP;
aggr.sta_index = ista->index; aggr.sta_index = ista->index;
rcu_read_unlock(); rcu_read_unlock();
aggr.tidno = tid; aggr.tidno = tid;
aggr.aggr_enable = oper; aggr.aggr_enable = oper;
if (oper)
ista->tid_state[tid] = AGGR_START;
else
ista->tid_state[tid] = AGGR_STOP;
WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
if (ret) if (ret)
ath_print(common, ATH_DBG_CONFIG, ath_print(common, ATH_DBG_CONFIG,
......
...@@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data) ...@@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data)
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
fc = hdr->frame_control; fc = hdr->frame_control;
tx_info = IEEE80211_SKB_CB(skb); tx_info = IEEE80211_SKB_CB(skb);
sta = tx_info->control.sta;
memset(&tx_info->status, 0, sizeof(tx_info->status));
rcu_read_lock(); rcu_read_lock();
sta = ieee80211_find_sta(priv->vif, hdr->addr1);
if (!sta) {
rcu_read_unlock();
ieee80211_tx_status(priv->hw, skb);
continue;
}
/* Check if we need to start aggregation */
if (sta && conf_is_ht(&priv->hw->conf) && if (sta && conf_is_ht(&priv->hw->conf) &&
(priv->op_flags & OP_TXAGGR) (priv->op_flags & OP_TXAGGR)
&& !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
...@@ -213,7 +223,7 @@ void ath9k_tx_tasklet(unsigned long data) ...@@ -213,7 +223,7 @@ void ath9k_tx_tasklet(unsigned long data)
rcu_read_unlock(); rcu_read_unlock();
memset(&tx_info->status, 0, sizeof(tx_info->status)); /* Send status to mac80211 */
ieee80211_tx_status(priv->hw, skb); ieee80211_tx_status(priv->hw, skb);
} }
} }
......
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