cxgb3: AEL2020 phy support update
[safe/jmp/linux-2.6] / net / mac80211 / tx.c
index ee1b77f..2ffb35d 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/unaligned.h>
 
 #include "ieee80211_i.h"
+#include "driver-ops.h"
 #include "led.h"
 #include "mesh.h"
 #include "wep.h"
@@ -399,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                        sta_info_set_tim_bit(sta);
 
                info->control.jiffies = jiffies;
+               info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                skb_queue_tail(&sta->ps_tx_buf, tx->skb);
                return TX_QUEUED;
        }
@@ -409,8 +411,24 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                       sta->sta.addr);
        }
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-       clear_sta_flags(sta, WLAN_STA_PSPOLL);
+       if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) {
+               /*
+                * The sleeping station with pending data is now snoozing.
+                * It queried us for its buffered frames and will go back
+                * to deep sleep once it got everything.
+                *
+                * inform the driver, in case the hardware does powersave
+                * frame filtering and keeps a station  blacklist on its own
+                * (e.g: p54), so that frames can be delivered unimpeded.
+                *
+                * Note: It should be safe to disable the filter now.
+                * As, it is really unlikely that we still have any pending
+                * frame for this station in the hw's buffers/fifos left,
+                * that is not rejected with a unsuccessful tx_status yet.
+                */
 
+               info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+       }
        return TX_CONTINUE;
 }
 
@@ -429,7 +447,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
-       struct ieee80211_key *key;
+       struct ieee80211_key *key = NULL;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 
@@ -500,7 +518,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,
-                        tx->local->fragmentation_threshold);
+                        tx->local->hw.wiphy->frag_threshold);
 
        /* set up the tx rate control struct we give the RC algo */
        txrc.hw = local_to_hw(tx->local);
@@ -511,8 +529,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
 
        /* set up RTS protection if desired */
-       if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD &&
-           len > tx->local->rts_threshold) {
+       if (len > tx->local->hw.wiphy->rts_threshold) {
                txrc.rts = rts = true;
        }
 
@@ -542,6 +559,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        if (unlikely(!info->control.rates[0].count))
                info->control.rates[0].count = 1;
 
+       if (WARN_ON_ONCE((info->control.rates[0].count > 1) &&
+                        (info->flags & IEEE80211_TX_CTL_NO_ACK)))
+               info->control.rates[0].count = 1;
+
        if (is_multicast_ether_addr(hdr->addr1)) {
                /*
                 * XXX: verify the rate is in the basic rateset
@@ -754,7 +775,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
        struct sk_buff *skb = tx->skb;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (void *)skb->data;
-       int frag_threshold = tx->local->fragmentation_threshold;
+       int frag_threshold = tx->local->hw.wiphy->frag_threshold;
        int hdrlen;
        int fragnum;
 
@@ -772,7 +793,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
        /* internal error, why is TX_FRAGMENTED set? */
-       if (WARN_ON(skb->len <= frag_threshold))
+       if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
                return TX_DROP;
 
        /*
@@ -852,6 +873,8 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
 
        do {
                hdr = (void *) skb->data;
+               if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
+                       break; /* must not overwrite AID */
                next_len = skb->next ? skb->next->len : 0;
                group_addr = is_multicast_ether_addr(hdr->addr1);
 
@@ -885,9 +908,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
  * deal with packet injection down monitor interface
  * with Radiotap Header -- only called for monitor mode interface
  */
-static ieee80211_tx_result
-__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
-                             struct sk_buff *skb)
+static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
+                                         struct sk_buff *skb)
 {
        /*
         * this is the moment to interpret and discard the radiotap header that
@@ -938,7 +960,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
                                 * on transmission
                                 */
                                if (skb->len < (iterator.max_length + FCS_LEN))
-                                       return TX_DROP;
+                                       return false;
 
                                skb_trim(skb, skb->len - FCS_LEN);
                        }
@@ -960,7 +982,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
        }
 
        if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
-               return TX_DROP;
+               return false;
 
        /*
         * remove the radiotap header
@@ -969,7 +991,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
         */
        skb_pull(skb, iterator.max_length);
 
-       return TX_CONTINUE;
+       return true;
 }
 
 /*
@@ -984,9 +1006,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
        struct ieee80211_hdr *hdr;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
        int hdrlen, tid;
        u8 *qc, *state;
+       bool queued = false;
 
        memset(tx, 0, sizeof(*tx));
        tx->skb = skb;
@@ -1003,7 +1025,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
        /* process and remove the injection radiotap header */
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
-               if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
+               if (!__ieee80211_parse_tx_radiotap(tx, skb))
                        return TX_DROP;
 
                /*
@@ -1013,20 +1035,53 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
                 */
        }
 
