Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
[pandora-kernel.git] / net / mac80211 / tx.c
index b0beaa5..34edf7f 100644 (file)
@@ -236,6 +236,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
        if (local->hw.conf.flags & IEEE80211_CONF_PS) {
                ieee80211_stop_queues_by_reason(&local->hw,
                                                IEEE80211_QUEUE_STOP_REASON_PS);
+               ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
                ieee80211_queue_work(&local->hw,
                                     &local->dynamic_ps_disable_work);
        }
@@ -257,7 +258,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
        if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
                return TX_CONTINUE;
 
-       if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
+       if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
+           test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
            !ieee80211_is_probe_req(hdr->frame_control) &&
            !ieee80211_is_nullfunc(hdr->frame_control))
                /*
@@ -1394,7 +1396,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        /* handlers after fragment must be aware of tx info fragmentation! */
        CALL_TXH(ieee80211_tx_h_stats);
        CALL_TXH(ieee80211_tx_h_encrypt);
-       CALL_TXH(ieee80211_tx_h_calculate_duration);
+       if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
+               CALL_TXH(ieee80211_tx_h_calculate_duration);
 #undef CALL_TXH
 
  txh_done:
@@ -1750,7 +1753,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        __le16 fc;
        struct ieee80211_hdr hdr;
        struct ieee80211s_hdr mesh_hdr __maybe_unused;
-       struct mesh_path *mppath = NULL;
+       struct mesh_path __maybe_unused *mppath = NULL;
        const u8 *encaps_data;
        int encaps_len, skip_header_bytes;
        int nh_pos, h_pos;
@@ -1815,19 +1818,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        mppath = mpp_path_lookup(skb->data, sdata);
 
                /*
-                * Do not use address extension, if it is a packet from
-                * the same interface and the destination is not being
-                * proxied by any other mest point.
+                * Use address extension if it is a packet from
+                * another interface or if we know the destination
+                * is being proxied by a portal (i.e. portal address
+                * differs from proxied address)
                 */
                if (compare_ether_addr(sdata->vif.addr,
                                       skb->data + ETH_ALEN) == 0 &&
-                   (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) {
+                   !(mppath && compare_ether_addr(mppath->mpp, skb->data))) {
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        skb->data, skb->data + ETH_ALEN);
                        meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
                                        sdata, NULL, NULL);
                } else {
-                       /* packet from other interface */
                        int is_mesh_mcast = 1;
                        const u8 *mesh_da;
 
@@ -2178,6 +2181,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
        if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
                aid0 = 1;
 
+       bss->dtim_bc_mc = aid0 == 1;
+
        if (have_bits) {
                /* Find largest even number N1 so that bits numbered 1 through
                 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
@@ -2241,7 +2246,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
                ap = &sdata->u.ap;
                beacon = rcu_dereference(ap->beacon);
-               if (ap && beacon) {
+               if (beacon) {
                        /*
                         * headroom, head length,
                         * tail length and maximum TIM length
@@ -2302,6 +2307,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                struct ieee80211_mgmt *mgmt;
                u8 *pos;
 
+#ifdef CONFIG_MAC80211_MESH
+               if (!sdata->u.mesh.mesh_id_len)
+                       goto out;
+#endif
+
                /* headroom, head length, tail length and maximum TIM length */
                skb = dev_alloc_skb(local->tx_headroom + 400 +
                                sdata->u.mesh.vendor_ie_len);
@@ -2543,7 +2553,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
        if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
                goto out;
 
-       if (bss->dtim_count != 0)
+       if (bss->dtim_count != 0 || !bss->dtim_bc_mc)
                goto out; /* send buffered bc/mc only after DTIM beacon */
 
        while (1) {