PKG_NAME:=mac80211
-PKG_VERSION:=2011-06-22
-PKG_RELEASE:=2
+PKG_VERSION:=2011-08-10
+PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=3ffdd5cecedcf4236f599bdbc55ba10d
+PKG_MD5SUM:=fb2ee04eaafbdf4117c475ba78f8f5b9
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
--- a/config.mk
+++ b/config.mk
-@@ -337,8 +337,8 @@ CONFIG_BCMA_HOST_PCI=y
+@@ -339,8 +339,8 @@ CONFIG_B43_BCMA_PIO=y
CONFIG_P54_PCI=m
ifeq ($(CONFIG_MAC80211),y)
$(error "ERROR: you have MAC80211 compiled into the kernel, CONFIG_MAC80211=y, as such you cannot replace its mac80211 driver. You need this set to CONFIG_MAC80211=m. If you are using Fedora upgrade your kernel as later version should this set as modular. For further information on Fedora see https://bugzilla.redhat.com/show_bug.cgi?id=470143. If you are using your own kernel recompile it and make mac80211 modular")
-@@ -646,10 +646,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+@@ -649,10 +649,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
# 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_KERNEL_2_6_31
else
include $(KLIB_BUILD)/.config
endif
-@@ -314,7 +313,8 @@ CONFIG_IPW2200_QOS=y
+@@ -315,7 +314,8 @@ CONFIG_IPW2200_QOS=y
# % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
endif #CONFIG_WIRELESS_EXT
# Sonics Silicon Backplane
CONFIG_SSB_SPROM=y
-@@ -327,7 +327,7 @@ endif #CONFIG_PCMCIA
+@@ -328,7 +328,7 @@ endif #CONFIG_PCMCIA
# CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_B43_SSB=y
CONFIG_BCMA=m
CONFIG_BCMA_BLOCKIO=y
-@@ -534,7 +534,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -537,7 +537,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
obj-$(CONFIG_COMPAT_STAGING) += drivers/staging/ath6kl/
--- a/config.mk
+++ b/config.mk
-@@ -329,9 +329,9 @@ CONFIG_SSB_DRIVER_PCICORE=y
+@@ -330,9 +330,9 @@ CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_B43_SSB=y
endif #__CONFIG_SSB
+# CONFIG_BCMA_BLOCKIO=y
+# CONFIG_BCMA_HOST_PCI=y
# CONFIG_BCMA_DEBUG=y
- # CONFIG_B43_BCMA=y
-
+ CONFIG_B43_BCMA=y
+ CONFIG_B43_BCMA_PIO=y
endif #CONFIG_STAGING
# mac80211 test driver
-@@ -365,13 +365,13 @@ endif #CONFIG_CRC_ITU_T
+@@ -367,13 +367,13 @@ endif #CONFIG_CRC_ITU_T
CONFIG_MWL8K=m
# Ethernet drivers go here
endif #CONFIG_COMPAT_KERNEL_2_6_27
ifdef CONFIG_WIRELESS_EXT
-@@ -431,21 +431,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -434,21 +434,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
# Note: this depends on CONFIG_USB_NET_RNDIS_HOST and CONFIG_USB_NET_CDCETHER
# it also requires new RNDIS_HOST and CDC_ETHER modules which we add
ifdef CONFIG_COMPAT_KERNEL_2_6_29
--- a/config.mk
+++ b/config.mk
-@@ -517,7 +517,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -520,7 +520,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
-CONFIG_B43_PHY_N=y
+# CONFIG_B43_PHY_N=y
# CONFIG_B43_PHY_HT=y
+ # CONFIG_B43_PHY_LCN=y
# CONFIG_B43_FORCE_PIO=y
- # CONFIG_B43_DEBUG=y
--- a/config.mk
+++ b/config.mk
-@@ -327,7 +327,7 @@ CONFIG_RTL8180=m
+@@ -329,7 +329,7 @@ CONFIG_RTL8180=m
CONFIG_ADM8211=m
CONFIG_RT2400PCI=m
CONFIG_RT2500PCI=m
ifdef CONFIG_CRC_CCITT
-@@ -466,7 +466,7 @@ CONFIG_RT2800USB_RT35XX=y
+@@ -469,7 +469,7 @@ CONFIG_RT2800USB_RT35XX=y
# CONFIG_RT2800USB_RT53XX=y
CONFIG_RT2800USB_UNKNOWN=y
endif #CONFIG_CRC_CCITT
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
-@@ -181,75 +181,52 @@ static int b43legacy_ratelimit(struct b4
+@@ -180,75 +180,52 @@ static int b43legacy_ratelimit(struct b4
void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
{
+++ /dev/null
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -3728,7 +3728,9 @@ static int nl80211_dump_scan(struct sk_b
- spin_lock_bh(&rdev->bss_lock);
- cfg80211_bss_expire(rdev);
-
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
- cb->seq = rdev->bss_generation;
-+#endif
-
- list_for_each_entry(scan, &rdev->bss_list, list) {
- if (++idx <= start)
+endif
--- a/include/linux/compat-2.6.31.h
+++ b/include/linux/compat-2.6.31.h
-@@ -199,6 +199,20 @@ void compat_synchronize_threaded_irq(str
- #define list_entry_rcu(ptr, type, member) \
- container_of(rcu_dereference(ptr), type, member)
+@@ -202,6 +202,20 @@ void compat_synchronize_threaded_irq(str
+ #define skb_walk_frags(skb, iter) \
+ for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
+#ifndef CONFIG_64BIT
+
+
--- a/include/linux/compat-3.1.h
+++ b/include/linux/compat-3.1.h
-@@ -24,6 +24,18 @@
-
- #define genl_dump_check_consistent(...) do {} while(0)
+@@ -36,6 +36,18 @@
+ .prod_id = { NULL, NULL, (v3), NULL }, \
+ .prod_id_hash = { 0, 0, (vh3), 0 }, }
+/*
+ * In many versions, several architectures do not seem to include an
+++ /dev/null
---- a/drivers/net/wireless/b43/main.c~ 2011-07-23 00:33:46.573306410 +0200
-+++ b/drivers/net/wireless/b43/main.c 2011-07-23 00:36:14.657726075 +0200
-@@ -4955,7 +4955,7 @@
- static void b43_wireless_core_detach(struct b43_wldev *dev)
- {
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
-- if (dev->sdev->bus->bustype != SSB_BUSTYPE_SDIO)
-+ if (dev->dev->sdev->bus->bustype != SSB_BUSTYPE_SDIO)
- compat_destroy_threaded_irq(&dev->irq_compat);
- #endif
- /* We release firmware that late to not be required to re-request
#endif
--- a/config.mk
+++ b/config.mk
-@@ -452,7 +452,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -455,7 +455,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
# This activates a threading fix for usb urb.
# this is mainline commit: b3e670443b7fb8a2d29831b62b44a039c283e351
# This fix will be included in some stable releases.
---- a/drivers/net/wireless/iwlwifi/iwl-agn.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
-@@ -27,6 +27,7 @@
- *
- *****************************************************************************/
-
-+#undef pr_fmt
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
- #include <linux/kernel.h>
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -27,6 +27,7 @@
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/slab.h>
+ #include <linux/hardirq.h>
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -9,6 +9,7 @@
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/slab.h>
+ #include <linux/hardirq.h>
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -4,6 +4,7 @@
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/sched.h>
+ #include <linux/hardirq.h>
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -21,6 +21,7 @@
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/moduleparam.h>
+ #include <linux/hardirq.h>
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -2,6 +2,7 @@
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
-@@ -58,8 +58,14 @@ static const struct ath5k_ini ar5210_ini
+@@ -57,8 +57,14 @@ static const struct ath5k_ini ar5210_ini
{ AR5K_IMR, 0 },
{ AR5K_IER, AR5K_IER_DISABLE },
{ AR5K_BSR, 0, AR5K_INI_READ },
{ AR5K_RXNOFRM, 8 },
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
-@@ -787,10 +787,18 @@ void ath5k_hw_dma_init(struct ath5k_hw *
+@@ -786,10 +786,18 @@ void ath5k_hw_dma_init(struct ath5k_hw *
* guess we can tweak it and see how it goes ;-)
*/
if (ah->ah_version != AR5K_AR5210) {
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -320,6 +320,10 @@ static void b43_wireless_core_exit(struc
+ static int b43_wireless_core_init(struct b43_wldev *dev);
+ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
+ static int b43_wireless_core_start(struct b43_wldev *dev);
++static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif,
++ struct ieee80211_bss_conf *conf,
++ u32 changed);
+
+ static int b43_ratelimit(struct b43_wl *wl)
+ {
+@@ -3754,14 +3758,24 @@ static int b43_op_config(struct ieee8021
+ struct ieee80211_conf *conf = &hw->conf;
+ int antenna;
+ int err = 0;
++ bool reload_bss = false;
+
+ mutex_lock(&wl->mutex);
+
++ dev = wl->current_dev;
++
+ /* Switch the band (if necessary). This might change the active core. */
+ err = b43_switch_band(wl, conf->channel);
+ if (err)
+ goto out_unlock_mutex;
+- dev = wl->current_dev;
++
++ /* Need to reload all settings if the core changed */
++ if (dev != wl->current_dev) {
++ dev = wl->current_dev;
++ changed = ~0;
++ reload_bss = true;
++ }
++
+ phy = &dev->phy;
+
+ if (conf_is_ht(conf))
+@@ -3822,6 +3836,9 @@ out_mac_enable:
+ out_unlock_mutex:
+ mutex_unlock(&wl->mutex);
+
++ if (wl->vif && reload_bss)
++ b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
++
+ return err;
+ }
+
+@@ -3910,7 +3927,8 @@ static void b43_op_bss_info_changed(stru
+ if (changed & BSS_CHANGED_BEACON_INT &&
+ (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
+- b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
++ b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
++ conf->beacon_int)
+ b43_set_beacon_int(dev, conf->beacon_int);
+
+ if (changed & BSS_CHANGED_BASIC_RATES)
+@@ -4691,6 +4709,9 @@ static int b43_op_add_interface(struct i
+ out_mutex_unlock:
+ mutex_unlock(&wl->mutex);
+
++ if (err == 0)
++ b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
++
+ return err;
+ }
+
+@@ -4761,6 +4782,9 @@ static int b43_op_start(struct ieee80211
+ out_mutex_unlock:
+ mutex_unlock(&wl->mutex);
+
++ /* reload configuration */
++ b43_op_config(hw, ~0);
++
+ return err;
+ }
+
+@@ -4917,10 +4941,18 @@ out:
+ if (err)
+ wl->current_dev = NULL; /* Failed to init the dev. */
+ mutex_unlock(&wl->mutex);
+- if (err)
++
++ if (err) {
+ b43err(wl, "Controller restart FAILED\n");
+- else
+- b43info(wl, "Controller restarted\n");
++ return;
++ }
++
++ /* reload configuration */
++ b43_op_config(wl->hw, ~0);
++ if (wl->vif)
++ b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
++
++ b43info(wl, "Controller restarted\n");
+ }
+
+ static int b43_setup_bands(struct b43_wldev *dev,
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
-@@ -176,6 +176,8 @@ static void ieee80211_send_addba_resp(st
+@@ -184,6 +184,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);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
-@@ -262,7 +264,11 @@ void ieee80211_process_addba_request(str
- "%pM on tid %u\n",
- mgmt->sa, tid);
- #endif /* CONFIG_MAC80211_HT_DEBUG */
-- goto end;
-+
-+ /* delete existing Rx BA session on the same tid */
-+ ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
-+ WLAN_STATUS_UNSPECIFIED_QOS,
-+ false);
- }
-
- /* prepare A-MPDU MLME for Rx aggregation */
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
return -EINVAL;
if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
-@@ -809,7 +811,7 @@ void ieee80211_process_addba_resp(struct
- * of at least 1.
- */
- if (!buf_size)
-- goto out;
-+ buf_size = 1;
-
- if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
- &tid_tx->state)) {
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
break;
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2147,7 +2147,8 @@ ieee80211_rx_h_action(struct ieee80211_r
*/
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
break;
/* verify action_code is present */
-@@ -2335,13 +2336,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2345,13 +2346,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
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
+@@ -2692,10 +2694,16 @@ static int prepare_for_handlers(struct i
}
break;
case NL80211_IFTYPE_WDS:
WLAN_STA_CLEAR_PS_FILT = 1<<9,
WLAN_STA_MFP = 1<<10,
WLAN_STA_BLOCK_BA = 1<<11,
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -360,6 +360,7 @@ void ath_beacon_tasklet(unsigned long da
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_buf *bf = NULL;
- struct ieee80211_vif *vif;
-+ struct ath_tx_status ts;
- int slot;
- u32 bfaddr, bc = 0;
-
-@@ -384,7 +385,9 @@ void ath_beacon_tasklet(unsigned long da
- ath_dbg(common, ATH_DBG_BSTUCK,
- "beacon is officially stuck\n");
- sc->sc_flags |= SC_OP_TSF_RESET;
-+ spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
-+ spin_unlock(&sc->sc_pcu_lock);
- }
-
- return;
-@@ -464,6 +467,11 @@ void ath_beacon_tasklet(unsigned long da
- ath9k_hw_txstart(ah, sc->beacon.beaconq);
-
- sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
-+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-+ spin_lock_bh(&sc->sc_pcu_lock);
-+ ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
-+ }
- }
- }
-
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -617,8 +617,11 @@ void ath_hw_check(struct work_struct *wo
- ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
- "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
- if (busy >= 99) {
-- if (++sc->hw_busy_count >= 3)
-+ if (++sc->hw_busy_count >= 3) {
-+ spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
-+ }
- } else if (busy >= 0)
- sc->hw_busy_count = 0;
-
-@@ -637,7 +640,9 @@ static void ath_hw_pll_rx_hang_check(str
- /* Rx is hung for more than 500ms. Reset it */
- ath_dbg(common, ATH_DBG_RESET,
- "Possible RX hang, resetting");
-+ spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
- count = 0;
- }
- } else
-@@ -674,7 +679,9 @@ void ath9k_tasklet(unsigned long data)
-
- if ((status & ATH9K_INT_FATAL) ||
- (status & ATH9K_INT_BB_WATCHDOG)) {
-+ spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
-+ spin_unlock(&sc->sc_pcu_lock);
- return;
- }
-
-@@ -980,7 +987,6 @@ int ath_reset(struct ath_softc *sc, bool
- del_timer_sync(&common->ani.timer);
-
- ath9k_ps_wakeup(sc);
-- spin_lock_bh(&sc->sc_pcu_lock);
-
- ieee80211_stop_queues(hw);
-
-@@ -1023,7 +1029,6 @@ int ath_reset(struct ath_softc *sc, bool
- }
-
- ieee80211_wake_queues(hw);
-- spin_unlock_bh(&sc->sc_pcu_lock);
-
- /* Start ANI */
- if (!common->disable_ani)
-@@ -2326,9 +2331,9 @@ static void ath9k_flush(struct ieee80211
- ath9k_ps_wakeup(sc);
- spin_lock_bh(&sc->sc_pcu_lock);
- drain_txq = ath_drain_all_txq(sc, false);
-- spin_unlock_bh(&sc->sc_pcu_lock);
- if (!drain_txq)
- ath_reset(sc, false);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
- ath9k_ps_restore(sc);
- ieee80211_wake_queues(hw);
-
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -565,11 +565,8 @@ static void ath_tx_complete_aggr(struct
-
- rcu_read_unlock();
-
-- if (needreset) {
-- spin_unlock_bh(&sc->sc_pcu_lock);
-+ if (needreset)
- ath_reset(sc, false);
-- spin_lock_bh(&sc->sc_pcu_lock);
-- }
- }
-
- static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
-@@ -664,7 +661,8 @@ static int ath_compute_num_delims(struct
- * TODO - this could be improved to be dependent on the rate.
- * The hardware can keep up at lower rates, but not higher rates
- */
-- if (fi->keyix != ATH9K_TXKEYIX_INVALID)
-+ if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
-+ !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
- ndelim += ATH_AGGR_ENCRYPTDELIM;
-
- /*
-@@ -2169,7 +2167,9 @@ static void ath_tx_complete_poll_work(st
- if (needreset) {
- ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
- "tx hung, resetting the chip\n");
-+ spin_lock_bh(&sc->sc_pcu_lock);
- ath_reset(sc, true);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
+@@ -551,7 +551,8 @@ static void ath_tx_complete_aggr(struct
+ if (clear_filter)
+ tid->ac->clear_ps_filter = true;
+ list_splice(&bf_pending, &tid->buf_q);
+- ath_tx_queue_tid(txq, tid);
++ if (!an->sleeping)
++ ath_tx_queue_tid(txq, tid);
+ spin_unlock_bh(&txq->axq_lock);
}
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
---- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-@@ -236,7 +236,7 @@ static void ar9003_paprd_get_gain_table(
- memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
- memset(index, 0, sizeof(ah->paprd_gain_table_index));
-
-- for (i = 0; i < 32; i++) {
-+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
- entry[i] = REG_READ(ah, reg);
- index[i] = (entry[i] >> 24) & 0xff;
- reg += 4;
-@@ -246,13 +246,13 @@ static void ar9003_paprd_get_gain_table(
- static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
- int target_power)
- {
-- int olpc_gain_delta = 0;
-+ int olpc_gain_delta = 0, cl_gain_mod;
- int alpha_therm, alpha_volt;
- int therm_cal_value, volt_cal_value;
- int therm_value, volt_value;
- int thermal_gain_corr, voltage_gain_corr;
- int desired_scale, desired_gain = 0;
-- u32 reg;
-+ u32 reg_olpc = 0, reg_cl_gain = 0;
-
- REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
- AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
-@@ -271,15 +271,29 @@ static unsigned int ar9003_get_desired_g
- volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
- AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
-
-- if (chain == 0)
-- reg = AR_PHY_TPC_11_B0;
-- else if (chain == 1)
-- reg = AR_PHY_TPC_11_B1;
-- else
-- reg = AR_PHY_TPC_11_B2;
-+ switch (chain) {
-+ case 0:
-+ reg_olpc = AR_PHY_TPC_11_B0;
-+ reg_cl_gain = AR_PHY_CL_TAB_0;
-+ break;
-+ case 1:
-+ reg_olpc = AR_PHY_TPC_11_B1;
-+ reg_cl_gain = AR_PHY_CL_TAB_1;
-+ break;
-+ case 2:
-+ reg_olpc = AR_PHY_TPC_11_B2;
-+ reg_cl_gain = AR_PHY_CL_TAB_2;
-+ break;
-+ default:
-+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-+ "Invalid chainmask: %d\n", chain);
-+ break;
-+ }
-
-- olpc_gain_delta = REG_READ_FIELD(ah, reg,
-+ olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
- AR_PHY_TPC_11_OLPC_GAIN_DELTA);
-+ cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
-+ AR_PHY_CL_TAB_CL_GAIN_MOD);
-
- if (olpc_gain_delta >= 128)
- olpc_gain_delta = olpc_gain_delta - 256;
-@@ -289,7 +303,7 @@ static unsigned int ar9003_get_desired_g
- voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
- (128 / 2)) / 128;
- desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
-- voltage_gain_corr + desired_scale;
-+ voltage_gain_corr + desired_scale + cl_gain_mod;
-
- return desired_gain;
- }
-@@ -727,7 +741,7 @@ int ar9003_paprd_setup_gain_table(struct
- desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
-
- gain_index = 0;
-- for (i = 0; i < 32; i++) {
-+ for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
- if (ah->paprd_gain_table_index[i] >= desired_gain)
- break;
- gain_index++;
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-@@ -1121,6 +1121,9 @@
- #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
- #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
-
-+#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
-+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
-+
- void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
-
- #endif /* AR9003_PHY_H */
---- a/drivers/net/wireless/ath/ath5k/eeprom.c
-+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
-@@ -691,14 +691,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k
- if (!chinfo[pier].pd_curves)
- continue;
-
-- for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-+ for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
- struct ath5k_pdgain_info *pd =
- &chinfo[pier].pd_curves[pdg];
-
-- if (pd != NULL) {
-- kfree(pd->pd_step);
-- kfree(pd->pd_pwr);
-- }
-+ kfree(pd->pd_step);
-+ kfree(pd->pd_pwr);
- }
-
- kfree(chinfo[pier].pd_curves);
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -229,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct
- static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
- struct ath_tx_status *ts)
- {
-+ struct ar9003_txc *txc = (struct ar9003_txc *) ds;
- struct ar9003_txs *ads;
- u32 status;
-
-@@ -238,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct
- if ((status & AR_TxDone) == 0)
- return -EINPROGRESS;
-
-- ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
-+ ts->qid = MS(ads->ds_info, AR_TxQcuNum);
-+ if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
-+ ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
-+ else
-+ return -ENOENT;
-
- if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
- (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
-@@ -254,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct
- ts->ts_seqnum = MS(status, AR_SeqNum);
- ts->tid = MS(status, AR_TxTid);
-
-- ts->qid = MS(ads->ds_info, AR_TxQcuNum);
- ts->desc_id = MS(ads->status1, AR_TxDescId);
- ts->ts_tstamp = ads->status4;
- ts->ts_status = 0;
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -15,6 +15,7 @@
- #include <linux/gfp.h>
- #include <asm/unaligned.h>
- #include <net/mac80211.h>
-+#include <crypto/aes.h>
-
- #include "ieee80211_i.h"
- #include "michael.h"
-@@ -86,6 +87,11 @@ ieee80211_rx_h_michael_mic_verify(struct
- struct sk_buff *skb = rx->skb;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ int queue = rx->queue;
-+
-+ /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-+ if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-+ queue = 0;
-
- /*
- * it makes no sense to check for MIC errors on anything other
-@@ -148,8 +154,8 @@ ieee80211_rx_h_michael_mic_verify(struct
-
- update_iv:
- /* update IV in key information to be able to detect replays */
-- rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
-- rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
-+ rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
-+ rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
-
- return RX_CONTINUE;
-
-@@ -165,6 +171,7 @@ static int tkip_encrypt_skb(struct ieee8
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_key *key = tx->key;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ unsigned long flags;
- unsigned int hdrlen;
- int len, tail;
- u8 *pos;
-@@ -192,11 +199,12 @@ static int tkip_encrypt_skb(struct ieee8
- pos += hdrlen;
-
- /* Increase IV for the frame */
-+ spin_lock_irqsave(&key->u.tkip.txlock, flags);
- key->u.tkip.tx.iv16++;
- if (key->u.tkip.tx.iv16 == 0)
- key->u.tkip.tx.iv32++;
--
-- pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
-+ pos = ieee80211_tkip_add_iv(pos, key);
-+ spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
-
- /* hwaccel - with software IV */
- if (info->control.hw_key)
-@@ -205,9 +213,8 @@ static int tkip_encrypt_skb(struct ieee8
- /* Add room for ICV */
- skb_put(skb, TKIP_ICV_LEN);
-
-- hdr = (struct ieee80211_hdr *) skb->data;
- return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
-- key, pos, len, hdr->addr2);
-+ key, skb, pos, len);
- }
-
-
-@@ -235,6 +242,11 @@ ieee80211_crypto_tkip_decrypt(struct iee
- struct ieee80211_key *key = rx->key;
- struct sk_buff *skb = rx->skb;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ int queue = rx->queue;
-+
-+ /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-+ if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-+ queue = 0;
-
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
-@@ -255,7 +267,7 @@ ieee80211_crypto_tkip_decrypt(struct iee
- res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
- key, skb->data + hdrlen,
- skb->len - hdrlen, rx->sta->sta.addr,
-- hdr->addr1, hwaccel, rx->queue,
-+ hdr->addr1, hwaccel, queue,
- &rx->tkip_iv32,
- &rx->tkip_iv16);
- if (res != TKIP_DECRYPT_OK)
-@@ -283,6 +295,8 @@ static void ccmp_special_blocks(struct s
- unsigned int hdrlen;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-
-+ memset(scratch, 0, 6 * AES_BLOCK_LEN);
-+
- b_0 = scratch + 3 * AES_BLOCK_LEN;
- aad = scratch + 4 * AES_BLOCK_LEN;
-
-@@ -373,8 +387,10 @@ static int ccmp_encrypt_skb(struct ieee8
- struct ieee80211_key *key = tx->key;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int hdrlen, len, tail;
-- u8 *pos, *pn;
-- int i;
-+ u8 *pos;
-+ u8 pn[6];
-+ u64 pn64;
-+ u8 scratch[6 * AES_BLOCK_LEN];
-
- if (info->control.hw_key &&
- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-@@ -402,14 +418,14 @@ static int ccmp_encrypt_skb(struct ieee8
- hdr = (struct ieee80211_hdr *) pos;
- pos += hdrlen;
-
-- /* PN = PN + 1 */
-- pn = key->u.ccmp.tx_pn;
-+ pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
-
-- for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
-- pn[i]++;
-- if (pn[i])
-- break;
-- }
-+ pn[5] = pn64;
-+ pn[4] = pn64 >> 8;
-+ pn[3] = pn64 >> 16;
-+ pn[2] = pn64 >> 24;
-+ pn[1] = pn64 >> 32;
-+ pn[0] = pn64 >> 40;
-
- ccmp_pn2hdr(pos, pn, key->conf.keyidx);
-
-@@ -418,8 +434,8 @@ static int ccmp_encrypt_skb(struct ieee8
- return 0;
-
- pos += CCMP_HDR_LEN;
-- ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
-- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len,
-+ ccmp_special_blocks(skb, pn, scratch, 0);
-+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
- pos, skb_put(skb, CCMP_MIC_LEN));
-
- return 0;
-@@ -475,11 +491,12 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+@@ -1413,7 +1414,8 @@ static void ath_tx_send_ampdu(struct ath
+ */
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
+ list_add_tail(&bf->list, &tid->buf_q);
+- ath_tx_queue_tid(txctl->txq, tid);
++ if (!txctl->an || !txctl->an->sleeping)
++ ath_tx_queue_tid(txctl->txq, tid);
+ return;
}
- if (!(status->flag & RX_FLAG_DECRYPTED)) {
-+ u8 scratch[6 * AES_BLOCK_LEN];
- /* hardware didn't decrypt/verify MIC */
-- ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
-+ ccmp_special_blocks(skb, pn, scratch, 1);
-
- if (ieee80211_aes_ccm_decrypt(
-- key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
-+ key->u.ccmp.tfm, scratch,
- skb->data + hdrlen + CCMP_HDR_LEN, data_len,
- skb->data + skb->len - CCMP_MIC_LEN,
- skb->data + hdrlen + CCMP_HDR_LEN))
---- a/drivers/net/wireless/b43/xmit.c
-+++ b/drivers/net/wireless/b43/xmit.c
-@@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev
- /* we give the phase1key and iv16 here, the key is stored in
- * shm. With that the hardware can do phase 2 and encryption.
- */
-- ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
-- IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
-+ ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
- /* phase1key is in host endian. Copy to little-endian txhdr->iv. */
- for (i = 0; i < 5; i++) {
- txhdr->iv[i * 2 + 0] = phase1key[i];
---- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
-+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
-@@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypt
-
- case WLAN_CIPHER_SUITE_TKIP:
- tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-- ieee80211_get_tkip_key(keyconf, skb_frag,
-- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
-+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
- IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
- break;
-
---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
-@@ -497,8 +497,7 @@ static void iwlagn_tx_cmd_build_hwcrypto
-
- case WLAN_CIPHER_SUITE_TKIP:
- tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-- ieee80211_get_tkip_key(keyconf, skb_frag,
-- IEEE80211_TKIP_P2_KEY, tx_cmd->key);
-+ ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
- IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
- break;
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -960,21 +960,6 @@ enum sta_notify_cmd {
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -421,6 +421,7 @@ struct station_parameters {
+ * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
+ * @STATION_INFO_BSS_PARAM: @bss_param filled
+ * @STATION_INFO_CONNECTED_TIME: @connected_time filled
++ * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
+ */
+ enum station_info_flags {
+ STATION_INFO_INACTIVE_TIME = 1<<0,
+@@ -439,7 +440,8 @@ enum station_info_flags {
+ STATION_INFO_SIGNAL_AVG = 1<<13,
+ STATION_INFO_RX_BITRATE = 1<<14,
+ STATION_INFO_BSS_PARAM = 1<<15,
+- STATION_INFO_CONNECTED_TIME = 1<<16
++ STATION_INFO_CONNECTED_TIME = 1<<16,
++ STATION_INFO_ASSOC_REQ_IES = 1<<17
};
/**
-- * enum ieee80211_tkip_key_type - get tkip key
-- *
-- * Used by drivers which need to get a tkip key for skb. Some drivers need a
-- * phase 1 key, others need a phase 2 key. A single function allows the driver
-- * to get the key, this enum indicates what type of key is required.
-- *
-- * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
-- * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
-- */
--enum ieee80211_tkip_key_type {
-- IEEE80211_TKIP_P1_KEY,
-- IEEE80211_TKIP_P2_KEY,
--};
--
--/**
- * enum ieee80211_hw_flags - hardware flags
- *
- * These flags are used to indicate hardware capabilities to
-@@ -2568,21 +2553,33 @@ struct sk_buff *
- ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-
- /**
-- * ieee80211_get_tkip_key - get a TKIP rc4 for skb
-+ * ieee80211_get_tkip_p1k - get a TKIP phase 1 key
-+ *
-+ * This function returns the TKIP phase 1 key for the IV32 taken
-+ * from the given packet.
-+ *
-+ * @keyconf: the parameter passed with the set key
-+ * @skb: the packet to take the IV32 value from that will be encrypted
-+ * with this P1K
-+ * @p1k: a buffer to which the key will be written, as 5 u16 values
-+ */
-+void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb, u16 *p1k);
-+
-+/**
-+ * ieee80211_get_tkip_p2k - get a TKIP phase 2 key
- *
-- * This function computes a TKIP rc4 key for an skb. It computes
-- * a phase 1 key if needed (iv16 wraps around). This function is to
-- * be used by drivers which can do HW encryption but need to compute
-- * to phase 1/2 key in SW.
-+ * This function computes the TKIP RC4 key for the IV values
-+ * in the packet.
- *
- * @keyconf: the parameter passed with the set key
-- * @skb: the skb for which the key is needed
-- * @type: TBD
-- * @key: a buffer to which the key will be written
-- */
--void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-- struct sk_buff *skb,
-- enum ieee80211_tkip_key_type type, u8 *key);
-+ * @skb: the packet to take the IV32/IV16 values from that will be
-+ * encrypted with this key
-+ * @p2k: a buffer to which the key will be written, 16 bytes
-+ */
-+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb, u8 *p2k);
-+
- /**
- * ieee80211_wake_queue - wake specific queue
- * @hw: pointer as obtained from ieee80211_alloc_hw().
---- a/net/mac80211/key.c
-+++ b/net/mac80211/key.c
-@@ -333,6 +333,7 @@ struct ieee80211_key *ieee80211_key_allo
- get_unaligned_le16(seq);
- }
- }
-+ spin_lock_init(&key->u.tkip.txlock);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- key->conf.iv_len = CCMP_HDR_LEN;
---- a/net/mac80211/key.h
-+++ b/net/mac80211/key.h
-@@ -52,9 +52,10 @@ enum ieee80211_internal_tkip_state {
- };
-
- struct tkip_ctx {
-- u32 iv32;
-- u16 iv16;
-- u16 p1k[5];
-+ u32 iv32; /* current iv32 */
-+ u16 iv16; /* current iv16 */
-+ u16 p1k[5]; /* p1k cache */
-+ u32 p1k_iv32; /* iv32 for which p1k computed */
- enum ieee80211_internal_tkip_state state;
- };
-
-@@ -71,6 +72,9 @@ struct ieee80211_key {
-
- union {
- struct {
-+ /* protects tx context */
-+ spinlock_t txlock;
-+
- /* last used TSC */
- struct tkip_ctx tx;
-
-@@ -78,7 +82,7 @@ struct ieee80211_key {
- struct tkip_ctx rx[NUM_RX_DATA_QUEUES];
- } tkip;
- struct {
-- u8 tx_pn[6];
-+ atomic64_t tx_pn;
- /*
- * Last received packet number. The first
- * NUM_RX_DATA_QUEUES counters are used with Data
-@@ -88,12 +92,9 @@ struct ieee80211_key {
- u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
- struct crypto_cipher *tfm;
- u32 replays; /* dot11RSNAStatsCCMPReplays */
-- /* scratch buffers for virt_to_page() (crypto API) */
- #ifndef AES_BLOCK_LEN
- #define AES_BLOCK_LEN 16
- #endif
-- u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
-- u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
- } ccmp;
- struct {
- u8 tx_pn[6];
---- a/net/mac80211/tkip.c
-+++ b/net/mac80211/tkip.c
-@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8
- p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
- }
- ctx->state = TKIP_STATE_PHASE1_DONE;
-+ ctx->p1k_iv32 = tsc_IV32;
- }
-
- static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
-@@ -140,60 +141,72 @@ static void tkip_mixing_phase2(const u8
- /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
- * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
- * the packet payload). */
--u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16)
-+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key)
- {
-- pos = write_tkip_iv(pos, iv16);
-+ lockdep_assert_held(&key->u.tkip.txlock);
-+
-+ pos = write_tkip_iv(pos, key->u.tkip.tx.iv16);
- *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
- put_unaligned_le32(key->u.tkip.tx.iv32, pos);
- return pos + 4;
- }
-
--void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-- struct sk_buff *skb, enum ieee80211_tkip_key_type type,
-- u8 *outkey)
-+static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32)
- {
-- struct ieee80211_key *key = (struct ieee80211_key *)
-- container_of(keyconf, struct ieee80211_key, conf);
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-- u8 *data;
-- const u8 *tk;
-- struct tkip_ctx *ctx;
-- u16 iv16;
-- u32 iv32;
--
-- data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-- iv16 = data[2] | (data[0] << 8);
-- iv32 = get_unaligned_le32(&data[4]);
--
-- tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-- ctx = &key->u.tkip.tx;
--
--#ifdef CONFIG_MAC80211_TKIP_DEBUG
-- printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
-- iv16, iv32);
-+ struct ieee80211_sub_if_data *sdata = key->sdata;
-+ struct tkip_ctx *ctx = &key->u.tkip.tx;
-+ const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-
-- if (iv32 != ctx->iv32) {
-- printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
-- iv32, ctx->iv32);
-- printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
-- "fragmented packet\n");
-- }
--#endif
-+ lockdep_assert_held(&key->u.tkip.txlock);
-
-- /* Update the p1k only when the iv16 in the packet wraps around, this
-- * might occur after the wrap around of iv16 in the key in case of
-- * fragmented packets. */
-- if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
-- tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32);
-+ /*
-+ * Update the P1K when the IV32 is different from the value it
-+ * had when we last computed it (or when not initialised yet).
-+ * This might flip-flop back and forth if packets are processed
-+ * out-of-order due to the different ACs, but then we have to
-+ * just compute the P1K more often.
-+ */
-+ if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT)
-+ tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32);
-+}
-
-- if (type == IEEE80211_TKIP_P1_KEY) {
-- memcpy(outkey, ctx->p1k, sizeof(u16) * 5);
-- return;
-- }
-+void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb, u16 *p1k)
-+{
-+ struct ieee80211_key *key = (struct ieee80211_key *)
-+ container_of(keyconf, struct ieee80211_key, conf);
-+ struct tkip_ctx *ctx = &key->u.tkip.tx;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-+ u32 iv32 = get_unaligned_le32(&data[4]);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&key->u.tkip.txlock, flags);
-+ ieee80211_compute_tkip_p1k(key, iv32);
-+ memcpy(p1k, ctx->p1k, sizeof(ctx->p1k));
-+ spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
-+}
-+EXPORT_SYMBOL(ieee80211_get_tkip_p1k);
-
-- tkip_mixing_phase2(tk, ctx, iv16, outkey);
-+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb, u8 *p2k)
-+{
-+ struct ieee80211_key *key = (struct ieee80211_key *)
-+ container_of(keyconf, struct ieee80211_key, conf);
-+ const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-+ struct tkip_ctx *ctx = &key->u.tkip.tx;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-+ u32 iv32 = get_unaligned_le32(&data[4]);
-+ u16 iv16 = data[2] | (data[0] << 8);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&key->u.tkip.txlock, flags);
-+ ieee80211_compute_tkip_p1k(key, iv32);
-+ tkip_mixing_phase2(tk, ctx, iv16, p2k);
-+ spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
- }
--EXPORT_SYMBOL(ieee80211_get_tkip_key);
-+EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
-
- /*
- * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
-@@ -204,19 +217,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
- */
- int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
- struct ieee80211_key *key,
-- u8 *pos, size_t payload_len, u8 *ta)
-+ struct sk_buff *skb,
-+ u8 *payload, size_t payload_len)
- {
- u8 rc4key[16];
-- struct tkip_ctx *ctx = &key->u.tkip.tx;
-- const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
--
-- /* Calculate per-packet key */
-- if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
-- tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
-
-- tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
-+ ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
-
-- return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
-+ return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
-+ payload, payload_len);
- }
-
- /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
---- a/net/mac80211/tkip.h
-+++ b/net/mac80211/tkip.h
-@@ -13,11 +13,13 @@
- #include <linux/crypto.h>
- #include "key.h"
-
--u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16);
-+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key);
-
- int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
-- struct ieee80211_key *key,
-- u8 *pos, size_t payload_len, u8 *ta);
-+ struct ieee80211_key *key,
-+ struct sk_buff *skb,
-+ u8 *payload, size_t payload_len);
-+
- enum {
- TKIP_DECRYPT_OK = 0,
- TKIP_DECRYPT_NO_EXT_IV = -1,
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiph
- u8 seq[6] = {0};
- struct key_params params;
- struct ieee80211_key *key = NULL;
-+ u64 pn64;
- u32 iv32;
- u16 iv16;
- int err = -ENOENT;
-@@ -256,12 +257,13 @@ static int ieee80211_get_key(struct wiph
- params.seq_len = 6;
- break;
- case WLAN_CIPHER_SUITE_CCMP:
-- seq[0] = key->u.ccmp.tx_pn[5];
-- seq[1] = key->u.ccmp.tx_pn[4];
-- seq[2] = key->u.ccmp.tx_pn[3];
-- seq[3] = key->u.ccmp.tx_pn[2];
-- seq[4] = key->u.ccmp.tx_pn[1];
-- seq[5] = key->u.ccmp.tx_pn[0];
-+ pn64 = atomic64_read(&key->u.ccmp.tx_pn);
-+ seq[0] = pn64;
-+ seq[1] = pn64 >> 8;
-+ seq[2] = pn64 >> 16;
-+ seq[3] = pn64 >> 24;
-+ seq[4] = pn64 >> 32;
-+ seq[5] = pn64 >> 40;
- params.seq = seq;
- params.seq_len = 6;
- break;
---- a/net/mac80211/debugfs_key.c
-+++ b/net/mac80211/debugfs_key.c
-@@ -79,6 +79,7 @@ static ssize_t key_tx_spec_read(struct f
- size_t count, loff_t *ppos)
- {
- const u8 *tpn;
-+ u64 pn;
- char buf[20];
- int len;
- struct ieee80211_key *key = file->private_data;
-@@ -94,9 +95,10 @@ static ssize_t key_tx_spec_read(struct f
- key->u.tkip.tx.iv16);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
-- tpn = key->u.ccmp.tx_pn;
-+ pn = atomic64_read(&key->u.ccmp.tx_pn);
- len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-- tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
-+ (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
-+ (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
- break;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- tpn = key->u.aes_cmac.tx_pn;
---- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-@@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_pos
- {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
- {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
-- {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
-+ {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
-+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
- {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
-@@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_cor
- {0x0000a3ec, 0x20202020},
- {0x0000a3f0, 0x00000000},
- {0x0000a3f4, 0x00000246},
-- {0x0000a3f8, 0x0cdbd380},
-+ {0x0000a3f8, 0x0c9bd380},
- {0x0000a3fc, 0x000f0f01},
- {0x0000a400, 0x8fa91f01},
- {0x0000a404, 0x00000000},
-@@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_cor
- {0x0000a43c, 0x00100000},
- {0x0000a440, 0x00000000},
- {0x0000a444, 0x00000000},
-- {0x0000a448, 0x06000080},
-+ {0x0000a448, 0x05000080},
- {0x0000a44c, 0x00000001},
- {0x0000a450, 0x00010000},
- {0x0000a458, 0x00000000},
-@@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2
- {0x0000816c, 0x00000000},
- {0x000081c0, 0x00000000},
- {0x000081c4, 0x33332210},
-- {0x000081c8, 0x00000000},
-- {0x000081cc, 0x00000000},
- {0x000081ec, 0x00000000},
- {0x000081f0, 0x00000000},
- {0x000081f4, 0x00000000},
---- a/net/mac80211/work.c
-+++ b/net/mac80211/work.c
-@@ -1075,14 +1075,13 @@ static void ieee80211_work_work(struct w
- continue;
- if (wk->chan != local->tmp_channel)
- continue;
-- if (ieee80211_work_ct_coexists(wk->chan_type,
-- local->tmp_channel_type))
-+ if (!ieee80211_work_ct_coexists(wk->chan_type,
-+ local->tmp_channel_type))
- continue;
- remain_off_channel = true;
- }
-
- if (!remain_off_channel && local->tmp_channel) {
-- bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
- local->tmp_channel = NULL;
- /* If tmp_channel wasn't operating channel, then
- * we need to go back on-channel.
-@@ -1092,7 +1091,7 @@ static void ieee80211_work_work(struct w
- * we still need to do a hardware config. Currently,
- * we cannot be here while scanning, however.
- */
-- if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
-+ if (!ieee80211_cfg_on_oper_channel(local))
- ieee80211_hw_config(local, 0);
-
- /* At the least, we need to disable offchannel_ps,
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -627,6 +627,11 @@ static void ar5008_hw_init_bb(struct ath
- else
- synthDelay /= 10;
-
-+ if (IS_CHAN_HALF_RATE(chan))
-+ synthDelay *= 2;
-+ else if (IS_CHAN_QUARTER_RATE(chan))
-+ synthDelay *= 4;
-+
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
---- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
-@@ -499,45 +499,6 @@ void ar9002_hw_enable_async_fifo(struct
- }
- }
-
--/*
-- * If Async FIFO is enabled, the following counters change as MAC now runs
-- * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
-- *
-- * The values below tested for ht40 2 chain.
-- * Overwrite the delay/timeouts initialized in process ini.
-- */
--void ar9002_hw_update_async_fifo(struct ath_hw *ah)
--{
-- if (AR_SREV_9287_13_OR_LATER(ah)) {
-- REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
-- AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
-- REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
-- AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
-- REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
-- AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
--
-- REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
-- REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
--
-- REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-- AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-- REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-- AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-- }
--}
--
--/*
-- * We don't enable WEP aggregation on mac80211 but we keep this
-- * around for HAL unification purposes.
-- */
--void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
--{
-- if (AR_SREV_9287_13_OR_LATER(ah)) {
-- REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-- AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
-- }
--}
--
- /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
- void ar9002_hw_attach_ops(struct ath_hw *ah)
- {
---- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
-@@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct
-
- switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
- case 0:
-- if ((freq % 20) == 0)
-+ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
-+ aModeRefSel = 0;
-+ else if ((freq % 20) == 0)
- aModeRefSel = 3;
- else if ((freq % 10) == 0)
- aModeRefSel = 2;
-@@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct
- channelSel = CHANSEL_5G(freq);
-
- /* RefDivA setting */
-- REG_RMW_FIELD(ah, AR_AN_SYNTH9,
-- AR_AN_SYNTH9_REFDIVA, refDivA);
-+ ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
-+ AR_AN_SYNTH9_REFDIVA,
-+ AR_AN_SYNTH9_REFDIVA_S, refDivA);
-
- }
-
-@@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_h
- static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-+ int ref_div = 5;
-+ int pll_div = 0x2c;
- u32 pll;
-
-- pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-+ if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
-+ if (AR_SREV_9280_20(ah)) {
-+ ref_div = 10;
-+ pll_div = 0x50;
-+ } else {
-+ pll_div = 0x28;
-+ }
-+ }
-+
-+ pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
-+ pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
-
- if (chan && IS_CHAN_HALF_RATE(chan))
- pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
- else if (chan && IS_CHAN_QUARTER_RATE(chan))
- pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-- if (chan && IS_CHAN_5GHZ(chan)) {
-- if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-- pll = 0x142c;
-- else if (AR_SREV_9280_20(ah))
-- pll = 0x2850;
-- else
-- pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-- } else {
-- pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-- }
--
- return pll;
- }
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -87,7 +87,10 @@ static void ath9k_hw_set_clockrate(struc
- struct ath_common *common = ath9k_hw_common(ah);
- unsigned int clockrate;
-
-- if (!ah->curchan) /* should really check for CCK instead */
-+ /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
-+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
-+ clockrate = 117;
-+ else if (!ah->curchan) /* should really check for CCK instead */
- clockrate = ATH9K_CLOCK_RATE_CCK;
- else if (conf->channel->band == IEEE80211_BAND_2GHZ)
- clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
-@@ -99,6 +102,13 @@ static void ath9k_hw_set_clockrate(struc
- if (conf_is_ht40(conf))
- clockrate *= 2;
-
-+ if (ah->curchan) {
-+ if (IS_CHAN_HALF_RATE(ah->curchan))
-+ clockrate /= 2;
-+ if (IS_CHAN_QUARTER_RATE(ah->curchan))
-+ clockrate /= 4;
-+ }
-+
- common->clockrate = clockrate;
- }
-
-@@ -895,6 +905,13 @@ static void ath9k_hw_init_interrupt_mask
- }
- }
-
-+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
-+{
-+ u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
-+ val = min(val, (u32) 0xFFFF);
-+ REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
-+}
-+
- static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
- {
- u32 val = ath9k_hw_mac_to_clks(ah, us);
-@@ -932,25 +949,60 @@ static bool ath9k_hw_set_global_txtimeou
-
- void ath9k_hw_init_global_settings(struct ath_hw *ah)
- {
-- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ struct ieee80211_conf *conf = &common->hw->conf;
-+ const struct ath9k_channel *chan = ah->curchan;
- int acktimeout;
- int slottime;
- int sifstime;
-+ int rx_lat = 0, tx_lat = 0, eifs = 0;
-+ u32 reg;
-
- ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
- ah->misc_mode);
-
-+ if (!chan)
-+ return;
-+
- if (ah->misc_mode != 0)
- REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
-
-- if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
-- sifstime = 16;
-- else
-- sifstime = 10;
-+ rx_lat = 37;
-+ tx_lat = 54;
-+
-+ if (IS_CHAN_HALF_RATE(chan)) {
-+ eifs = 175;
-+ rx_lat *= 2;
-+ tx_lat *= 2;
-+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-+ tx_lat += 11;
-+
-+ slottime = 13;
-+ sifstime = 32;
-+ } else if (IS_CHAN_QUARTER_RATE(chan)) {
-+ eifs = 340;
-+ rx_lat *= 4;
-+ tx_lat *= 4;
-+ if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-+ tx_lat += 22;
-+
-+ slottime = 21;
-+ sifstime = 64;
-+ } else {
-+ eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
-+ reg = REG_READ(ah, AR_USEC);
-+ rx_lat = MS(reg, AR_USEC_RX_LAT);
-+ tx_lat = MS(reg, AR_USEC_TX_LAT);
-+
-+ slottime = ah->slottime;
-+ if (IS_CHAN_5GHZ(chan))
-+ sifstime = 16;
-+ else
-+ sifstime = 10;
-+ }
-
- /* As defined by IEEE 802.11-2007 17.3.8.6 */
-- slottime = ah->slottime + 3 * ah->coverage_class;
-- acktimeout = slottime + sifstime;
-+ acktimeout = slottime + sifstime + 3 * ah->coverage_class;
-
- /*
- * Workaround for early ACK timeouts, add an offset to match the
-@@ -962,11 +1014,20 @@ void ath9k_hw_init_global_settings(struc
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
- acktimeout += 64 - sifstime - ah->slottime;
-
-- ath9k_hw_setslottime(ah, ah->slottime);
-+ ath9k_hw_set_sifs_time(ah, sifstime);
-+ ath9k_hw_setslottime(ah, slottime);
- ath9k_hw_set_ack_timeout(ah, acktimeout);
- ath9k_hw_set_cts_timeout(ah, acktimeout);
- if (ah->globaltxtimeout != (u32) -1)
- ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
-+
-+ REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
-+ REG_RMW(ah, AR_USEC,
-+ (common->clockrate - 1) |
-+ SM(rx_lat, AR_USEC_RX_LAT) |
-+ SM(tx_lat, AR_USEC_TX_LAT),
-+ AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
-+
- }
- EXPORT_SYMBOL(ath9k_hw_init_global_settings);
-
-@@ -1570,9 +1631,13 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-
- ath9k_hw_init_global_settings(ah);
-
-- if (!AR_SREV_9300_20_OR_LATER(ah)) {
-- ar9002_hw_update_async_fifo(ah);
-- ar9002_hw_enable_wep_aggregation(ah);
-+ if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
-+ REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-+ REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-+ AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-+ AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
- }
-
- REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
-@@ -1932,12 +1997,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_ti
- /* HW Capabilities */
- /*******************/
-
-+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
-+{
-+ eeprom_chainmask &= chip_chainmask;
-+ if (eeprom_chainmask)
-+ return eeprom_chainmask;
-+ else
-+ return chip_chainmask;
-+}
-+
- int ath9k_hw_fill_cap_info(struct ath_hw *ah)
- {
- struct ath9k_hw_capabilities *pCap = &ah->caps;
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
-+ unsigned int chip_chainmask;
-
- u16 eeval;
- u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
-@@ -1974,6 +2049,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw
- if (eeval & AR5416_OPFLAGS_11G)
- pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
-
-+ if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
-+ chip_chainmask = 1;
-+ else if (!AR_SREV_9280_20_OR_LATER(ah))
-+ chip_chainmask = 7;
-+ else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
-+ chip_chainmask = 3;
-+ else
-+ chip_chainmask = 7;
-+
- pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
- /*
- * For AR9271 we will temporarilly uses the rx chainmax as read from
-@@ -1990,6 +2074,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw
- /* Use rx_chainmask from EEPROM. */
- pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
-
-+ pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
-+ pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
-+
- ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
-
- /* enable key search for every frame in an aggregate */
-@@ -2079,10 +2166,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw
- pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
- } else {
- pCap->tx_desc_len = sizeof(struct ath_desc);
-- if (AR_SREV_9280_20(ah) &&
-- ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
-- AR5416_EEP_MINOR_VER_16) ||
-- ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
-+ if (AR_SREV_9280_20(ah))
- pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
- }
-
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -983,8 +983,6 @@ void ath9k_hw_get_delta_slope_vals(struc
- void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
- int ar9002_hw_rf_claim(struct ath_hw *ah);
- void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
--void ar9002_hw_update_async_fifo(struct ath_hw *ah);
--void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
-
- /*
- * Code specific to AR9003, we stuff these here to avoid callbacks
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -814,16 +814,19 @@ static bool ath9k_rx_accept(struct ath_c
- struct ath_rx_status *rx_stats,
- bool *decrypt_error)
- {
--#define is_mc_or_valid_tkip_keyix ((is_mc || \
-- (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
-- test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
--
-+ bool is_mc, is_valid_tkip, strip_mic, mic_error = false;
- struct ath_hw *ah = common->ah;
- __le16 fc;
- u8 rx_status_len = ah->caps.rx_status_len;
-
- fc = hdr->frame_control;
-
-+ is_mc = !!is_multicast_ether_addr(hdr->addr1);
-+ is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
-+ test_bit(rx_stats->rs_keyix, common->tkip_keymap);
-+ strip_mic = is_valid_tkip && !(rx_stats->rs_status &
-+ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
-+
- if (!rx_stats->rs_datalen)
- return false;
- /*
-@@ -838,6 +841,11 @@ static bool ath9k_rx_accept(struct ath_c
- if (rx_stats->rs_more)
- return true;
-
-+ mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
-+ !ieee80211_has_morefrags(fc) &&
-+ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-+ (rx_stats->rs_status & ATH9K_RXERR_MIC);
-+
- /*
- * The rx_stats->rs_status will not be set until the end of the
- * chained descriptors so it can be ignored if rs_more is set. The
-@@ -845,30 +853,18 @@ static bool ath9k_rx_accept(struct ath_c
- * descriptors.
- */
- if (rx_stats->rs_status != 0) {
-- if (rx_stats->rs_status & ATH9K_RXERR_CRC)
-+ if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
- rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
-+ mic_error = false;
-+ }
- if (rx_stats->rs_status & ATH9K_RXERR_PHY)
- return false;
-
- if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
- *decrypt_error = true;
-- } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
-- bool is_mc;
-- /*
-- * The MIC error bit is only valid if the frame
-- * is not a control frame or fragment, and it was
-- * decrypted using a valid TKIP key.
-- */
-- is_mc = !!is_multicast_ether_addr(hdr->addr1);
--
-- if (!ieee80211_is_ctl(fc) &&
-- !ieee80211_has_morefrags(fc) &&
-- !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-- is_mc_or_valid_tkip_keyix)
-- rxs->flag |= RX_FLAG_MMIC_ERROR;
-- else
-- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
-+ mic_error = false;
- }
-+
- /*
- * Reject error frames with the exception of
- * decryption and MIC failures. For monitor mode,
-@@ -886,6 +882,18 @@ static bool ath9k_rx_accept(struct ath_c
- }
- }
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -2236,7 +2236,7 @@ static int nl80211_send_station(struct s
}
-+
-+ /*
-+ * For unicast frames the MIC error bit can have false positives,
-+ * so all MIC error reports need to be validated in software.
-+ * False negatives are not common, so skip software verification
-+ * if the hardware considers the MIC valid.
-+ */
-+ if (strip_mic)
-+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;
-+ else if (is_mc && mic_error)
-+ rxs->flag |= RX_FLAG_MMIC_ERROR;
-+
- return true;
- }
-
-@@ -1938,6 +1946,9 @@ int ath_rx_tasklet(struct ath_softc *sc,
- sc->rx.rxotherant = 0;
- }
-
-+ if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
-+ skb_trim(skb, skb->len - 8);
-+
- spin_lock_irqsave(&sc->sc_pm_lock, flags);
-
- if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -600,7 +600,6 @@
-
- #define AR_D_GBL_IFS_SIFS 0x1030
- #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF
--#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
- #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF
-
- #define AR_D_TXBLK_BASE 0x1038
-@@ -616,12 +615,10 @@
- #define AR_D_GBL_IFS_SLOT 0x1070
- #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF
- #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000
--#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
-
- #define AR_D_GBL_IFS_EIFS 0x10b0
- #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF
- #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000
--#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB
-
- #define AR_D_GBL_IFS_MISC 0x10f0
- #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
-@@ -1477,7 +1474,6 @@ enum {
- #define AR_TIME_OUT_ACK_S 0
- #define AR_TIME_OUT_CTS 0x3FFF0000
- #define AR_TIME_OUT_CTS_S 16
--#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56
+ nla_nest_end(msg, sinfoattr);
- #define AR_RSSI_THR 0x8018
- #define AR_RSSI_THR_MASK 0x000000FF
-@@ -1493,7 +1489,6 @@ enum {
- #define AR_USEC_TX_LAT_S 14
- #define AR_USEC_RX_LAT 0x1F800000
- #define AR_USEC_RX_LAT_S 23
--#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074
+- if (sinfo->assoc_req_ies)
++ if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES)
+ NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
+ sinfo->assoc_req_ies);
- #define AR_RESET_TSF 0x8020
- #define AR_RESET_TSF_ONCE 0x01000000
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -1038,6 +1038,7 @@ struct cfg80211_ibss_params {
+@@ -1045,6 +1045,7 @@ struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
-@@ -2539,6 +2540,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
+@@ -2478,6 +2479,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
const u8 *bssid,
const u8 *ssid, size_t ssid_len,
u16 capa_mask, u16 capa_val);
static inline struct cfg80211_bss *
cfg80211_get_ibss(struct wiphy *wiphy,
struct ieee80211_channel *channel,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4351,13 +4351,41 @@ static int nl80211_join_ibss(struct sk_b
+ ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ }
+
+- ibss.channel = ieee80211_get_channel(wiphy,
+- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
++ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
++ enum nl80211_channel_type channel_type;
++
++ channel_type = nla_get_u32(
++ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
++ if (channel_type != NL80211_CHAN_NO_HT &&
++ channel_type != NL80211_CHAN_HT20 &&
++ channel_type != NL80211_CHAN_HT40PLUS &&
++ channel_type != NL80211_CHAN_HT40MINUS)
++ return -EINVAL;
++ ibss.channel_type = channel_type;
++ } else {
++ ibss.channel_type = NL80211_CHAN_NO_HT;
++ }
++
++ ibss.channel = rdev_freq_to_chan(rdev,
++ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
++ ibss.channel_type);
+ if (!ibss.channel ||
++ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
+- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
++ ibss.channel->flags & IEEE80211_CHAN_RADAR)
+ return -EINVAL;
+
++ /* Both channels should be able to initiate communication */
++ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
++ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
++ !can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
++ ibss.channel_type)) {
++ printk(KERN_DEBUG
++ "cfg80211: Secondary channel not "
++ "allowed to initiate communication\n");
++ return -EINVAL;
++ }
++
+ ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
+ ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
+
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -44,7 +44,7 @@ rdev_freq_to_chan(struct cfg80211_regist
+ return chan;
+ }
+
+-static bool can_beacon_sec_chan(struct wiphy *wiphy,
++bool can_beacon_sec_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+ {
+@@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
+
+ return true;
+ }
++EXPORT_SYMBOL(can_beacon_sec_chan);
+
+ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -441,6 +441,9 @@ cfg80211_can_add_interface(struct cfg802
+ struct ieee80211_channel *
+ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
+ int freq, enum nl80211_channel_type channel_type);
++bool can_beacon_sec_chan(struct wiphy *wiphy,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type);
+ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type);
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -365,6 +365,19 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val)
+ {
++ /* call HT version with no HT requirements */
++ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
++ capa_mask, capa_val, NL80211_CHAN_NO_HT);
++}
++EXPORT_SYMBOL(cfg80211_get_bss);
++
++struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
++ struct ieee80211_channel *channel,
++ const u8 *bssid,
++ const u8 *ssid, size_t ssid_len,
++ u16 capa_mask, u16 capa_val,
++ enum nl80211_channel_type require_ht)
++{
+ struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
+ struct cfg80211_internal_bss *bss, *res = NULL;
+ unsigned long now = jiffies;
+@@ -374,8 +387,26 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ list_for_each_entry(bss, &dev->bss_list, list) {
+ if ((bss->pub.capability & capa_mask) != capa_val)
+ continue;
+- if (channel && bss->pub.channel != channel)
+- continue;
++ if (channel) {
++ if (bss->pub.channel != channel)
++ continue;
++ if (require_ht != NL80211_CHAN_NO_HT) {
++ struct ieee80211_ht_info *ht_info;
++ ht_info = (struct ieee80211_ht_info *)
++ ieee80211_bss_get_ie(&bss->pub,
++ WLAN_EID_HT_INFORMATION);
++ if (!ht_info)
++ continue;
++ if (require_ht == NL80211_CHAN_HT40MINUS &&
++ !(ht_info->ht_param &
++ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
++ continue;
++ if (require_ht == NL80211_CHAN_HT40PLUS &&
++ !(ht_info->ht_param &
++ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
++ continue;
++ }
++ }
+ /* Don't get expired BSS structs */
+ if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
+ !atomic_read(&bss->hold))
+@@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ return NULL;
+ return &res->pub;
+ }
+-EXPORT_SYMBOL(cfg80211_get_bss);
++EXPORT_SYMBOL(cfg80211_get_bss_ht);
+
+ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -439,6 +439,7 @@ struct ieee80211_if_ibss {
+@@ -464,6 +464,7 @@ struct ieee80211_if_ibss {
u8 ssid_len, ie_len;
u8 *ie;
struct ieee80211_channel *channel;
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
-@@ -1121,6 +1122,7 @@ void ieee80211_ibss_notify_scan_complete
+@@ -1151,6 +1152,7 @@ void ieee80211_ibss_notify_scan_complete
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 *addr, u32 supp_rates,
gfp_t gfp);
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
-@@ -1373,6 +1375,12 @@ void ieee80211_recalc_smps(struct ieee80
+@@ -1405,6 +1407,12 @@ void ieee80211_recalc_smps(struct ieee80
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids, size_t offset);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
-@@ -1401,6 +1409,8 @@ ieee80211_get_channel_mode(struct ieee80
+@@ -1433,6 +1441,8 @@ ieee80211_get_channel_mode(struct ieee80
bool ieee80211_set_channel_type(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
enum nl80211_channel_type chantype);
#define debug_noinline noinline
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
-@@ -1007,23 +1007,8 @@ int ieee80211_build_preq_ies(struct ieee
+@@ -1008,23 +1008,8 @@ int ieee80211_build_preq_ies(struct ieee
offset = noffset;
}
/*
* If adding more here, adjust code in main.c
-@@ -1464,3 +1449,100 @@ size_t ieee80211_ie_split_vendor(const u
-
- return pos;
+@@ -1548,3 +1533,100 @@ void ieee80211_disable_rssi_reports(stru
+ _ieee80211_enable_rssi_reports(sdata, 0, 0);
}
+ EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
+
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+ u16 cap)
+}
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
-@@ -117,7 +117,6 @@ static void ieee80211_add_ht_ie(struct s
+@@ -118,7 +118,6 @@ static void ieee80211_add_ht_ie(struct s
u8 *pos;
u32 flags = channel->flags;
u16 cap = sband->ht_cap.cap;
if (!sband->ht_cap.ht_supported)
return;
-@@ -168,34 +167,8 @@ static void ieee80211_add_ht_ie(struct s
+@@ -169,34 +168,8 @@ static void ieee80211_add_ht_ie(struct s
}
/* reserve and fill IE */
}
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
---- a/net/wireless/scan.c
-+++ b/net/wireless/scan.c
-@@ -365,6 +365,18 @@ struct cfg80211_bss *cfg80211_get_bss(st
- const u8 *ssid, size_t ssid_len,
- u16 capa_mask, u16 capa_val)
- {
-+ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
-+ capa_mask, capa_val, NL80211_CHAN_NO_HT);
-+}
-+EXPORT_SYMBOL(cfg80211_get_bss);
-+
-+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
-+ struct ieee80211_channel *channel,
-+ const u8 *bssid,
-+ const u8 *ssid, size_t ssid_len,
-+ u16 capa_mask, u16 capa_val,
-+ enum nl80211_channel_type channel_type)
-+{
- struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
- struct cfg80211_internal_bss *bss, *res = NULL;
- unsigned long now = jiffies;
-@@ -374,8 +386,27 @@ struct cfg80211_bss *cfg80211_get_bss(st
- list_for_each_entry(bss, &dev->bss_list, list) {
- if ((bss->pub.capability & capa_mask) != capa_val)
- continue;
-- if (channel && bss->pub.channel != channel)
-- continue;
-+ if (channel) {
-+ if (bss->pub.channel != channel)
-+ continue;
-+ if (channel_type == NL80211_CHAN_HT40MINUS ||
-+ channel_type == NL80211_CHAN_HT40PLUS) {
-+ struct ieee80211_ht_info *ht_info;
-+ ht_info = (struct ieee80211_ht_info *)
-+ ieee80211_bss_get_ie(&bss->pub,
-+ WLAN_EID_HT_INFORMATION);
-+ if (!ht_info)
-+ continue;
-+ if (channel_type == NL80211_CHAN_HT40MINUS &&
-+ !(ht_info->ht_param &
-+ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
-+ continue;
-+ if (channel_type == NL80211_CHAN_HT40PLUS &&
-+ !(ht_info->ht_param &
-+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
-+ continue;
-+ }
-+ }
- /* Don't get expired BSS structs */
- if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
- !atomic_read(&bss->hold))
-@@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
- return NULL;
- return &res->pub;
- }
--EXPORT_SYMBOL(cfg80211_get_bss);
-+EXPORT_SYMBOL(cfg80211_get_bss_ht);
-
- struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -4282,13 +4282,42 @@ static int nl80211_join_ibss(struct sk_b
- ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
- }
-
-- ibss.channel = ieee80211_get_channel(wiphy,
-- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
-+ enum nl80211_channel_type channel_type;
-+
-+ channel_type = nla_get_u32(
-+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
-+ if (channel_type != NL80211_CHAN_NO_HT &&
-+ channel_type != NL80211_CHAN_HT20 &&
-+ channel_type != NL80211_CHAN_HT40PLUS &&
-+ channel_type != NL80211_CHAN_HT40MINUS)
-+ return -EINVAL;
-+ ibss.channel_type = channel_type;
-+ } else {
-+ ibss.channel_type = NL80211_CHAN_NO_HT;
-+ }
-+
-+ ibss.channel = rdev_freq_to_chan(rdev,
-+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
-+ ibss.channel_type);
-+
- if (!ibss.channel ||
-+ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
- return -EINVAL;
-
-+#if 0
-+ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
-+ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
-+ !can_beacon_sec_chan(&rdev->wiphy, ibss.chan, ibss.channel_type)) {
-+ printk(KERN_DEBUG
-+ "cfg80211: Secondary channel not "
-+ "allowed to initiate communication\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
- ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
- ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
-
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -178,6 +178,8 @@ static void ieee80211_send_addba_resp(st
- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
- else if (sdata->vif.type == NL80211_IFTYPE_WDS)
- memcpy(mgmt->bssid, da, ETH_ALEN);
-+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, 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
@@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
IEEE80211_STYPE_ACTION);
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
-@@ -64,6 +64,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
+@@ -35,6 +35,76 @@
+
+ #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
+
++static bool ieee80211_can_use_ext_chan(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_channel *channel,
++ enum nl80211_channel_type channel_type)
++{
++ /* check if we are legally allowed to use HT extension channel */
++ if ((channel_type == NL80211_CHAN_HT40PLUS) ||
++ (channel_type == NL80211_CHAN_HT40MINUS)) {
++ int sec_freq = channel->center_freq +
++ (channel_type == NL80211_CHAN_HT40PLUS ? 20 : -20);
++ struct ieee80211_channel *sec_chan =
++ ieee80211_get_channel(sdata->wdev.wiphy, sec_freq);
++ if (!sec_chan || sec_chan->flags & (IEEE80211_CHAN_DISABLED |
++ IEEE80211_CHAN_PASSIVE_SCAN |
++ IEEE80211_CHAN_NO_IBSS |
++ IEEE80211_CHAN_RADAR)) {
++ return false;
++ }
++ }
++ return true;
++}
++
++static void ieee80211_update_ht_elems(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_mgmt *mgmt,
++ struct ieee80211_ht_info *ht_info)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_supported_band *sband =
++ local->hw.wiphy->bands[local->oper_channel->band];
++ enum nl80211_channel_type channel_type =
++ ieee80211_ht_info_to_channel_type(ht_info);
++
++ if (!ieee80211_can_use_ext_chan(sdata, local->oper_channel, channel_type))
++ channel_type = NL80211_CHAN_HT20;
++
++ if (channel_type != local->_oper_channel_type) {
++ struct sk_buff *skb = rcu_dereference_protected(
++ sdata->u.ibss.presp,
++ lockdep_is_held(&ifibss->mtx));
++ struct sk_buff *nskb;
++ u8 *ht_ie;
++
++ /* update HT IE. If not yet existing, create one */
++ nskb = skb_copy(skb, GFP_ATOMIC);
++ ht_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
++ (const u8 *)(nskb->data + 24 +
++ sizeof(mgmt->u.beacon)),
++ nskb->len - 24 -
++ sizeof(mgmt->u.beacon));
++ if (!ht_ie)
++ ht_ie = skb_put(nskb, 4 +
++ sizeof(struct ieee80211_ht_cap) +
++ sizeof(struct ieee80211_ht_info));
++
++ ht_ie = ieee80211_ie_build_ht_cap(ht_ie, sband,
++ sband->ht_cap.cap);
++ ht_ie = ieee80211_ie_build_ht_info(ht_ie, &sband->ht_cap,
++ local->oper_channel, channel_type);
++ rcu_assign_pointer(sdata->u.ibss.presp, nskb);
++ kfree_skb(skb);
++
++ if(!ieee80211_set_channel_type(local, sdata, channel_type)) {
++ channel_type = NL80211_CHAN_HT20;
++ WARN_ON(!ieee80211_set_channel_type(local, sdata,
++ channel_type));
++ }
++
++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
++ }
++
++}
+
+ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt,
+@@ -64,6 +134,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, const int beacon_int,
struct ieee80211_channel *chan,
const u32 basic_rates,
const u16 capability, u64 tsf)
{
-@@ -104,8 +105,12 @@ static void __ieee80211_sta_join_ibss(st
+@@ -104,8 +175,17 @@ static void __ieee80211_sta_join_ibss(st
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+ /* entering a legacy IBSS. Use given HT configuration. */
+ if (channel_type == NL80211_CHAN_NO_HT)
+ channel_type = ifibss->channel_type;
-+
local->oper_channel = chan;
- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
-+ WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
++
++ /* if phy is on a different extension channel, setting ht40 will fail */
++ if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
++ channel_type = NL80211_CHAN_HT20;
++ WARN_ON(!ieee80211_set_channel_type(local, sdata,
++ channel_type));
++ }
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
sband = local->hw.wiphy->bands[chan->band];
-@@ -171,6 +176,17 @@ static void __ieee80211_sta_join_ibss(st
+@@ -171,6 +251,18 @@ static void __ieee80211_sta_join_ibss(st
memcpy(skb_put(skb, ifibss->ie_len),
ifibss->ie, ifibss->ie_len);
++ /* add HT capability and information IEs */
+ if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) {
+ pos = skb_put(skb, 4 +
+ sizeof(struct ieee80211_ht_cap) +
if (local->hw.queues >= 4) {
pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
-@@ -219,6 +235,8 @@ static void ieee80211_sta_join_ibss(stru
+@@ -219,6 +311,8 @@ static void ieee80211_sta_join_ibss(stru
u32 basic_rates;
int i, j;
u16 beacon_int = cbss->beacon_interval;
lockdep_assert_held(&sdata->u.ibss.mtx);
-@@ -242,9 +260,15 @@ static void ieee80211_sta_join_ibss(stru
+@@ -242,9 +336,23 @@ static void ieee80211_sta_join_ibss(stru
}
}
+ if (ht_info_ie)
+ channel_type = ieee80211_ht_info_to_channel_type(
+ (struct ieee80211_ht_info *) (ht_info_ie + 2));
++
++ if (!ieee80211_can_use_ext_chan(sdata, cbss->channel, channel_type)) {
++ channel_type = NL80211_CHAN_HT20;
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG "%s: IBSS not allowed on secondary channel\n",
++ sdata->name);
++#endif
++ }
+
__ieee80211_sta_join_ibss(sdata, cbss->bssid,
beacon_int,
basic_rates,
cbss->capability,
cbss->tsf);
-@@ -310,11 +334,65 @@ static void ieee80211_rx_bss_info(struct
+@@ -310,11 +418,24 @@ static void ieee80211_rx_bss_info(struct
} else
sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
mgmt->sa, supp_rates,
+ if (elems->wmm_info)
+ set_sta_flags(sta, WLAN_STA_WME);
+
++ /* remote station uses ht */
+ if (elems->ht_info_elem) {
-+ struct ieee80211_supported_band *sband =
-+ local->hw.wiphy->bands[channel->band];
-+ enum nl80211_channel_type channel_type;
-+
-+ channel_type =
-+ ieee80211_ht_info_to_channel_type(
-+ elems->ht_info_elem);
-+ if (channel_type != local->_oper_channel_type) {
-+ struct sk_buff *skb =
-+ sdata->u.ibss.presp;
-+ struct sk_buff *nskb;
-+ u8 *ht_ie;
-+
-+ nskb = skb_copy(skb, GFP_ATOMIC);
-+ ht_ie = (u8 *) cfg80211_find_ie(
-+ WLAN_EID_HT_CAPABILITY,
-+ nskb->data + 24 +
-+ sizeof(mgmt->u.beacon),
-+ nskb->len - 24 -
-+ sizeof(mgmt->u.beacon));
-+
-+ if (!ht_ie)
-+ ht_ie = skb_put(nskb, 4 +
-+ sizeof(struct ieee80211_ht_cap) +
-+ sizeof(struct ieee80211_ht_info));
-+ ht_ie = ieee80211_ie_build_ht_cap(ht_ie,
-+ sband,
-+ sband->ht_cap.cap);
-+ ht_ie = ieee80211_ie_build_ht_info(
-+ ht_ie,
-+ &sband->ht_cap,
-+ channel,
-+ channel_type);
-+ sdata->u.ibss.presp = nskb;
-+ kfree_skb(skb);
-+
-+ local->_oper_channel_type =
-+ channel_type;
-+ WARN_ON(!ieee80211_set_channel_type(
-+ local,
-+ sdata,
-+ channel_type));
-+ ieee80211_hw_config(local,
-+ IEEE80211_CONF_CHANGE_CHANNEL);
-+ }
-+ ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
-+ elems->ht_cap_elem,
-+ &sta->sta.ht_cap);
-+
++ ieee80211_update_ht_elems(sdata, mgmt,
++ elems->ht_info_elem);
++ ieee80211_ht_cap_ie_to_sta_ht_cap(
++ local->hw.wiphy->bands[
++ local->oper_channel->band],
++ elems->ht_cap_elem,
++ &sta->sta.ht_cap);
+ }
+ }
rcu_read_unlock();
}
-@@ -404,7 +482,7 @@ static void ieee80211_rx_bss_info(struct
+@@ -404,7 +525,7 @@ static void ieee80211_rx_bss_info(struct
ieee80211_sta_join_ibss(sdata, bss);
supp_rates = ieee80211_sta_get_rates(local, elems, band);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
}
put_bss:
-@@ -417,7 +495,8 @@ static void ieee80211_rx_bss_info(struct
+@@ -417,7 +538,8 @@ static void ieee80211_rx_bss_info(struct
* must be callable in atomic context.
*/
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
gfp_t gfp)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-@@ -458,6 +537,11 @@ struct sta_info *ieee80211_ibss_add_sta(
+@@ -458,6 +580,11 @@ struct sta_info *ieee80211_ibss_add_sta(
sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band);
rate_control_rate_init(sta);
/* If it fails, maybe we raced another insertion? */
-@@ -556,8 +640,8 @@ static void ieee80211_sta_create_ibss(st
+@@ -556,8 +683,8 @@ static void ieee80211_sta_create_ibss(st
sdata->drop_unencrypted = 0;
__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
}
/*
-@@ -594,10 +678,10 @@ static void ieee80211_sta_find_ibss(stru
+@@ -594,10 +721,10 @@ static void ieee80211_sta_find_ibss(stru
chan = ifibss->channel;
if (!is_zero_ether_addr(ifibss->bssid))
bssid = ifibss->bssid;
if (cbss) {
struct ieee80211_bss *bss;
-@@ -896,10 +980,15 @@ int ieee80211_ibss_join(struct ieee80211
+@@ -896,10 +1023,15 @@ int ieee80211_ibss_join(struct ieee80211
struct sk_buff *skb;
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
params->ie_len);
if (!skb)
return -ENOMEM;
-@@ -920,13 +1009,14 @@ int ieee80211_ibss_join(struct ieee80211
+@@ -920,13 +1052,15 @@ int ieee80211_ibss_join(struct ieee80211
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
sdata->u.ibss.channel = params->channel;
/* fix ourselves to that channel now already */
if (params->channel_fixed) {
sdata->local->oper_channel = params->channel;
- WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
+- WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
- NL80211_CHAN_NO_HT));
-+ params->channel_type));
++ if(!ieee80211_set_channel_type(sdata->local, sdata,
++ params->channel_type))
++ return -EINVAL;
}
if (params->ie) {
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2138,7 +2138,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2148,7 +2148,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 &&
break;
/* verify action_code is present */
-@@ -2654,7 +2655,8 @@ static int prepare_for_handlers(struct i
+@@ -2666,7 +2667,8 @@ static int prepare_for_handlers(struct i
else
rate_idx = status->rate_idx;
rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
}
break;
case NL80211_IFTYPE_MESH_POINT:
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -186,6 +186,8 @@ static void ieee80211_send_addba_resp(st
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_WDS)
+ memcpy(mgmt->bssid, da, ETH_ALEN);
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -34,7 +34,7 @@ int ath9k_modparam_nohwcrypt;
+@@ -35,7 +35,7 @@ int ath9k_modparam_nohwcrypt;
module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
#include <asm/unaligned.h>
#include "hw.h"
-@@ -453,8 +454,16 @@ static int ath9k_hw_init_macaddr(struct
+@@ -460,8 +461,16 @@ static int ath9k_hw_init_macaddr(struct
common->macaddr[2 * i] = eeval >> 8;
common->macaddr[2 * i + 1] = eeval & 0xff;
}
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
-@@ -1643,6 +1643,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1642,6 +1642,8 @@ void regulatory_hint_11d(struct wiphy *w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
mutex_lock(®_mutex);
if (unlikely(!last_request))
-@@ -1849,6 +1851,8 @@ static void restore_regulatory_settings(
+@@ -1848,6 +1850,8 @@ static void restore_regulatory_settings(
void regulatory_hint_disconnect(void)
{
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1495,15 +1495,6 @@ static int ath9k_add_interface(struct ie
+@@ -1499,15 +1499,6 @@ static int ath9k_add_interface(struct ie
}
}
ath_dbg(common, ATH_DBG_CONFIG,
"Attach a VIF of type: %d\n", vif->type);
-@@ -1529,15 +1520,6 @@ static int ath9k_change_interface(struct
+@@ -1533,15 +1524,6 @@ static int ath9k_change_interface(struct
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-@@ -95,13 +95,8 @@ ath5k_add_interface(struct ieee80211_hw
+@@ -83,13 +83,8 @@ ath5k_add_interface(struct ieee80211_hw
goto end;
}
- * We would need to operate the HW in ad-hoc mode to allow TSF updates
- * for the IBSS, but this breaks with additional AP or STA interfaces
- * at the moment. */
-- if (sc->num_adhoc_vifs ||
-- (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+- if (ah->num_adhoc_vifs ||
+- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+ /* Don't allow more than one ad-hoc interface */
-+ if (sc->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
- ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
ret = -ELNRNG;
goto end;
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1883,7 +1883,7 @@ ath5k_beacon_send(struct ath5k_softc *sc
- sc->bmisscount = 0;
+@@ -1866,7 +1866,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+ ah->bmisscount = 0;
}
-- if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
-+ if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs + sc->num_adhoc_vifs > 1) ||
- sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+- if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
++ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + ah->num_adhoc_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
-@@ -1961,7 +1961,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -1951,7 +1951,7 @@ ath5k_beacon_update_timers(struct ath5k_
u64 hw_tsf;
- intval = sc->bintval & AR5K_BEACON_PERIOD;
-- if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
-+ if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs + sc->num_adhoc_vifs > 1) {
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+- if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
++ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + ah->num_adhoc_vifs > 1) {
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15)
- ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1035,6 +1035,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
+@@ -1040,6 +1040,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
tsf_lo = 0;
mode = 0;
/*
* Sanity check for fast flag
* Fast channel change only available
-@@ -1042,6 +1043,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
+@@ -1047,6 +1048,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
*/
if (fast && (ah->ah_radio != AR5K_RF2413) &&
(ah->ah_radio != AR5K_RF5413))
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -1604,11 +1604,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_
- int ret;
-
- if (ah->ah_radio == AR5K_RF5110)
-- ret = ath5k_hw_rf5110_calibrate(ah, channel);
-- else {
-- ret = ath5k_hw_rf511x_iq_calibrate(ah);
-+ return ath5k_hw_rf5110_calibrate(ah, channel);
-+
-+ ret = ath5k_hw_rf511x_iq_calibrate(ah);
-+
-+ if (ah->ah_radio == AR5K_RF5112 &&
-+ (channel->hw_value & (CHANNEL_5GHZ | CHANNEL_OFDM)))
- ath5k_hw_request_rfgain_probe(ah);
-- }
-
- return ret;
- }
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -970,17 +970,20 @@ static int ath5k_hw_rfregs_init(struct a
- }
-
- /* Lower synth voltage on Rev 2 */
-- ath5k_hw_rfb_op(ah, rf_regs, 2,
-- AR5K_RF_HIGH_VC_CP, true);
-+ if (ah->ah_radio == AR5K_RF5112 &&
-+ (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) {
-+ ath5k_hw_rfb_op(ah, rf_regs, 2,
-+ AR5K_RF_HIGH_VC_CP, true);
-
-- ath5k_hw_rfb_op(ah, rf_regs, 2,
-- AR5K_RF_MID_VC_CP, true);
-+ ath5k_hw_rfb_op(ah, rf_regs, 2,
-+ AR5K_RF_MID_VC_CP, true);
-
-- ath5k_hw_rfb_op(ah, rf_regs, 2,
-- AR5K_RF_LOW_VC_CP, true);
-+ ath5k_hw_rfb_op(ah, rf_regs, 2,
-+ AR5K_RF_LOW_VC_CP, true);
-
-- ath5k_hw_rfb_op(ah, rf_regs, 2,
-- AR5K_RF_PUSH_UP, true);
-+ ath5k_hw_rfb_op(ah, rf_regs, 2,
-+ AR5K_RF_PUSH_UP, true);
-+ }
-
- /* Decrease power consumption on 5213+ BaseBand */
- if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -105,6 +105,7 @@ bool ath5k_hw_chan_has_spur_noise(struct
-
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
-+ (ah->ah_radio == AR5K_RF2413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
- refclk_freq = 40;
- else
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -2422,6 +2422,7 @@ ath5k_init_softc(struct ath5k_softc *sc,
- common->ah = sc->ah;
- common->hw = hw;
- common->priv = sc;
-+ common->clockrate = 40;
-
- /*
- * Cache line size is used to size and align various
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -2728,7 +2728,7 @@ ath5k_reset(struct ath5k_softc *sc, stru
-
- ath5k_ani_init(ah, ani_mode);
-
-- ah->ah_cal_next_full = jiffies;
-+ ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);
- ah->ah_cal_next_ani = jiffies;
- ah->ah_cal_next_nf = jiffies;
- ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/reset.c
-+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -233,7 +233,7 @@ static void ath5k_hw_init_core_clock(str
- static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
- {
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-- u32 scal, spending;
-+ u32 scal, spending, sclock;
-
- /* Only set 32KHz settings if we have an external
- * 32KHz crystal present */
-@@ -317,6 +317,15 @@ static void ath5k_hw_set_sleep_clock(str
-
- /* Set up tsf increment on each cycle */
- AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
-+
-+ if ((ah->ah_radio == AR5K_RF5112) ||
-+ (ah->ah_radio == AR5K_RF5413) ||
-+ (ah->ah_radio == AR5K_RF2316) ||
-+ (ah->ah_radio == AR5K_RF2317))
-+ sclock = 40 - 1;
-+ else
-+ sclock = 32 - 1;
-+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
- }
- }
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/reset.c
-+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1287,15 +1287,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah,
- */
- ath5k_hw_dma_init(ah);
-
--
-- /* Enable 32KHz clock function for AR5212+ chips
-- * Set clocks to 32KHz operation and use an
-- * external 32KHz crystal when sleeping if one
-- * exists */
-- if (ah->ah_version == AR5K_AR5212 &&
-- op_mode != NL80211_IFTYPE_AP)
-- ath5k_hw_set_sleep_clock(ah, true);
--
- /*
- * Disable beacons and reset the TSF
- */
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1555,7 +1555,8 @@ ath5k_tx_queue(struct ieee80211_hw *hw,
- goto drop_packet;
- }
-
-- if (txq->txq_len >= txq->txq_max)
-+ if (txq->txq_len >= txq->txq_max &&
-+ txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)
- ieee80211_stop_queue(hw, txq->qnum);
-
- spin_lock_irqsave(&sc->txbuflock, flags);
-@@ -1931,6 +1932,10 @@ ath5k_beacon_send(struct ath5k_softc *sc
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
- while (skb) {
- ath5k_tx_queue(sc->hw, skb, sc->cabq);
-+
-+ if (sc->cabq->txq_len >= sc->cabq->txq_max)
-+ break;
-+
- skb = ieee80211_get_buffered_bc(sc->hw, vif);
- }
-
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1181,6 +1181,53 @@ static const struct file_operations fops
- .llseek = default_llseek,/* read accesses f_pos */
+@@ -1219,6 +1219,53 @@ static const struct file_operations fops
+ .llseek = default_llseek,
};
+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1231,6 +1278,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1273,6 +1320,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1656,8 +1656,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1664,8 +1664,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
REG_WRITE(ah, AR_OBS, 8);
if (ah->config.rx_intr_mitigation) {
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -363,7 +363,7 @@ struct ath_vif {
+@@ -366,7 +366,7 @@ struct ath_vif {
* number of beacon intervals, the game's up.
*/
#define BSTUCK_THRESH 9
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -374,8 +374,8 @@ static void ath9k_hw_init_config(struct
+@@ -382,8 +382,8 @@ static void ath9k_hw_init_config(struct
{
int i;
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -117,7 +117,7 @@ void ath_descdma_cleanup(struct ath_soft
+@@ -123,7 +123,7 @@ void ath_descdma_cleanup(struct ath_soft
/* RX / TX */
/***********/
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -586,6 +586,7 @@ struct ath_softc {
+@@ -588,6 +588,7 @@ struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
struct survey_info *cur_survey;
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1281,6 +1281,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1323,6 +1323,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_eeprom);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/calib.c
-+++ b/drivers/net/wireless/ath/ath9k/calib.c
-@@ -63,6 +63,19 @@ static s16 ath9k_hw_get_default_nf(struc
- return ath9k_hw_get_nf_limits(ah, chan)->nominal;
- }
-
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
-+{
-+ s8 noise = ATH_DEFAULT_NOISE_FLOOR;
-+
-+ if (chan && chan->noisefloor) {
-+ s8 delta = chan->noisefloor -
-+ ath9k_hw_get_default_nf(ah, chan);
-+ if (delta > 0)
-+ noise += delta;
-+ }
-+ return noise;
-+}
-+EXPORT_SYMBOL(ath9k_hw_getchan_noise);
-
- static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
- struct ath9k_hw_cal_data *cal,
-@@ -378,6 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
-
- if (!caldata) {
- chan->noisefloor = nf;
-+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
- return false;
- }
-
-@@ -385,6 +399,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
- caldata->nfcal_pending = false;
- ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
- chan->noisefloor = h[0].privNF;
-+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
- return true;
- }
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1488,6 +1488,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- memset(caldata, 0, sizeof(*caldata));
- ath9k_init_nfcal_hist_buffer(ah, chan);
- }
-+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
-
- if (bChannelChange &&
- (ah->chip_fullsleep != true) &&
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -688,6 +688,7 @@ struct ath_hw {
- enum nl80211_iftype opmode;
- enum ath9k_power_mode power_mode;
-
-+ s8 noise;
- struct ath9k_hw_cal_data *caldata;
- struct ath9k_pacal_info pacal_info;
- struct ar5416Stats stats;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -163,7 +163,7 @@ static void ath_update_survey_nf(struct
-
- if (chan->noisefloor) {
- survey->filled |= SURVEY_INFO_NOISE_DBM;
-- survey->noise = chan->noisefloor;
-+ survey->noise = ath9k_hw_getchan_noise(ah, chan);
- }
- }
-
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -994,6 +994,8 @@ static int ath9k_rx_skb_preprocess(struc
- struct ieee80211_rx_status *rx_status,
- bool *decrypt_error)
- {
-+ struct ath_hw *ah = common->ah;
-+
- memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-
- /*
-@@ -1014,7 +1016,7 @@ static int ath9k_rx_skb_preprocess(struc
-
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
-- rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
-+ rx_status->signal = ah->noise + rx_stats->rs_rssi;
- rx_status->antenna = rx_stats->rs_antenna;
- rx_status->flag |= RX_FLAG_MACTIME_MPDU;
-
---- a/drivers/net/wireless/ath/ath9k/calib.h
-+++ b/drivers/net/wireless/ath/ath9k/calib.h
-@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct
- void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
- void ath9k_hw_reset_calibration(struct ath_hw *ah,
- struct ath9k_cal_list *currCal);
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
-
-
- #endif /* CALIB_H */
--- /dev/null
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -790,7 +790,7 @@ enum ieee80211_smps_mode {
+ */
+ struct ieee80211_conf {
+ u32 flags;
+- int power_level, dynamic_ps_timeout;
++ int cur_power_level, power_level, dynamic_ps_timeout;
+ int max_sleep_period;
+
+ u16 listen_interval;
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1532,7 +1532,7 @@ static int ieee80211_get_tx_power(struct
+ {
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+
+- *dbm = local->hw.conf.power_level;
++ *dbm = local->hw.conf.cur_power_level;
+
+ return 0;
+ }
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -210,6 +210,7 @@ int ieee80211_hw_config(struct ieee80211
+
+ if (local->hw.conf.power_level != power) {
+ changed |= IEEE80211_CONF_CHANGE_POWER;
++ local->hw.conf.cur_power_level = power;
+ local->hw.conf.power_level = power;
+ }
+
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1731,6 +1731,8 @@ static int ath9k_config(struct ieee80211
+ return -EINVAL;
+ }
+
++ conf->cur_power_level = sc->curtxpow / 2;
++
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+@@ -1748,6 +1750,7 @@ static int ath9k_config(struct ieee80211
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+ ath9k_ps_restore(sc);
++ conf->cur_power_level = sc->curtxpow / 2;
+ }
+
+ if (disable_radio) {
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
+ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+ u16 new_txpow, u16 *txpower)
+ {
++ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
+ if (cur_txpow != new_txpow) {
+ ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+ /* read back in case value is clamped */
+- *txpower = ath9k_hw_regulatory(ah)->power_limit;
++ *txpower = min_t(u16, reg->power_limit, reg->max_power_level);
+ }
+ }
+ EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -737,7 +737,9 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
-
- if (!AR_SREV_9300_20_OR_LATER(ah)) {
- mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
-- if (mac_status == 0x1c0 && mac_status == last_mac_status) {
-+ if (mac_status == last_mac_status &&
-+ (mac_status == 0x1c0 ||
-+ (AR_SREV_9100(ah) && mac_status == 0x020))) {
- *reset = true;
- break;
- }
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -248,13 +248,16 @@ static void ath_tid_drain(struct ath_sof
+ }
+
+ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+- struct sk_buff *skb)
++ struct sk_buff *skb, int count)
+ {
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct ieee80211_hdr *hdr;
++ int prev = fi->retries;
+
+ TX_STAT_INC(txq->axq_qnum, a_retries);
+- if (fi->retries++ > 0)
++ fi->retries += count;
++
++ if (prev > 0)
+ return;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+@@ -359,6 +362,7 @@ static void ath_tx_complete_aggr(struct
+ int nframes;
+ u8 tidno;
+ bool clear_filter;
++ int i, retries;
+
+ skb = bf->bf_mpdu;
+ hdr = (struct ieee80211_hdr *)skb->data;
+@@ -367,6 +371,10 @@ static void ath_tx_complete_aggr(struct
+
+ memcpy(rates, tx_info->control.rates, sizeof(rates));
+
++ retries = ts->ts_longretry + 1;
++ for (i = 0; i < ts->ts_rateindex; i++)
++ retries += rates[i].count;
++
+ rcu_read_lock();
+
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+@@ -451,7 +459,8 @@ static void ath_tx_complete_aggr(struct
+ } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+ if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
+ !an->sleeping)
+- ath_tx_set_retry(sc, txq, bf->bf_mpdu);
++ ath_tx_set_retry(sc, txq, bf->bf_mpdu,
++ retries);
+
+ clear_filter = true;
+ txpending = 1;
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -538,7 +538,7 @@ struct ath_ant_comb {
+ #define DEFAULT_CACHELINE 32
+ #define ATH_REGCLASSIDS_MAX 10
+ #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
+-#define ATH_MAX_SW_RETRIES 10
++#define ATH_MAX_SW_RETRIES 20
+ #define ATH_CHAN_MAX 255
+
+ #define ATH_TXPOWER_MAX 100 /* .5 dBm units */
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -206,6 +206,7 @@ struct ath_atx_ac {
+ };
+
+ struct ath_frame_info {
++ struct ath_buf *bf;
+ int framelen;
+ u32 keyix;
+ enum ath9k_key_type keytype;
+@@ -235,7 +236,7 @@ struct ath_buf {
+
+ struct ath_atx_tid {
+ struct list_head list;
+- struct list_head buf_q;
++ struct sk_buff_head buf_q;
+ struct ath_node *an;
+ struct ath_atx_ac *ac;
+ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct
+ " tid: %p %s %s %i %p %p\n",
+ tid, tid->sched ? "sched" : "idle",
+ tid->paused ? "paused" : "running",
+- list_empty(&tid->buf_q),
++ skb_queue_empty(&tid->buf_q),
+ tid->an, tid->ac);
+ if (len >= size)
+ goto done;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath
+ spin_lock_bh(&txq->axq_lock);
+ tid->paused = false;
+
+- if (list_empty(&tid->buf_q))
++ if (skb_queue_empty(&tid->buf_q))
+ goto unlock;
+
+ ath_tx_queue_tid(txq, tid);
+@@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_
+ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+ {
+ struct ath_txq *txq = tid->ac->txq;
++ struct sk_buff *skb;
+ struct ath_buf *bf;
+ struct list_head bf_head;
+ struct ath_tx_status ts;
+@@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_
+ memset(&ts, 0, sizeof(ts));
+ spin_lock_bh(&txq->axq_lock);
+
+- while (!list_empty(&tid->buf_q)) {
+- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+- list_move_tail(&bf->list, &bf_head);
++ while ((skb = __skb_dequeue(&tid->buf_q))) {
++ fi = get_frame_info(skb);
++ bf = fi->bf;
++
++ list_add_tail(&bf->list, &bf_head);
+
+ spin_unlock_bh(&txq->axq_lock);
+- fi = get_frame_info(bf->bf_mpdu);
+ if (fi->retries) {
+ ath_tx_update_baw(sc, tid, fi->seqno);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+@@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_sof
+ struct ath_atx_tid *tid)
+
+ {
++ struct sk_buff *skb;
+ struct ath_buf *bf;
+ struct list_head bf_head;
+ struct ath_tx_status ts;
+@@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_sof
+ memset(&ts, 0, sizeof(ts));
+ INIT_LIST_HEAD(&bf_head);
+
+- for (;;) {
+- if (list_empty(&tid->buf_q))
+- break;
++ while ((skb = __skb_dequeue(&tid->buf_q))) {
++ fi = get_frame_info(skb);
++ bf = fi->bf;
+
+- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+- list_move_tail(&bf->list, &bf_head);
++ list_add_tail(&bf->list, &bf_head);
+
+- fi = get_frame_info(bf->bf_mpdu);
+ if (fi->retries)
+ ath_tx_update_baw(sc, tid, fi->seqno);
+
+@@ -352,7 +353,8 @@ static void ath_tx_complete_aggr(struct
+ struct ieee80211_tx_info *tx_info;
+ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+- struct list_head bf_head, bf_pending;
++ struct list_head bf_head;
++ struct sk_buff_head bf_pending;
+ u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
+ u32 ba[WME_BA_BMP_SIZE >> 5];
+ int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+@@ -430,8 +432,7 @@ static void ath_tx_complete_aggr(struct
+ }
+ }
+
+- INIT_LIST_HEAD(&bf_pending);
+- INIT_LIST_HEAD(&bf_head);
++ __skb_queue_head_init(&bf_pending);
+
+ ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
+ while (bf) {
+@@ -476,10 +477,10 @@ static void ath_tx_complete_aggr(struct
+ * Make sure the last desc is reclaimed if it
+ * not a holding desc.
+ */
+- if (!bf_last->bf_stale || bf_next != NULL)
++ INIT_LIST_HEAD(&bf_head);
++ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
++ bf_next != NULL || !bf_last->bf_stale)
+ list_move_tail(&bf->list, &bf_head);
+- else
+- INIT_LIST_HEAD(&bf_head);
+
+ if (!txpending || (tid->state & AGGR_CLEANUP)) {
+ /*
+@@ -530,7 +531,7 @@ static void ath_tx_complete_aggr(struct
+
+ ath9k_hw_cleartxdesc(sc->sc_ah,
+ tbf->bf_desc);
+- list_add_tail(&tbf->list, &bf_head);
++ fi->bf = tbf;
+ } else {
+ /*
+ * Clear descriptor status words for
+@@ -545,21 +546,21 @@ static void ath_tx_complete_aggr(struct
+ * Put this buffer to the temporary pending
+ * queue to retain ordering
+ */
+- list_splice_tail_init(&bf_head, &bf_pending);
++ __skb_queue_tail(&bf_pending, skb);
+ }
+
+ bf = bf_next;
+ }
+
+ /* prepend un-acked frames to the beginning of the pending frame queue */
+- if (!list_empty(&bf_pending)) {
++ if (!skb_queue_empty(&bf_pending)) {
+ if (an->sleeping)
+ ieee80211_sta_set_tim(sta);
+
+ spin_lock_bh(&txq->axq_lock);
+ if (clear_filter)
+ tid->ac->clear_ps_filter = true;
+- list_splice(&bf_pending, &tid->buf_q);
++ skb_queue_splice(&bf_pending, &tid->buf_q);
+ if (!an->sleeping)
+ ath_tx_queue_tid(txq, tid);
+ spin_unlock_bh(&txq->axq_lock);
+@@ -721,19 +722,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ int *aggr_len)
+ {
+ #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
+- struct ath_buf *bf, *bf_first, *bf_prev = NULL;
++ struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
+ int rl = 0, nframes = 0, ndelim, prev_al = 0;
+ u16 aggr_limit = 0, al = 0, bpad = 0,
+ al_delta, h_baw = tid->baw_size / 2;
+ enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
+ struct ieee80211_tx_info *tx_info;
+ struct ath_frame_info *fi;
+-
+- bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
++ struct sk_buff *skb;
+
+ do {
+- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+- fi = get_frame_info(bf->bf_mpdu);
++ skb = skb_peek(&tid->buf_q);
++ fi = get_frame_info(skb);
++ bf = fi->bf;
++
++ if (!bf_first)
++ bf_first = bf;
+
+ /* do not step over block-ack window */
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
+@@ -784,7 +788,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ if (!fi->retries)
+ ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+- list_move_tail(&bf->list, bf_q);
++
++ __skb_unlink(skb, &tid->buf_q);
++ list_add_tail(&bf->list, bf_q);
+ if (bf_prev) {
+ bf_prev->bf_next = bf;
+ ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
+@@ -792,7 +798,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ }
+ bf_prev = bf;
+
+- } while (!list_empty(&tid->buf_q));
++ } while (!skb_queue_empty(&tid->buf_q));
+
+ *aggr_len = al;
+
+@@ -810,7 +816,7 @@ static void ath_tx_sched_aggr(struct ath
+ int aggr_len;
+
+ do {
+- if (list_empty(&tid->buf_q))
++ if (skb_queue_empty(&tid->buf_q))
+ return;
+
+ INIT_LIST_HEAD(&bf_q);
+@@ -931,7 +937,7 @@ bool ath_tx_aggr_sleep(struct ath_softc
+
+ spin_lock_bh(&txq->axq_lock);
+
+- if (!list_empty(&tid->buf_q))
++ if (!skb_queue_empty(&tid->buf_q))
+ buffered = true;
+
+ tid->sched = false;
+@@ -964,7 +970,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+ spin_lock_bh(&txq->axq_lock);
+ ac->clear_ps_filter = true;
+
+- if (!list_empty(&tid->buf_q) && !tid->paused) {
++ if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
+ ath_tx_queue_tid(txq, tid);
+ ath_txq_schedule(sc, txq);
+ }
+@@ -1308,7 +1314,7 @@ void ath_txq_schedule(struct ath_softc *
+ * add tid to round-robin queue if more frames
+ * are pending for the tid
+ */
+- if (!list_empty(&tid->buf_q))
++ if (!skb_queue_empty(&tid->buf_q))
+ ath_tx_queue_tid(txq, tid);
+
+ if (tid == last_tid ||
+@@ -1414,7 +1420,7 @@ static void ath_tx_send_ampdu(struct ath
+ * - seqno is not within block-ack window
+ * - h/w queue depth exceeds low water mark
+ */
+- if (!list_empty(&tid->buf_q) || tid->paused ||
++ if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+ txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
+ /*
+@@ -1422,7 +1428,7 @@ static void ath_tx_send_ampdu(struct ath
+ * for aggregation.
+ */
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
+- list_add_tail(&bf->list, &tid->buf_q);
++ __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
+ if (!txctl->an || !txctl->an->sleeping)
+ ath_tx_queue_tid(txctl->txq, tid);
+ return;
+@@ -1753,6 +1759,7 @@ static struct ath_buf *ath_tx_setup_buff
+ bf->bf_buf_addr,
+ txq->axq_qnum);
+
++ fi->bf = bf;
+
+ return bf;
+ }
+@@ -2370,7 +2377,7 @@ void ath_tx_node_init(struct ath_softc *
+ tid->sched = false;
+ tid->paused = false;
+ tid->state &= ~AGGR_CLEANUP;
+- INIT_LIST_HEAD(&tid->buf_q);
++ __skb_queue_head_init(&tid->buf_q);
+ acno = TID_TO_WME_AC(tidno);
+ tid->ac = &an->ac[acno];
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -240,6 +240,7 @@ struct ath_atx_tid {
+ struct ath_node *an;
+ struct ath_atx_ac *ac;
+ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
++ int buf_pending;
+ u16 seq_start;
+ u16 seq_next;
+ u16 baw_size;
+@@ -286,6 +287,9 @@ struct ath_tx_control {
+ * (axq_qnum).
+ */
+ struct ath_tx {
++ u32 qlen_single;
++ u32 qlen_aggr;
++
+ u16 seq_no;
+ u32 txqsetup;
+ spinlock_t txbuflock;
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1288,6 +1288,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+ sc, &fops_wiphy);
+ debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_xmit);
++ debugfs_create_u32("qlen_single", S_IRUSR | S_IWUSR,
++ sc->debug.debugfs_phy, &sc->tx.qlen_single);
++ debugfs_create_u32("qlen_aggr", S_IRUSR | S_IWUSR,
++ sc->debug.debugfs_phy, &sc->tx.qlen_aggr);
+ debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_stations);
+ debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -340,6 +340,14 @@ static void ath_tx_count_frames(struct a
+ }
+ }
+
++static struct ath_atx_tid *ath_get_tid(struct ath_node *an, struct sk_buff *skb)
++{
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ u8 tidno;
++
++ tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
++ return ATH_AN_2_TID(an, tidno);
++}
+
+ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf, struct list_head *bf_q,
+@@ -435,6 +443,8 @@ static void ath_tx_complete_aggr(struct
+ __skb_queue_head_init(&bf_pending);
+
+ ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
++ tid->buf_pending -= nframes;
++
+ while (bf) {
+ txfail = txpending = sendbar = 0;
+ bf_next = bf->bf_next;
+@@ -789,6 +799,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ ath_tx_addto_baw(sc, tid, fi->seqno);
+ ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+
++ tid->buf_pending++;
+ __skb_unlink(skb, &tid->buf_q);
+ list_add_tail(&bf->list, bf_q);
+ if (bf_prev) {
+@@ -1441,6 +1452,8 @@ static void ath_tx_send_ampdu(struct ath
+ if (!fi->retries)
+ ath_tx_addto_baw(sc, tid, fi->seqno);
+
++ tid->buf_pending++;
++
+ /* Queue to h/w without aggregation */
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+ bf->bf_lastbf = bf;
+@@ -1505,7 +1518,6 @@ static void setup_frame_info(struct ieee
+ struct ath_atx_tid *tid;
+ enum ath9k_key_type keytype;
+ u16 seqno = 0;
+- u8 tidno;
+
+ keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
+
+@@ -1516,13 +1528,11 @@ static void setup_frame_info(struct ieee
+ if (an && ieee80211_is_data_qos(hdr->frame_control) &&
+ conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
+
+- tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+-
+ /*
+ * Override seqno set by upper layer with the one
+ * in tx aggregation state.
+ */
+- tid = ATH_AN_2_TID(an, tidno);
++ tid = ath_get_tid(an, skb);
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+@@ -1766,24 +1776,14 @@ static struct ath_buf *ath_tx_setup_buff
+
+ /* FIXME: tx power */
+ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+- struct ath_tx_control *txctl)
++ struct ath_tx_control *txctl,
++ struct ath_atx_tid *tid)
+ {
+ struct sk_buff *skb = bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct list_head bf_head;
+- struct ath_atx_tid *tid = NULL;
+- u8 tidno;
+
+ spin_lock_bh(&txctl->txq->axq_lock);
+- if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
+- ieee80211_is_data_qos(hdr->frame_control)) {
+- tidno = ieee80211_get_qos_ctl(hdr)[0] &
+- IEEE80211_QOS_CTL_TID_MASK;
+- tid = ATH_AN_2_TID(txctl->an, tidno);
+-
+- WARN_ON(tid->ac->txq != txctl->txq);
+- }
+
+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+ /*
+@@ -1823,6 +1823,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ struct ieee80211_vif *vif = info->control.vif;
+ struct ath_softc *sc = hw->priv;
+ struct ath_txq *txq = txctl->txq;
++ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
+ int padpos, padsize;
+ int frmlen = skb->len + FCS_LEN;
+@@ -1856,6 +1857,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+
+ skb_push(skb, padsize);
+ memmove(skb->data, skb->data + padsize, padpos);
++ hdr = (struct ieee80211_hdr *) skb->data;
+ }
+
+ if ((vif && vif->type != NL80211_IFTYPE_AP &&
+@@ -1865,6 +1867,24 @@ int ath_tx_start(struct ieee80211_hw *hw
+
+ setup_frame_info(hw, skb, frmlen);
+
++ if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
++ ieee80211_is_data_qos(hdr->frame_control)) {
++ tid = ath_get_tid(txctl->an, skb);
++
++ WARN_ON(tid->ac->txq != txq);
++ }
++
++ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
++ if (sc->tx.qlen_aggr > 0 && skb_queue_len(&tid->buf_q) +
++ tid->buf_pending >= sc->tx.qlen_aggr)
++ return -ENOMEM;
++ } else {
++ if (sc->tx.qlen_single > 0 &&
++ txq->axq_depth - txq->axq_ampdu_depth >=
++ sc->tx.qlen_single)
++ return -ENOMEM;
++ }
++
+ /*
+ * At this point, the vif, hw_key and sta pointers in the tx control
+ * info are no longer valid (overwritten by the ath_frame_info data.
+@@ -1883,7 +1903,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ }
+ spin_unlock_bh(&txq->axq_lock);
+
+- ath_tx_start_dma(sc, bf, txctl);
++ ath_tx_start_dma(sc, bf, txctl, tid);
+
+ return 0;
+ }
+++ /dev/null
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -779,7 +779,7 @@ enum ieee80211_smps_mode {
- */
- struct ieee80211_conf {
- u32 flags;
-- int power_level, dynamic_ps_timeout;
-+ int cur_power_level, power_level, dynamic_ps_timeout;
- int max_sleep_period;
-
- u16 listen_interval;
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1524,7 +1524,7 @@ static int ieee80211_get_tx_power(struct
- {
- struct ieee80211_local *local = wiphy_priv(wiphy);
-
-- *dbm = local->hw.conf.power_level;
-+ *dbm = local->hw.conf.cur_power_level;
-
- return 0;
- }
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -210,6 +210,7 @@ int ieee80211_hw_config(struct ieee80211
-
- if (local->hw.conf.power_level != power) {
- changed |= IEEE80211_CONF_CHANGE_POWER;
-+ local->hw.conf.cur_power_level = power;
- local->hw.conf.power_level = power;
- }
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -667,8 +667,10 @@ static void ath9k_init_band_txpower(stru
- static void ath9k_init_txpower_limits(struct ath_softc *sc)
- {
- struct ath_hw *ah = sc->sc_ah;
-+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath9k_channel *curchan = ah->curchan;
-
-+ ah->txchainmask = common->tx_chainmask;
- if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
- ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
- if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -247,8 +247,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct
- }
-
- static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
-- struct ath9k_channel *chan,
-- int16_t *pTxPowerIndexOffset)
-+ struct ath9k_channel *chan)
- {
- struct ath_common *common = ath9k_hw_common(ah);
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-@@ -358,8 +357,6 @@ static void ath9k_hw_set_4k_power_cal_ta
- REGWRITE_BUFFER_FLUSH(ah);
- }
- }
--
-- *pTxPowerIndexOffset = 0;
- }
-
- static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
-@@ -582,7 +579,6 @@ static void ath9k_hw_4k_set_txpower(stru
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
- struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
- int16_t ratesArray[Ar5416RateSize];
-- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i;
-
-@@ -599,11 +595,10 @@ static void ath9k_hw_4k_set_txpower(stru
- twiceMaxRegulatoryPower,
- powerLimit);
-
-- ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
-+ ath9k_hw_set_4k_power_cal_table(ah, chan);
-
- regulatory->max_power_level = 0;
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > MAX_RATE_POWER)
- ratesArray[i] = MAX_RATE_POWER;
-
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -306,8 +306,7 @@ static void ar9287_eeprom_olpc_set_pdadc
- }
-
- static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
-- struct ath9k_channel *chan,
-- int16_t *pTxPowerIndexOffset)
-+ struct ath9k_channel *chan)
- {
- struct cal_data_per_freq_ar9287 *pRawDataset;
- struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
-@@ -446,8 +445,6 @@ static void ath9k_hw_set_ar9287_power_ca
- REGWRITE_BUFFER_FLUSH(ah);
- }
- }
--
-- *pTxPowerIndexOffset = 0;
- }
-
- static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
-@@ -722,7 +719,6 @@ static void ath9k_hw_ar9287_set_txpower(
- struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
- struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
- int16_t ratesArray[Ar5416RateSize];
-- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i;
-
-@@ -738,11 +734,10 @@ static void ath9k_hw_ar9287_set_txpower(
- twiceMaxRegulatoryPower,
- powerLimit);
-
-- ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
-+ ath9k_hw_set_ar9287_power_cal_table(ah, chan);
-
- regulatory->max_power_level = 0;
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > MAX_RATE_POWER)
- ratesArray[i] = MAX_RATE_POWER;
-
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -692,8 +692,7 @@ static void ath9k_adjust_pdadc_values(st
- }
-
- static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
-- struct ath9k_channel *chan,
-- int16_t *pTxPowerIndexOffset)
-+ struct ath9k_channel *chan)
- {
- #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
- #define SM_PDGAIN_B(x, y) \
-@@ -857,7 +856,6 @@ static void ath9k_hw_set_def_power_cal_t
- }
- }
-
-- *pTxPowerIndexOffset = 0;
- #undef SM_PD_GAIN
- #undef SM_PDGAIN_B
- }
-@@ -1145,7 +1143,6 @@ static void ath9k_hw_def_set_txpower(str
- struct modal_eep_header *pModal =
- &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
- int16_t ratesArray[Ar5416RateSize];
-- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i, cck_ofdm_delta = 0;
-
-@@ -1162,11 +1159,10 @@ static void ath9k_hw_def_set_txpower(str
- twiceMaxRegulatoryPower,
- powerLimit);
-
-- ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
-+ ath9k_hw_set_def_power_cal_table(ah, chan);
-
- regulatory->max_power_level = 0;
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > MAX_RATE_POWER)
- ratesArray[i] = MAX_RATE_POWER;
- if (ratesArray[i] > regulatory->max_power_level)
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -4922,25 +4922,7 @@ static void ath9k_hw_ar9300_set_txpower(
- "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
- }
-
-- /*
-- * This is the TX power we send back to driver core,
-- * and it can use to pass to userspace to display our
-- * currently configured TX power setting.
-- *
-- * Since power is rate dependent, use one of the indices
-- * from the AR9300_Rates enum to select an entry from
-- * targetPowerValT2[] to report. Currently returns the
-- * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
-- * as CCK power is less interesting (?).
-- */
-- i = ALL_TARGET_LEGACY_6_24; /* legacy */
-- if (IS_CHAN_HT40(chan))
-- i = ALL_TARGET_HT40_0_8_16; /* ht40 */
-- else if (IS_CHAN_HT20(chan))
-- i = ALL_TARGET_HT20_0_8_16; /* ht20 */
--
-- ah->txpower_limit = targetPowerValT2[i];
-- regulatory->max_power_level = targetPowerValT2[i];
-+ ah->txpower_limit = regulatory->max_power_level;
-
- /* Write target power array to registers */
- ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -609,15 +609,6 @@ static void ath9k_hw_4k_set_txpower(stru
- if (test)
- return;
-
-- /* Update regulatory */
-- i = rate6mb;
-- if (IS_CHAN_HT40(chan))
-- i = rateHt40_0;
-- else if (IS_CHAN_HT20(chan))
-- i = rateHt20_0;
--
-- regulatory->max_power_level = ratesArray[i];
--
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -748,13 +748,6 @@ static void ath9k_hw_ar9287_set_txpower(
- if (test)
- return;
-
-- if (IS_CHAN_2GHZ(chan))
-- i = rate1l;
-- else
-- i = rate6mb;
--
-- regulatory->max_power_level = ratesArray[i];
--
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -1169,17 +1169,6 @@ static void ath9k_hw_def_set_txpower(str
- regulatory->max_power_level = ratesArray[i];
- }
-
-- if (!test) {
-- i = rate6mb;
--
-- if (IS_CHAN_HT40(chan))
-- i = rateHt40_0;
-- else if (IS_CHAN_HT20(chan))
-- i = rateHt20_0;
--
-- regulatory->max_power_level = ratesArray[i];
-- }
--
- switch(ar5416_get_ntxchains(ah->txchainmask)) {
- case 1:
- break;
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2442,15 +2442,18 @@ void ath9k_hw_set_txpowerlimit(struct at
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath9k_channel *chan = ah->curchan;
- struct ieee80211_channel *channel = chan->chan;
-+ int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit);
-+ int chan_pwr = channel->max_power * 2;
-+
-+ if (test)
-+ reg_pwr = chan_pwr = MAX_RATE_POWER;
-
- regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(regulatory, chan),
- channel->max_antenna_gain * 2,
-- channel->max_power * 2,
-- min((u32) MAX_RATE_POWER,
-- (u32) regulatory->power_limit), test);
-+ chan_pwr, reg_pwr, test);
- }
- EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1727,6 +1727,8 @@ static int ath9k_config(struct ieee80211
- return -EINVAL;
- }
-
-+ conf->cur_power_level = sc->curtxpow / 2;
-+
- /*
- * The most recent snapshot of channel->noisefloor for the old
- * channel is only available after the hardware reset. Copy it to
-@@ -1744,6 +1746,7 @@ static int ath9k_config(struct ieee80211
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
- ath9k_ps_restore(sc);
-+ conf->cur_power_level = sc->curtxpow / 2;
- }
-
- if (disable_radio) {
---- a/drivers/net/wireless/ath/ath9k/common.c
-+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
- void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
- u16 new_txpow, u16 *txpower)
- {
-+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
- if (cur_txpow != new_txpow) {
- ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
- /* read back in case value is clamped */
-- *txpower = ath9k_hw_regulatory(ah)->power_limit;
-+ *txpower = min_t(u16, reg->power_limit, reg->max_power_level);
- }
- }
- EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -550,7 +550,8 @@ static void ath_tx_complete_aggr(struct
- if (clear_filter)
- tid->ac->clear_ps_filter = true;
- list_splice(&bf_pending, &tid->buf_q);
-- ath_tx_queue_tid(txq, tid);
-+ if (!an->sleeping)
-+ ath_tx_queue_tid(txq, tid);
- spin_unlock_bh(&txq->axq_lock);
- }
-
-@@ -1410,7 +1411,8 @@ static void ath_tx_send_ampdu(struct ath
- */
- TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
- list_add_tail(&bf->list, &tid->buf_q);
-- ath_tx_queue_tid(txctl->txq, tid);
-+ if (!txctl->an || !txctl->an->sleeping)
-+ ath_tx_queue_tid(txctl->txq, tid);
- return;
- }
-
+++ /dev/null
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -109,8 +109,9 @@ static void ieee80211_send_addba_request
- ieee80211_tx_skb(sdata, skb);
- }
-
--void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
-+void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
- {
-+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- struct ieee80211_local *local = sdata->local;
- struct sk_buff *skb;
- struct ieee80211_bar *bar;
-@@ -138,6 +139,7 @@ void ieee80211_send_bar(struct ieee80211
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- ieee80211_tx_skb(sdata, skb);
- }
-+EXPORT_SYMBOL(ieee80211_send_bar);
-
- void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
- struct tid_ampdu_tx *tid_tx)
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -3007,6 +3007,19 @@ void ieee80211_remain_on_channel_expired
- void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
- const u8 *addr);
-
-+/**
-+ * ieee80211_send_bar - send a BlockAckReq frame
-+ *
-+ * can be used to flush pending frames from the peer's aggregation reorder
-+ * buffer.
-+ *
-+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
-+ * @ra: the peer's destination address
-+ * @tid: the TID of the aggregation session
-+ * @ssn: the new starting sequence number for the receiver
-+ */
-+void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
-+
- /* Rate control API */
-
- /**
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1225,7 +1225,6 @@ struct ieee80211_tx_status_rtap_hdr {
- void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
- struct ieee80211_ht_cap *ht_cap_ie,
- struct ieee80211_sta_ht_cap *ht_cap);
--void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn);
- void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
- const u8 *da, u16 tid,
- u16 initiator, u16 reason_code);
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -239,7 +239,7 @@ void ieee80211_tx_status(struct ieee8021
- tid = qc[0] & 0xf;
- ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
- & IEEE80211_SCTL_SEQ);
-- ieee80211_send_bar(sta->sdata, hdr->addr1,
-+ ieee80211_send_bar(&sta->sdata->vif, hdr->addr1,
- tid, ssn);
- }
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -246,6 +246,7 @@ struct ath_atx_tid {
- };
-
- struct ath_node {
-+ struct ieee80211_vif *vif;
- #ifdef CONFIG_ATH9K_DEBUGFS
- struct list_head list; /* for sc->nodes */
- struct ieee80211_sta *sta; /* station struct we're part of */
-@@ -274,7 +275,6 @@ struct ath_tx_control {
-
- #define ATH_TX_ERROR 0x01
- #define ATH_TX_XRETRY 0x02
--#define ATH_TX_BAR 0x04
-
- /**
- * @txq_map: Index is mac80211 queue number. This is
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1801,6 +1801,7 @@ static int ath9k_sta_add(struct ieee8021
- struct ieee80211_key_conf ps_key = { };
-
- ath_node_attach(sc, sta);
-+ an->vif = vif;
-
- if (vif->type != NL80211_IFTYPE_AP &&
- vif->type != NL80211_IFTYPE_AP_VLAN)
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -51,7 +51,7 @@ static void ath_tx_send_normal(struct at
- struct list_head *bf_head);
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_txq *txq, struct list_head *bf_q,
-- struct ath_tx_status *ts, int txok, int sendbar);
-+ struct ath_tx_status *ts, int txok);
- static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head, bool internal);
- static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
-@@ -166,7 +166,7 @@ static void ath_tx_flush_tid(struct ath_
- fi = get_frame_info(bf->bf_mpdu);
- if (fi->retries) {
- ath_tx_update_baw(sc, tid, fi->seqno);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
- } else {
- ath_tx_send_normal(sc, txq, NULL, &bf_head);
- }
-@@ -238,7 +238,7 @@ static void ath_tid_drain(struct ath_sof
- ath_tx_update_baw(sc, tid, fi->seqno);
-
- spin_unlock(&txq->axq_lock);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
- spin_lock(&txq->axq_lock);
- }
-
-@@ -381,8 +381,7 @@ static void ath_tx_complete_aggr(struct
- list_move_tail(&bf->list, &bf_head);
-
- ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-- 0, 0);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
-
- bf = bf_next;
- }
-@@ -426,7 +425,7 @@ static void ath_tx_complete_aggr(struct
-
- ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
- while (bf) {
-- txfail = txpending = sendbar = 0;
-+ txfail = txpending = 0;
- bf_next = bf->bf_next;
-
- skb = bf->bf_mpdu;
-@@ -489,7 +488,7 @@ static void ath_tx_complete_aggr(struct
- }
-
- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-- !txfail, sendbar);
-+ !txfail);
- } else {
- /* retry the un-acked ones */
- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
-@@ -514,7 +513,7 @@ static void ath_tx_complete_aggr(struct
- nbad, 0, false);
- ath_tx_complete_buf(sc, bf, txq,
- &bf_head,
-- ts, 0, 0);
-+ ts, 0);
- break;
- }
-
-@@ -564,6 +563,9 @@ static void ath_tx_complete_aggr(struct
- }
- }
-
-+ if (sendbar || (tid->state & AGGR_CLEANUP))
-+ ieee80211_send_bar(an->vif, sta->addr, tidno, tid->seq_start << 4);
-+
- rcu_read_unlock();
-
- if (needreset)
-@@ -900,6 +902,7 @@ void ath_tx_aggr_stop(struct ath_softc *
- spin_unlock_bh(&txq->axq_lock);
-
- ath_tx_flush_tid(sc, txtid);
-+ ieee80211_send_bar(an->vif, sta->addr, tid, txtid->seq_start << 4);
- }
-
- bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
-@@ -1178,7 +1181,7 @@ static void ath_drain_txq_list(struct at
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
- retry_tx);
- else
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
- spin_lock_bh(&txq->axq_lock);
- }
- }
-@@ -1885,9 +1888,6 @@ static void ath_tx_complete(struct ath_s
-
- ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
-
-- if (tx_flags & ATH_TX_BAR)
-- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
--
- if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
- /* Frame was ACKed */
- tx_info->flags |= IEEE80211_TX_STAT_ACK;
-@@ -1932,15 +1932,12 @@ static void ath_tx_complete(struct ath_s
-
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_txq *txq, struct list_head *bf_q,
-- struct ath_tx_status *ts, int txok, int sendbar)
-+ struct ath_tx_status *ts, int txok)
- {
- struct sk_buff *skb = bf->bf_mpdu;
- unsigned long flags;
- int tx_flags = 0;
-
-- if (sendbar)
-- tx_flags = ATH_TX_BAR;
--
- if (!txok) {
- tx_flags |= ATH_TX_ERROR;
-
-@@ -2056,7 +2053,7 @@ static void ath_tx_process_buffer(struct
- if (ts->ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
-- ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
-+ ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
- } else
- ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -247,13 +247,16 @@ static void ath_tid_drain(struct ath_sof
- }
-
- static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
-- struct sk_buff *skb)
-+ struct sk_buff *skb, int count)
- {
- struct ath_frame_info *fi = get_frame_info(skb);
- struct ieee80211_hdr *hdr;
-+ int prev = fi->retries;
-
- TX_STAT_INC(txq->axq_qnum, a_retries);
-- if (fi->retries++ > 0)
-+ fi->retries += count;
-+
-+ if (prev > 0)
- return;
-
- hdr = (struct ieee80211_hdr *)skb->data;
-@@ -358,6 +361,7 @@ static void ath_tx_complete_aggr(struct
- int nframes;
- u8 tidno;
- bool clear_filter;
-+ int i, retries;
-
- skb = bf->bf_mpdu;
- hdr = (struct ieee80211_hdr *)skb->data;
-@@ -366,6 +370,10 @@ static void ath_tx_complete_aggr(struct
-
- memcpy(rates, tx_info->control.rates, sizeof(rates));
-
-+ retries = ts->ts_longretry + 1;
-+ for (i = 0; i < ts->ts_rateindex; i++)
-+ retries += rates[i].count;
-+
- rcu_read_lock();
-
- sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
-@@ -449,7 +457,8 @@ static void ath_tx_complete_aggr(struct
- } else if (fi->retries < ATH_MAX_SW_RETRIES) {
- if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
- !an->sleeping)
-- ath_tx_set_retry(sc, txq, bf->bf_mpdu);
-+ ath_tx_set_retry(sc, txq, bf->bf_mpdu,
-+ retries);
-
- clear_filter = true;
- txpending = 1;
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -535,7 +535,7 @@ struct ath_ant_comb {
- #define DEFAULT_CACHELINE 32
- #define ATH_REGCLASSIDS_MAX 10
- #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
--#define ATH_MAX_SW_RETRIES 10
-+#define ATH_MAX_SW_RETRIES 20
- #define ATH_CHAN_MAX 255
-
- #define ATH_TXPOWER_MAX 100 /* .5 dBm units */
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -200,6 +200,7 @@ struct ath_atx_ac {
- };
-
- struct ath_frame_info {
-+ struct ath_buf *bf;
- int framelen;
- u32 keyix;
- enum ath9k_key_type keytype;
-@@ -230,7 +231,7 @@ struct ath_buf {
-
- struct ath_atx_tid {
- struct list_head list;
-- struct list_head buf_q;
-+ struct sk_buff_head buf_q;
- struct ath_node *an;
- struct ath_atx_ac *ac;
- unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct
- " tid: %p %s %s %i %p %p\n",
- tid, tid->sched ? "sched" : "idle",
- tid->paused ? "paused" : "running",
-- list_empty(&tid->buf_q),
-+ skb_queue_empty(&tid->buf_q),
- tid->an, tid->ac);
- if (len >= size)
- goto done;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -128,7 +128,7 @@ static void ath_tx_resume_tid(struct ath
- spin_lock_bh(&txq->axq_lock);
- tid->paused = false;
-
-- if (list_empty(&tid->buf_q))
-+ if (skb_queue_empty(&tid->buf_q))
- goto unlock;
-
- ath_tx_queue_tid(txq, tid);
-@@ -148,6 +148,7 @@ static struct ath_frame_info *get_frame_
- static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
- {
- struct ath_txq *txq = tid->ac->txq;
-+ struct sk_buff *skb;
- struct ath_buf *bf;
- struct list_head bf_head;
- struct ath_tx_status ts;
-@@ -158,12 +159,13 @@ static void ath_tx_flush_tid(struct ath_
- memset(&ts, 0, sizeof(ts));
- spin_lock_bh(&txq->axq_lock);
-
-- while (!list_empty(&tid->buf_q)) {
-- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-- list_move_tail(&bf->list, &bf_head);
-+ while ((skb = __skb_dequeue(&tid->buf_q))) {
-+ fi = get_frame_info(skb);
-+ bf = fi->bf;
-+
-+ list_add_tail(&bf->list, &bf_head);
-
- spin_unlock_bh(&txq->axq_lock);
-- fi = get_frame_info(bf->bf_mpdu);
- if (fi->retries) {
- ath_tx_update_baw(sc, tid, fi->seqno);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
-@@ -218,6 +220,7 @@ static void ath_tid_drain(struct ath_sof
- struct ath_atx_tid *tid)
-
- {
-+ struct sk_buff *skb;
- struct ath_buf *bf;
- struct list_head bf_head;
- struct ath_tx_status ts;
-@@ -226,14 +229,12 @@ static void ath_tid_drain(struct ath_sof
- memset(&ts, 0, sizeof(ts));
- INIT_LIST_HEAD(&bf_head);
-
-- for (;;) {
-- if (list_empty(&tid->buf_q))
-- break;
-+ while ((skb = __skb_dequeue(&tid->buf_q))) {
-+ fi = get_frame_info(skb);
-+ bf = fi->bf;
-
-- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-- list_move_tail(&bf->list, &bf_head);
-+ list_add_tail(&bf->list, &bf_head);
-
-- fi = get_frame_info(bf->bf_mpdu);
- if (fi->retries)
- ath_tx_update_baw(sc, tid, fi->seqno);
-
-@@ -351,7 +352,8 @@ static void ath_tx_complete_aggr(struct
- struct ieee80211_tx_info *tx_info;
- struct ath_atx_tid *tid = NULL;
- struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
-- struct list_head bf_head, bf_pending;
-+ struct list_head bf_head;
-+ struct sk_buff_head bf_pending;
- u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
- u32 ba[WME_BA_BMP_SIZE >> 5];
- int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-@@ -428,8 +430,7 @@ static void ath_tx_complete_aggr(struct
- }
- }
-
-- INIT_LIST_HEAD(&bf_pending);
-- INIT_LIST_HEAD(&bf_head);
-+ __skb_queue_head_init(&bf_pending);
-
- ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
- while (bf) {
-@@ -474,10 +475,10 @@ static void ath_tx_complete_aggr(struct
- * Make sure the last desc is reclaimed if it
- * not a holding desc.
- */
-- if (!bf_last->bf_stale || bf_next != NULL)
-+ INIT_LIST_HEAD(&bf_head);
-+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
-+ bf_next != NULL || !bf_last->bf_stale)
- list_move_tail(&bf->list, &bf_head);
-- else
-- INIT_LIST_HEAD(&bf_head);
-
- if (!txpending || (tid->state & AGGR_CLEANUP)) {
- /*
-@@ -528,7 +529,7 @@ static void ath_tx_complete_aggr(struct
-
- ath9k_hw_cleartxdesc(sc->sc_ah,
- tbf->bf_desc);
-- list_add_tail(&tbf->list, &bf_head);
-+ fi->bf = tbf;
- } else {
- /*
- * Clear descriptor status words for
-@@ -543,21 +544,21 @@ static void ath_tx_complete_aggr(struct
- * Put this buffer to the temporary pending
- * queue to retain ordering
- */
-- list_splice_tail_init(&bf_head, &bf_pending);
-+ __skb_queue_tail(&bf_pending, skb);
- }
-
- bf = bf_next;
- }
-
- /* prepend un-acked frames to the beginning of the pending frame queue */
-- if (!list_empty(&bf_pending)) {
-+ if (!skb_queue_empty(&bf_pending)) {
- if (an->sleeping)
- ieee80211_sta_set_tim(sta);
-
- spin_lock_bh(&txq->axq_lock);
- if (clear_filter)
- tid->ac->clear_ps_filter = true;
-- list_splice(&bf_pending, &tid->buf_q);
-+ skb_queue_splice(&bf_pending, &tid->buf_q);
- if (!an->sleeping)
- ath_tx_queue_tid(txq, tid);
- spin_unlock_bh(&txq->axq_lock);
-@@ -722,19 +723,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- int *aggr_len)
- {
- #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
-- struct ath_buf *bf, *bf_first, *bf_prev = NULL;
-+ struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
- int rl = 0, nframes = 0, ndelim, prev_al = 0;
- u16 aggr_limit = 0, al = 0, bpad = 0,
- al_delta, h_baw = tid->baw_size / 2;
- enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
- struct ieee80211_tx_info *tx_info;
- struct ath_frame_info *fi;
--
-- bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
-+ struct sk_buff *skb;
-
- do {
-- bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-- fi = get_frame_info(bf->bf_mpdu);
-+ skb = skb_peek(&tid->buf_q);
-+ fi = get_frame_info(skb);
-+ bf = fi->bf;
-+
-+ if (!bf_first)
-+ bf_first = bf;
-
- /* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
-@@ -785,7 +789,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
-- list_move_tail(&bf->list, bf_q);
-+
-+ __skb_unlink(skb, &tid->buf_q);
-+ list_add_tail(&bf->list, bf_q);
- if (bf_prev) {
- bf_prev->bf_next = bf;
- ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
-@@ -793,7 +799,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- }
- bf_prev = bf;
-
-- } while (!list_empty(&tid->buf_q));
-+ } while (!skb_queue_empty(&tid->buf_q));
-
- *aggr_len = al;
-
-@@ -811,7 +817,7 @@ static void ath_tx_sched_aggr(struct ath
- int aggr_len;
-
- do {
-- if (list_empty(&tid->buf_q))
-+ if (skb_queue_empty(&tid->buf_q))
- return;
-
- INIT_LIST_HEAD(&bf_q);
-@@ -933,7 +939,7 @@ bool ath_tx_aggr_sleep(struct ath_softc
-
- spin_lock_bh(&txq->axq_lock);
-
-- if (!list_empty(&tid->buf_q))
-+ if (!skb_queue_empty(&tid->buf_q))
- buffered = true;
-
- tid->sched = false;
-@@ -966,7 +972,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
- spin_lock_bh(&txq->axq_lock);
- ac->clear_ps_filter = true;
-
-- if (!list_empty(&tid->buf_q) && !tid->paused) {
-+ if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
- ath_tx_queue_tid(txq, tid);
- ath_txq_schedule(sc, txq);
- }
-@@ -1308,7 +1314,7 @@ void ath_txq_schedule(struct ath_softc *
- * add tid to round-robin queue if more frames
- * are pending for the tid
- */
-- if (!list_empty(&tid->buf_q))
-+ if (!skb_queue_empty(&tid->buf_q))
- ath_tx_queue_tid(txq, tid);
-
- if (tid == last_tid ||
-@@ -1414,7 +1420,7 @@ static void ath_tx_send_ampdu(struct ath
- * - seqno is not within block-ack window
- * - h/w queue depth exceeds low water mark
- */
-- if (!list_empty(&tid->buf_q) || tid->paused ||
-+ if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
- txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
- /*
-@@ -1422,7 +1428,7 @@ static void ath_tx_send_ampdu(struct ath
- * for aggregation.
- */
- TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
-- list_add_tail(&bf->list, &tid->buf_q);
-+ __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
- if (!txctl->an || !txctl->an->sleeping)
- ath_tx_queue_tid(txctl->txq, tid);
- return;
-@@ -1753,6 +1759,7 @@ static struct ath_buf *ath_tx_setup_buff
- bf->bf_buf_addr,
- txq->axq_qnum);
-
-+ fi->bf = bf;
-
- return bf;
- }
-@@ -2364,7 +2371,7 @@ void ath_tx_node_init(struct ath_softc *
- tid->sched = false;
- tid->paused = false;
- tid->state &= ~AGGR_CLEANUP;
-- INIT_LIST_HEAD(&tid->buf_q);
-+ __skb_queue_head_init(&tid->buf_q);
- acno = TID_TO_WME_AC(tidno);
- tid->ac = &an->ac[acno];
- tid->state &= ~AGGR_ADDBA_COMPLETE;
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -235,6 +235,7 @@ struct ath_atx_tid {
- struct ath_node *an;
- struct ath_atx_ac *ac;
- unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
-+ int buf_pending;
- u16 seq_start;
- u16 seq_next;
- u16 baw_size;
-@@ -283,6 +284,9 @@ struct ath_tx_control {
- * (axq_qnum).
- */
- struct ath_tx {
-+ u32 qlen_single;
-+ u32 qlen_aggr;
-+
- u16 seq_no;
- u32 txqsetup;
- spinlock_t txbuflock;
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1250,6 +1250,10 @@ int ath9k_init_debug(struct ath_hw *ah)
- sc, &fops_wiphy);
- debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_xmit);
-+ debugfs_create_u32("qlen_single", S_IRUSR | S_IWUSR,
-+ sc->debug.debugfs_phy, &sc->tx.qlen_single);
-+ debugfs_create_u32("qlen_aggr", S_IRUSR | S_IWUSR,
-+ sc->debug.debugfs_phy, &sc->tx.qlen_aggr);
- debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_stations);
- debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -339,6 +339,14 @@ static void ath_tx_count_frames(struct a
- }
- }
-
-+static struct ath_atx_tid *ath_get_tid(struct ath_node *an, struct sk_buff *skb)
-+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ u8 tidno;
-+
-+ tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-+ return ATH_AN_2_TID(an, tidno);
-+}
-
- static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_buf *bf, struct list_head *bf_q,
-@@ -433,6 +441,8 @@ static void ath_tx_complete_aggr(struct
- __skb_queue_head_init(&bf_pending);
-
- ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
-+ tid->buf_pending -= nframes;
-+
- while (bf) {
- txfail = txpending = 0;
- bf_next = bf->bf_next;
-@@ -790,6 +800,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- ath_tx_addto_baw(sc, tid, fi->seqno);
- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
-
-+ tid->buf_pending++;
- __skb_unlink(skb, &tid->buf_q);
- list_add_tail(&bf->list, bf_q);
- if (bf_prev) {
-@@ -1441,6 +1452,8 @@ static void ath_tx_send_ampdu(struct ath
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, fi->seqno);
-
-+ tid->buf_pending++;
-+
- /* Queue to h/w without aggregation */
- TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
- bf->bf_lastbf = bf;
-@@ -1505,7 +1518,6 @@ static void setup_frame_info(struct ieee
- struct ath_atx_tid *tid;
- enum ath9k_key_type keytype;
- u16 seqno = 0;
-- u8 tidno;
-
- keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
-
-@@ -1516,13 +1528,11 @@ static void setup_frame_info(struct ieee
- if (an && ieee80211_is_data_qos(hdr->frame_control) &&
- conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
-
-- tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
--
- /*
- * Override seqno set by upper layer with the one
- * in tx aggregation state.
- */
-- tid = ATH_AN_2_TID(an, tidno);
-+ tid = ath_get_tid(an, skb);
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-@@ -1766,24 +1776,14 @@ static struct ath_buf *ath_tx_setup_buff
-
- /* FIXME: tx power */
- static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
-- struct ath_tx_control *txctl)
-+ struct ath_tx_control *txctl,
-+ struct ath_atx_tid *tid)
- {
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct list_head bf_head;
-- struct ath_atx_tid *tid = NULL;
-- u8 tidno;
-
- spin_lock_bh(&txctl->txq->axq_lock);
-- if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
-- ieee80211_is_data_qos(hdr->frame_control)) {
-- tidno = ieee80211_get_qos_ctl(hdr)[0] &
-- IEEE80211_QOS_CTL_TID_MASK;
-- tid = ATH_AN_2_TID(txctl->an, tidno);
--
-- WARN_ON(tid->ac->txq != txctl->txq);
-- }
-
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
- /*
-@@ -1824,6 +1824,7 @@ int ath_tx_start(struct ieee80211_hw *hw
- struct ieee80211_vif *vif = info->control.vif;
- struct ath_softc *sc = hw->priv;
- struct ath_txq *txq = txctl->txq;
-+ struct ath_atx_tid *tid = NULL;
- struct ath_buf *bf;
- int padpos, padsize;
- int frmlen = skb->len + FCS_LEN;
-@@ -1857,6 +1858,7 @@ int ath_tx_start(struct ieee80211_hw *hw
-
- skb_push(skb, padsize);
- memmove(skb->data, skb->data + padsize, padpos);
-+ hdr = (struct ieee80211_hdr *) skb->data;
- }
-
- if ((vif && vif->type != NL80211_IFTYPE_AP &&
-@@ -1866,6 +1868,24 @@ int ath_tx_start(struct ieee80211_hw *hw
-
- setup_frame_info(hw, skb, frmlen);
-
-+ if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
-+ ieee80211_is_data_qos(hdr->frame_control)) {
-+ tid = ath_get_tid(txctl->an, skb);
-+
-+ WARN_ON(tid->ac->txq != txq);
-+ }
-+
-+ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
-+ if (sc->tx.qlen_aggr > 0 && skb_queue_len(&tid->buf_q) +
-+ tid->buf_pending >= sc->tx.qlen_aggr)
-+ return -ENOMEM;
-+ } else {
-+ if (sc->tx.qlen_single > 0 &&
-+ txq->axq_depth - txq->axq_ampdu_depth >=
-+ sc->tx.qlen_single)
-+ return -ENOMEM;
-+ }
-+
- /*
- * At this point, the vif, hw_key and sta pointers in the tx control
- * info are no longer valid (overwritten by the ath_frame_info data.
-@@ -1884,7 +1904,7 @@ int ath_tx_start(struct ieee80211_hw *hw
- }
- spin_unlock_bh(&txq->axq_lock);
-
-- ath_tx_start_dma(sc, bf, txctl);
-+ ath_tx_start_dma(sc, bf, txctl, tid);
-
- return 0;
- }
+#endif /* _RT2X00_PLATFORM_H */
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -38,6 +38,7 @@
+@@ -39,6 +39,7 @@
#include <linux/input-polldev.h>
#include <linux/kfifo.h>
#include <linux/timer.h>
+}
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -538,6 +538,7 @@ struct rt2x00lib_ops {
+@@ -539,6 +539,7 @@ struct rt2x00lib_ops {
const u8 *data, const size_t len);
int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
/*
* Device initialization/deinitialization handlers.
-@@ -684,6 +685,7 @@ enum rt2x00_capability_flags {
+@@ -685,6 +686,7 @@ enum rt2x00_capability_flags {
REQUIRE_SW_SEQNO,
REQUIRE_HT_TX_DESC,
REQUIRE_PS_AUTOWAKE,
/*
* Capabilities
-@@ -939,6 +941,11 @@ struct rt2x00_dev {
+@@ -940,6 +942,11 @@ struct rt2x00_dev {
const struct firmware *fw;
/*
#ifdef CONFIG_PCI
static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-@@ -315,6 +305,20 @@ static int rt2800pci_write_firmware(stru
+@@ -311,6 +301,20 @@ static int rt2800pci_write_firmware(stru
}
/*
* Initialization functions.
*/
static bool rt2800pci_get_entry_state(struct queue_entry *entry)
-@@ -1057,6 +1061,7 @@ static const struct rt2x00lib_ops rt2800
+@@ -1050,6 +1054,7 @@ static const struct rt2x00lib_ops rt2800
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware,
.get_entry_state = rt2800pci_get_entry_state,
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1122,6 +1122,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+@@ -1121,6 +1121,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
/*
* Let the driver probe the device to detect the capabilities.
*/
-@@ -1223,6 +1227,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+@@ -1222,6 +1226,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
* Free queue structures.
*/
rt2x00queue_free(rt2x00dev);
--- a/config.mk
+++ b/config.mk
-@@ -578,6 +578,7 @@ CONFIG_RT2X00=y
+@@ -581,6 +581,7 @@ CONFIG_RT2X00=y
CONFIG_RT2X00_LIB=m
CONFIG_RT2800_LIB=m
CONFIG_RT2X00_LIB_FIRMWARE=y
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
-@@ -5194,6 +5194,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5195,6 +5195,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
-@@ -740,6 +740,7 @@ struct b43_wldev {
+@@ -746,6 +746,7 @@ struct b43_wldev {
bool qos_enabled; /* TRUE, if QoS is used. */
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
bool use_pio; /* TRUE if next init should use PIO */
struct b43_phy phy;
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+@@ -75,6 +75,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
MODULE_FIRMWARE("b43/ucode5.fw");
MODULE_FIRMWARE("b43/ucode9.fw");
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2575,10 +2580,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2671,10 +2676,10 @@ static int b43_gpio_init(struct b43_wlde
& ~B43_MACCTL_GPOUTSMSK);
b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
if (dev->dev->chip_id == 0x4301) {
mask |= 0x0060;
set |= 0x0060;
-@@ -5137,10 +5142,10 @@ static void b43_print_driverinfo(void)
+@@ -5441,10 +5446,10 @@ static void b43_print_driverinfo(void)
feat_sdio = "S";
#endif
printk(KERN_INFO "Broadcom 43xx driver loaded "
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
-@@ -17,7 +17,7 @@ b43-y += xmit.o
+@@ -19,7 +19,7 @@ b43-y += xmit.o
b43-y += lo.o
b43-y += wa.o
b43-y += dma.o
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -1834,9 +1834,11 @@ static void b43_do_interrupt_thread(stru
+@@ -1884,9 +1884,11 @@ static void b43_do_interrupt_thread(stru
dma_reason[4], dma_reason[5]);
b43err(dev->wl, "This device does not support DMA "
"on your system. It will now be switched to PIO.\n");
+++ /dev/null
---- a/drivers/net/wireless/b43/Kconfig
-+++ b/drivers/net/wireless/b43/Kconfig
-@@ -90,6 +90,12 @@ config B43_SDIO
-
- #Data transfers to the device via PIO. We want it as a fallback even
- # if we can do DMA.
-+config B43_BCMA_PIO
-+ bool
-+ depends on B43_BCMA
-+ select BCMA_BLOCKIO
-+ default y
-+
- config B43_PIO
- bool
- depends on B43
-@@ -125,6 +131,14 @@ config B43_PHY_HT
-
- Say N, this is BROKEN and crashes driver.
-
-+config B43_PHY_LCN
-+ bool "Support for LCN-PHY devices (BROKEN)"
-+ depends on B43 && BROKEN
-+ ---help---
-+ Support for the LCN-PHY.
-+
-+ Say N, this is BROKEN and crashes driver.
-+
- # This config option automatically enables b43 LEDS support,
- # if it's possible.
- config B43_LEDS
---- a/drivers/net/wireless/b43/Makefile
-+++ b/drivers/net/wireless/b43/Makefile
-@@ -11,7 +11,9 @@ b43-$(CONFIG_B43_PHY_N) += phy_n.o
- b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
- b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
- b43-$(CONFIG_B43_PHY_HT) += phy_ht.o
-+b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o
- b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
-+b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o
- b43-y += sysfs.o
- b43-y += xmit.o
- b43-y += lo.o
---- a/drivers/net/wireless/b43/b43.h
-+++ b/drivers/net/wireless/b43/b43.h
-@@ -433,6 +433,12 @@ enum {
- #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */
- #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */
-
-+/* BCMA 802.11 core specific IO status (BCMA_IOST) flags */
-+#define B43_BCMA_IOST_2G_PHY 0x00000001 /* 2.4G capable phy */
-+#define B43_BCMA_IOST_5G_PHY 0x00000002 /* 5G capable phy */
-+#define B43_BCMA_IOST_FASTCLKA 0x00000004 /* Fast Clock Available */
-+#define B43_BCMA_IOST_DUALB_PHY 0x00000008 /* Dualband phy */
-+
- /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
- #define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
- #define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
-@@ -588,6 +594,7 @@ struct b43_dma {
- struct b43_dmaring *rx_ring;
-
- u32 translation; /* Routing bits */
-+ bool parity; /* Check for parity */
- };
-
- struct b43_pio_txqueue;
-@@ -726,7 +733,6 @@ enum {
-
- /* Data structure for one wireless device (802.11 core) */
- struct b43_wldev {
-- struct ssb_device *sdev; /* TODO: remove when b43_bus_dev is ready */
- struct b43_bus_dev *dev;
- struct b43_wl *wl;
-
---- a/drivers/net/wireless/b43/bus.c
-+++ b/drivers/net/wireless/b43/bus.c
-@@ -23,58 +23,155 @@
- #include "b43.h"
- #include "bus.h"
-
-+/* BCMA */
-+#ifdef CONFIG_B43_BCMA
-+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
-+{
-+ return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
-+}
-+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
-+ bool dynamic_pctl)
-+{
-+ return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
-+}
-+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
-+{
-+ return bcma_core_is_enabled(dev->bdev);
-+}
-+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
-+ u32 core_specific_flags)
-+{
-+ bcma_core_enable(dev->bdev, core_specific_flags);
-+}
-+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
-+ u32 core_specific_flags)
-+{
-+ bcma_core_disable(dev->bdev, core_specific_flags);
-+}
-+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
-+{
-+ return bcma_read16(dev->bdev, offset);
-+}
-+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
-+{
-+ return bcma_read32(dev->bdev, offset);
-+}
-+static
-+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
-+{
-+ bcma_write16(dev->bdev, offset, value);
-+}
-+static
-+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
-+{
-+ bcma_write32(dev->bdev, offset, value);
-+}
-+static
-+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
-+}
-+static
-+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
-+}
-+
-+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
-+{
-+ struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (!dev)
-+ return NULL;
-+
-+ dev->bus_type = B43_BUS_BCMA;
-+ dev->bdev = core;
-+
-+ dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
-+ dev->bus_powerup = b43_bus_bcma_bus_powerup;
-+ dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
-+ dev->device_enable = b43_bus_bcma_device_enable;
-+ dev->device_disable = b43_bus_bcma_device_disable;
-+
-+ dev->read16 = b43_bus_bcma_read16;
-+ dev->read32 = b43_bus_bcma_read32;
-+ dev->write16 = b43_bus_bcma_write16;
-+ dev->write32 = b43_bus_bcma_write32;
-+ dev->block_read = b43_bus_bcma_block_read;
-+ dev->block_write = b43_bus_bcma_block_write;
-+
-+ dev->dev = &core->dev;
-+ dev->dma_dev = core->dma_dev;
-+ dev->irq = core->irq;
-+
-+ /*
-+ dev->board_vendor = core->bus->boardinfo.vendor;
-+ dev->board_type = core->bus->boardinfo.type;
-+ dev->board_rev = core->bus->boardinfo.rev;
-+ */
-+
-+ dev->chip_id = core->bus->chipinfo.id;
-+ dev->chip_rev = core->bus->chipinfo.rev;
-+ dev->chip_pkg = core->bus->chipinfo.pkg;
-+
-+ dev->bus_sprom = &core->bus->sprom;
-+
-+ dev->core_id = core->id.id;
-+ dev->core_rev = core->id.rev;
-+
-+ return dev;
-+}
-+#endif /* CONFIG_B43_BCMA */
-
- /* SSB */
- #ifdef CONFIG_B43_SSB
--static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
-+static int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
- {
- return ssb_bus_may_powerdown(dev->sdev->bus);
- }
--static inline int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
-+static int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev,
- bool dynamic_pctl)
- {
- return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl);
- }
--static inline int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
-+static int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
- {
- return ssb_device_is_enabled(dev->sdev);
- }
--static inline void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
-+static void b43_bus_ssb_device_enable(struct b43_bus_dev *dev,
- u32 core_specific_flags)
- {
- ssb_device_enable(dev->sdev, core_specific_flags);
- }
--static inline void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
-+static void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
- u32 core_specific_flags)
- {
- ssb_device_disable(dev->sdev, core_specific_flags);
- }
-
--static inline u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
-+static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
- {
- return ssb_read16(dev->sdev, offset);
- }
--static inline u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
-+static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
- {
- return ssb_read32(dev->sdev, offset);
- }
--static inline
--void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
-+static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
- {
- ssb_write16(dev->sdev, offset, value);
- }
--static inline
--void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
-+static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
- {
- ssb_write32(dev->sdev, offset, value);
- }
--static inline
--void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
-- size_t count, u16 offset, u8 reg_width)
-+static void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
- {
- ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
- }
--static inline
-+static
- void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
- size_t count, u16 offset, u8 reg_width)
- {
-@@ -125,3 +222,32 @@ struct b43_bus_dev *b43_bus_dev_ssb_init
- return dev;
- }
- #endif /* CONFIG_B43_SSB */
-+
-+void *b43_bus_get_wldev(struct b43_bus_dev *dev)
-+{
-+ switch (dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ return bcma_get_drvdata(dev->bdev);
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ return ssb_get_drvdata(dev->sdev);
-+#endif
-+ }
-+ return NULL;
-+}
-+
-+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev)
-+{
-+ switch (dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_set_drvdata(dev->bdev, wldev);
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ ssb_set_drvdata(dev->sdev, wldev);
-+#endif
-+ }
-+}
---- a/drivers/net/wireless/b43/bus.h
-+++ b/drivers/net/wireless/b43/bus.h
-@@ -2,12 +2,16 @@
- #define B43_BUS_H_
-
- enum b43_bus_type {
-+#ifdef CONFIG_B43_BCMA
-+ B43_BUS_BCMA,
-+#endif
- B43_BUS_SSB,
- };
-
- struct b43_bus_dev {
- enum b43_bus_type bus_type;
- union {
-+ struct bcma_device *bdev;
- struct ssb_device *sdev;
- };
-
-@@ -57,6 +61,10 @@ static inline bool b43_bus_host_is_sdio(
- dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
- }
-
-+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
- struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
-
-+void *b43_bus_get_wldev(struct b43_bus_dev *dev);
-+void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data);
-+
- #endif /* B43_BUS_H_ */
---- a/drivers/net/wireless/b43/dma.c
-+++ b/drivers/net/wireless/b43/dma.c
-@@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct
- addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
-- addrhi |= (ring->dev->dma.translation << 1);
-+ addrhi |= ring->dev->dma.translation;
- if (slot == ring->nr_slots - 1)
- ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
- if (start)
-@@ -659,6 +659,7 @@ static int dmacontroller_setup(struct b4
- u32 value;
- u32 addrext;
- u32 trans = ring->dev->dma.translation;
-+ bool parity = ring->dev->dma.parity;
-
- if (ring->tx) {
- if (ring->type == B43_DMA_64BIT) {
-@@ -669,13 +670,15 @@ static int dmacontroller_setup(struct b4
- value = B43_DMA64_TXENABLE;
- value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
- & B43_DMA64_TXADDREXT_MASK;
-+ if (!parity)
-+ value |= B43_DMA64_TXPARITYDISABLE;
- b43_dma_write(ring, B43_DMA64_TXCTL, value);
- b43_dma_write(ring, B43_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_TXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
-- | (trans << 1));
-+ | trans);
- } else {
- u32 ringbase = (u32) (ring->dmabase);
-
-@@ -684,6 +687,8 @@ static int dmacontroller_setup(struct b4
- value = B43_DMA32_TXENABLE;
- value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
- & B43_DMA32_TXADDREXT_MASK;
-+ if (!parity)
-+ value |= B43_DMA32_TXPARITYDISABLE;
- b43_dma_write(ring, B43_DMA32_TXCTL, value);
- b43_dma_write(ring, B43_DMA32_TXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
-@@ -702,13 +707,15 @@ static int dmacontroller_setup(struct b4
- value |= B43_DMA64_RXENABLE;
- value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
- & B43_DMA64_RXADDREXT_MASK;
-+ if (!parity)
-+ value |= B43_DMA64_RXPARITYDISABLE;
- b43_dma_write(ring, B43_DMA64_RXCTL, value);
- b43_dma_write(ring, B43_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
-- | (trans << 1));
-+ | trans);
- b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
- sizeof(struct b43_dmadesc64));
- } else {
-@@ -720,6 +727,8 @@ static int dmacontroller_setup(struct b4
- value |= B43_DMA32_RXENABLE;
- value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
- & B43_DMA32_RXADDREXT_MASK;
-+ if (!parity)
-+ value |= B43_DMA32_RXPARITYDISABLE;
- b43_dma_write(ring, B43_DMA32_RXCTL, value);
- b43_dma_write(ring, B43_DMA32_RXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
-@@ -1055,7 +1064,26 @@ int b43_dma_init(struct b43_wldev *dev)
- err = b43_dma_set_mask(dev, dmamask);
- if (err)
- return err;
-- dma->translation = ssb_dma_translation(dev->sdev);
-+
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ dma->translation = bcma_core_dma_translation(dev->dev->bdev);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ dma->translation = ssb_dma_translation(dev->dev->sdev);
-+ break;
-+#endif
-+ }
-+
-+ dma->parity = true;
-+#ifdef CONFIG_B43_BCMA
-+ /* TODO: find out which SSB devices need disabling parity */
-+ if (dev->dev->bus_type == B43_BUS_BCMA)
-+ dma->parity = false;
-+#endif
-
- err = -ENOMEM;
- /* setup TX DMA channels. */
-@@ -1600,6 +1628,7 @@ void b43_dma_rx(struct b43_dmaring *ring
- dma_rx(ring, &slot);
- update_max_used_slots(ring, ++used_slots);
- }
-+ wmb();
- ops->set_current_rxslot(ring, slot);
- ring->current_slot = slot;
- }
---- a/drivers/net/wireless/b43/dma.h
-+++ b/drivers/net/wireless/b43/dma.h
-@@ -20,6 +20,7 @@
- #define B43_DMA32_TXSUSPEND 0x00000002
- #define B43_DMA32_TXLOOPBACK 0x00000004
- #define B43_DMA32_TXFLUSH 0x00000010
-+#define B43_DMA32_TXPARITYDISABLE 0x00000800
- #define B43_DMA32_TXADDREXT_MASK 0x00030000
- #define B43_DMA32_TXADDREXT_SHIFT 16
- #define B43_DMA32_TXRING 0x04
-@@ -44,6 +45,7 @@
- #define B43_DMA32_RXFROFF_MASK 0x000000FE
- #define B43_DMA32_RXFROFF_SHIFT 1
- #define B43_DMA32_RXDIRECTFIFO 0x00000100
-+#define B43_DMA32_RXPARITYDISABLE 0x00000800
- #define B43_DMA32_RXADDREXT_MASK 0x00030000
- #define B43_DMA32_RXADDREXT_SHIFT 16
- #define B43_DMA32_RXRING 0x14
-@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
- #define B43_DMA64_TXSUSPEND 0x00000002
- #define B43_DMA64_TXLOOPBACK 0x00000004
- #define B43_DMA64_TXFLUSH 0x00000010
-+#define B43_DMA64_TXPARITYDISABLE 0x00000800
- #define B43_DMA64_TXADDREXT_MASK 0x00030000
- #define B43_DMA64_TXADDREXT_SHIFT 16
- #define B43_DMA64_TXINDEX 0x04
-@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
- #define B43_DMA64_RXFROFF_MASK 0x000000FE
- #define B43_DMA64_RXFROFF_SHIFT 1
- #define B43_DMA64_RXDIRECTFIFO 0x00000100
-+#define B43_DMA64_RXPARITYDISABLE 0x00000800
- #define B43_DMA64_RXADDREXT_MASK 0x00030000
- #define B43_DMA64_RXADDREXT_SHIFT 16
- #define B43_DMA64_RXINDEX 0x24
---- a/drivers/net/wireless/b43/main.c
-+++ b/drivers/net/wireless/b43/main.c
-@@ -1136,6 +1136,41 @@ void b43_power_saving_ctl_bits(struct b4
- }
- }
-
-+#ifdef CONFIG_B43_BCMA
-+static void b43_bcma_phy_reset(struct b43_wldev *dev)
-+{
-+ u32 flags;
-+
-+ /* Put PHY into reset */
-+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
-+ flags |= B43_BCMA_IOCTL_PHY_RESET;
-+ flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */
-+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
-+ udelay(2);
-+
-+ /* Take PHY out of reset */
-+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
-+ flags &= ~B43_BCMA_IOCTL_PHY_RESET;
-+ flags |= BCMA_IOCTL_FGC;
-+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
-+ udelay(1);
-+
-+ /* Do not force clock anymore */
-+ flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
-+ flags &= ~BCMA_IOCTL_FGC;
-+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
-+ udelay(1);
-+}
-+
-+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
-+{
-+ b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
-+ bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
-+ b43_bcma_phy_reset(dev);
-+ bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
-+}
-+#endif
-+
- static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
- {
- struct ssb_device *sdev = dev->dev->sdev;
-@@ -1168,7 +1203,18 @@ void b43_wireless_core_reset(struct b43_
- {
- u32 macctl;
-
-- b43_ssb_wireless_core_reset(dev, gmode);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ b43_bcma_wireless_core_reset(dev, gmode);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ b43_ssb_wireless_core_reset(dev, gmode);
-+ break;
-+#endif
-+ }
-
- /* Turn Analog ON, but only if we already know the PHY-type.
- * This protects against very early setup where we don't know the
-@@ -1921,7 +1967,7 @@ static irqreturn_t b43_do_interrupt(stru
- return IRQ_NONE;
- reason &= dev->irq_mask;
- if (!reason)
-- return IRQ_HANDLED;
-+ return IRQ_NONE;
-
- dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
- & 0x0001DC00;
-@@ -2116,21 +2162,43 @@ static int b43_try_request_fw(struct b43
- u32 tmshigh;
- int err;
-
-+ /* Files for HT and LCN were found by trying one by one */
-+
- /* Get microcode */
-- if ((rev >= 5) && (rev <= 10))
-+ if ((rev >= 5) && (rev <= 10)) {
- filename = "ucode5";
-- else if ((rev >= 11) && (rev <= 12))
-+ } else if ((rev >= 11) && (rev <= 12)) {
- filename = "ucode11";
-- else if (rev == 13)
-+ } else if (rev == 13) {
- filename = "ucode13";
-- else if (rev == 14)
-+ } else if (rev == 14) {
- filename = "ucode14";
-- else if (rev == 15)
-+ } else if (rev == 15) {
- filename = "ucode15";
-- else if ((rev >= 16) && (rev <= 20))
-- filename = "ucode16_mimo";
-- else
-- goto err_no_ucode;
-+ } else {
-+ switch (dev->phy.type) {
-+ case B43_PHYTYPE_N:
-+ if (rev >= 16)
-+ filename = "ucode16_mimo";
-+ else
-+ goto err_no_ucode;
-+ break;
-+ case B43_PHYTYPE_HT:
-+ if (rev == 29)
-+ filename = "ucode29_mimo";
-+ else
-+ goto err_no_ucode;
-+ break;
-+ case B43_PHYTYPE_LCN:
-+ if (rev == 24)
-+ filename = "ucode24_mimo";
-+ else
-+ goto err_no_ucode;
-+ break;
-+ default:
-+ goto err_no_ucode;
-+ }
-+ }
- err = b43_do_request_fw(ctx, filename, &fw->ucode);
- if (err)
- goto err_load;
-@@ -2189,6 +2257,18 @@ static int b43_try_request_fw(struct b43
- else
- goto err_no_initvals;
- break;
-+ case B43_PHYTYPE_HT:
-+ if (rev == 29)
-+ filename = "ht0initvals29";
-+ else
-+ goto err_no_initvals;
-+ break;
-+ case B43_PHYTYPE_LCN:
-+ if (rev == 24)
-+ filename = "lcn0initvals24";
-+ else
-+ goto err_no_initvals;
-+ break;
- default:
- goto err_no_initvals;
- }
-@@ -2236,6 +2316,18 @@ static int b43_try_request_fw(struct b43
- else
- goto err_no_initvals;
- break;
-+ case B43_PHYTYPE_HT:
-+ if (rev == 29)
-+ filename = "ht0bsinitvals29";
-+ else
-+ goto err_no_initvals;
-+ break;
-+ case B43_PHYTYPE_LCN:
-+ if (rev == 24)
-+ filename = "lcn0bsinitvals24";
-+ else
-+ goto err_no_initvals;
-+ break;
- default:
- goto err_no_initvals;
- }
-@@ -2607,11 +2699,24 @@ static int b43_gpio_init(struct b43_wlde
- if (dev->dev->core_rev >= 2)
- mask |= 0x0010; /* FIXME: This is redundant. */
-
-- gpiodev = b43_ssb_gpio_dev(dev);
-- if (gpiodev)
-- ssb_write32(gpiodev, B43_GPIO_CONTROL,
-- (ssb_read32(gpiodev, B43_GPIO_CONTROL)
-- & mask) | set);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
-+ (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc,
-+ BCMA_CC_GPIOCTL) & mask) | set);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ gpiodev = b43_ssb_gpio_dev(dev);
-+ if (gpiodev)
-+ ssb_write32(gpiodev, B43_GPIO_CONTROL,
-+ (ssb_read32(gpiodev, B43_GPIO_CONTROL)
-+ & mask) | set);
-+ break;
-+#endif
-+ }
-
- return 0;
- }
-@@ -2621,9 +2726,21 @@ static void b43_gpio_cleanup(struct b43_
- {
- struct ssb_device *gpiodev;
-
-- gpiodev = b43_ssb_gpio_dev(dev);
-- if (gpiodev)
-- ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,
-+ 0);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ gpiodev = b43_ssb_gpio_dev(dev);
-+ if (gpiodev)
-+ ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
-+ break;
-+#endif
-+ }
- }
-
- /* http://bcm-specs.sipsolutions.net/EnableMac */
-@@ -2695,12 +2812,30 @@ out:
- /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
- void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
- {
-- u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-- if (on)
-- tmslow |= B43_TMSLOW_MACPHYCLKEN;
-- else
-- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
-- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
-+ u32 tmp;
-+
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
-+ if (on)
-+ tmp |= B43_BCMA_IOCTL_MACPHYCLKEN;
-+ else
-+ tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN;
-+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
-+ if (on)
-+ tmp |= B43_TMSLOW_MACPHYCLKEN;
-+ else
-+ tmp &= ~B43_TMSLOW_MACPHYCLKEN;
-+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
-+ break;
-+#endif
-+ }
- }
-
- static void b43_adjust_opmode(struct b43_wldev *dev)
-@@ -2939,8 +3074,20 @@ static int b43_chip_init(struct b43_wlde
-
- b43_mac_phy_clock_set(dev, true);
-
-- b43_write16(dev, B43_MMIO_POWERUP_DELAY,
-- dev->sdev->bus->chipco.fast_pwrup_delay);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ /* FIXME: 0xE74 is quite common, but should be read from CC */
-+ b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ b43_write16(dev, B43_MMIO_POWERUP_DELAY,
-+ dev->dev->sdev->bus->chipco.fast_pwrup_delay);
-+ break;
-+#endif
-+ }
-
- err = 0;
- b43dbg(dev->wl, "Chip initialized\n");
-@@ -3456,21 +3603,33 @@ static void b43_op_set_tsf(struct ieee80
-
- static void b43_put_phy_into_reset(struct b43_wldev *dev)
- {
-- struct ssb_device *sdev = dev->sdev;
-- u32 tmslow;
-+ u32 tmp;
-
-- tmslow = ssb_read32(sdev, SSB_TMSLOW);
-- tmslow &= ~B43_TMSLOW_GMODE;
-- tmslow |= B43_TMSLOW_PHYRESET;
-- tmslow |= SSB_TMSLOW_FGC;
-- ssb_write32(sdev, SSB_TMSLOW, tmslow);
-- msleep(1);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ b43err(dev->wl,
-+ "Putting PHY into reset not supported on BCMA\n");
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
-+ tmp &= ~B43_TMSLOW_GMODE;
-+ tmp |= B43_TMSLOW_PHYRESET;
-+ tmp |= SSB_TMSLOW_FGC;
-+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
-+ msleep(1);
-+
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
-+ tmp &= ~SSB_TMSLOW_FGC;
-+ tmp |= B43_TMSLOW_PHYRESET;
-+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
-+ msleep(1);
-
-- tmslow = ssb_read32(sdev, SSB_TMSLOW);
-- tmslow &= ~SSB_TMSLOW_FGC;
-- tmslow |= B43_TMSLOW_PHYRESET;
-- ssb_write32(sdev, SSB_TMSLOW, tmslow);
-- msleep(1);
-+ break;
-+#endif
-+ }
- }
-
- static const char *band_to_string(enum ieee80211_band band)
-@@ -4100,6 +4259,12 @@ static int b43_phy_versioning(struct b43
- unsupported = 1;
- break;
- #endif
-+#ifdef CONFIG_B43_PHY_LCN
-+ case B43_PHYTYPE_LCN:
-+ if (phy_rev > 1)
-+ unsupported = 1;
-+ break;
-+#endif
- default:
- unsupported = 1;
- };
-@@ -4113,22 +4278,42 @@ static int b43_phy_versioning(struct b43
- analog_type, phy_type, phy_rev);
-
- /* Get RADIO versioning */
-- if (dev->dev->chip_id == 0x4317) {
-- if (dev->dev->chip_rev == 0)
-- tmp = 0x3205017F;
-- else if (dev->dev->chip_rev == 1)
-- tmp = 0x4205017F;
-- else
-- tmp = 0x5205017F;
-+ if (dev->dev->core_rev >= 24) {
-+ u16 radio24[3];
-+
-+ for (tmp = 0; tmp < 3; tmp++) {
-+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
-+ radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
-+ }
-+
-+ /* Broadcom uses "id" for our "ver" and has separated "ver" */
-+ /* radio_ver = (radio24[0] & 0xF0) >> 4; */
-+
-+ radio_manuf = 0x17F;
-+ radio_ver = (radio24[2] << 8) | radio24[1];
-+ radio_rev = (radio24[0] & 0xF);
- } else {
-- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
-- tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
-- }
-- radio_manuf = (tmp & 0x00000FFF);
-- radio_ver = (tmp & 0x0FFFF000) >> 12;
-- radio_rev = (tmp & 0xF0000000) >> 28;
-+ if (dev->dev->chip_id == 0x4317) {
-+ if (dev->dev->chip_rev == 0)
-+ tmp = 0x3205017F;
-+ else if (dev->dev->chip_rev == 1)
-+ tmp = 0x4205017F;
-+ else
-+ tmp = 0x5205017F;
-+ } else {
-+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
-+ B43_RADIOCTL_ID);
-+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
-+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
-+ B43_RADIOCTL_ID);
-+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
-+ << 16;
-+ }
-+ radio_manuf = (tmp & 0x00000FFF);
-+ radio_ver = (tmp & 0x0FFFF000) >> 12;
-+ radio_rev = (tmp & 0xF0000000) >> 28;
-+ }
-+
- if (radio_manuf != 0x17F /* Broadcom */)
- unsupported = 1;
- switch (phy_type) {
-@@ -4160,6 +4345,10 @@ static int b43_phy_versioning(struct b43
- if (radio_ver != 0x2059)
- unsupported = 1;
- break;
-+ case B43_PHYTYPE_LCN:
-+ if (radio_ver != 0x2064)
-+ unsupported = 1;
-+ break;
- default:
- B43_WARN_ON(1);
- }
-@@ -4343,7 +4532,6 @@ static void b43_wireless_core_exit(struc
- /* Initialize a wireless core */
- static int b43_wireless_core_init(struct b43_wldev *dev)
- {
-- struct ssb_bus *bus = dev->sdev->bus;
- struct ssb_sprom *sprom = dev->dev->bus_sprom;
- struct b43_phy *phy = &dev->phy;
- int err;
-@@ -4362,7 +4550,20 @@ static int b43_wireless_core_init(struct
- phy->ops->prepare_structs(dev);
-
- /* Enable IRQ routing to this device. */
-- ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
-+ dev->dev->bdev, true);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore,
-+ dev->dev->sdev);
-+ break;
-+#endif
-+ }
-
- b43_imcfglo_timeouts_workaround(dev);
- b43_bluetooth_coext_disable(dev);
-@@ -4393,8 +4594,9 @@ static int b43_wireless_core_init(struct
- if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
- hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
- #ifdef CONFIG_SSB_DRIVER_PCICORE
-- if ((bus->bustype == SSB_BUSTYPE_PCI) &&
-- (bus->pcicore.dev->id.revision <= 10))
-+ if (dev->dev->bus_type == B43_BUS_SSB &&
-+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
-+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
- hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */
- #endif
- hf &= ~B43_HF_SKCFPUP;
-@@ -4764,9 +4966,9 @@ static void b43_wireless_core_detach(str
- static int b43_wireless_core_attach(struct b43_wldev *dev)
- {
- struct b43_wl *wl = dev->wl;
-- struct ssb_bus *bus = dev->sdev->bus;
-- struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
-+ struct pci_dev *pdev = NULL;
- int err;
-+ u32 tmp;
- bool have_2ghz_phy = 0, have_5ghz_phy = 0;
-
- /* Do NOT do any device initialization here.
-@@ -4776,20 +4978,38 @@ static int b43_wireless_core_attach(stru
- * that in core_init(), too.
- */
-
-+#ifdef CONFIG_B43_SSB
-+ if (dev->dev->bus_type == B43_BUS_SSB &&
-+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
-+ pdev = dev->dev->sdev->bus->host_pci;
-+#endif
-+
- err = b43_bus_powerup(dev, 0);
- if (err) {
- b43err(wl, "Bus powerup failed\n");
- goto out;
- }
-- /* Get the PHY type. */
-- if (dev->dev->core_rev >= 5) {
-- u32 tmshigh;
-
-- tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
-- have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
-- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
-- } else
-- B43_WARN_ON(1);
-+ /* Get the PHY type. */
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
-+ have_2ghz_phy = !!(tmp & B43_BCMA_IOST_2G_PHY);
-+ have_5ghz_phy = !!(tmp & B43_BCMA_IOST_5G_PHY);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ if (dev->dev->core_rev >= 5) {
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
-+ have_2ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_2GHZ_PHY);
-+ have_5ghz_phy = !!(tmp & B43_TMSHIGH_HAVE_5GHZ_PHY);
-+ } else
-+ B43_WARN_ON(1);
-+ break;
-+#endif
-+ }
-
- dev->phy.gmode = have_2ghz_phy;
- dev->phy.radio_on = 1;
-@@ -4815,6 +5035,8 @@ static int b43_wireless_core_attach(stru
- #endif
- case B43_PHYTYPE_G:
- case B43_PHYTYPE_N:
-+ case B43_PHYTYPE_HT:
-+ case B43_PHYTYPE_LCN:
- have_2ghz_phy = 1;
- break;
- default:
-@@ -4877,13 +5099,13 @@ static void b43_one_core_detach(struct b
- /* Do not cancel ieee80211-workqueue based work here.
- * See comment in b43_remove(). */
-
-- wldev = ssb_get_drvdata(dev->sdev);
-+ wldev = b43_bus_get_wldev(dev);
- wl = wldev->wl;
- b43_debugfs_remove_device(wldev);
- b43_wireless_core_detach(wldev);
- list_del(&wldev->list);
- wl->nr_devs--;
-- ssb_set_drvdata(dev->sdev, NULL);
-+ b43_bus_set_wldev(dev, NULL);
- kfree(wldev);
- }
-
-@@ -4898,7 +5120,6 @@ static int b43_one_core_attach(struct b4
-
- wldev->use_pio = b43_modparam_pio;
- wldev->dev = dev;
-- wldev->sdev = dev->sdev; /* TODO: Remove when not needed */
- wldev->wl = wl;
- b43_set_status(wldev, B43_STAT_UNINIT);
- wldev->bad_frames_preempt = modparam_bad_frames_preempt;
-@@ -4910,7 +5131,7 @@ static int b43_one_core_attach(struct b4
-
- list_add(&wldev->list, &wl->devlist);
- wl->nr_devs++;
-- ssb_set_drvdata(dev->sdev, wldev);
-+ b43_bus_set_wldev(dev, wldev);
- b43_debugfs_add_device(wldev);
-
- out:
-@@ -4959,11 +5180,12 @@ static void b43_wireless_exit(struct b43
- ieee80211_free_hw(hw);
- }
-
--static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
-+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
- {
-- struct ssb_sprom *sprom = &dev->bus->sprom;
-+ struct ssb_sprom *sprom = dev->bus_sprom;
- struct ieee80211_hw *hw;
- struct b43_wl *wl;
-+ char chip_name[6];
-
- hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
- if (!hw) {
-@@ -5002,21 +5224,70 @@ static struct b43_wl *b43_wireless_init(
- INIT_WORK(&wl->tx_work, b43_tx_work);
- skb_queue_head_init(&wl->tx_queue);
-
-- b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
-- dev->bus->chip_id, dev->id.revision);
-+ snprintf(chip_name, ARRAY_SIZE(chip_name),
-+ (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
-+ b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name,
-+ dev->core_rev);
- return wl;
- }
-
- #ifdef CONFIG_B43_BCMA
- static int b43_bcma_probe(struct bcma_device *core)
- {
-- b43err(NULL, "BCMA is not supported yet!");
-- return -EOPNOTSUPP;
-+ struct b43_bus_dev *dev;
-+ struct b43_wl *wl;
-+ int err;
-+
-+ dev = b43_bus_dev_bcma_init(core);
-+ if (!dev)
-+ return -ENODEV;
-+
-+ wl = b43_wireless_init(dev);
-+ if (IS_ERR(wl)) {
-+ err = PTR_ERR(wl);
-+ goto bcma_out;
-+ }
-+
-+ err = b43_one_core_attach(dev, wl);
-+ if (err)
-+ goto bcma_err_wireless_exit;
-+
-+ err = ieee80211_register_hw(wl->hw);
-+ if (err)
-+ goto bcma_err_one_core_detach;
-+ b43_leds_register(wl->current_dev);
-+
-+bcma_out:
-+ return err;
-+
-+bcma_err_one_core_detach:
-+ b43_one_core_detach(dev);
-+bcma_err_wireless_exit:
-+ ieee80211_free_hw(wl->hw);
-+ return err;
- }
-
- static void b43_bcma_remove(struct bcma_device *core)
- {
-- /* TODO */
-+ struct b43_wldev *wldev = bcma_get_drvdata(core);
-+ struct b43_wl *wl = wldev->wl;
-+
-+ /* We must cancel any work here before unregistering from ieee80211,
-+ * as the ieee80211 unreg will destroy the workqueue. */
-+ cancel_work_sync(&wldev->restart_work);
-+
-+ /* Restore the queues count before unregistering, because firmware detect
-+ * might have modified it. Restoring is important, so the networking
-+ * stack can properly free resources. */
-+ wl->hw->queues = wl->mac80211_initially_registered_queues;
-+ b43_leds_stop(wldev);
-+ ieee80211_unregister_hw(wl->hw);
-+
-+ b43_one_core_detach(wldev->dev);
-+
-+ b43_leds_unregister(wl);
-+
-+ ieee80211_free_hw(wl->hw);
- }
-
- static struct bcma_driver b43_bcma_driver = {
-@@ -5045,7 +5316,7 @@ int b43_ssb_probe(struct ssb_device *sde
- /* Probing the first core. Must setup common struct b43_wl */
- first = 1;
- b43_sprom_fixup(sdev->bus);
-- wl = b43_wireless_init(sdev);
-+ wl = b43_wireless_init(dev);
- if (IS_ERR(wl)) {
- err = PTR_ERR(wl);
- goto out;
---- a/drivers/net/wireless/b43/phy_common.c
-+++ b/drivers/net/wireless/b43/phy_common.c
-@@ -32,6 +32,7 @@
- #include "phy_n.h"
- #include "phy_lp.h"
- #include "phy_ht.h"
-+#include "phy_lcn.h"
- #include "b43.h"
- #include "main.h"
-
-@@ -65,6 +66,11 @@ int b43_phy_allocate(struct b43_wldev *d
- phy->ops = &b43_phyops_ht;
- #endif
- break;
-+ case B43_PHYTYPE_LCN:
-+#ifdef CONFIG_B43_PHY_LCN
-+ phy->ops = &b43_phyops_lcn;
-+#endif
-+ break;
- }
- if (B43_WARN_ON(!phy->ops))
- return -ENODEV;
---- a/drivers/net/wireless/b43/phy_common.h
-+++ b/drivers/net/wireless/b43/phy_common.h
-@@ -198,6 +198,7 @@ struct b43_phy_g;
- struct b43_phy_n;
- struct b43_phy_lp;
- struct b43_phy_ht;
-+struct b43_phy_lcn;
-
- struct b43_phy {
- /* Hardware operation callbacks. */
-@@ -222,6 +223,8 @@ struct b43_phy {
- struct b43_phy_lp *lp;
- /* HT-PHY specific information */
- struct b43_phy_ht *ht;
-+ /* LCN-PHY specific information */
-+ struct b43_phy_lcn *lcn;
- };
-
- /* Band support flags. */
---- a/drivers/net/wireless/b43/phy_ht.c
-+++ b/drivers/net/wireless/b43/phy_ht.c
-@@ -24,9 +24,14 @@
-
- #include "b43.h"
- #include "phy_ht.h"
-+#include "tables_phy_ht.h"
- #include "radio_2059.h"
- #include "main.h"
-
-+/**************************************************
-+ * Radio 2059.
-+ **************************************************/
-+
- static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
- const struct b43_phy_ht_channeltab_e_radio2059 *e)
- {
-@@ -56,7 +61,7 @@ static void b43_radio_2059_channel_setup
- b43_radio_write(dev, 0x98, e->radio_syn98);
-
- for (i = 0; i < 2; i++) {
-- routing = i ? 0x800 : 0x400;
-+ routing = i ? R2059_RXRX1 : R2059_TXRX0;
- b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
- b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
- b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
-@@ -78,11 +83,120 @@ static void b43_radio_2059_channel_setup
- udelay(300);
- }
-
-+static void b43_radio_2059_init(struct b43_wldev *dev)
-+{
-+ const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
-+ const u16 radio_values[3][2] = {
-+ { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
-+ };
-+ u16 i, j;
-+
-+ b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
-+ b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
-+
-+ for (i = 0; i < ARRAY_SIZE(routing); i++)
-+ b43_radio_set(dev, routing[i] | 0x146, 0x3);
-+
-+ b43_radio_set(dev, 0x2e, 0x0078);
-+ b43_radio_set(dev, 0xc0, 0x0080);
-+ msleep(2);
-+ b43_radio_mask(dev, 0x2e, ~0x0078);
-+ b43_radio_mask(dev, 0xc0, ~0x0080);
-+
-+ if (1) { /* FIXME */
-+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
-+ udelay(10);
-+ b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
-+ b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
-+
-+ b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
-+ udelay(100);
-+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
-+
-+ for (i = 0; i < 10000; i++) {
-+ if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
-+ i = 0;
-+ break;
-+ }
-+ udelay(100);
-+ }
-+ if (i)
-+ b43err(dev->wl, "radio 0x945 timeout\n");
-+
-+ b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
-+ b43_radio_set(dev, 0xa, 0x60);
-+
-+ for (i = 0; i < 3; i++) {
-+ b43_radio_write(dev, 0x17F, radio_values[i][0]);
-+ b43_radio_write(dev, 0x13D, 0x6E);
-+ b43_radio_write(dev, 0x13E, radio_values[i][1]);
-+ b43_radio_write(dev, 0x13C, 0x55);
-+
-+ for (j = 0; j < 10000; j++) {
-+ if (b43_radio_read(dev, 0x140) & 2) {
-+ j = 0;
-+ break;
-+ }
-+ udelay(500);
-+ }
-+ if (j)
-+ b43err(dev->wl, "radio 0x140 timeout\n");
-+
-+ b43_radio_write(dev, 0x13C, 0x15);
-+ }
-+
-+ b43_radio_mask(dev, 0x17F, ~0x1);
-+ }
-+
-+ b43_radio_mask(dev, 0x11, ~0x0008);
-+}
-+
-+/**************************************************
-+ * Channel switching ops.
-+ **************************************************/
-+
- static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
- const struct b43_phy_ht_channeltab_e_phy *e,
- struct ieee80211_channel *new_channel)
- {
-- /* TODO */
-+ bool old_band_5ghz;
-+ u8 i;
-+
-+ old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
-+ if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
-+ /* TODO */
-+ } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
-+ /* TODO */
-+ }
-+
-+ b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
-+ b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
-+ b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
-+ b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
-+ b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
-+ b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
-+
-+ /* TODO: some ops on PHY regs 0x0B0 and 0xC0A */
-+
-+ /* TODO: separated function? */
-+ for (i = 0; i < 3; i++) {
-+ u16 mask;
-+ u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
-+
-+ if (0) /* FIXME */
-+ mask = 0x2 << (i * 4);
-+ else
-+ mask = 0;
-+ b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
-+
-+ b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
-+ b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
-+ tmp & 0xFF);
-+ b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
-+ tmp & 0xFF);
-+ }
-+
-+ b43_phy_write(dev, 0x017e, 0x3830);
- }
-
- static int b43_phy_ht_set_channel(struct b43_wldev *dev,
-@@ -139,6 +253,13 @@ static void b43_phy_ht_op_prepare_struct
- memset(phy_ht, 0, sizeof(*phy_ht));
- }
-
-+static int b43_phy_ht_op_init(struct b43_wldev *dev)
-+{
-+ b43_phy_ht_tables_init(dev);
-+
-+ return 0;
-+}
-+
- static void b43_phy_ht_op_free(struct b43_wldev *dev)
- {
- struct b43_phy *phy = &dev->phy;
-@@ -155,13 +276,25 @@ static void b43_phy_ht_op_software_rfkil
- if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
- b43err(dev->wl, "MAC not suspended\n");
-
-+ /* In the following PHY ops we copy wl's dummy behaviour.
-+ * TODO: Find out if reads (currently hidden in masks/masksets) are
-+ * needed and replace following ops with just writes or w&r.
-+ * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can
-+ * cause delayed (!) machine lock up. */
- if (blocked) {
-- b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
-+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
- } else {
-- b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
-- b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1);
-- b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
-- b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2);
-+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
-+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1);
-+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
-+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2);
-+
-+ if (dev->phy.radio_ver == 0x2059)
-+ b43_radio_2059_init(dev);
-+ else
-+ B43_WARN_ON(1);
-+
-+ b43_switch_channel(dev, dev->phy.channel);
- }
- }
-
-@@ -203,7 +336,7 @@ static int b43_phy_ht_op_switch_channel(
- static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
- {
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-- return 1;
-+ return 11;
- return 36;
- }
-
-@@ -247,6 +380,16 @@ static void b43_phy_ht_op_radio_write(st
- b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
- }
-
-+static enum b43_txpwr_result
-+b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
-+{
-+ return B43_TXPWR_RES_DONE;
-+}
-+
-+static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
-+{
-+}
-+
- /**************************************************
- * PHY ops struct.
- **************************************************/
-@@ -255,9 +398,7 @@ const struct b43_phy_operations b43_phyo
- .allocate = b43_phy_ht_op_allocate,
- .free = b43_phy_ht_op_free,
- .prepare_structs = b43_phy_ht_op_prepare_structs,
-- /*
- .init = b43_phy_ht_op_init,
-- */
- .phy_read = b43_phy_ht_op_read,
- .phy_write = b43_phy_ht_op_write,
- .phy_maskset = b43_phy_ht_op_maskset,
-@@ -267,8 +408,6 @@ const struct b43_phy_operations b43_phyo
- .switch_analog = b43_phy_ht_op_switch_analog,
- .switch_channel = b43_phy_ht_op_switch_channel,
- .get_default_chan = b43_phy_ht_op_get_default_chan,
-- /*
- .recalc_txpower = b43_phy_ht_op_recalc_txpower,
- .adjust_txpower = b43_phy_ht_op_adjust_txpower,
-- */
- };
---- a/drivers/net/wireless/b43/phy_ht.h
-+++ b/drivers/net/wireless/b43/phy_ht.h
-@@ -4,9 +4,16 @@
- #include "phy_common.h"
-
-
-+#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
- #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */
- #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */
- #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */
-+#define B43_PHY_HT_BW1 0x1CE
-+#define B43_PHY_HT_BW2 0x1CF
-+#define B43_PHY_HT_BW3 0x1D0
-+#define B43_PHY_HT_BW4 0x1D1
-+#define B43_PHY_HT_BW5 0x1D2
-+#define B43_PHY_HT_BW6 0x1D3
-
- #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)
-
-@@ -20,7 +27,12 @@
-
- /* Values for PHY registers used on channel switching */
- struct b43_phy_ht_channeltab_e_phy {
-- /* TODO */
-+ u16 bw1;
-+ u16 bw2;
-+ u16 bw3;
-+ u16 bw4;
-+ u16 bw5;
-+ u16 bw6;
- };
-
-
---- /dev/null
-+++ b/drivers/net/wireless/b43/phy_lcn.c
-@@ -0,0 +1,52 @@
-+/*
-+
-+ Broadcom B43 wireless driver
-+ IEEE 802.11n LCN-PHY support
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING. If not, write to
-+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-+ Boston, MA 02110-1301, USA.
-+
-+*/
-+
-+#include <linux/slab.h>
-+
-+#include "b43.h"
-+#include "phy_lcn.h"
-+#include "tables_phy_lcn.h"
-+#include "main.h"
-+
-+/**************************************************
-+ * PHY ops struct.
-+ **************************************************/
-+
-+const struct b43_phy_operations b43_phyops_lcn = {
-+ /*
-+ .allocate = b43_phy_lcn_op_allocate,
-+ .free = b43_phy_lcn_op_free,
-+ .prepare_structs = b43_phy_lcn_op_prepare_structs,
-+ .init = b43_phy_lcn_op_init,
-+ .phy_read = b43_phy_lcn_op_read,
-+ .phy_write = b43_phy_lcn_op_write,
-+ .phy_maskset = b43_phy_lcn_op_maskset,
-+ .radio_read = b43_phy_lcn_op_radio_read,
-+ .radio_write = b43_phy_lcn_op_radio_write,
-+ .software_rfkill = b43_phy_lcn_op_software_rfkill,
-+ .switch_analog = b43_phy_lcn_op_switch_analog,
-+ .switch_channel = b43_phy_lcn_op_switch_channel,
-+ .get_default_chan = b43_phy_lcn_op_get_default_chan,
-+ .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
-+ .adjust_txpower = b43_phy_lcn_op_adjust_txpower,
-+ */
-+};
---- /dev/null
-+++ b/drivers/net/wireless/b43/phy_lcn.h
-@@ -0,0 +1,14 @@
-+#ifndef B43_PHY_LCN_H_
-+#define B43_PHY_LCN_H_
-+
-+#include "phy_common.h"
-+
-+
-+struct b43_phy_lcn {
-+};
-+
-+
-+struct b43_phy_operations;
-+extern const struct b43_phy_operations b43_phyops_lcn;
-+
-+#endif /* B43_PHY_LCN_H_ */
-\ No newline at end of file
---- a/drivers/net/wireless/b43/phy_n.c
-+++ b/drivers/net/wireless/b43/phy_n.c
-@@ -603,17 +603,33 @@ static void b43_nphy_tx_lp_fbw(struct b4
- /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
- static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
- {
-- u32 tmslow;
-+ u32 tmp;
-
- if (dev->phy.type != B43_PHYTYPE_N)
- return;
-
-- tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
-- if (force)
-- tmslow |= SSB_TMSLOW_FGC;
-- else
-- tmslow &= ~SSB_TMSLOW_FGC;
-- ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
-+ if (force)
-+ tmp |= BCMA_IOCTL_FGC;
-+ else
-+ tmp &= ~BCMA_IOCTL_FGC;
-+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
-+ if (force)
-+ tmp |= SSB_TMSLOW_FGC;
-+ else
-+ tmp &= ~SSB_TMSLOW_FGC;
-+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
-+ break;
-+#endif
-+ }
- }
-
- /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
-@@ -958,8 +974,21 @@ static void b43_nphy_superswitch_init(st
- b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
- b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
-
-- ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
-- 0xFC00);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
-+ 0xFC00, 0xFC00);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
-+ 0xFC00, 0xFC00);
-+ break;
-+#endif
-+ }
-+
- b43_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL) &
- ~B43_MACCTL_GPOUTSMSK);
-@@ -3600,7 +3629,20 @@ int b43_phy_initn(struct b43_wldev *dev)
- if ((dev->phy.rev >= 3) &&
- (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
- (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
-- chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
-+ BCMA_CC_CHIPCTL, 0x40);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ chipco_set32(&dev->dev->sdev->bus->chipco,
-+ SSB_CHIPCO_CHIPCTL, 0x40);
-+ break;
-+#endif
-+ }
- }
- nphy->deaf_count = 0;
- b43_nphy_tables_init(dev);
---- a/drivers/net/wireless/b43/radio_2059.c
-+++ b/drivers/net/wireless/b43/radio_2059.c
-@@ -23,8 +23,152 @@
- #include "b43.h"
- #include "radio_2059.h"
-
-+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
-+ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
-+ r20, r21, r22, r23, r24, r25, r26, r27, r28) \
-+ .radio_syn16 = r00, \
-+ .radio_syn17 = r01, \
-+ .radio_syn22 = r02, \
-+ .radio_syn25 = r03, \
-+ .radio_syn27 = r04, \
-+ .radio_syn28 = r05, \
-+ .radio_syn29 = r06, \
-+ .radio_syn2c = r07, \
-+ .radio_syn2d = r08, \
-+ .radio_syn37 = r09, \
-+ .radio_syn41 = r10, \
-+ .radio_syn43 = r11, \
-+ .radio_syn47 = r12, \
-+ .radio_syn4a = r13, \
-+ .radio_syn58 = r14, \
-+ .radio_syn5a = r15, \
-+ .radio_syn6a = r16, \
-+ .radio_syn6d = r17, \
-+ .radio_syn6e = r18, \
-+ .radio_syn92 = r19, \
-+ .radio_syn98 = r20, \
-+ .radio_rxtx4a = r21, \
-+ .radio_rxtx58 = r22, \
-+ .radio_rxtx5a = r23, \
-+ .radio_rxtx6a = r24, \
-+ .radio_rxtx6d = r25, \
-+ .radio_rxtx6e = r26, \
-+ .radio_rxtx92 = r27, \
-+ .radio_rxtx98 = r28
-+
-+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
-+ .phy_regs.bw1 = r0, \
-+ .phy_regs.bw2 = r1, \
-+ .phy_regs.bw3 = r2, \
-+ .phy_regs.bw4 = r3, \
-+ .phy_regs.bw5 = r4, \
-+ .phy_regs.bw6 = r5
-+
-+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
-+ { .freq = 2412,
-+ RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
-+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
-+ },
-+ { .freq = 2417,
-+ RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
-+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
-+ },
-+ { .freq = 2422,
-+ RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
-+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
-+ },
-+ { .freq = 2427,
-+ RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
-+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
-+ },
-+ { .freq = 2432,
-+ RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
-+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
-+ },
-+ { .freq = 2437,
-+ RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
-+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
-+ },
-+ { .freq = 2442,
-+ RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
-+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
-+ },
-+ { .freq = 2447,
-+ RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
-+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
-+ },
-+ { .freq = 2452,
-+ RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
-+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
-+ },
-+ { .freq = 2457,
-+ RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
-+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
-+ },
-+ { .freq = 2462,
-+ RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
-+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
-+ },
-+ { .freq = 2467,
-+ RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
-+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
-+ },
-+ { .freq = 2472,
-+ RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
-+ 0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
-+ 0x00, 0x00, 0x00, 0xf0, 0x00),
-+ PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
-+ },
-+};
-+
- const struct b43_phy_ht_channeltab_e_radio2059
- *b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
- {
-+ const struct b43_phy_ht_channeltab_e_radio2059 *e;
-+ unsigned int i;
-+
-+ e = b43_phy_ht_channeltab_radio2059;
-+ for (i = 0; i < ARRAY_SIZE(b43_phy_ht_channeltab_radio2059); i++, e++) {
-+ if (e->freq == freq)
-+ return e;
-+ }
-+
- return NULL;
- }
---- a/drivers/net/wireless/b43/radio_2059.h
-+++ b/drivers/net/wireless/b43/radio_2059.h
-@@ -5,6 +5,11 @@
-
- #include "phy_ht.h"
-
-+#define R2059_SYN 0x000
-+#define R2059_TXRX0 0x400
-+#define R2059_RXRX1 0x800
-+#define R2059_ALL 0xC00
-+
- /* Values for various registers uploaded on channel switching */
- struct b43_phy_ht_channeltab_e_radio2059 {
- /* The channel frequency in MHz */
---- /dev/null
-+++ b/drivers/net/wireless/b43/tables_phy_ht.c
-@@ -0,0 +1,750 @@
-+/*
-+
-+ Broadcom B43 wireless driver
-+ IEEE 802.11n HT-PHY data tables
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING. If not, write to
-+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-+ Boston, MA 02110-1301, USA.
-+
-+*/
-+
-+#include "b43.h"
-+#include "tables_phy_ht.h"
-+#include "phy_common.h"
-+#include "phy_ht.h"
-+
-+static const u16 b43_httab_0x12[] = {
-+ 0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
-+ 0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
-+ 0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
-+ 0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
-+ 0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
-+ 0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
-+ 0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
-+ 0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
-+ 0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
-+ 0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
-+ 0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
-+ 0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
-+ 0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
-+ 0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
-+ 0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
-+ 0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
-+ 0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
-+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
-+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
-+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
-+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
-+ 0x0007, 0x0007,
-+};
-+
-+static const u16 b43_httab_0x27[] = {
-+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
-+ 0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014,
-+ 0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e,
-+ 0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020,
-+ 0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a,
-+ 0x001d, 0x0020,
-+};
-+
-+static const u16 b43_httab_0x26[] = {
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000,
-+};
-+
-+static const u32 b43_httab_0x25[] = {
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+};
-+
-+static const u32 b43_httab_0x2f[] = {
-+ 0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f,
-+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
-+ 0x0001581f, 0x0001581f, 0x0001581f, 0x00035700,
-+ 0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f,
-+ 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
-+ 0x0001581f, 0x0001581f,
-+};
-+
-+static const u16 b43_httab_0x1a[] = {
-+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
-+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
-+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
-+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
-+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
-+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
-+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
-+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
-+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
-+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
-+ 0x000b, 0x0007, 0x0002, 0x00fd,
-+};
-+
-+static const u16 b43_httab_0x1b[] = {
-+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
-+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
-+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
-+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
-+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
-+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
-+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
-+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
-+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
-+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
-+ 0x000b, 0x0007, 0x0002, 0x00fd,
-+};
-+
-+static const u16 b43_httab_0x1c[] = {
-+ 0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052,
-+ 0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e,
-+ 0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a,
-+ 0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046,
-+ 0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040,
-+ 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a,
-+ 0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033,
-+ 0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b,
-+ 0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f,
-+ 0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e,
-+ 0x000b, 0x0007, 0x0002, 0x00fd,
-+};
-+
-+static const u32 b43_httab_0x1a_0xc0[] = {
-+ 0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
-+ 0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
-+ 0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
-+ 0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
-+ 0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
-+ 0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
-+ 0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
-+ 0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
-+ 0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
-+ 0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
-+ 0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
-+ 0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
-+ 0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
-+ 0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
-+ 0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
-+ 0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
-+ 0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
-+ 0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
-+ 0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
-+ 0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
-+ 0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
-+ 0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
-+ 0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
-+ 0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
-+ 0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
-+ 0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
-+ 0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
-+ 0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
-+ 0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
-+ 0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
-+ 0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
-+ 0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
-+};
-+
-+static const u32 b43_httab_0x1a_0x140[] = {
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+};
-+
-+static const u32 b43_httab_0x1b_0x140[] = {
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+};
-+
-+static const u32 b43_httab_0x1c_0x140[] = {
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-+};
-+
-+static const u16 b43_httab_0x1a_0x1c0[] = {
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000,
-+};
-+
-+static const u16 b43_httab_0x1b_0x1c0[] = {
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000,
-+};
-+
-+static const u16 b43_httab_0x1c_0x1c0[] = {
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-+ 0x0000, 0x0000,
-+};
-+
-+static const u16 b43_httab_0x1a_0x240[] = {
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6,
-+};
-+
-+static const u16 b43_httab_0x1b_0x240[] = {
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6,
-+};
-+
-+static const u16 b43_httab_0x1c_0x240[] = {
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036,
-+ 0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e,
-+ 0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e,
-+ 0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6,
-+ 0x01d6, 0x01d6,
-+};
-+
-+static const u32 b43_httab_0x1f[] = {
-+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
-+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
-+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
-+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
-+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
-+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
-+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
-+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
-+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
-+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
-+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
-+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
-+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
-+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
-+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
-+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
-+};
-+
-+static const u32 b43_httab_0x21[] = {
-+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
-+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
-+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
-+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
-+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
-+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
-+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
-+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
-+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
-+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
-+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
-+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
-+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
-+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
-+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
-+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
-+};
-+
-+static const u32 b43_httab_0x23[] = {
-+ 0x00000000, 0x00000000, 0x00016023, 0x00006028,
-+ 0x00034036, 0x0003402e, 0x0007203c, 0x0006e037,
-+ 0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d,
-+ 0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9,
-+ 0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9,
-+ 0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6,
-+ 0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c,
-+ 0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b,
-+ 0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15,
-+ 0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9,
-+ 0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87,
-+ 0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3,
-+ 0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa,
-+ 0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff,
-+ 0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff,
-+ 0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff,
-+};
-+
-+static const u32 b43_httab_0x20[] = {
-+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
-+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
-+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
-+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
-+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
-+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
-+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
-+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
-+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
-+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
-+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
-+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
-+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
-+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
-+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
-+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
-+};
-+
-+static const u32 b43_httab_0x22[] = {
-+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
-+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
-+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
-+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
-+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
-+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
-+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
-+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
-+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
-+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
-+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
-+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
-+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
-+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
-+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
-+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
-+};
-+
-+static const u32 b43_httab_0x24[] = {
-+ 0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035,
-+ 0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043,
-+ 0x07340047, 0x06d2004b, 0x067a004f, 0x06170054,
-+ 0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a,
-+ 0x04910070, 0x044c0077, 0x040f007e, 0x03d90085,
-+ 0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8,
-+ 0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3,
-+ 0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a,
-+ 0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e,
-+ 0x01720162, 0x015d0177, 0x0149018e, 0x013701a5,
-+ 0x012601be, 0x011501d8, 0x010601f4, 0x00f70212,
-+ 0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b,
-+ 0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348,
-+ 0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422,
-+ 0x00750460, 0x006e04a3, 0x006804e9, 0x00620533,
-+ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
-+};
-+
-+/**************************************************
-+ * R/W ops.
-+ **************************************************/
-+
-+u32 b43_httab_read(struct b43_wldev *dev, u32 offset)
-+{
-+ u32 type, value;
-+
-+ type = offset & B43_HTTAB_TYPEMASK;
-+ offset &= ~B43_HTTAB_TYPEMASK;
-+ B43_WARN_ON(offset > 0xFFFF);
-+
-+ switch (type) {
-+ case B43_HTTAB_8BIT:
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
-+ break;
-+ case B43_HTTAB_16BIT:
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
-+ break;
-+ case B43_HTTAB_32BIT:
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
-+ value <<= 16;
-+ value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ value = 0;
-+ }
-+
-+ return value;
-+}
-+
-+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
-+ unsigned int nr_elements, void *_data)
-+{
-+ u32 type;
-+ u8 *data = _data;
-+ unsigned int i;
-+
-+ type = offset & B43_HTTAB_TYPEMASK;
-+ offset &= ~B43_HTTAB_TYPEMASK;
-+ B43_WARN_ON(offset > 0xFFFF);
-+
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+
-+ for (i = 0; i < nr_elements; i++) {
-+ switch (type) {
-+ case B43_HTTAB_8BIT:
-+ *data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF;
-+ data++;
-+ break;
-+ case B43_HTTAB_16BIT:
-+ *((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
-+ data += 2;
-+ break;
-+ case B43_HTTAB_32BIT:
-+ *((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI);
-+ *((u32 *)data) <<= 16;
-+ *((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO);
-+ data += 4;
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ }
-+ }
-+}
-+
-+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
-+{
-+ u32 type;
-+
-+ type = offset & B43_HTTAB_TYPEMASK;
-+ offset &= 0xFFFF;
-+
-+ switch (type) {
-+ case B43_HTTAB_8BIT:
-+ B43_WARN_ON(value & ~0xFF);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
-+ break;
-+ case B43_HTTAB_16BIT:
-+ B43_WARN_ON(value & ~0xFFFF);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
-+ break;
-+ case B43_HTTAB_32BIT:
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF);
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ }
-+
-+ return;
-+}
-+
-+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
-+ unsigned int nr_elements, const void *_data)
-+{
-+ u32 type, value;
-+ const u8 *data = _data;
-+ unsigned int i;
-+
-+ type = offset & B43_HTTAB_TYPEMASK;
-+ offset &= ~B43_HTTAB_TYPEMASK;
-+ B43_WARN_ON(offset > 0xFFFF);
-+
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
-+
-+ for (i = 0; i < nr_elements; i++) {
-+ switch (type) {
-+ case B43_HTTAB_8BIT:
-+ value = *data;
-+ data++;
-+ B43_WARN_ON(value & ~0xFF);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
-+ break;
-+ case B43_HTTAB_16BIT:
-+ value = *((u16 *)data);
-+ data += 2;
-+ B43_WARN_ON(value & ~0xFFFF);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
-+ break;
-+ case B43_HTTAB_32BIT:
-+ value = *((u32 *)data);
-+ data += 4;
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16);
-+ b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
-+ value & 0xFFFF);
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ }
-+ }
-+}
-+
-+/**************************************************
-+ * Tables ops.
-+ **************************************************/
-+
-+#define httab_upload(dev, offset, data) do { \
-+ b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
-+ } while (0)
-+void b43_phy_ht_tables_init(struct b43_wldev *dev)
-+{
-+ httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
-+ httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
-+ httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
-+ httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25);
-+ httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f);
-+ httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a);
-+ httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b);
-+ httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c);
-+ httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0);
-+ httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140);
-+ httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140);
-+ httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140);
-+ httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0);
-+ httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0);
-+ httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0);
-+ httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240);
-+ httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240);
-+ httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240);
-+ httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f);
-+ httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21);
-+ httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23);
-+ httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20);
-+ httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22);
-+ httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24);
-+}
---- /dev/null
-+++ b/drivers/net/wireless/b43/tables_phy_ht.h
-@@ -0,0 +1,22 @@
-+#ifndef B43_TABLES_PHY_HT_H_
-+#define B43_TABLES_PHY_HT_H_
-+
-+/* The HT-PHY tables. */
-+#define B43_HTTAB_TYPEMASK 0xF0000000
-+#define B43_HTTAB_8BIT 0x10000000
-+#define B43_HTTAB_16BIT 0x20000000
-+#define B43_HTTAB_32BIT 0x30000000
-+#define B43_HTTAB8(table, offset) (((table) << 10) | (offset) | B43_HTTAB_8BIT)
-+#define B43_HTTAB16(table, offset) (((table) << 10) | (offset) | B43_HTTAB_16BIT)
-+#define B43_HTTAB32(table, offset) (((table) << 10) | (offset) | B43_HTTAB_32BIT)
-+
-+u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
-+void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
-+ unsigned int nr_elements, void *_data);
-+void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
-+void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
-+ unsigned int nr_elements, const void *_data);
-+
-+void b43_phy_ht_tables_init(struct b43_wldev *dev);
-+
-+#endif /* B43_TABLES_PHY_HT_H_ */
---- /dev/null
-+++ b/drivers/net/wireless/b43/tables_phy_lcn.c
-@@ -0,0 +1,34 @@
-+/*
-+
-+ Broadcom B43 wireless driver
-+ IEEE 802.11n LCN-PHY data tables
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING. If not, write to
-+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-+ Boston, MA 02110-1301, USA.
-+
-+*/
-+
-+#include "b43.h"
-+#include "tables_phy_lcn.h"
-+#include "phy_common.h"
-+#include "phy_lcn.h"
-+
-+/**************************************************
-+ * Tables ops.
-+ **************************************************/
-+
-+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
-+{
-+}
---- /dev/null
-+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
-@@ -0,0 +1,6 @@
-+#ifndef B43_TABLES_PHY_LCN_H_
-+#define B43_TABLES_PHY_LCN_H_
-+
-+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
-+
-+#endif /* B43_TABLES_PHY_LCN_H_ */
+++ /dev/null
-From f706821596d8a3dcda314c38b13d91f108fdc435 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Fri, 22 Jul 2011 17:10:29 +0200
-Subject: [PATCH 21/22] b43: read correct register on bcma bus.
-
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/net/wireless/b43/dma.c | 20 +++++++++++++++++---
- 1 files changed, 17 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/b43/dma.c
-+++ b/drivers/net/wireless/b43/dma.c
-@@ -795,9 +795,23 @@ static u64 supported_dma_mask(struct b43
- u32 tmp;
- u16 mmio_base;
-
-- tmp = b43_read32(dev, SSB_TMSHIGH);
-- if (tmp & SSB_TMSHIGH_DMA64)
-- return DMA_BIT_MASK(64);
-+ switch (dev->dev->bus_type) {
-+#ifdef CONFIG_B43_BCMA
-+ case B43_BUS_BCMA:
-+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
-+ if (tmp & BCMA_IOST_DMA64)
-+ return DMA_BIT_MASK(64);
-+ break;
-+#endif
-+#ifdef CONFIG_B43_SSB
-+ case B43_BUS_SSB:
-+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
-+ if (tmp & SSB_TMSHIGH_DMA64)
-+ return DMA_BIT_MASK(64);
-+ break;
-+#endif
-+ }
-+
- mmio_base = b43_dmacontroller_base(0, 0);
- b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
- tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
+++ /dev/null
-Fixes bug described in:\r
-https://bugzilla.kernel.org/show_bug.cgi?id=39172\r
-\r
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>\r
----\r
-John: this is trivial and fixes quite ugly memory (linked list exactly)\r
-corruption. I believe this fix should be taken for 3.1.\r
----\r
- drivers/net/wireless/b43/bus.c | 2 ++\r
- 1 files changed, 2 insertions(+), 0 deletions(-)\r
-\r
---- a/drivers/net/wireless/b43/bus.c
-+++ b/drivers/net/wireless/b43/bus.c
-@@ -244,10 +244,12 @@ void b43_bus_set_wldev(struct b43_bus_de
- #ifdef CONFIG_B43_BCMA
- case B43_BUS_BCMA:
- bcma_set_drvdata(dev->bdev, wldev);
-+ break;
- #endif
- #ifdef CONFIG_B43_SSB
- case B43_BUS_SSB:
- ssb_set_drvdata(dev->sdev, wldev);
-+ break;
- #endif
- }
- }
+++ /dev/null
-From 46c79b0cdc60a974da409d641a69086694046ea0 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Fri, 22 Jul 2011 17:47:46 +0200
-Subject: [PATCH 23/23] b43: add core rev 17 used on bcma SoC
-
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/net/wireless/b43/main.c | 1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
-
---- a/drivers/net/wireless/b43/main.c
-+++ b/drivers/net/wireless/b43/main.c
-@@ -120,6 +120,7 @@ MODULE_PARM_DESC(pio, "Use PIO accesses
-
- #ifdef CONFIG_B43_BCMA
- static const struct bcma_device_id b43_bcma_tbl[] = {
-+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
- BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
- BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
- BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+++ /dev/null
---- a/drivers/net/wireless/b43/main.c
-+++ b/drivers/net/wireless/b43/main.c
-@@ -326,6 +326,10 @@ static void b43_wireless_core_exit(struc
- static int b43_wireless_core_init(struct b43_wldev *dev);
- static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
- static int b43_wireless_core_start(struct b43_wldev *dev);
-+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_bss_conf *conf,
-+ u32 changed);
-
- static int b43_ratelimit(struct b43_wl *wl)
- {
-@@ -3762,14 +3766,24 @@ static int b43_op_config(struct ieee8021
- struct ieee80211_conf *conf = &hw->conf;
- int antenna;
- int err = 0;
-+ bool reload_bss = false;
-
- mutex_lock(&wl->mutex);
-
-+ dev = wl->current_dev;
-+
- /* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(wl, conf->channel);
- if (err)
- goto out_unlock_mutex;
-- dev = wl->current_dev;
-+
-+ /* Need to reload all settings if the core changed */
-+ if (dev != wl->current_dev) {
-+ dev = wl->current_dev;
-+ changed = ~0;
-+ reload_bss = true;
-+ }
-+
- phy = &dev->phy;
-
- if (conf_is_ht(conf))
-@@ -3830,6 +3844,9 @@ out_mac_enable:
- out_unlock_mutex:
- mutex_unlock(&wl->mutex);
-
-+ if (wl->vif && reload_bss)
-+ b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
-+
- return err;
- }
-
-@@ -3918,7 +3935,8 @@ static void b43_op_bss_info_changed(stru
- if (changed & BSS_CHANGED_BEACON_INT &&
- (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
- b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
-- b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
-+ b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
-+ conf->beacon_int)
- b43_set_beacon_int(dev, conf->beacon_int);
-
- if (changed & BSS_CHANGED_BASIC_RATES)
-@@ -4699,6 +4717,9 @@ static int b43_op_add_interface(struct i
- out_mutex_unlock:
- mutex_unlock(&wl->mutex);
-
-+ if (err == 0)
-+ b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
-+
- return err;
- }
-
-@@ -4769,6 +4790,9 @@ static int b43_op_start(struct ieee80211
- out_mutex_unlock:
- mutex_unlock(&wl->mutex);
-
-+ /* reload configuration */
-+ b43_op_config(hw, ~0);
-+
- return err;
- }
-
-@@ -4925,10 +4949,18 @@ out:
- if (err)
- wl->current_dev = NULL; /* Failed to init the dev. */
- mutex_unlock(&wl->mutex);
-- if (err)
-+
-+ if (err) {
- b43err(wl, "Controller restart FAILED\n");
-- else
-- b43info(wl, "Controller restarted\n");
-+ return;
-+ }
-+
-+ /* reload configuration */
-+ b43_op_config(wl->hw, ~0);
-+ if (wl->vif)
-+ b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
-+
-+ b43info(wl, "Controller restarted\n");
- }
-
- static int b43_setup_bands(struct b43_wldev *dev,