+       /*
+        * If this flag is set to true anywhere, and we get here,
+        * we are doing the needed processing, so remove the flag
+        * now.
+        */
+       info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+
        hdr = (struct ieee80211_hdr *) skb->data;
 
        tx->sta = sta_info_get(local, hdr->addr1);
 
-       if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+       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);
+               /*
+                * XXX: This spinlock could be fairly expensive, but see the
+                *      comment in agg-tx.c:ieee80211_agg_tx_operational().
+                *      One way to solve this would be to do something RCU-like
+                *      for managing the tid_tx struct and using atomic bitops
+                *      for the actual state -- by introducing an actual
+                *      'operational' bit that would be possible. It would
+                *      require changing ieee80211_agg_tx_operational() to
+                *      set that bit, and changing the way tid_tx is managed
+                *      everywhere, including races between that bit and
+                *      tid_tx going away (tid_tx being added can be easily
+                *      committed to memory before the 'operational' bit).
+                */
+               tid_tx = tx->sta->ampdu_mlme.tid_tx[tid];
                state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
-               if (*state == HT_AGG_STATE_OPERATIONAL)
+               if (*state == HT_AGG_STATE_OPERATIONAL) {
                        info->flags |= IEEE80211_TX_CTL_AMPDU;
+               } else if (*state != HT_AGG_STATE_IDLE) {
+                       /* in progress */
+                       queued = true;
+                       info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+                       __skb_queue_tail(&tid_tx->pending, skb);
+               }
                spin_unlock_irqrestore(&tx->sta->lock, flags);
+
+               if (unlikely(queued))
+                       return TX_QUEUED;
        }
 
        if (is_multicast_ether_addr(hdr->addr1)) {
@@ -1034,12 +1089,15 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
                info->flags |= IEEE80211_TX_CTL_NO_ACK;
        } else {
                tx->flags |= IEEE80211_TX_UNICAST;
-               info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
+               if (unlikely(local->wifi_wme_noack_test))
+                       info->flags |= IEEE80211_TX_CTL_NO_ACK;
+               else
+                       info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
        }
 
        if (tx->flags & IEEE80211_TX_FRAGMENTED) {
                if ((tx->flags & IEEE80211_TX_UNICAST) &&
-                   skb->len + FCS_LEN > local->fragmentation_threshold &&
+                   skb->len + FCS_LEN > local->hw.wiphy->frag_threshold &&
                    !(info->flags & IEEE80211_TX_CTL_AMPDU))
                        tx->flags |= IEEE80211_TX_FRAGMENTED;
                else
@@ -1077,18 +1135,26 @@ static int ieee80211_tx_prepare(struct ieee80211_local *local,
        }
        if (unlikely(!dev))
                return -ENODEV;
-       /* initialises tx with control */
+       /*
+        * initialises tx with control
+        *
+        * return value is safe to ignore here because this function
+        * can only be invoked for multicast frames
+        *
+        * XXX: clean up
+        */
        __ieee80211_tx_prepare(tx, skb, dev);
        dev_put(dev);
        return 0;
 }
 
 static int __ieee80211_tx(struct ieee80211_local *local,
-                         struct ieee80211_tx_data *tx)
+                         struct sk_buff **skbp,
+                         struct sta_info *sta)
 {
-       struct sk_buff *skb = tx->skb, *next;
+       struct sk_buff *skb = *skbp, *next;
        struct ieee80211_tx_info *info;
-       int ret;
+       int ret, len;
        bool fragm = false;
 
        local->mdev->trans_start = jiffies;
@@ -1104,30 +1170,16 @@ static int __ieee80211_tx(struct ieee80211_local *local,
                        info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
                                         IEEE80211_TX_CTL_FIRST_FRAGMENT);
 
-               /*
-                * Internally, we need to have the queue mapping point to
-                * the real AC queue, not the virtual A-MPDU queue. This
-                * now finally sets the queue to what the driver wants.
-                * We will later move this down into the only driver that
-                * needs it, iwlwifi.
-                */
-               if (tx->sta && local->hw.ampdu_queues &&
-                   info->flags & IEEE80211_TX_CTL_AMPDU) {
-                       unsigned long flags;
-                       u8 *qc = ieee80211_get_qos_ctl((void *) skb->data);
-                       int tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
-
-                       spin_lock_irqsave(&tx->sta->lock, flags);
-                       skb_set_queue_mapping(skb, local->hw.queues +
-                                                  tx->sta->tid_to_tx_q[tid]);
-                       spin_unlock_irqrestore(&tx->sta->lock, flags);
-               }
-
                next = skb->next;
-               ret = local->ops->tx(local_to_hw(local), skb);
+               len = skb->len;
+               ret = drv_tx(local, skb);
+               if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
+                       dev_kfree_skb(skb);
+                       ret = NETDEV_TX_OK;
+               }
                if (ret != NETDEV_TX_OK)
                        return IEEE80211_TX_AGAIN;
