]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ath9k_htc: Fix bug in aggregation initiation
authorSujith <Sujith.Manoharan@atheros.com>
Mon, 29 Mar 2010 10:37:11 +0000 (16:07 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 31 Mar 2010 18:46:39 +0000 (14:46 -0400)
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>
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c

index e5f78c7b2b1f6945f8ca1e07ee5e97518561afe0..90b13ed1ae4ca5eaf91d90127b0da4dc438395fd 100644 (file)
@@ -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,
index 94e299fabbb2ad240fa8c9bffae17b70b12c215e..838365607aa5d4213efa7c2e34affd6c9e395926 100644 (file)
@@ -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))) {
@@ -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);
        }
 }