Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mcheha...
[safe/jmp/linux-2.6] / net / mac80211 / tx.c
index da557b0..680bcb7 100644 (file)
@@ -429,6 +429,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+       struct ieee80211_local *local = tx->local;
        u32 staflags;
 
        if (unlikely(!sta ||
@@ -476,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                info->control.vif = &tx->sdata->vif;
                info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                skb_queue_tail(&sta->ps_tx_buf, tx->skb);
+
+               if (!timer_pending(&local->sta_cleanup))
+                       mod_timer(&local->sta_cleanup,
+                                 round_jiffies(jiffies +
+                                               STA_INFO_CLEANUP_INTERVAL));
+
                return TX_QUEUED;
        }
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
@@ -513,6 +520,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
        else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
                tx->key = key;
        else if (ieee80211_is_mgmt(hdr->frame_control) &&
+                is_multicast_ether_addr(hdr->addr1) &&
+                ieee80211_is_robust_mgmt_frame(hdr) &&
                 (key = rcu_dereference(tx->sdata->default_mgmt_key)))
                tx->key = key;
        else if ((key = rcu_dereference(tx->sdata->default_key)))
@@ -547,9 +556,10 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                            !ieee80211_use_mfp(hdr->frame_control, tx->sta,
                                               tx->skb))
                                tx->key = NULL;
-                       skip_hw = (tx->key->conf.flags &
-                                               IEEE80211_KEY_FLAG_SW_MGMT) &&
-                                  ieee80211_is_mgmt(hdr->frame_control);
+                       else
+                               skip_hw = (tx->key->conf.flags &
+                                          IEEE80211_KEY_FLAG_SW_MGMT) &&
+                                       ieee80211_is_mgmt(hdr->frame_control);
                        break;
                case ALG_AES_CMAC:
                        if (!ieee80211_is_mgmt(hdr->frame_control))
@@ -557,8 +567,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                        break;
                }
 
-               if (!skip_hw &&
-                   tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+               if (!skip_hw && tx->key &&
+                   tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
                        info->control.hw_key = &tx->key->conf;
        }
 
@@ -570,7 +580,7 @@ ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
 
-       if (tx->sta)
+       if (tx->sta && tx->sta->uploaded)
                info->control.sta = &tx->sta->sta;
 
        return TX_CONTINUE;
@@ -583,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        struct ieee80211_hdr *hdr = (void *)tx->skb->data;
        struct ieee80211_supported_band *sband;
        struct ieee80211_rate *rate;
-       int i, len;
+       int i;
+       u32 len;
        bool inval = false, rts = false, short_preamble = false;
        struct ieee80211_tx_rate_control txrc;
        u32 sta_flags;
@@ -592,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
 
        sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
-       len = min_t(int, tx->skb->len + FCS_LEN,
+       len = min_t(u32, tx->skb->len + FCS_LEN,
                         tx->local->hw.wiphy->frag_threshold);
 
        /* set up the tx rate control struct we give the RC algo */
@@ -1009,7 +1020,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
                (struct ieee80211_radiotap_header *) skb->data;
        struct ieee80211_supported_band *sband;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+       int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
+                                                  NULL);
 
        sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
@@ -1045,7 +1057,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
                                 * because it will be recomputed and added
                                 * on transmission
                                 */
-                               if (skb->len < (iterator.max_length + FCS_LEN))
+                               if (skb->len < (iterator._max_length + FCS_LEN))
                                        return false;
 
                                skb_trim(skb, skb->len - FCS_LEN);
@@ -1072,10 +1084,10 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
 
        /*
         * remove the radiotap header
-        * iterator->max_length was sanity-checked against
+        * iterator->_max_length was sanity-checked against
         * skb->len by iterator init
         */
-       skb_pull(skb, iterator.max_length);
+       skb_pull(skb, iterator._max_length);
 
        return true;
 }
@@ -1107,7 +1119,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
        tx->flags |= IEEE80211_TX_FRAGMENTED;
 
        /* process and remove the injection radiotap header */
-       if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
+       if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
                if (!__ieee80211_parse_tx_radiotap(tx, skb))
                        return TX_DROP;
 
@@ -1116,6 +1128,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                 * the radiotap header that was present and pre-filled
                 * 'tx' with tx control information.
                 */
+               info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
        }
 
        /*
@@ -1131,19 +1144,20 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                tx->sta = rcu_dereference(sdata->u.vlan.sta);
                if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
                        return TX_DROP;
+       } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+               tx->sta = sta_info_get_bss(sdata, hdr->addr1);
        }
        if (!tx->sta)
                tx->sta = sta_info_get(sdata, hdr->addr1);
 
        if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
            (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
-               unsigned long flags;
                struct tid_ampdu_tx *tid_tx;
 
                qc = ieee80211_get_qos_ctl(hdr);
                tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
 
-               spin_lock_irqsave(&tx->sta->lock, flags);
+               spin_lock(&tx->sta->lock);
                /*
                 * XXX: This spinlock could be fairly expensive, but see the
                 *      comment in agg-tx.c:ieee80211_agg_tx_operational().
@@ -1168,7 +1182,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                        __skb_queue_tail(&tid_tx->pending, skb);
                }
-               spin_unlock_irqrestore(&tx->sta->lock, flags);
+               spin_unlock(&tx->sta->lock);
 
                if (unlikely(queued))
                        return TX_QUEUED;
@@ -1498,7 +1512,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                int hdrlen;
                u16 len_rthdr;
 
-               info->flags |= IEEE80211_TX_CTL_INJECTED;
+               info->flags |= IEEE80211_TX_CTL_INJECTED |
+                              IEEE80211_TX_INTFL_HAS_RADIOTAP;
 
                len_rthdr = ieee80211_get_radiotap_len(skb->data);
                hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
@@ -1985,6 +2000,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
 void ieee80211_tx_pending(unsigned long data)
 {
        struct ieee80211_local *local = (struct ieee80211_local *)data;
+       struct ieee80211_sub_if_data *sdata;
        unsigned long flags;
        int i;
        bool txok;
@@ -2004,14 +2020,12 @@ void ieee80211_tx_pending(unsigned long data)
                while (!skb_queue_empty(&local->pending[i])) {
                        struct sk_buff *skb = __skb_dequeue(&local->pending[i]);
                        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-                       struct ieee80211_sub_if_data *sdata;
 
                        if (WARN_ON(!info->control.vif)) {
                                kfree_skb(skb);
                                continue;
                        }
 
-                       sdata = vif_to_sdata(info->control.vif);
                        spin_unlock_irqrestore(&local->queue_stop_reason_lock,
                                                flags);
 
@@ -2023,6 +2037,11 @@ void ieee80211_tx_pending(unsigned long data)
                        if (!txok)
                                break;
                }
+
+               if (skb_queue_empty(&local->pending[i]))
+                       list_for_each_entry_rcu(sdata, &local->interfaces, list)
+                               netif_tx_wake_queue(
+                                       netdev_get_tx_queue(sdata->dev, i));
        }
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
@@ -2232,8 +2251,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 
        info->control.vif = vif;
 
-       info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-       info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
+       info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
+                       IEEE80211_TX_CTL_ASSIGN_SEQ |
+                       IEEE80211_TX_CTL_FIRST_FRAGMENT;
  out:
        rcu_read_unlock();
        return skb;