-               tx->skb = skb = next;
+               *skbp = skb = next;
                ieee80211_led_tx(local, 1);
                fragm = true;
        }
@@ -1182,10 +1234,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        return 0;
 }
 
-static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
+static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+                        bool txpending)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct sta_info *sta;
        struct ieee80211_tx_data tx;
        ieee80211_tx_result res_prepare;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1196,11 +1248,11 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
 
        queue = skb_get_queue_mapping(skb);
 
-       WARN_ON(!skb_queue_empty(&local->pending[queue]));
+       WARN_ON(!txpending && !skb_queue_empty(&local->pending[queue]));
 
        if (unlikely(skb->len < 10)) {
                dev_kfree_skb(skb);
-               return 0;
+               return;
        }
 
        rcu_read_lock();
@@ -1208,13 +1260,15 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
        /* initialises tx */
        res_prepare = __ieee80211_tx_prepare(&tx, skb, dev);
 
-       if (res_prepare == TX_DROP) {
+       if (unlikely(res_prepare == TX_DROP)) {
                dev_kfree_skb(skb);
                rcu_read_unlock();
-               return 0;
+               return;
+       } else if (unlikely(res_prepare == TX_QUEUED)) {
+               rcu_read_unlock();
+               return;
        }
 
-       sta = tx.sta;
        tx.channel = local->hw.conf.channel;
        info->band = tx.channel->band;
 
@@ -1223,7 +1277,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
 
        retries = 0;
  retry:
-       ret = __ieee80211_tx(local, &tx);
+       ret = __ieee80211_tx(local, &tx.skb, tx.sta);
        switch (ret) {
        case IEEE80211_TX_OK:
                break;
@@ -1245,7 +1299,12 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
                        do {
                                next = skb->next;
                                skb->next = NULL;
-                               skb_queue_tail(&local->pending[queue], skb);
+                               if (unlikely(txpending))
+                                       skb_queue_head(&local->pending[queue],
+                                                      skb);
+                               else
+                                       skb_queue_tail(&local->pending[queue],
+                                                      skb);
                        } while ((skb = next));
 
                        /*
@@ -1270,7 +1329,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
        }
  out:
        rcu_read_unlock();
-       return 0;
+       return;
 
  drop:
        rcu_read_unlock();
@@ -1281,7 +1340,6 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
                dev_kfree_skb(skb);
                skb = next;
        }
-       return 0;
 }
 
 /* device xmit handlers */
@@ -1340,7 +1398,6 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                FOUND_SDATA,
                UNKNOWN_ADDRESS,
        } monitor_iface = NOT_MONITOR;
-       int ret;
 
        if (skb->iif)
                odev = dev_get_by_index(&init_net, skb->iif);
@@ -1354,11 +1411,12 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                       "originating device\n", dev->name);
 #endif
                dev_kfree_skb(skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
-           local->hw.conf.dynamic_ps_timeout > 0) {
+           local->hw.conf.dynamic_ps_timeout > 0 &&
+           !local->sw_scanning && !local->hw_scanning && local->ps_sdata) {
                if (local->hw.conf.flags & IEEE80211_CONF_PS) {
                        ieee80211_stop_queues_by_reason(&local->hw,
                                        IEEE80211_QUEUE_STOP_REASON_PS);
@@ -1383,7 +1441,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                else
                        if (mesh_nexthop_lookup(skb, osdata)) {
                                dev_put(odev);
-                               return 0;
+                               return NETDEV_TX_OK;
                        }
                if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
                        IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
@@ -1445,7 +1503,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) {
                dev_kfree_skb(skb);
                dev_put(odev);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -1454,10 +1512,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                      u.ap);
        if (likely(monitor_iface != UNKNOWN_ADDRESS))
                info->control.vif = &osdata->vif;
-       ret = ieee80211_tx(odev, skb);
+
+       ieee80211_tx(odev, skb, false);
        dev_put(odev);
 
-       return ret;
+       return NETDEV_TX_OK;
 }
 
 int ieee80211_monitor_start_xmit(struct sk_buff *skb,
@@ -1556,7 +1615,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       int ret = 1, head_need;
+       int ret = NETDEV_TX_BUSY, head_need;
        u16 ethertype, hdrlen,  meshhdrlen = 0;
        __le16 fc;
        struct ieee80211_hdr hdr;
@@ -1568,7 +1627,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
        u32 sta_flags = 0;
 
        if (unlikely(skb->len < ETH_HLEN)) {
-               ret = 0;
+               ret = NETDEV_TX_OK;
                goto fail;
        }
 
@@ -1605,7 +1664,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
                if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
                        /* Do not send frames with mesh_ttl == 0 */
                        sdata->u.mesh.mshstats.dropped_frames_ttl++;
-                       ret = 0;
+                       ret = NETDEV_TX_OK;
                        goto fail;
                }
                memset(&mesh_hdr, 0, sizeof(mesh_hdr));
