mac80211: update copyrights to 2009
[safe/jmp/linux-2.6] / net / mac80211 / tx.c
index 844609c..3ad053f 100644 (file)
@@ -374,7 +374,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 
        staflags = get_sta_flags(sta);
 
-       if (unlikely((staflags & WLAN_STA_PS) &&
+       if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) &&
                     !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) {
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries "
@@ -397,8 +397,13 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                } else
                        tx->local->total_ps_buffered++;
 
-               /* Queue frame to be sent after STA sends an PS Poll frame */
-               if (skb_queue_empty(&sta->ps_tx_buf))
+               /*
+                * Queue frame to be sent after STA wakes up/polls,
+                * but don't set the TIM bit if the driver is blocking
+                * wakeup or poll response transmissions anyway.
+                */
+               if (skb_queue_empty(&sta->ps_tx_buf) &&
+                   !(staflags & WLAN_STA_PS_DRIVER))
                        sta_info_set_tim_bit(sta);
 
                info->control.jiffies = jiffies;
@@ -408,7 +413,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                return TX_QUEUED;
        }
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) {
+       else if (unlikely(staflags & WLAN_STA_PS_STA)) {
                printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll "
                       "set -> send frame\n", tx->dev->name,
                       sta->sta.addr);
@@ -1046,7 +1051,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 
        hdr = (struct ieee80211_hdr *) skb->data;
 
-       tx->sta = sta_info_get(local, hdr->addr1);
+       if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr)
+               tx->sta = rcu_dereference(sdata->u.vlan.sta);
+       if (!tx->sta)
+               tx->sta = sta_info_get(local, hdr->addr1);
 
        if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
            (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1200,23 +1208,25 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
        struct sk_buff *skb = tx->skb;
        ieee80211_tx_result res = TX_DROP;
 
-#define CALL_TXH(txh)          \
-       res = txh(tx);          \
-       if (res != TX_CONTINUE) \
-               goto txh_done;
-
-       CALL_TXH(ieee80211_tx_h_check_assoc)
-       CALL_TXH(ieee80211_tx_h_ps_buf)
-       CALL_TXH(ieee80211_tx_h_select_key)
-       CALL_TXH(ieee80211_tx_h_michael_mic_add)
-       CALL_TXH(ieee80211_tx_h_rate_ctrl)
-       CALL_TXH(ieee80211_tx_h_misc)
-       CALL_TXH(ieee80211_tx_h_sequence)
-       CALL_TXH(ieee80211_tx_h_fragment)
+#define CALL_TXH(txh) \
+       do {                            \
+               res = txh(tx);          \
+               if (res != TX_CONTINUE) \
+                       goto txh_done;  \
+       } while (0)
+
+       CALL_TXH(ieee80211_tx_h_check_assoc);
+       CALL_TXH(ieee80211_tx_h_ps_buf);
+       CALL_TXH(ieee80211_tx_h_select_key);
+       CALL_TXH(ieee80211_tx_h_michael_mic_add);
+       CALL_TXH(ieee80211_tx_h_rate_ctrl);
+       CALL_TXH(ieee80211_tx_h_misc);
+       CALL_TXH(ieee80211_tx_h_sequence);
+       CALL_TXH(ieee80211_tx_h_fragment);
        /* 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)
+       CALL_TXH(ieee80211_tx_h_stats);
+       CALL_TXH(ieee80211_tx_h_encrypt);
+       CALL_TXH(ieee80211_tx_h_calculate_duration);
 #undef CALL_TXH
 
  txh_done:
@@ -1606,7 +1616,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        const u8 *encaps_data;
        int encaps_len, skip_header_bytes;
        int nh_pos, h_pos;
-       struct sta_info *sta;
+       struct sta_info *sta = NULL;
        u32 sta_flags = 0;
 
        if (unlikely(skb->len < ETH_HLEN)) {
@@ -1623,8 +1633,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
 
        switch (sdata->vif.type) {
-       case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_AP_VLAN:
+               rcu_read_lock();
+               if (sdata->use_4addr)
+                       sta = rcu_dereference(sdata->u.vlan.sta);
+               if (sta) {
+                       fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
+                       /* RA TA DA SA */
+                       memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
+                       memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+                       memcpy(hdr.addr3, skb->data, ETH_ALEN);
+                       memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+                       hdrlen = 30;
+                       sta_flags = get_sta_flags(sta);
+               }
+               rcu_read_unlock();
+               if (sta)
+                       break;
+               /* fall through */
+       case NL80211_IFTYPE_AP:
                fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
                /* DA BSSID SA */
                memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1698,12 +1725,21 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                break;
 #endif
        case NL80211_IFTYPE_STATION:
-               fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
-               /* BSSID SA DA */
                memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               hdrlen = 24;
+               if (sdata->use_4addr && ethertype != ETH_P_PAE) {
+                       fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
+                       /* RA TA DA SA */
+                       memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+                       memcpy(hdr.addr3, skb->data, ETH_ALEN);
+                       memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+                       hdrlen = 30;
+               } else {
+                       fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
+                       /* BSSID SA DA */
+                       memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+                       memcpy(hdr.addr3, skb->data, ETH_ALEN);
+                       hdrlen = 24;
+               }
                break;
        case NL80211_IFTYPE_ADHOC:
                /* DA SA BSSID */
@@ -2112,7 +2148,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                    cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
                memset(mgmt->da, 0xff, ETH_ALEN);
                memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
-               /* BSSID is left zeroed, wildcard value */
+               memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
                mgmt->u.beacon.beacon_int =
                        cpu_to_le16(sdata->vif.bss_conf.beacon_int);
                mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */