mac80211: update to wireless-testing 2011-06-22
[openwrt.git] / package / mac80211 / patches / 300-pending_work.patch
index 4cd18b4c716255da18f6503497c9530e7f48d20e..c2dbae572bebcafcc2ce8739ee775ceec6bb373b 100644 (file)
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1048,6 +1048,8 @@ static int ath9k_start(struct ieee80211_
-               "Starting driver with initial channel: %d MHz\n",
-               curchan->center_freq);
-+      ath9k_ps_wakeup(sc);
-+
-       mutex_lock(&sc->mutex);
-       /* setup initial channel */
-@@ -1143,6 +1145,8 @@ static int ath9k_start(struct ieee80211_
- mutex_unlock:
-       mutex_unlock(&sc->mutex);
-+      ath9k_ps_restore(sc);
-+
-       return r;
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -176,6 +176,8 @@ static void ieee80211_send_addba_resp(st
+               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
++      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
++              memcpy(mgmt->bssid, da, ETH_ALEN);
+       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                         IEEE80211_STYPE_ACTION);
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
+       memcpy(mgmt->da, da, ETH_ALEN);
+       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+       if (sdata->vif.type == NL80211_IFTYPE_AP ||
+-          sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++          sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
++          sdata->vif.type == NL80211_IFTYPE_WDS)
+               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+@@ -398,7 +399,8 @@ int ieee80211_start_tx_ba_session(struct
+        */
+       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+-          sdata->vif.type != NL80211_IFTYPE_AP)
++          sdata->vif.type != NL80211_IFTYPE_AP &&
++          sdata->vif.type != NL80211_IFTYPE_WDS)
+               return -EINVAL;
+       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
+       char buf[100];
+       struct sta_info *sta = file->private_data;
+       u32 staflags = get_sta_flags(sta);
+-      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
++      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
+               staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
+               staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+               staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
+@@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil
+               staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+               staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+               staflags & WLAN_STA_WME ? "WME\n" : "",
+-              staflags & WLAN_STA_WDS ? "WDS\n" : "",
+               staflags & WLAN_STA_MFP ? "MFP\n" : "");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  }
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -661,7 +661,6 @@ static void ieee80211_sta_find_ibss(stru
- static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
-                                       struct sk_buff *req)
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
  {
--      struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req);
-       struct ieee80211_mgmt *mgmt = (void *)req->data;
-       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-@@ -685,7 +684,7 @@ static void ieee80211_rx_mgmt_probe_req(
-              mgmt->bssid, tx_last_beacon);
- #endif /* CONFIG_MAC80211_IBSS_DEBUG */
--      if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH))
-+      if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
-               return;
-       if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 &&
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -659,18 +659,14 @@ minstrel_ht_update_caps(void *priv, stru
-       struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
-       struct ieee80211_local *local = hw_to_local(mp->hw);
-       u16 sta_cap = sta->ht_cap.cap;
-+      int n_supported = 0;
-       int ack_dur;
-       int stbc;
-       int i;
-       /* fall back to the old minstrel for legacy stations */
--      if (!sta->ht_cap.ht_supported) {
--              msp->is_ht = false;
--              memset(&msp->legacy, 0, sizeof(msp->legacy));
--              msp->legacy.r = msp->ratelist;
--              msp->legacy.sample_table = msp->sample_table;
--              return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
+-      struct sta_info *sta;
+       u32 changed = 0;
+       int res;
+       u32 hw_reconf_flags = 0;
+@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
+       set_bit(SDATA_STATE_RUNNING, &sdata->state);
+-      if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+-              /* Create STA entry for the WDS peer */
+-              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
+-                                   GFP_KERNEL);
+-              if (!sta) {
+-                      res = -ENOMEM;
+-                      goto err_del_interface;
+-              }
+-
+-              /* no locking required since STA is not live yet */
+-              sta->flags |= WLAN_STA_AUTHORIZED;
+-
+-              res = sta_info_insert(sta);
+-              if (res) {
+-                      /* STA has been freed */
+-                      goto err_del_interface;
+-              }
+-
+-              rate_control_rate_init(sta);
 -      }