@@ -1665,7 +1724,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
                hdrlen = 24;
                break;
        default:
-               ret = 0;
+               ret = NETDEV_TX_OK;
                goto fail;
        }
 
@@ -1707,7 +1766,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
 
                I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
 
-               ret = 0;
+               ret = NETDEV_TX_OK;
                goto fail;
        }
 
@@ -1799,10 +1858,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
        dev->trans_start = jiffies;
        dev_queue_xmit(skb);
 
-       return 0;
+       return NETDEV_TX_OK;
 
  fail:
-       if (!ret)
+       if (ret == NETDEV_TX_OK)
                dev_kfree_skb(skb);
 
        return ret;
@@ -1821,6 +1880,54 @@ void ieee80211_clear_tx_pending(struct ieee80211_local *local)
                skb_queue_purge(&local->pending[i]);
 }
 
+static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
+                                    struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+       struct ieee80211_hdr *hdr;
+       struct net_device *dev;
+       int ret;
+       bool result = true;
+
+       /* does interface still exist? */
+       dev = dev_get_by_index(&init_net, skb->iif);
+       if (!dev) {
+               dev_kfree_skb(skb);
+               return true;
+       }
+
+       /* validate info->control.vif against skb->iif */
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss,
+                                    struct ieee80211_sub_if_data,
+                                    u.ap);
+
+       if (unlikely(info->control.vif && info->control.vif != &sdata->vif)) {
+               dev_kfree_skb(skb);
+               result = true;
+               goto out;
+       }
+
+       if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
+               ieee80211_tx(dev, skb, true);
+       } else {
+               hdr = (struct ieee80211_hdr *)skb->data;
+               sta = sta_info_get(local, hdr->addr1);
+
+               ret = __ieee80211_tx(local, &skb, sta);
+               if (ret != IEEE80211_TX_OK)
+                       result = false;
+       }
+
+ out:
+       dev_put(dev);
+
+       return result;
+}
+
 /*
  * Transmit all pending packets. Called from tasklet, locks master device
  * TX lock so that no new packets can come in.
@@ -1829,10 +1936,8 @@ void ieee80211_tx_pending(unsigned long data)
 {
        struct ieee80211_local *local = (struct ieee80211_local *)data;
        struct net_device *dev = local->mdev;
-       struct ieee80211_hdr *hdr;
        unsigned long flags;
-       struct ieee80211_tx_data tx;
-       int i, ret;
+       int i;
        bool next;
 
        rcu_read_lock();
@@ -1862,14 +1967,10 @@ void ieee80211_tx_pending(unsigned long data)
                netif_start_subqueue(local->mdev, i);
 
                while (!skb_queue_empty(&local->pending[i])) {
-                       tx.flags = 0;
-                       tx.skb = skb_dequeue(&local->pending[i]);
-                       hdr = (struct ieee80211_hdr *)tx.skb->data;
-                       tx.sta = sta_info_get(local, hdr->addr1);
-
-                       ret = __ieee80211_tx(local, &tx);
-                       if (ret != IEEE80211_TX_OK) {
-                               skb_queue_head(&local->pending[i], tx.skb);
+                       struct sk_buff *skb = skb_dequeue(&local->pending[i]);
+
+                       if (!ieee80211_tx_pending_skb(local, skb)) {
+                               skb_queue_head(&local->pending[i], skb);
                                break;
                        }
                }
@@ -2009,18 +2110,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
        } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
                struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
                struct ieee80211_hdr *hdr;
+               struct sk_buff *presp = rcu_dereference(ifibss->presp);
 
-               if (!ifibss->probe_resp)
+               if (!presp)
                        goto out;
 
-               skb = skb_copy(ifibss->probe_resp, GFP_ATOMIC);
+               skb = skb_copy(presp, GFP_ATOMIC);
                if (!skb)
                        goto out;
 
                hdr = (struct ieee80211_hdr *) skb->data;
                hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                                 IEEE80211_STYPE_BEACON);
-
        } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                struct ieee80211_mgmt *mgmt;
                u8 *pos;
@@ -2040,7 +2141,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
                memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
                /* BSSID is left zeroed, wildcard value */
                mgmt->u.beacon.beacon_int =
-                       cpu_to_le16(local->hw.conf.beacon_int);
+                       cpu_to_le16(sdata->vif.bss_conf.beacon_int);
                mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
 
                pos = skb_put(skb, 2);