mac80211: update to 2009-11-13 and add some of my new performance improvement patches...
authorFelix Fietkau <nbd@openwrt.org>
Sat, 14 Nov 2009 02:35:04 +0000 (02:35 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 14 Nov 2009 02:35:04 +0000 (02:35 +0000)
SVN-Revision: 18415

14 files changed:
package/mac80211/Makefile
package/mac80211/patches/002-disable_rfkill.patch
package/mac80211/patches/009-remove_mac80211_module_dependence.patch
package/mac80211/patches/010-b43_config.patch
package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch
package/mac80211/patches/405-b43_locking_fix.patch [deleted file]
package/mac80211/patches/500-4addr_bcast_fix.patch [new file with mode: 0644]
package/mac80211/patches/500-nl80211_4addr.patch [deleted file]
package/mac80211/patches/510-mac80211_4addr_vlan.patch [deleted file]
package/mac80211/patches/510-nl80211_vlan_add_fix.patch [new file with mode: 0644]
package/mac80211/patches/520-driver_flags.patch [new file with mode: 0644]
package/mac80211/patches/520-nl80211_vlan_add_fix.patch [deleted file]
package/mac80211/patches/530-ath9k_cleanup.patch [new file with mode: 0644]
package/mac80211/patches/540-monitor_tx_status.patch [new file with mode: 0644]

index 13d1670..e4e9b7b 100644 (file)
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2009-11-03
-PKG_RELEASE:=2
+PKG_VERSION:=2009-11-13
+PKG_RELEASE:=1
 PKG_SOURCE_URL:= \
        http://www.orbit-lab.org/kernel/compat-wireless-2.6/2009/11 \
        http://wireless.kernel.org/download/compat-wireless-2.6
-PKG_MD5SUM:=f8434790c9552abb9c98926d7ae616fe
+PKG_MD5SUM:=920c3bcfd1b4cd6079a8f9db4afe4e4f
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -323,9 +323,10 @@ define KernelPackage/ath9k
   URL:=http://linuxwireless.org/en/users/Drivers/ath9k
   DEPENDS+= +kmod-ath
   FILES:= \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.$(LINUX_KMOD_SUFFIX) \
        $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.$(LINUX_KMOD_SUFFIX) \
        $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.$(LINUX_KMOD_SUFFIX)
-  AUTOLOAD:=$(call AutoLoad,27,ath9k_hw ath9k)
+  AUTOLOAD:=$(call AutoLoad,27,ath9k_hw ath9k_common ath9k)
 endef
 
 define KernelPackage/ath9k/description
index 0140ea2..3aab629 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -145,7 +145,7 @@ ifneq ($(CONFIG_PCI),)
+@@ -147,7 +147,7 @@ ifneq ($(CONFIG_PCI),)
  
  CONFIG_ATH5K=m
  # CONFIG_ATH5K_DEBUG=y
@@ -8,8 +8,8 @@
 +# CONFIG_ATH5K_RFKILL=y
  CONFIG_ATH9K_HW=m
  CONFIG_ATH9K=m
- # CONFIG_ATH9K_DEBUG=y
-@@ -153,7 +153,7 @@ CONFIG_ATH9K=m
+ # Note: once ath9k_htc is added we'll have to move
+@@ -159,7 +159,7 @@ CONFIG_ATH9K_COMMON=m
  
  CONFIG_IWLWIFI=m
  CONFIG_IWLWIFI_LEDS=y
@@ -18,7 +18,7 @@
  CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT=y
  # CONFIG_IWLWIFI_DEBUG=y
  # CONFIG_IWLWIFI_DEBUGFS=y
-@@ -173,7 +173,7 @@ CONFIG_B43_PCMCIA=y
+@@ -179,7 +179,7 @@ CONFIG_B43_PCMCIA=y
  endif
  CONFIG_B43_PIO=y
  CONFIG_B43_LEDS=y
@@ -27,7 +27,7 @@
  CONFIG_B43_PHY_LP=y
  # CONFIG_B43_DEBUG=y
  # CONFIG_B43_FORCE_PIO=y
-@@ -183,7 +183,7 @@ CONFIG_B43LEGACY_HWRNG=y
+@@ -189,7 +189,7 @@ CONFIG_B43LEGACY_HWRNG=y
  CONFIG_B43LEGACY_PCI_AUTOSELECT=y
  CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
  CONFIG_B43LEGACY_LEDS=y
  # CONFIG_B43LEGACY_DEBUG=y
  CONFIG_B43LEGACY_DMA=y
  CONFIG_B43LEGACY_PIO=y
-@@ -373,7 +373,7 @@ CONFIG_RT2X00_LIB=m
- CONFIG_RT2X00_LIB_HT=y
- CONFIG_RT2X00_LIB_FIRMWARE=y
- CONFIG_RT2X00_LIB_CRYPTO=y
--CONFIG_RT2X00_LIB_RFKILL=y
-+# CONFIG_RT2X00_LIB_RFKILL=y
- CONFIG_RT2X00_LIB_LEDS=y
- # CONFIG_RT2X00_LIB_DEBUGFS=y
- # CONFIG_RT2X00_DEBUG=y
-@@ -415,8 +415,8 @@ endif
+@@ -422,8 +422,8 @@ endif
  # We need the backported rfkill module on kernel < 2.6.31.
  # In more recent kernel versions use the in kernel rfkill module.
  ifdef CONFIG_COMPAT_WIRELESS_31
index d1c9159..14d4290 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -47,21 +47,6 @@ $(error "ERROR: Your 2.6.27 kernel has C
+@@ -49,21 +49,6 @@ $(error "ERROR: Your 2.6.27 kernel has C
  endif
  endif
  
index ba97e76..9074ee7 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -154,12 +154,12 @@ CONFIG_B43_HWRNG=y
+@@ -160,12 +160,12 @@ CONFIG_B43_HWRNG=y
  CONFIG_B43_PCI_AUTOSELECT=y
  CONFIG_B43_PCICORE_AUTOSELECT=y
  ifneq ($(CONFIG_PCMCIA),)
@@ -16,7 +16,7 @@
  # CONFIG_B43_DEBUG=y
  # CONFIG_B43_FORCE_PIO=y
  
-@@ -208,8 +208,8 @@ CONFIG_SSB_PCIHOST_POSSIBLE=y
+@@ -219,8 +219,8 @@ CONFIG_SSB_PCIHOST_POSSIBLE=y
  CONFIG_SSB_PCIHOST=y
  CONFIG_SSB_B43_PCI_BRIDGE=y
  ifneq ($(CONFIG_PCMCIA),)
index b458dde..2a9bdc8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1135,6 +1135,9 @@ static void ath_unregister_led(struct at
+@@ -1139,6 +1139,9 @@ static void ath_unregister_led(struct at
  
  static void ath_deinit_leds(struct ath_softc *sc)
  {
@@ -10,7 +10,7 @@
        ath_unregister_led(&sc->assoc_led);
        sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
        ath_unregister_led(&sc->tx_led);
-@@ -1153,6 +1156,9 @@ static void ath_init_leds(struct ath_sof
+@@ -1157,6 +1160,9 @@ static void ath_init_leds(struct ath_sof
        else
                sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
  
diff --git a/package/mac80211/patches/405-b43_locking_fix.patch b/package/mac80211/patches/405-b43_locking_fix.patch
deleted file mode 100644 (file)
index c90890a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Subject: [PATCH] b43: work around a locking issue in ->set_tim()
-
-ops->set_tim() must be atomic, so b43 trying to acquire a mutex leads
-to a kernel crash. This patch trades an easy to trigger crash in AP
-mode for an unlikely race condition. According to Michael, the real
-fix would be to allow set_tim() callbacks to sleep, since b43 is
-not the only driver that needs to sleep in all callbacks.
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
---- a/drivers/net/wireless/b43/main.c
-+++ b/drivers/net/wireless/b43/main.c
-@@ -4534,9 +4534,8 @@ static int b43_op_beacon_set_tim(struct 
- {
-       struct b43_wl *wl = hw_to_b43_wl(hw);
--      mutex_lock(&wl->mutex);
-+      /* FIXME: add locking */
-       b43_update_templates(wl);
--      mutex_unlock(&wl->mutex);
-       return 0;
- }
diff --git a/package/mac80211/patches/500-4addr_bcast_fix.patch b/package/mac80211/patches/500-4addr_bcast_fix.patch
new file mode 100644 (file)
index 0000000..3143aaf
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1236,7 +1236,7 @@ ieee80211_deliver_skb(struct ieee80211_r
+       if ((sdata->vif.type == NL80211_IFTYPE_AP ||
+            sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+           !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
+-          (rx->flags & IEEE80211_RX_RA_MATCH)) {
++          (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) {
+               if (is_multicast_ether_addr(ehdr->h_dest)) {
+                       /*
+                        * send multicast frames both to higher layers in
diff --git a/package/mac80211/patches/500-nl80211_4addr.patch b/package/mac80211/patches/500-nl80211_4addr.patch
deleted file mode 100644 (file)
index de3b78f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
---- a/include/linux/nl80211.h
-+++ b/include/linux/nl80211.h
-@@ -584,6 +584,8 @@ enum nl80211_commands {
-  *    changed then the list changed and the dump should be repeated
-  *    completely from scratch.
-  *
-+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
-+ *
-  * @NL80211_ATTR_MAX: highest attribute number currently defined
-  * @__NL80211_ATTR_AFTER_LAST: internal use
-  */
-@@ -714,6 +716,8 @@ enum nl80211_attrs {
-       NL80211_ATTR_PID,
-+      NL80211_ATTR_4ADDR,
-+
-       /* add attributes here, update the policy in nl80211.c */
-       __NL80211_ATTR_AFTER_LAST,
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -207,10 +207,12 @@ struct ieee80211_supported_band {
-  * struct vif_params - describes virtual interface parameters
-  * @mesh_id: mesh ID to use
-  * @mesh_id_len: length of the mesh ID
-+ * @use_4addr: use 4-address frames
-  */
- struct vif_params {
-        u8 *mesh_id;
-        int mesh_id_len;
-+       int use_4addr;
- };
- /**
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -140,6 +140,7 @@ static struct nla_policy nl80211_policy[
-       [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
-       [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
-       [NL80211_ATTR_PID] = { .type = NLA_U32 },
-+      [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
- };
- /* policy for the attributes */
-@@ -989,6 +990,13 @@ static int nl80211_set_interface(struct 
-               change = true;
-       }
-+      if (info->attrs[NL80211_ATTR_4ADDR]) {
-+              params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
-+              change = true;
-+      } else {
-+              params.use_4addr = -1;
-+      }
-+
-       if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
-               if (ntype != NL80211_IFTYPE_MONITOR) {
-                       err = -EINVAL;
-@@ -1055,6 +1063,9 @@ static int nl80211_new_interface(struct 
-               params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
-       }
-+      if (info->attrs[NL80211_ATTR_4ADDR])
-+              params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
-+
-       err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
-                                 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
-                                 &flags);
diff --git a/package/mac80211/patches/510-mac80211_4addr_vlan.patch b/package/mac80211/patches/510-mac80211_4addr_vlan.patch
deleted file mode 100644 (file)
index d3d1e82..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -208,6 +208,9 @@ struct ieee80211_if_wds {
- struct ieee80211_if_vlan {
-       struct list_head list;
-+
-+      /* used for all tx if the VLAN is configured to 4-addr mode */
-+      struct sta_info *sta;
- };
- struct mesh_stats {
-@@ -457,6 +460,8 @@ struct ieee80211_sub_if_data {
-       int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
-       int max_ratectrl_rateidx; /* max TX rateidx for rate control */
-+      bool use_4addr; /* use 4-address frames */
-+
-       union {
-               struct ieee80211_if_ap ap;
-               struct ieee80211_if_wds wds;
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -36,6 +36,24 @@ static bool nl80211_type_check(enum nl80
-       }
- }
-+static bool nl80211_params_check(enum nl80211_iftype type,
-+                               struct vif_params *params)
-+{
-+      if (!nl80211_type_check(type))
-+              return false;
-+
-+      if (params->use_4addr > 0) {
-+              switch(type) {
-+              case NL80211_IFTYPE_AP_VLAN:
-+              case NL80211_IFTYPE_STATION:
-+                      break;
-+              default:
-+                      return false;
-+              }
-+      }
-+      return true;
-+}
-+
- static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
-                              enum nl80211_iftype type, u32 *flags,
-                              struct vif_params *params)
-@@ -45,7 +63,7 @@ static int ieee80211_add_iface(struct wi
-       struct ieee80211_sub_if_data *sdata;
-       int err;
--      if (!nl80211_type_check(type))
-+      if (!nl80211_params_check(type, params))
-               return -EINVAL;
-       err = ieee80211_if_add(local, name, &dev, type, params);
-@@ -75,7 +93,7 @@ static int ieee80211_change_iface(struct
-       if (netif_running(dev))
-               return -EBUSY;
--      if (!nl80211_type_check(type))
-+      if (!nl80211_params_check(type, params))
-               return -EINVAL;
-       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-@@ -89,6 +107,9 @@ static int ieee80211_change_iface(struct
-                                           params->mesh_id_len,
-                                           params->mesh_id);
-+      if (params->use_4addr >= 0)
-+              sdata->use_4addr = !!params->use_4addr;
-+
-       if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
-               return 0;
-@@ -806,6 +827,13 @@ static int ieee80211_change_station(stru
-                       return -EINVAL;
-               }
-+              if (vlansdata->use_4addr) {
-+                      if (vlansdata->u.vlan.sta)
-+                              return -EBUSY;
-+
-+                      rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
-+              }
-+
-               sta->sdata = vlansdata;
-               ieee80211_send_layer2_update(sta);
-       }
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -489,6 +489,9 @@ static void __sta_info_unlink(struct sta
-       local->num_sta--;
-       local->sta_generation++;
-+      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+              rcu_assign_pointer(sdata->u.vlan.sta, NULL);
-+
-       if (local->ops->sta_notify) {
-               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-                       sdata = container_of(sdata->bss,
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1046,7 +1046,10 @@ ieee80211_tx_prepare(struct ieee80211_su
-       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)) {
-@@ -1608,7 +1611,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
-       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)) {
-@@ -1625,8 +1628,25 @@ netdev_tx_t ieee80211_subif_start_xmit(s
-       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);
-@@ -1700,12 +1720,21 @@ netdev_tx_t ieee80211_subif_start_xmit(s
-               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 */
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -772,6 +772,7 @@ int ieee80211_if_change_type(struct ieee
-               ieee80211_mandatory_rates(sdata->local,
-                       sdata->local->hw.conf.channel->band);
-       sdata->drop_unencrypted = 0;
-+      sdata->use_4addr = 0;
-       return 0;
- }
-@@ -853,6 +854,9 @@ int ieee80211_if_add(struct ieee80211_lo
-                                           params->mesh_id_len,
-                                           params->mesh_id);
-+      if (params && params->use_4addr >= 0)
-+              sdata->use_4addr = !!params->use_4addr;
-+
-       mutex_lock(&local->iflist_mtx);
-       list_add_tail_rcu(&sdata->list, &local->interfaces);
-       mutex_unlock(&local->iflist_mtx);
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1237,6 +1237,13 @@ __ieee80211_data_to_8023(struct ieee8021
- {
-       struct net_device *dev = rx->dev;
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+
-+      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr &&
-+          ieee80211_has_a4(hdr->frame_control))
-+              return -1;
-+      if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1))
-+              return -1;
-       return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
- }
-@@ -1285,7 +1292,7 @@ ieee80211_deliver_skb(struct ieee80211_r
-       if ((sdata->vif.type == NL80211_IFTYPE_AP ||
-            sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-           !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
--          (rx->flags & IEEE80211_RX_RA_MATCH)) {
-+          (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) {
-               if (is_multicast_ether_addr(ehdr->h_dest)) {
-                       /*
-                        * send multicast frames both to higher layers in
-@@ -1590,6 +1597,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
- {
-       struct net_device *dev = rx->dev;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       __le16 fc = hdr->frame_control;
-       int err;
-@@ -1599,6 +1607,14 @@ ieee80211_rx_h_data(struct ieee80211_rx_
-       if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
-               return RX_DROP_MONITOR;
-+      /*
-+       * Allow the cooked monitor interface of an AP to see 4-addr frames so
-+       * that a 4-addr station can be detected and moved into a separate VLAN
-+       */
-+      if (ieee80211_has_a4(hdr->frame_control) &&
-+          sdata->vif.type == NL80211_IFTYPE_AP)
-+              return RX_DROP_MONITOR;
-+
-       err = __ieee80211_data_to_8023(rx);
-       if (unlikely(err))
-               return RX_DROP_UNUSABLE;
-@@ -2039,7 +2055,7 @@ static int prepare_for_handlers(struct i
-       switch (sdata->vif.type) {
-       case NL80211_IFTYPE_STATION:
--              if (!bssid)
-+              if (!bssid && !sdata->use_4addr)
-                       return 0;
-               if (!multicast &&
-                   compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -320,7 +320,9 @@ int ieee80211_data_to_8023(struct sk_buf
-               break;
-       case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
-               if (unlikely(iftype != NL80211_IFTYPE_WDS &&
--                           iftype != NL80211_IFTYPE_MESH_POINT))
-+                           iftype != NL80211_IFTYPE_MESH_POINT &&
-+                           iftype != NL80211_IFTYPE_AP_VLAN &&
-+                           iftype != NL80211_IFTYPE_STATION))
-                       return -1;
-               if (iftype == NL80211_IFTYPE_MESH_POINT) {
-                       struct ieee80211s_hdr *meshdr =
diff --git a/package/mac80211/patches/510-nl80211_vlan_add_fix.patch b/package/mac80211/patches/510-nl80211_vlan_add_fix.patch
new file mode 100644 (file)
index 0000000..e0cdaea
--- /dev/null
@@ -0,0 +1,20 @@
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -1813,7 +1813,7 @@ static int nl80211_get_station(struct sk
+ }
+ /*
+- * Get vlan interface making sure it is on the right wiphy.
++ * Get vlan interface making sure it is running and on the right wiphy.
+  */
+ static int get_vlan(struct genl_info *info,
+                   struct cfg80211_registered_device *rdev,
+@@ -1831,6 +1831,8 @@ static int get_vlan(struct genl_info *in
+                       return -EINVAL;
+               if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
+                       return -EINVAL;
++              if (!netif_running(*vlan))
++                      return -ENETDOWN;
+       }
+       return 0;
+ }
diff --git a/package/mac80211/patches/520-driver_flags.patch b/package/mac80211/patches/520-driver_flags.patch
new file mode 100644 (file)
index 0000000..2dc2092
--- /dev/null
@@ -0,0 +1,27 @@
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -386,11 +386,12 @@ struct ieee80211_tx_rate {
+  * @flags: transmit info flags, defined above
+  * @band: the band to transmit on (use for checking for races)
+  * @antenna_sel_tx: antenna to use, 0 for automatic diversity
++ * @driver_flags: flags for internal driver use
+  * @pad: padding, ignore
+  * @control: union for control data
+  * @status: union for status data
+  * @driver_data: array of driver_data pointers
+- * @ampdu_ack_len: number of aggregated frames.
++ * @ampdu_ack_len: number of acked aggregated frames.
+  *    relevant only if IEEE80211_TX_STATUS_AMPDU was set.
+  * @ampdu_ack_map: block ack bit map for the aggregation.
+  *    relevant only if IEEE80211_TX_STATUS_AMPDU was set.
+@@ -403,8 +404,8 @@ struct ieee80211_tx_info {
+       u8 antenna_sel_tx;
+-      /* 2 byte hole */
+-      u8 pad[2];
++      u8 driver_flags;
++      u8 ampdu_len;
+       union {
+               struct {
diff --git a/package/mac80211/patches/520-nl80211_vlan_add_fix.patch b/package/mac80211/patches/520-nl80211_vlan_add_fix.patch
deleted file mode 100644 (file)
index e0cdaea..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1813,7 +1813,7 @@ static int nl80211_get_station(struct sk
- }
- /*
-- * Get vlan interface making sure it is on the right wiphy.
-+ * Get vlan interface making sure it is running and on the right wiphy.
-  */
- static int get_vlan(struct genl_info *info,
-                   struct cfg80211_registered_device *rdev,
-@@ -1831,6 +1831,8 @@ static int get_vlan(struct genl_info *in
-                       return -EINVAL;
-               if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
-                       return -EINVAL;
-+              if (!netif_running(*vlan))
-+                      return -ENETDOWN;
-       }
-       return 0;
- }
diff --git a/package/mac80211/patches/530-ath9k_cleanup.patch b/package/mac80211/patches/530-ath9k_cleanup.patch
new file mode 100644 (file)
index 0000000..49a1143
--- /dev/null
@@ -0,0 +1,460 @@
+--- a/drivers/net/wireless/ath/ath9k/common.h
++++ b/drivers/net/wireless/ath/ath9k/common.h
+@@ -81,6 +81,7 @@ struct ath_buf {
+       u16 bf_flags;
+       struct ath_buf_state bf_state;
+       dma_addr_t bf_dmacontext;
++      struct ath_wiphy *aphy;
+ };
+ struct ath_atx_tid {
+--- a/drivers/net/wireless/ath/ath9k/rc.h
++++ b/drivers/net/wireless/ath/ath9k/rc.h
+@@ -167,24 +167,18 @@ struct ath_rate_priv {
+       struct ath_rate_softc *asc;
+ };
++#define ATH_TX_INFO_FRAME_TYPE_INTERNAL       (1 << 0)
++#define ATH_TX_INFO_FRAME_TYPE_PAUSE  (1 << 1)
++#define ATH_TX_INFO_UPDATE_RC         (1 << 2)
++#define ATH_TX_INFO_XRETRY            (1 << 3)
++#define ATH_TX_INFO_UNDERRUN          (1 << 4)
++
+ enum ath9k_internal_frame_type {
+       ATH9K_NOT_INTERNAL,
+       ATH9K_INT_PAUSE,
+       ATH9K_INT_UNPAUSE
+ };
+-struct ath_tx_info_priv {
+-      struct ath_wiphy *aphy;
+-      struct ath_tx_status tx;
+-      int n_frames;
+-      int n_bad_frames;
+-      bool update_rc;
+-      enum ath9k_internal_frame_type frame_type;
+-};
+-
+-#define ATH_TX_INFO_PRIV(tx_info) \
+-      ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
+-
+ void ath_rate_attach(struct ath_softc *sc);
+ u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
+ int ath_rate_control_register(void);
+--- a/drivers/net/wireless/ath/ath9k/virtual.c
++++ b/drivers/net/wireless/ath/ath9k/virtual.c
+@@ -338,13 +338,11 @@ void ath9k_wiphy_chan_work(struct work_s
+ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+ {
+       struct ath_wiphy *aphy = hw->priv;
+-      struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+-      if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE &&
++      if ((tx_info->driver_flags & ATH_TX_INFO_FRAME_TYPE_PAUSE) &&
+           aphy->state == ATH_WIPHY_PAUSING) {
+-              if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
++              if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
+                       printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
+                              "frame\n", wiphy_name(hw->wiphy));
+                       /*
+@@ -363,9 +361,6 @@ void ath9k_tx_status(struct ieee80211_hw
+               }
+       }
+-      kfree(tx_info_priv);
+-      tx_info->rate_driver_data[0] = NULL;
+-
+       dev_kfree_skb(skb);
+ }
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -251,6 +251,7 @@ static struct ath_buf* ath_clone_txbuf(s
+       ATH_TXBUF_RESET(tbf);
++      tbf->aphy = bf->aphy;
+       tbf->bf_mpdu = bf->bf_mpdu;
+       tbf->bf_buf_addr = bf->bf_buf_addr;
+       *(tbf->bf_desc) = *(bf->bf_desc);
+@@ -270,7 +271,6 @@ static void ath_tx_complete_aggr(struct 
+       struct ieee80211_hw *hw;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_tx_info *tx_info;
+-      struct ath_tx_info_priv *tx_info_priv;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+       struct ath_desc *ds = bf_last->bf_desc;
+@@ -284,8 +284,7 @@ static void ath_tx_complete_aggr(struct 
+       hdr = (struct ieee80211_hdr *)skb->data;
+       tx_info = IEEE80211_SKB_CB(skb);
+-      tx_info_priv = (struct ath_tx_info_priv *) tx_info->rate_driver_data[0];
+-      hw = tx_info_priv->aphy->hw;
++      hw = bf->aphy->hw;
+       rcu_read_lock();
+@@ -464,7 +463,6 @@ static u32 ath_lookup_rate(struct ath_so
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+-      struct ath_tx_info_priv *tx_info_priv;
+       u32 max_4ms_framelen, frmlen;
+       u16 aggr_limit, legacy = 0;
+       int i;
+@@ -472,7 +470,6 @@ static u32 ath_lookup_rate(struct ath_so
+       skb = bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+-      tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
+       /*
+        * Find the lowest frame length among the rate series that will have a
+@@ -1560,21 +1557,26 @@ static int ath_tx_setup_buffer(struct ie
+       struct ath_softc *sc = aphy->sc;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-      struct ath_tx_info_priv *tx_info_priv;
+       int hdrlen;
+       __le16 fc;
+-      tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
+-      if (unlikely(!tx_info_priv))
+-              return -ENOMEM;
+-      tx_info->rate_driver_data[0] = tx_info_priv;
+-      tx_info_priv->aphy = aphy;
+-      tx_info_priv->frame_type = txctl->frame_type;
++      tx_info->driver_flags = 0;
++      switch (txctl->frame_type) {
++      case ATH9K_NOT_INTERNAL:
++              break;
++      case ATH9K_INT_PAUSE:
++              tx_info->driver_flags |= ATH_TX_INFO_FRAME_TYPE_PAUSE;
++              /* fall through */
++      case ATH9K_INT_UNPAUSE:
++              tx_info->driver_flags |= ATH_TX_INFO_FRAME_TYPE_INTERNAL;
++              break;
++      }
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+       fc = hdr->frame_control;
+       ATH_TXBUF_RESET(bf);
++      bf->aphy = aphy;
+       bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
+       if (conf_is_ht(&hw->conf) && !is_pae(skb))
+@@ -1599,8 +1601,6 @@ static int ath_tx_setup_buffer(struct ie
+                                          skb->len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
+               bf->bf_mpdu = NULL;
+-              kfree(tx_info_priv);
+-              tx_info->rate_driver_data[0] = NULL;
+               ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
+                         "dma_mapping_error() on TX\n");
+               return -ENOMEM;
+@@ -1781,27 +1781,17 @@ exit:
+ /*****************/
+ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+-                          int tx_flags)
++                          struct ath_wiphy *aphy, int tx_flags)
+ {
+       struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       int hdrlen, padsize;
+-      int frame_type = ATH9K_NOT_INTERNAL;
+       ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+-      if (tx_info_priv) {
+-              hw = tx_info_priv->aphy->hw;
+-              frame_type = tx_info_priv->frame_type;
+-      }
+-
+-      if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
+-          tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
+-              kfree(tx_info_priv);
+-              tx_info->rate_driver_data[0] = NULL;
+-      }
++      if (aphy)
++              hw = aphy->hw;
+       if (tx_flags & ATH_TX_BAR)
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+@@ -1833,10 +1823,10 @@ static void ath_tx_complete(struct ath_s
+                                       SC_OP_WAIT_FOR_TX_ACK));
+       }
+-      if (frame_type == ATH9K_NOT_INTERNAL)
+-              ieee80211_tx_status(hw, skb);
+-      else
++      if (unlikely(tx_info->driver_flags & ATH_TX_INFO_FRAME_TYPE_INTERNAL))
+               ath9k_tx_status(hw, skb);
++      else
++              ieee80211_tx_status(hw, skb);
+ }
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+@@ -1859,7 +1849,7 @@ static void ath_tx_complete_buf(struct a
+       }
+       dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
+-      ath_tx_complete(sc, skb, tx_flags);
++      ath_tx_complete(sc, skb, bf->aphy, tx_flags);
+       ath_debug_stat_tx(sc, txq, bf);
+       /*
+@@ -1907,8 +1897,7 @@ static void ath_tx_rc_status(struct ath_
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+-      struct ieee80211_hw *hw = tx_info_priv->aphy->hw;
++      struct ieee80211_hw *hw = bf->aphy->hw;
+       u8 i, tx_rateindex;
+       if (txok)
+@@ -1917,17 +1906,22 @@ static void ath_tx_rc_status(struct ath_
+       tx_rateindex = ds->ds_txstat.ts_rateindex;
+       WARN_ON(tx_rateindex >= hw->max_rates);
+-      tx_info_priv->update_rc = update_rc;
++      if (update_rc)
++              tx_info->driver_flags |= ATH_TX_INFO_UPDATE_RC;
+       if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
+               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+       if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
+           (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+               if (ieee80211_is_data(hdr->frame_control)) {
+-                      memcpy(&tx_info_priv->tx, &ds->ds_txstat,
+-                             sizeof(tx_info_priv->tx));
+-                      tx_info_priv->n_frames = bf->bf_nframes;
+-                      tx_info_priv->n_bad_frames = nbad;
++                      if (ds->ds_txstat.ts_flags &
++                          (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN))
++                              tx_info->driver_flags |= ATH_TX_INFO_UNDERRUN;
++                      if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) ||
++                          (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO))
++                              tx_info->driver_flags |= ATH_TX_INFO_XRETRY;
++                      tx_info->ampdu_len = bf->bf_nframes;
++                      tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+               }
+       }
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -257,14 +257,17 @@ static const struct file_operations fops
+ void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
+ {
+-      struct ath_tx_info_priv *tx_info_priv = NULL;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *rates = tx_info->status.rates;
+-      int final_ts_idx, idx;
++      int final_ts_idx = 0, idx, i;
+       struct ath_rc_stats *stats;
+-      tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+-      final_ts_idx = tx_info_priv->tx.ts_rateindex;
++      for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
++              if (!rates[i].count)
++                      break;
++
++              final_ts_idx = i;
++      }
+       idx = rates[final_ts_idx].idx;
+       stats = &sc->debug.stats.rcstats[idx];
+       stats->success++;
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -859,12 +859,12 @@ static void ath_get_rate(void *priv, str
+ static bool ath_rc_update_per(struct ath_softc *sc,
+                             const struct ath_rate_table *rate_table,
+                             struct ath_rate_priv *ath_rc_priv,
+-                            struct ath_tx_info_priv *tx_info_priv,
++                                struct ieee80211_tx_info *tx_info,
+                             int tx_rate, int xretries, int retries,
+                             u32 now_msec)
+ {
+       bool state_change = false;
+-      int count;
++      int count, n_bad_frames;
+       u8 last_per;
+       static u32 nretry_to_per_lookup[10] = {
+               100 * 0 / 1,
+@@ -880,6 +880,7 @@ static bool ath_rc_update_per(struct ath
+       };
+       last_per = ath_rc_priv->per[tx_rate];
++      n_bad_frames = tx_info->ampdu_len - tx_info->status.ampdu_ack_len;
+       if (xretries) {
+               if (xretries == 1) {
+@@ -907,7 +908,7 @@ static bool ath_rc_update_per(struct ath
+               if (retries >= count)
+                       retries = count - 1;
+-              if (tx_info_priv->n_bad_frames) {
++              if (n_bad_frames) {
+                       /* new_PER = 7/8*old_PER + 1/8*(currentPER)
+                        * Assuming that n_frames is not 0.  The current PER
+                        * from the retries is 100 * retries / (retries+1),
+@@ -920,14 +921,14 @@ static bool ath_rc_update_per(struct ath
+                        * the above PER.  The expression below is a
+                        * simplified version of the sum of these two terms.
+                        */
+-                      if (tx_info_priv->n_frames > 0) {
+-                              int n_frames, n_bad_frames;
++                      if (tx_info->ampdu_len > 0) {
++                              int n_frames, n_bad_tries;
+                               u8 cur_per, new_per;
+-                              n_bad_frames = retries * tx_info_priv->n_frames +
+-                                      tx_info_priv->n_bad_frames;
+-                              n_frames = tx_info_priv->n_frames * (retries + 1);
+-                              cur_per = (100 * n_bad_frames / n_frames) >> 3;
++                              n_bad_tries = retries * tx_info->ampdu_len +
++                                      n_bad_frames;
++                              n_frames = tx_info->ampdu_len * (retries + 1);
++                              cur_per = (100 * n_bad_tries / n_frames) >> 3;
+                               new_per = (u8)(last_per - (last_per >> 3) + cur_per);
+                               ath_rc_priv->per[tx_rate] = new_per;
+                       }
+@@ -943,8 +944,7 @@ static bool ath_rc_update_per(struct ath
+                * this was a probe.  Otherwise, ignore the probe.
+                */
+               if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
+-                      if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
+-                              tx_info_priv->n_frames) {
++                      if (retries > 0 || 2 * n_bad_frames > tx_info->ampdu_len) {
+                               /*
+                                * Since we probed with just a single attempt,
+                                * any retries means the probe failed.  Also,
+@@ -1003,7 +1003,7 @@ static bool ath_rc_update_per(struct ath
+ static void ath_rc_update_ht(struct ath_softc *sc,
+                            struct ath_rate_priv *ath_rc_priv,
+-                           struct ath_tx_info_priv *tx_info_priv,
++                           struct ieee80211_tx_info *tx_info,
+                            int tx_rate, int xretries, int retries)
+ {
+       u32 now_msec = jiffies_to_msecs(jiffies);
+@@ -1020,7 +1020,7 @@ static void ath_rc_update_ht(struct ath_
+       /* Update PER first */
+       state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
+-                                       tx_info_priv, tx_rate, xretries,
++                                       tx_info, tx_rate, xretries,
+                                        retries, now_msec);
+       /*
+@@ -1098,7 +1098,6 @@ static void ath_rc_tx_status(struct ath_
+                            struct ieee80211_tx_info *tx_info,
+                            int final_ts_idx, int xretries, int long_retry)
+ {
+-      struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+       const struct ath_rate_table *rate_table;
+       struct ieee80211_tx_rate *rates = tx_info->status.rates;
+       u8 flags;
+@@ -1124,9 +1123,8 @@ static void ath_rc_tx_status(struct ath_
+                                       return;
+                               rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+-                              ath_rc_update_ht(sc, ath_rc_priv,
+-                                              tx_info_priv, rix,
+-                                              xretries ? 1 : 2,
++                              ath_rc_update_ht(sc, ath_rc_priv, tx_info,
++                                              rix, xretries ? 1 : 2,
+                                               rates[i].count);
+                       }
+               }
+@@ -1149,8 +1147,7 @@ static void ath_rc_tx_status(struct ath_
+               return;
+       rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+-      ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
+-                       xretries, long_retry);
++      ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry);
+ }
+ static const
+@@ -1301,23 +1298,30 @@ static void ath_tx_status(void *priv, st
+ {
+       struct ath_softc *sc = priv;
+       struct ath_rate_priv *ath_rc_priv = priv_sta;
+-      struct ath_tx_info_priv *tx_info_priv = NULL;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr;
+-      int final_ts_idx, tx_status = 0, is_underrun = 0;
++      int final_ts_idx = 0, tx_status = 0, is_underrun = 0;
++      int long_retry = 0;
+       __le16 fc;
++      int i;
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
+-      tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+-      final_ts_idx = tx_info_priv->tx.ts_rateindex;
++      for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
++              struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
++              if (!rate->count)
++                      break;
++
++              final_ts_idx = i;
++              long_retry = rate->count - 1;
++      }
+       if (!priv_sta || !ieee80211_is_data(fc) ||
+-          !tx_info_priv->update_rc)
+-              goto exit;
++          !(tx_info->driver_flags & ATH_TX_INFO_UPDATE_RC))
++              return;
+-      if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
+-              goto exit;
++      if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
++              return;
+       /*
+        * If underrun error is seen assume it as an excessive retry only
+@@ -1325,20 +1329,17 @@ static void ath_tx_status(void *priv, st
+        * Adjust the long retry as if the frame was tried hw->max_rate_tries
+        * times. This affects how ratectrl updates PER for the failed rate.
+        */
+-      if (tx_info_priv->tx.ts_flags &
+-          (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
+-          ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
++      if ((tx_info->driver_flags & ATH_TX_INFO_UNDERRUN) &&
++          (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {
+               tx_status = 1;
+               is_underrun = 1;
+       }
+-      if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
+-          (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
++      if (tx_info->driver_flags & ATH_TX_INFO_XRETRY)
+               tx_status = 1;
+       ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
+-                       (is_underrun) ? sc->hw->max_rate_tries :
+-                       tx_info_priv->tx.ts_longretry);
++                       (is_underrun) ? sc->hw->max_rate_tries : long_retry);
+       /* Check if aggregation has to be enabled for this tid */
+       if (conf_is_ht(&sc->hw->conf) &&
+@@ -1357,8 +1358,6 @@ static void ath_tx_status(void *priv, st
+       }
+       ath_debug_stat_rc(sc, skb);
+-exit:
+-      kfree(tx_info_priv);
+ }
+ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
diff --git a/package/mac80211/patches/540-monitor_tx_status.patch b/package/mac80211/patches/540-monitor_tx_status.patch
new file mode 100644 (file)
index 0000000..b2a35de
--- /dev/null
@@ -0,0 +1,14 @@
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -587,6 +587,11 @@ void ieee80211_tx_status(struct ieee8021
+                       if (!netif_running(sdata->dev))
+                               continue;
++                      if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
++                          !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
++                          (type == IEEE80211_FTYPE_DATA))
++                              continue;
++
+                       if (prev_dev) {
+                               skb2 = skb_clone(skb, GFP_ATOMIC);
+                               if (skb2) {