-+      if (!sta->ht_cap.ht_supported)
-+              goto use_legacy;
+-
+       /*
+        * set_multicast_list will be invoked by the networking core
+        * which will check whether any increments here were done in
+@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
+       netif_tx_start_all_queues(dev);
  
-       BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
-               MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS);
-@@ -725,7 +721,22 @@ minstrel_ht_update_caps(void *priv, stru
+       return 0;
+- err_del_interface:
+-      drv_remove_interface(local, &sdata->vif);
++
+  err_stop:
+       if (!local->open_count)
+               drv_stop(local);
+@@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne
+       dev->destructor = free_netdev;
+ }
  
-               mi->groups[i].supported =
-                       mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
++static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
++                                       struct sk_buff *skb)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_rx_status *rx_status;
++      struct ieee802_11_elems elems;
++      struct ieee80211_mgmt *mgmt;
++      struct sta_info *sta;
++      size_t baselen;
++      u32 rates = 0;
++      u16 stype;
++      bool new = false;
++      enum ieee80211_band band = local->hw.conf.channel->band;
++      struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 +
-+              if (mi->groups[i].supported)
-+                      n_supported++;
-       }
++      rx_status = IEEE80211_SKB_RXCB(skb);
++      mgmt = (struct ieee80211_mgmt *) skb->data;
++      stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
 +
-+      if (!n_supported)
-+              goto use_legacy;
++      if (stype != IEEE80211_STYPE_BEACON)
++              return;
 +
-+      return;
++      baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
++      if (baselen > skb->len)
++              return;
 +
-+use_legacy:
-+      msp->is_ht = false;
-+      memset(&msp->legacy, 0, sizeof(msp->legacy));
-+      msp->legacy.r = msp->ratelist;
-+      msp->legacy.sample_table = msp->sample_table;
-+      return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
- }
- static void
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -814,8 +814,8 @@ struct ieee80211_local {
-       struct rate_control_ref *rate_ctrl;
--      struct crypto_blkcipher *wep_tx_tfm;
--      struct crypto_blkcipher *wep_rx_tfm;
-+      struct crypto_cipher *wep_tx_tfm;
-+      struct crypto_cipher *wep_rx_tfm;
-       u32 wep_iv;
-       /* see iface.c */
---- a/net/mac80211/tkip.c
-+++ b/net/mac80211/tkip.c
-@@ -202,7 +202,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
-  * @payload_len is the length of payload (_not_ including IV/ICV length).
-  * @ta is the transmitter addresses.
-  */
--int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
-+int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
-                               struct ieee80211_key *key,
-                               u8 *pos, size_t payload_len, u8 *ta)
- {
-@@ -223,7 +223,7 @@ int ieee80211_tkip_encrypt_data(struct c
-  * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
-  * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
-  * length of payload, including IV, Ext. IV, MIC, ICV.  */
--int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
-+int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
-                               struct ieee80211_key *key,
-                               u8 *payload, size_t payload_len, u8 *ta,
-                               u8 *ra, int only_iv, int queue,
---- a/net/mac80211/tkip.h
-+++ b/net/mac80211/tkip.h
-@@ -15,7 +15,7 @@
- u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16);
--int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
-+int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
-                                struct ieee80211_key *key,
-                                u8 *pos, size_t payload_len, u8 *ta);
- enum {
-@@ -24,7 +24,7 @@ enum {
-       TKIP_DECRYPT_INVALID_KEYIDX = -2,
-       TKIP_DECRYPT_REPLAY = -3,
- };
--int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
-+int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm,
-                               struct ieee80211_key *key,
-                               u8 *payload, size_t payload_len, u8 *ta,
-                               u8 *ra, int only_iv, int queue,
---- a/net/mac80211/wep.c
-+++ b/net/mac80211/wep.c
-@@ -30,17 +30,15 @@ int ieee80211_wep_init(struct ieee80211_
-       /* start WEP IV from a random value */
-       get_random_bytes(&local->wep_iv, WEP_IV_LEN);
--      local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
--                                              CRYPTO_ALG_ASYNC);
-+      local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(local->wep_tx_tfm)) {
-               local->wep_rx_tfm = ERR_PTR(-EINVAL);
-               return PTR_ERR(local->wep_tx_tfm);
-       }
--      local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
--                                              CRYPTO_ALG_ASYNC);
-+      local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(local->wep_rx_tfm)) {
--              crypto_free_blkcipher(local->wep_tx_tfm);
-+              crypto_free_cipher(local->wep_tx_tfm);
-               local->wep_tx_tfm = ERR_PTR(-EINVAL);
-               return PTR_ERR(local->wep_rx_tfm);
-       }
-@@ -51,9 +49,9 @@ int ieee80211_wep_init(struct ieee80211_
- void ieee80211_wep_free(struct ieee80211_local *local)
- {
-       if (!IS_ERR(local->wep_tx_tfm))
--              crypto_free_blkcipher(local->wep_tx_tfm);
-+              crypto_free_cipher(local->wep_tx_tfm);
-       if (!IS_ERR(local->wep_rx_tfm))
--              crypto_free_blkcipher(local->wep_rx_tfm);
-+              crypto_free_cipher(local->wep_rx_tfm);
- }
- static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
-@@ -127,12 +125,11 @@ static void ieee80211_wep_remove_iv(stru
- /* Perform WEP encryption using given key. data buffer must have tailroom
-  * for 4-byte ICV. data_len must not include this ICV. Note: this function
-  * does _not_ add IV. data = RC4(data | CRC32(data)) */
--int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
-+int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
-                              size_t klen, u8 *data, size_t data_len)
- {
--      struct blkcipher_desc desc = { .tfm = tfm };
--      struct scatterlist sg;
-       __le32 icv;
-+      int i;
-       if (IS_ERR(tfm))
-               return -1;
-@@ -140,9 +137,9 @@ int ieee80211_wep_encrypt_data(struct cr
-       icv = cpu_to_le32(~crc32_le(~0, data, data_len));
-       put_unaligned(icv, (__le32 *)(data + data_len));
--      crypto_blkcipher_setkey(tfm, rc4key, klen);
--      sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
--      crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
-+      crypto_cipher_setkey(tfm, rc4key, klen);
-+      for (i = 0; i < data_len + WEP_ICV_LEN; i++)
-+              crypto_cipher_encrypt_one(tfm, data + i, data + i);
-       return 0;
- }
-@@ -186,19 +183,18 @@ int ieee80211_wep_encrypt(struct ieee802
- /* Perform WEP decryption using given key. data buffer includes encrypted
-  * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
-  * Return 0 on success and -1 on ICV mismatch. */
--int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
-+int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
-                              size_t klen, u8 *data, size_t data_len)
++      ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
++                             skb->len - baselen, &elems);
++
++      rates = ieee80211_sta_get_rates(local, &elems, band);
++
++      rcu_read_lock();
++
++      sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
++
++      if (!sta) {
++              rcu_read_unlock();
++              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++                                   GFP_KERNEL);
++              if (!sta)
++                      return;
++
++              new = true;
++      }
++
++      sta->last_rx = jiffies;
++      sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
++
++      if (elems.ht_cap_elem)
++              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
++                              elems.ht_cap_elem, &sta->sta.ht_cap);
++
++      if (elems.wmm_param)
++              set_sta_flags(sta, WLAN_STA_WME);
++
++      if (new) {
++              sta->flags = WLAN_STA_AUTHORIZED;
++              rate_control_rate_init(sta);
++              sta_info_insert_rcu(sta);
++      }
++
++      rcu_read_unlock();
++}
++
+ static void ieee80211_iface_work(struct work_struct *work)
  {
--      struct blkcipher_desc desc = { .tfm = tfm };
--      struct scatterlist sg;
-       __le32 crc;
-+      int i;
-       if (IS_ERR(tfm))
-               return -1;
--      crypto_blkcipher_setkey(tfm, rc4key, klen);
--      sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
--      crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
-+      crypto_cipher_setkey(tfm, rc4key, klen);
-+      for (i = 0; i < data_len + WEP_ICV_LEN; i++)
-+              crypto_cipher_decrypt_one(tfm, data + i, data + i);
-       crc = cpu_to_le32(~crc32_le(~0, data, data_len));
-       if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
---- a/net/mac80211/wep.h
-+++ b/net/mac80211/wep.h
-@@ -18,12 +18,12 @@
- int ieee80211_wep_init(struct ieee80211_local *local);
- void ieee80211_wep_free(struct ieee80211_local *local);
--int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
-+int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
-                               size_t klen, u8 *data, size_t data_len);
- int ieee80211_wep_encrypt(struct ieee80211_local *local,
-                         struct sk_buff *skb,
-                         const u8 *key, int keylen, int keyidx);
--int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
-+int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
-                              size_t klen, u8 *data, size_t data_len);
- bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+       struct ieee80211_sub_if_data *sdata =
+@@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct 
+                               break;
+                       ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+                       break;
++              case NL80211_IFTYPE_WDS:
++                      ieee80211_wds_rx_queued_mgmt(sdata, skb);
++                      break;
+               default:
+                       WARN(1, "frame for unexpected interface type");
+                       break;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+                */
+               if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+-                  sdata->vif.type != NL80211_IFTYPE_AP)
++                  sdata->vif.type != NL80211_IFTYPE_AP &&
++                  sdata->vif.type != NL80211_IFTYPE_WDS)
+                       break;
+               /* verify action_code is present */
+@@ -2335,13 +2336,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+           sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+-          sdata->vif.type != NL80211_IFTYPE_STATION)
++          sdata->vif.type != NL80211_IFTYPE_STATION &&
++          sdata->vif.type != NL80211_IFTYPE_WDS)
+               return RX_DROP_MONITOR;
+       switch (stype) {
+       case cpu_to_le16(IEEE80211_STYPE_BEACON):
+       case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+-              /* process for all: mesh, mlme, ibss */
++              /* process for all: mesh, mlme, ibss, wds */
+               break;
+       case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+       case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+@@ -2680,10 +2682,16 @@ static int prepare_for_handlers(struct i
+               }
+               break;
+       case NL80211_IFTYPE_WDS:
+-              if (bssid || !ieee80211_is_data(hdr->frame_control))
+-                      return 0;
+               if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
+                       return 0;
++
++              if (ieee80211_is_data(hdr->frame_control) ||
++                  ieee80211_is_action(hdr->frame_control)) {
++                      if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
++                              return 0;
++              } else if (!ieee80211_is_beacon(hdr->frame_control))
++                      return 0;
++
+               break;
+       default:
+               /* should never get here */
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -31,7 +31,6 @@
+  *    frames.
+  * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
+  * @WLAN_STA_WME: Station is a QoS-STA.
+- * @WLAN_STA_WDS: Station is one of our WDS peers.
+  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
+  *    IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
+  *    frame to this station is transmitted.
+@@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags {
+       WLAN_STA_SHORT_PREAMBLE = 1<<4,
+       WLAN_STA_ASSOC_AP       = 1<<5,
+       WLAN_STA_WME            = 1<<6,
+-      WLAN_STA_WDS            = 1<<7,
+       WLAN_STA_CLEAR_PS_FILT  = 1<<9,
+       WLAN_STA_MFP            = 1<<10,
+       WLAN_STA_BLOCK_BA       = 1<<11,