netlink: ensure to loop over all netns in genlmsg_multicast_allns()
[pandora-kernel.git] / net / mac80211 / tx.c
index eff1f4e..91826b6 100644 (file)
@@ -278,9 +278,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
        if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
                return TX_CONTINUE;
 
-       if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-               return TX_CONTINUE;
-
        if (tx->flags & IEEE80211_TX_PS_BUFFERED)
                return TX_CONTINUE;
 
@@ -464,6 +461,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
                        purge_old_ps_buffers(tx->local);
+
+               /* sync with ieee80211_sta_ps_deliver_wakeup */
+               spin_lock(&sta->ps_lock);
+               /*
+                * STA woke up the meantime and all the frames on ps_tx_buf have
+                * been queued to pending queue. No reordering can happen, go
+                * ahead and Tx the packet.
+                */
+               if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
+                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+                       spin_unlock(&sta->ps_lock);
+                       return TX_CONTINUE;
+               }
+
                if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
                        struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
@@ -480,6 +491,7 @@ 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[ac], tx->skb);
+               spin_unlock(&sta->ps_lock);
 
                if (!timer_pending(&local->sta_cleanup))
                        mod_timer(&local->sta_cleanup,
@@ -522,9 +534,11 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
 
-       if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol &&
-                    tx->sdata->control_port_no_encrypt))
-               info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+       if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) {
+               if (tx->sdata->control_port_no_encrypt)
+                       info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+               info->flags |= IEEE80211_TX_CTL_USE_MINRATE;
+       }
 
        return TX_CONTINUE;
 }
@@ -884,7 +898,7 @@ static int ieee80211_fragment(struct ieee80211_local *local,
                pos += fraglen;
        }
 
-       skb->len = hdrlen + per_fragm;
+       skb_trim(skb, hdrlen + per_fragm);
        return 0;
 }
 
@@ -1121,7 +1135,8 @@ 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) {
+       } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+                  tx->sdata->control_port_protocol == tx->skb->protocol) {
                tx->sta = sta_info_get_bss(sdata, hdr->addr1);
        }
        if (!tx->sta)