Skip to content

Commit

Permalink
ath9k_htc: Fix bug in aggregation initiation
Browse files Browse the repository at this point in the history
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: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Sujith authored and John W. Linville committed Mar 31, 2010
1 parent 0995d11 commit ef98c3c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 15 deletions.
25 changes: 12 additions & 13 deletions drivers/net/wireless/ath/ath9k/htc_drv_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,32 +412,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
if (tid > ATH9K_HTC_MAX_TID)
return -EINVAL;

memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));

rcu_read_lock();

/* Check if we are able to retrieve the station */
sta = ieee80211_find_sta(vif, sta_addr);
if (sta) {
ista = (struct ath9k_htc_sta *) sta->drv_priv;
} else {
if (!sta) {
rcu_read_unlock();
return -EINVAL;
}

if (!ista) {
rcu_read_unlock();
return -EINVAL;
}
ista = (struct ath9k_htc_sta *) sta->drv_priv;

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;

rcu_read_unlock();

aggr.tidno = tid;
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);
if (ret)
ath_print(common, ATH_DBG_CONFIG,
Expand Down
14 changes: 12 additions & 2 deletions drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data)
hdr = (struct ieee80211_hdr *) skb->data;
fc = hdr->frame_control;
tx_info = IEEE80211_SKB_CB(skb);
sta = tx_info->control.sta;

memset(&tx_info->status, 0, sizeof(tx_info->status));

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) &&
(priv->op_flags & OP_TXAGGR)
&& !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
Expand All @@ -213,7 +223,7 @@ void ath9k_tx_tasklet(unsigned long data)

rcu_read_unlock();

memset(&tx_info->status, 0, sizeof(tx_info->status));
/* Send status to mac80211 */
ieee80211_tx_status(priv->hw, skb);
}
}
Expand Down

0 comments on commit ef98c3c

Please sign in to comment.