]> Git Repo - linux.git/commitdiff
Merge remote branch 'wireless-next/master' into ath6kl-next
authorKalle Valo <[email protected]>
Thu, 22 Sep 2011 07:33:13 +0000 (10:33 +0300)
committerKalle Valo <[email protected]>
Thu, 22 Sep 2011 07:33:13 +0000 (10:33 +0300)
251 files changed:
MAINTAINERS
drivers/bcma/driver_chipcommon_pmu.c
drivers/bcma/main.c
drivers/bcma/sprom.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bluetooth/btwilink.c
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/ani.h
drivers/net/wireless/ath/ath9k/ar5008_initvals.h
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9001_initvals.h
drivers/net/wireless/ath/ath9k/ar9002_calib.c
drivers/net/wireless/ath/ath9k/ar9002_hw.c
drivers/net/wireless/ath/ath9k/ar9002_initvals.h
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9480_1p0_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9480_2p0_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw-ops.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/bus.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_ht.c
drivers/net/wireless/b43/phy_lcn.c
drivers/net/wireless/b43/phy_lcn.h
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/b43/phy_n.h
drivers/net/wireless/b43/radio_2055.c
drivers/net/wireless/b43/radio_2056.c
drivers/net/wireless/b43/radio_2056.h
drivers/net/wireless/b43/radio_2059.c
drivers/net/wireless/b43/tables_nphy.c
drivers/net/wireless/b43/tables_phy_ht.c
drivers/net/wireless/b43/tables_phy_lcn.c
drivers/net/wireless/b43/tables_phy_lcn.h
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlegacy/iwl-3945-rs.c
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000-hw.h
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.c
drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c [deleted file]
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
drivers/net/wireless/iwlwifi/iwl-agn-tt.h
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-bus.h
drivers/net/wireless/iwlwifi/iwl-cfg.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-helpers.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/iwlwifi/iwl-pci.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-sta.h
drivers/net/wireless/iwlwifi/iwl-sv-open.c
drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c [deleted file]
drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c [deleted file]
drivers/net/wireless/iwlwifi/iwl-trans.c
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/libertas/if_usb.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800lib.h
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/rtl8192de/sw.c
drivers/net/wireless/rtlwifi/rtl8192de/trx.h
drivers/net/wireless/rtlwifi/rtl8192se/def.h
drivers/net/wireless/rtlwifi/rtl8192se/sw.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/wl1251/acx.c
drivers/net/wireless/wl1251/cmd.c
drivers/net/wireless/wl12xx/Kconfig
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/wl12xx.h
drivers/nfc/Kconfig
drivers/nfc/Makefile
drivers/nfc/nfcwilink.c [new file with mode: 0644]
drivers/nfc/pn533.c
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/ieee80211.h
include/linux/nfc.h
include/linux/nl80211.h
include/linux/ssb/ssb.h
include/net/cfg80211.h
include/net/mac80211.h
include/net/nfc.h [deleted file]
include/net/nfc/nci.h [new file with mode: 0644]
include/net/nfc/nci_core.h [new file with mode: 0644]
include/net/nfc/nfc.h [new file with mode: 0644]
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/bnep.h
net/bluetooth/bnep/core.c
net/bluetooth/cmtp/capi.c
net/bluetooth/cmtp/cmtp.h
net/bluetooth/cmtp/core.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/debugfs_netdev.c
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/spectmgmt.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wme.c
net/mac80211/wme.h
net/mac80211/work.c
net/nfc/Kconfig
net/nfc/Makefile
net/nfc/core.c
net/nfc/nci/Kconfig [new file with mode: 0644]
net/nfc/nci/Makefile [new file with mode: 0644]
net/nfc/nci/core.c [new file with mode: 0644]
net/nfc/nci/data.c [new file with mode: 0644]
net/nfc/nci/lib.c [new file with mode: 0644]
net/nfc/nci/ntf.c [new file with mode: 0644]
net/nfc/nci/rsp.c [new file with mode: 0644]
net/nfc/netlink.c
net/nfc/nfc.h
net/rfkill/core.c
net/rfkill/rfkill-regulator.c
net/wireless/core.c
net/wireless/core.h
net/wireless/lib80211_crypt_ccmp.c
net/wireless/lib80211_crypt_tkip.c
net/wireless/lib80211_crypt_wep.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c
net/wireless/sme.c
net/wireless/sysfs.c
net/wireless/util.c

index c66c093978d7fbf25bee751cfb39f9110dbb002a..1789ce22ea8c5f66bc92e2f1243a80c894fdbeb3 100644 (file)
@@ -1246,6 +1246,14 @@ W:       http://wireless.kernel.org/en/users/Drivers/ath5k
 S:     Maintained
 F:     drivers/net/wireless/ath/ath5k/
 
+ATHEROS ATH6KL WIRELESS DRIVER
+M:     Kalle Valo <[email protected]>
+L:     [email protected]
+W:     http://wireless.kernel.org/en/users/Drivers/ath6kl
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath6kl.git
+S:     Supported
+F:     drivers/net/wireless/ath/ath6kl/
+
 ATHEROS ATH9K WIRELESS DRIVER
 M:     "Luis R. Rodriguez" <[email protected]>
 M:     Jouni Malinen <[email protected]>
@@ -4500,7 +4508,7 @@ L:        [email protected]
 S:     Maintained
 F:     net/nfc/
 F:     include/linux/nfc.h
-F:     include/net/nfc.h
+F:     include/net/nfc/
 F:     drivers/nfc/
 
 NFS, SUNRPC, AND LOCKD CLIENTS
@@ -6122,12 +6130,6 @@ M:       Jakub Schmidtke <[email protected]>
 S:     Odd Fixes
 F:     drivers/staging/asus_oled/
 
-STAGING - ATHEROS ATH6KL WIRELESS DRIVER
-M:     Luis R. Rodriguez <[email protected]>
-M:     Naveen Singh <[email protected]>
-S:     Odd Fixes
-F:     drivers/staging/ath6kl/
-
 STAGING - COMEDI
 M:     Ian Abbott <[email protected]>
 M:     Mori Hess <[email protected]>
index 4bc10aa57bd425cf61cb0cb65f1e8f064b169e38..2968d809d49f8357cae15ef644cdd5a81cbe0a5a 100644 (file)
@@ -18,20 +18,40 @@ static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
        return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
 }
 
-static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
-                                       u32 offset, u32 mask, u32 set)
+void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
 {
-       u32 value;
+       bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+       bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+       bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
 
-       bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
+void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+                            u32 set)
+{
+       bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+       bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
+       bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
+
+void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
+                                u32 offset, u32 mask, u32 set)
+{
        bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
        bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
-       value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
-       value &= mask;
-       value |= set;
-       bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
-       bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
+       bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
+
+void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
+                               u32 set)
+{
+       bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
+       bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
+       bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
 
 static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
 {
index 7072216a2a3f02c2d41f426cb6f318a791c622b2..8c09c3e547cd1d305050d9885a6641c9b33dcd01 100644 (file)
@@ -15,6 +15,7 @@ MODULE_LICENSE("GPL");
 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
 static int bcma_device_probe(struct device *dev);
 static int bcma_device_remove(struct device *dev);
+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 
 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -49,6 +50,7 @@ static struct bus_type bcma_bus_type = {
        .match          = bcma_bus_match,
        .probe          = bcma_device_probe,
        .remove         = bcma_device_remove,
+       .uevent         = bcma_device_uevent,
        .dev_attrs      = bcma_device_attrs,
 };
 
@@ -295,6 +297,16 @@ static int bcma_device_remove(struct device *dev)
        return 0;
 }
 
+static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+
+       return add_uevent_var(env,
+                             "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
+                             core->id.manuf, core->id.id,
+                             core->id.rev, core->id.class);
+}
+
 static int __init bcma_modinit(void)
 {
        int err;
index 166ed13ec06685667aa00fe9cf381d08a2af71ed..d7292390d236dddf8a8979bf313d904762c76d70 100644 (file)
@@ -133,6 +133,15 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
                v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
                *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
        }
+
+       bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
+
+       bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
+       bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
+       bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
+       bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
+
+       bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
 }
 
 int bcma_sprom_get(struct bcma_bus *bus)
index a5854735bb2e7882124ad1dc2c1b9c9296c93820..db7cb8111fbe58a89f21ee6ccea50467356bd38a 100644 (file)
@@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = {
        /* Atheros AR3011 with sflash firmware*/
        { USB_DEVICE(0x0CF3, 0x3002) },
        { USB_DEVICE(0x13d3, 0x3304) },
+       { USB_DEVICE(0x0930, 0x0215) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
index 91d13a9e8c657f9b838c56ecbae6608965342bc0..9cbac6b445e1fa17a30d4924f3b384b08a115a4e 100644 (file)
@@ -72,9 +72,15 @@ static struct usb_device_id btusb_table[] = {
        /* Apple MacBookAir3,1, MacBookAir3,2 */
        { USB_DEVICE(0x05ac, 0x821b) },
 
+       /* Apple MacBookAir4,1 */
+       { USB_DEVICE(0x05ac, 0x821f) },
+
        /* Apple MacBookPro8,2 */
        { USB_DEVICE(0x05ac, 0x821a) },
 
+       /* Apple MacMini5,1 */
+       { USB_DEVICE(0x05ac, 0x8281) },
+
        /* AVM BlueFRITZ! USB v2.0 */
        { USB_DEVICE(0x057c, 0x3800) },
 
@@ -106,6 +112,7 @@ static struct usb_device_id blacklist_table[] = {
        /* Atheros 3011 with sflash firmware */
        { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
@@ -256,7 +263,9 @@ static void btusb_intr_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
@@ -341,7 +350,9 @@ static void btusb_bulk_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
@@ -431,7 +442,9 @@ static void btusb_isoc_complete(struct urb *urb)
 
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err < 0) {
-               if (err != -EPERM)
+               /* -EPERM: urb is being killed;
+                * -ENODEV: device got disconnected */
+               if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
                                                hdev->name, urb, -err);
                usb_unanchor_urb(urb);
index 65d27aff553ae1bdbef834ffc7145e6d9f1f656e..04d353f58d717ec7763d8aa853b434e644ea67af 100644 (file)
@@ -124,6 +124,13 @@ static long st_receive(void *priv_data, struct sk_buff *skb)
 /* ------- Interfaces to HCI layer ------ */
 /* protocol structure registered with shared transport */
 static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
+       {
+               .chnl_id = HCI_EVENT_PKT, /* HCI Events */
+               .hdr_len = sizeof(struct hci_event_hdr),
+               .offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
+               .len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
+               .reserve = 8,
+       },
        {
                .chnl_id = HCI_ACLDATA_PKT, /* ACL */
                .hdr_len = sizeof(struct hci_acl_hdr),
@@ -138,13 +145,6 @@ static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
                .len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */
                .reserve = 8,
        },
-       {
-               .chnl_id = HCI_EVENT_PKT, /* HCI Events */
-               .hdr_len = sizeof(struct hci_event_hdr),
-               .offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
-               .len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
-               .reserve = 8,
-       },
 };
 
 /* Called from HCI core to initialize the device */
@@ -240,7 +240,7 @@ static int ti_st_close(struct hci_dev *hdev)
        if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
                return 0;
 
-       for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+       for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
                err = st_unregister(&ti_st_proto[i]);
                if (err)
                        BT_ERR("st_unregister(%d) failed with error %d",
index 9891fb605a019bc8ff99b366d1f2aa933b9ebb44..4ed7f248a577a25ac198a8ad5a1dc50846b49457 100644 (file)
@@ -140,9 +140,6 @@ struct ath_common {
        u8 curbssid[ETH_ALEN];
        u8 bssidmask[ETH_ALEN];
 
-       u8 tx_chainmask;
-       u8 rx_chainmask;
-
        u32 rx_bufsize;
 
        u32 keymax;
index 108d55a0696514e52a4892df398b1cd9b7d914cc..e9ea38d0fff604359728103ad9051c5ba3e662a8 100644 (file)
@@ -1729,6 +1729,8 @@ ath5k_beacon_setup(struct ath5k_hw *ah, struct ath5k_buf *bf)
 
        if (dma_mapping_error(ah->dev, bf->skbaddr)) {
                ATH5K_ERR(ah, "beacon DMA mapping failed\n");
+               dev_kfree_skb_any(skb);
+               bf->skb = NULL;
                return -EIO;
        }
 
@@ -1813,8 +1815,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        ath5k_txbuf_free_skb(ah, avf->bbuf);
        avf->bbuf->skb = skb;
        ret = ath5k_beacon_setup(ah, avf->bbuf);
-       if (ret)
-               avf->bbuf->skb = NULL;
 out:
        return ret;
 }
@@ -1834,6 +1834,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
        struct ath5k_vif *avf;
        struct ath5k_buf *bf;
        struct sk_buff *skb;
+       int err;
 
        ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
@@ -1882,11 +1883,6 @@ ath5k_beacon_send(struct ath5k_hw *ah)
 
        avf = (void *)vif->drv_priv;
        bf = avf->bbuf;
-       if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
-                    ah->opmode == NL80211_IFTYPE_MONITOR)) {
-               ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
-               return;
-       }
 
        /*
         * Stop any current dma and put the new frame on the queue.
@@ -1900,8 +1896,17 @@ ath5k_beacon_send(struct ath5k_hw *ah)
 
        /* refresh the beacon for AP or MESH mode */
        if (ah->opmode == NL80211_IFTYPE_AP ||
-           ah->opmode == NL80211_IFTYPE_MESH_POINT)
-               ath5k_beacon_update(ah->hw, vif);
+           ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+               err = ath5k_beacon_update(ah->hw, vif);
+               if (err)
+                       return;
+       }
+
+       if (unlikely(bf->skb == NULL || ah->opmode == NL80211_IFTYPE_STATION ||
+                    ah->opmode == NL80211_IFTYPE_MONITOR)) {
+               ATH5K_WARN(ah, "bf=%p bf_skb=%p\n", bf, bf->skb);
+               return;
+       }
 
        trace_ath5k_tx(ah, bf->skb, &ah->txqs[ah->bhalq]);
 
index d969a11e342584f71be1abe9e9cceacd9d4ae026..01240d63896ed27d08c7948bc1b49e6f2e658370 100644 (file)
@@ -273,7 +273,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
                immunityLevel, aniState->noiseFloor,
                aniState->rssiThrLow, aniState->rssiThrHigh);
 
-       aniState->ofdmNoiseImmunityLevel = immunityLevel;
+       if (aniState->update_ani)
+               aniState->ofdmNoiseImmunityLevel = immunityLevel;
 
        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -346,7 +347,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
            immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
                immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
 
-       aniState->cckNoiseImmunityLevel = immunityLevel;
+       if (aniState->update_ani)
+               aniState->cckNoiseImmunityLevel = immunityLevel;
 
        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
@@ -593,6 +595,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
                                aniState->ofdmNoiseImmunityLevel,
                                aniState->cckNoiseImmunityLevel);
 
+                       aniState->update_ani = false;
                        ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
                        ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
                }
@@ -609,6 +612,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
                        aniState->ofdmNoiseImmunityLevel,
                        aniState->cckNoiseImmunityLevel);
 
+                       aniState->update_ani = true;
                        ath9k_hw_set_ofdm_nil(ah,
                                              aniState->ofdmNoiseImmunityLevel);
                        ath9k_hw_set_cck_nil(ah,
@@ -892,6 +896,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
                ani->ofdmWeakSigDetectOff =
                        !ATH9K_ANI_USE_OFDM_WEAK_SIG;
                ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+               ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+               ani->update_ani = false;
        }
 
        /*
index a547005572e7f4a7edcccf9957ab9b6aac53cabf..83029d6c7b2258ae1e59ca8a2483fbe85a4f26a8 100644 (file)
@@ -122,6 +122,7 @@ struct ar5416AniState {
        u8 firstepLevel;
        u8 ofdmWeakSigDetectOff;
        u8 cckWeakSigThreshold;
+       bool update_ani;
        u32 listenTime;
        int32_t rssiThrLow;
        int32_t rssiThrHigh;
index 234617c948a1d8589e4b1a56f30e758ffb597993..f81e7fc60a364b499dfc9fba0d5ea6483ee5aba5 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-static const u32 ar5416Modes[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
-       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
-       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
-       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
-       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
-       {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
-       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
-       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
-       {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
-       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
-       {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
-       {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
-       {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
-       {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
-       {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
-       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
-       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
-       {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
-       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
-       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
-       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
-       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
-       {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
-       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
-       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
-       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
-       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
-       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
-       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
-       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
-       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
-       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
-       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
-       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
+       {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+       {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
+       {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
+       {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
 static const u32 ar5416Common[][2] = {
@@ -668,6 +669,6 @@ static const u32 ar5416Addac[][2] = {
        {0x0000989c, 0x00000000},
        {0x0000989c, 0x00000000},
        {0x0000989c, 0x00000000},
-       {0x000098cc, 0x00000000},
+       {0x000098c4, 0x00000000},
 };
 
index fac2c6da6ca4d14986120e0c8079d27ac584fda1..0a749c8fa634830cbb90239e13ebc7ed8a343685 100644 (file)
@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
                REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
        }
 
-       if (!AR_SREV_5416_20_OR_LATER(ah) ||
-           AR_SREV_9280_20_OR_LATER(ah))
+       REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+       if (AR_SREV_9280_20_OR_LATER(ah))
                return;
        /*
         * Disable BB clock gating
@@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
 
        /* Write ADDAC shifts */
        REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-       ah->eep_ops->set_addac(ah, chan);
+       if (ah->eep_ops->set_addac)
+               ah->eep_ops->set_addac(ah, chan);
 
        if (AR_SREV_5416_22_OR_LATER(ah)) {
                REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
@@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(struct ath_hw *ah)
        }
 }
 
-static void ar5008_set_diversity(struct ath_hw *ah, bool value)
-{
-       u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
-       if (value)
-               v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       else
-               v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
-static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
-                                        struct ath9k_channel *chan)
-{
-       if (chan && IS_CHAN_5GHZ(chan))
-               return 0x1450;
-       return 0x1458;
-}
-
 static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
                                         struct ath9k_channel *chan)
 {
@@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
        priv_ops->rfbus_req = ar5008_hw_rfbus_req;
        priv_ops->rfbus_done = ar5008_hw_rfbus_done;
        priv_ops->restore_chainmask = ar5008_restore_chainmask;
-       priv_ops->set_diversity = ar5008_set_diversity;
        priv_ops->do_getnf = ar5008_hw_do_getnf;
        priv_ops->set_radar_params = ar5008_hw_set_radar_params;
 
@@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
        } else
                priv_ops->ani_control = ar5008_hw_ani_control_old;
 
-       if (AR_SREV_9100(ah))
-               priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
-       else if (AR_SREV_9160_10_OR_LATER(ah))
+       if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
                priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
        else
                priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
index 6d2e2f3303f9125db9f4b7b3fcf47388b61223c7..e8bdc75405f15df52bb84297916bd3b447a916d0 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-static const u32 ar5416Modes_9100[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
-       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
-       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
-       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
-       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
-       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
-       {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
-       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
-       {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204},
-       {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
-       {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e},
-       {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff},
-       {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
-       {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
-       {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
-       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
-       {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00},
-       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
-       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
-       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
-       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
-       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
-       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
-       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
-       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
-       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
-       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
-       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
-       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
-       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
-       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
-       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
-       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
-       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
-       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
-       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9100[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
+       {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+       {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
+       {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
+       {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+       {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
 static const u32 ar5416Common_9100[][2] = {
@@ -666,71 +667,72 @@ static const u32 ar5416Addac_9100[][2] = {
        {0x000098cc, 0x00000000},
 };
 
-static const u32 ar5416Modes_9160[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
-       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
-       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
-       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
-       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
-       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
-       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
-       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
-       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
-       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
-       {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
-       {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
-       {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
-       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
-       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
-       {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00},
-       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
-       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
-       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
-       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
-       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
-       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
-       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
-       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
-       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
-       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
-       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
-       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
-       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
-       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
-       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
-       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
-       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
-       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
-       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar5416Modes_9160[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
+       {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
+       {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+       {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+       {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+       {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
+       {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+       {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
+       {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
+       {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+       {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
+       {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
+       {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
+       {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
+       {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
+       {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
+       {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
+       {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
+       {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
+       {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
 static const u32 ar5416Common_9160[][2] = {
index 2d4c0910295bd39b08cb4abdc845c140d6bc22de..e0ab0657cc3a8808379ae0cc93e32e0863e13305 100644 (file)
@@ -41,7 +41,8 @@ static bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
        case ADC_DC_CAL:
                /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
                if (!IS_CHAN_B(chan) &&
-                   !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+                   !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
+                     IS_CHAN_HT20(chan)))
                        supported = true;
                break;
        }
@@ -868,6 +869,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
        ar9002_hw_pa_cal(ah, true);
 
        /* Do NF Calibration after DC offset and other calibrations */
+       ath9k_hw_loadnf(ah, chan);
        ath9k_hw_start_nfcal(ah, true);
 
        if (ah->caldata)
index b54ab78fb092231f16dc8f33039bad8f6f1f0435..626d547d2f0666f452a64be7ab6066ed495be1d7 100644 (file)
@@ -30,7 +30,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
 {
        if (AR_SREV_9271(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
-                              ARRAY_SIZE(ar9271Modes_9271), 6);
+                              ARRAY_SIZE(ar9271Modes_9271), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
                               ARRAY_SIZE(ar9271Common_9271), 2);
                INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
@@ -41,21 +41,21 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
                               ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
                INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
                               ar9271Modes_9271_1_0_only,
-                              ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
+                              ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
                INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
-                              ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
+                              ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
                INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
                               ar9271Modes_high_power_tx_gain_9271,
-                              ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
+                              ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
                INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
                               ar9271Modes_normal_power_tx_gain_9271,
-                              ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
+                              ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
                return;
        }
 
        if (AR_SREV_9287_11_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
-                               ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
+                               ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
                                ARRAY_SIZE(ar9287Common_9287_1_1), 2);
                if (ah->config.pcie_clock_req)
@@ -71,7 +71,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
 
 
                INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
-                              ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+                              ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
                               ARRAY_SIZE(ar9285Common_9285_1_2), 2);
 
@@ -87,7 +87,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
                }
        } else if (AR_SREV_9280_20_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
-                              ARRAY_SIZE(ar9280Modes_9280_2), 6);
+                              ARRAY_SIZE(ar9280Modes_9280_2), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
                               ARRAY_SIZE(ar9280Common_9280_2), 2);
 
@@ -105,7 +105,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
                               ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
        } else if (AR_SREV_9160_10_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
-                              ARRAY_SIZE(ar5416Modes_9160), 6);
+                              ARRAY_SIZE(ar5416Modes_9160), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
                               ARRAY_SIZE(ar5416Common_9160), 2);
                INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
@@ -134,7 +134,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
                }
        } else if (AR_SREV_9100_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
-                              ARRAY_SIZE(ar5416Modes_9100), 6);
+                              ARRAY_SIZE(ar5416Modes_9100), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
                               ARRAY_SIZE(ar5416Common_9100), 2);
                INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
@@ -157,7 +157,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
                               ARRAY_SIZE(ar5416Addac_9100), 2);
        } else {
                INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
-                              ARRAY_SIZE(ar5416Modes), 6);
+                              ARRAY_SIZE(ar5416Modes), 5);
                INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
                               ARRAY_SIZE(ar5416Common), 2);
                INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
@@ -207,19 +207,19 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
                if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
                        INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9280Modes_backoff_13db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
                else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
                        INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9280Modes_backoff_23db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
                else
                        INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
        } else {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
        }
 }
 
@@ -234,15 +234,15 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
                if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9280Modes_high_power_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
                else
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9280Modes_original_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+                       ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
        } else {
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                ar9280Modes_original_tx_gain_9280_2,
-               ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+               ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
        }
 }
 
@@ -251,14 +251,14 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
        if (AR_SREV_9287_11_OR_LATER(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                ar9287Modes_rx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
+               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
        else if (AR_SREV_9280_20(ah))
                ar9280_20_hw_init_rxgain_ini(ah);
 
        if (AR_SREV_9287_11_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                ar9287Modes_tx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
+               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
        } else if (AR_SREV_9280_20(ah)) {
                ar9280_20_hw_init_txgain_ini(ah);
        } else if (AR_SREV_9285_12_OR_LATER(ah)) {
@@ -270,24 +270,24 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
                                INIT_INI_ARRAY(&ah->iniModesTxGain,
                                ar9285Modes_XE2_0_high_power,
                                ARRAY_SIZE(
-                                 ar9285Modes_XE2_0_high_power), 6);
+                                 ar9285Modes_XE2_0_high_power), 5);
                        } else {
                                INIT_INI_ARRAY(&ah->iniModesTxGain,
                                ar9285Modes_high_power_tx_gain_9285_1_2,
                                ARRAY_SIZE(
-                                 ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+                                 ar9285Modes_high_power_tx_gain_9285_1_2), 5);
                        }
                } else {
                        if (AR_SREV_9285E_20(ah)) {
                                INIT_INI_ARRAY(&ah->iniModesTxGain,
                                ar9285Modes_XE2_0_normal_power,
                                ARRAY_SIZE(
-                                 ar9285Modes_XE2_0_normal_power), 6);
+                                 ar9285Modes_XE2_0_normal_power), 5);
                        } else {
                                INIT_INI_ARRAY(&ah->iniModesTxGain,
                                ar9285Modes_original_tx_gain_9285_1_2,
                                ARRAY_SIZE(
-                                 ar9285Modes_original_tx_gain_9285_1_2), 6);
+                                 ar9285Modes_original_tx_gain_9285_1_2), 5);
                        }
                }
        }
index 7573257731b6d7e865f97f50b2f41adbf860dec5..863db321070d7b31a8c390129ee7e33588a14cef 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-static const u32 ar9280Modes_9280_2[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
-       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
-       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e},
-       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
-       {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
-       {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
-       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
-       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
-       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
-       {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
-       {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
-       {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
-       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
-       {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
-       {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
-       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
-       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000},
-       {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000},
-       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
-       {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000},
-       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
+static const u32 ar9280Modes_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+       {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
+       {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b},
+       {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+       {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+       {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+       {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+       {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+       {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000},
+       {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+       {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000},
+       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
 };
 
 static const u32 ar9280Common_9280_2[][2] = {
@@ -424,471 +425,476 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
        {0x00009918, 0x0000000b, 0x00000016},
 };
 
-static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
-       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
-       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
-       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
-       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
-       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
-       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
-       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
-       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
-       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
-       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
-       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
-       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
-       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
-       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
-       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
-       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
-       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
-       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
-       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
-       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
-       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
-       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
-       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
-       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
-       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
-       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
-       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
-       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
-       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
-       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
-       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
-       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
-       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
-       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
-       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
-       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
-       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
-       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
-       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
-       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
-       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
-       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
-       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
-       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
-       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
-       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
-       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
-       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10},
-       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80, 0x00008b80},
-       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84, 0x00008b84},
-       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88, 0x00008b88},
-       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c, 0x00008b8c},
-       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90, 0x00008b90},
-       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94, 0x00008b94},
-       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98, 0x00008b98},
-       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4, 0x00008ba4},
-       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8, 0x00008ba8},
-       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac, 0x00008bac},
-       {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0, 0x00008bb0},
-       {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4, 0x00008bb4},
-       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1, 0x00008ba1},
-       {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5, 0x00008ba5},
-       {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9, 0x00008ba9},
-       {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad, 0x00008bad},
-       {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1, 0x00008bb1},
-       {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5, 0x00008bb5},
-       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2, 0x00008ba2},
-       {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6, 0x00008ba6},
-       {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa, 0x00008baa},
-       {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae, 0x00008bae},
-       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2, 0x00008bb2},
-       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6, 0x00008bb6},
-       {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3, 0x00008ba3},
-       {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7, 0x00008ba7},
-       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab, 0x00008bab},
-       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf, 0x00008baf},
-       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3, 0x00008bb3},
-       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7, 0x00008bb7},
-       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3, 0x00008bc3},
-       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7, 0x00008bc7},
-       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb, 0x00008bcb},
-       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf, 0x00008bcf},
-       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3, 0x00008bd3},
-       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7, 0x00008bd7},
-       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb, 0x00008bdb},
-       {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
-       {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055},
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b80, 0x00008b80},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b84, 0x00008b84},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b88, 0x00008b88},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b8c, 0x00008b8c},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b90, 0x00008b90},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b94, 0x00008b94},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008b98, 0x00008b98},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008ba4, 0x00008ba4},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008ba8, 0x00008ba8},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00008bac, 0x00008bac},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00008bb0, 0x00008bb0},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00008bb4, 0x00008bb4},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008ba1, 0x00008ba1},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00008ba5, 0x00008ba5},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x00008ba9, 0x00008ba9},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x00008bad, 0x00008bad},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x00008bb1, 0x00008bb1},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00008bb5, 0x00008bb5},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008ba2, 0x00008ba2},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00008ba6, 0x00008ba6},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x00008baa, 0x00008baa},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00008bae, 0x00008bae},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00008bb2, 0x00008bb2},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008bb6, 0x00008bb6},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x00008ba3, 0x00008ba3},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x00008ba7, 0x00008ba7},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008bab, 0x00008bab},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008baf, 0x00008baf},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008bb3, 0x00008bb3},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008bb7, 0x00008bb7},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008bc3, 0x00008bc3},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008bc7, 0x00008bc7},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008bcb, 0x00008bcb},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008bcf, 0x00008bcf},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008bd3, 0x00008bd3},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008bd7, 0x00008bd7},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008bdb, 0x00008bdb},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008bdb, 0x00008bdb},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008bdb, 0x00008bdb},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008bdb, 0x00008bdb},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008bdb, 0x00008bdb},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008bdb, 0x00008bdb},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008bdb, 0x00008bdb},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008bdb, 0x00008bdb},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008bdb, 0x00008bdb},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008bdb, 0x00008bdb},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008bdb, 0x00008bdb},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008bdb, 0x00008bdb},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008bdb, 0x00008bdb},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008bdb, 0x00008bdb},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008bdb, 0x00008bdb},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008bdb, 0x00008bdb},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008bdb, 0x00008bdb},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008bdb, 0x00008bdb},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055},
 };
 
-static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
-       {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
-       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
-       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
-       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
-       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
-       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
-       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
-       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
-       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
-       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
-       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
-       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
-       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
-       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
-       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
-       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
-       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
-       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
-       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
-       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
-       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
-       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
-       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
-       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
-       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
-       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
-       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
-       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
-       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
-       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
-       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
-       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
-       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
-       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
-       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
-       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
-       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
-       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
-       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
-       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
-       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
-       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
-       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
-       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
-       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
-       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
-       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
-       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
-       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
-       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
-       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
-       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
-       {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c},
-       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310},
-       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384},
-       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388},
-       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324},
-       {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704},
-       {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4},
-       {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8},
-       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710},
-       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714},
-       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720},
-       {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724},
-       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728},
-       {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c},
-       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0},
-       {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4},
-       {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8},
-       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0},
-       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4},
-       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8},
-       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5},
-       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9},
-       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad},
-       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1},
-       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5},
-       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9},
-       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5},
-       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9},
-       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1},
-       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5},
-       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9},
-       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6},
-       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca},
-       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce},
-       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2},
-       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6},
-       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3},
-       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7},
-       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb},
-       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf},
-       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7},
-       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db},
-       {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
-       {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063},
+static const u32 ar9280Modes_original_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00008000, 0x00008000},
+       {0x00009a10, 0x00008194, 0x00008194, 0x00008000, 0x00008000},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063},
 };
 
-static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
-       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290},
-       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300},
-       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304},
-       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308},
-       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c},
-       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000},
-       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004},
-       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008},
-       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c},
-       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080},
-       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084},
-       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088},
-       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c},
-       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100},
-       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104},
-       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108},
-       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c},
-       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110},
-       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114},
-       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180},
-       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184},
-       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188},
-       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c},
-       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190},
-       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194},
-       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0},
-       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c},
-       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8},
-       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284},
-       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288},
-       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224},
-       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290},
-       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300},
-       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304},
-       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308},
-       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c},
-       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380},
-       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384},
-       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700},
-       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704},
-       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708},
-       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c},
-       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780},
-       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784},
-       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00},
-       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04},
-       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08},
-       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c},
-       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80},
-       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84},
-       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88},
-       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c},
-       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90},
-       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80},
-       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84},
-       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88},
-       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c},
-       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90},
-       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310},
-       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314},
-       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320},
-       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324},
-       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328},
-       {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c},
-       {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330},
-       {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334},
-       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321},
-       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325},
-       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329},
-       {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d},
-       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331},
-       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335},
-       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322},
-       {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326},
-       {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a},
-       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e},
-       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332},
-       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336},
-       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323},
-       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327},
-       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b},
-       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f},
-       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333},
-       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337},
-       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343},
-       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347},
-       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b},
-       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f},
-       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353},
-       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357},
-       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b},
-       {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
-       {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a},
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290},
+       {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300},
+       {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304},
+       {0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308},
+       {0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c},
+       {0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000},
+       {0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004},
+       {0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008},
+       {0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c},
+       {0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080},
+       {0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084},
+       {0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088},
+       {0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c},
+       {0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100},
+       {0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104},
+       {0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108},
+       {0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c},
+       {0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110},
+       {0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114},
+       {0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180},
+       {0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184},
+       {0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188},
+       {0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c},
+       {0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190},
+       {0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194},
+       {0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0},
+       {0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c},
+       {0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8},
+       {0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284},
+       {0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288},
+       {0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224},
+       {0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290},
+       {0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300},
+       {0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304},
+       {0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308},
+       {0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c},
+       {0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380},
+       {0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384},
+       {0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700},
+       {0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704},
+       {0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708},
+       {0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c},
+       {0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780},
+       {0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784},
+       {0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00},
+       {0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04},
+       {0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08},
+       {0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c},
+       {0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80},
+       {0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84},
+       {0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88},
+       {0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c},
+       {0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90},
+       {0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80},
+       {0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84},
+       {0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88},
+       {0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c},
+       {0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90},
+       {0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310},
+       {0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314},
+       {0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320},
+       {0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324},
+       {0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328},
+       {0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c},
+       {0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330},
+       {0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334},
+       {0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321},
+       {0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325},
+       {0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329},
+       {0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d},
+       {0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331},
+       {0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335},
+       {0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322},
+       {0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326},
+       {0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a},
+       {0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e},
+       {0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332},
+       {0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336},
+       {0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323},
+       {0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327},
+       {0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b},
+       {0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f},
+       {0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333},
+       {0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337},
+       {0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343},
+       {0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347},
+       {0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b},
+       {0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f},
+       {0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353},
+       {0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357},
+       {0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b},
+       {0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b},
+       {0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b},
+       {0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b},
+       {0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b},
+       {0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b},
+       {0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b},
+       {0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b},
+       {0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b},
+       {0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b},
+       {0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b},
+       {0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b},
+       {0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b},
+       {0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
+       {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a},
 };
 
-static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
-       {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
-       {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002},
-       {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008},
-       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010},
-       {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012},
-       {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014},
-       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a},
-       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211},
-       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
-       {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411},
-       {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413},
-       {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811},
-       {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813},
-       {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14},
-       {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50},
-       {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c},
-       {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a},
-       {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92},
-       {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2},
-       {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5},
-       {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54},
-       {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5},
-       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
-       {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
-       {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
-       {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
-       {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
-       {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
-       {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652},
+       {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce},
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002},
+       {0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008},
+       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010},
+       {0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012},
+       {0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014},
+       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a},
+       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211},
+       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+       {0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411},
+       {0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413},
+       {0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811},
+       {0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813},
+       {0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14},
+       {0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50},
+       {0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c},
+       {0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a},
+       {0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92},
+       {0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2},
+       {0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5},
+       {0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54},
+       {0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5},
+       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+       {0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+       {0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff},
+       {0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+       {0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000},
+       {0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
+       {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480},
 };
 
-static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
-       {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652},
-       {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
-       {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009},
-       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b},
-       {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
-       {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048},
-       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a},
-       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211},
-       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213},
-       {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b},
-       {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412},
-       {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414},
-       {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a},
-       {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649},
-       {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b},
-       {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49},
-       {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48},
-       {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a},
-       {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88},
-       {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a},
-       {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9},
-       {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42},
-       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
-       {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
-       {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
-       {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
-       {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
-       {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
-       {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652},
+       {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce},
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002},
+       {0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009},
+       {0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b},
+       {0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012},
+       {0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048},
+       {0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a},
+       {0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211},
+       {0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213},
+       {0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b},
+       {0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412},
+       {0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414},
+       {0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a},
+       {0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649},
+       {0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b},
+       {0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49},
+       {0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48},
+       {0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a},
+       {0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88},
+       {0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a},
+       {0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9},
+       {0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42},
+       {0x0000a3ec, 0x00f70081, 0x00f70081, 0x00f70081, 0x00f70081},
+       {0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+       {0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff},
+       {0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+       {0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000},
+       {0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
+       {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
 };
 
 static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
@@ -947,309 +953,310 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = {
        {0x00004044, 0x00000000},
 };
 
-static const u32 ar9285Modes_9285_1_2[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
-       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
-       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
-       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
-       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
-       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
-       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
-       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18},
-       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
-       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
-       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
-       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
-       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
-       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
-       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
-       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
-       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
-       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
-       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
-       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
-       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
-       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
-       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
-       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
-       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
-       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
-       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
-       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
-       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
-       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
-       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
-       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
-       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
-       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
-       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
-       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
-       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
-       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
-       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
-       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
-       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
-       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
-       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
-       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
-       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
-       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
-       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
-       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
-       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
-       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
-       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
-       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
-       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
-       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
-       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
-       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
-       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
-       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
-       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
-       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
-       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
-       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
-       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
-       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
-       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
-       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
-       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
-       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
-       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
-       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
-       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
-       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
-       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
-       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
-       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
-       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
-       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
-       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
-       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
-       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
-       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
-       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
-       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
-       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
-       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
-       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
-       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
-       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
-       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
-       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
-       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
-       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
-       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
-       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
-       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
-       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
-       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
-       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
-       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
-       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
-       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
-       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
-       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
-       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
-       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
-       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
-       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
-       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
-       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
-       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
-       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
-       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
-       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
-       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
-       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
-       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
-       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
-       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
-       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
-       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
-       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
-       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
-       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
-       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
-       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
-       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
-       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
-       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
-       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
-       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
-       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
-       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
-       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
-       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
-       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
-       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
-       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
-       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
-       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
-       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
-       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
-       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
-       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
-       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
-       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
-       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
-       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
-       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
-       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
-       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
-       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
-       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
-       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
-       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
-       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
-       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
-       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
-       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
-       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
-       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
-       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
-       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
-       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
-       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
-       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
-       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
-       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
-       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
-       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
-       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
-       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
-       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
-       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
-       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
-       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
-       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
-       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
-       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
-       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
-       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
-       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
-       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
-       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
-       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
-       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
-       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
-       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
-       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
-       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
-       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
-       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
-       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
-       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
-       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
-       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
-       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
-       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9285Modes_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20},
+       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
 };
 
 static const u32 ar9285Common_9285_1_2[][2] = {
@@ -1572,164 +1579,168 @@ static const u32 ar9285Common_9285_1_2[][2] = {
        {0x00007870, 0x10142c00},
 };
 
-static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
-       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
-       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
-       {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
-       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
-       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
-       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
-       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
-       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
-       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
-       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+       {0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803},
+       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
 };
 
-static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
-       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
-       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
-       {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
-       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
-       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
-       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
-       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
-       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
-       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
-       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
-       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_original_tx_gain_9285_1_2[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8},
+       {0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b},
+       {0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e},
+       {0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801},
+       {0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe},
+       {0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
 };
 
-static const u32 ar9285Modes_XE2_0_normal_power[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
-       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
-       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae},
-       {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
-       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
-       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
-       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
-       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
-       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652},
-       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
-       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
-       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
-       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+static const u32 ar9285Modes_XE2_0_normal_power[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f},
+       {0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+       {0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441},
+       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652},
+       {0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c},
+       {0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
+       {0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c},
+       {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c},
 };
 
-static const u32 ar9285Modes_XE2_0_high_power[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
-       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b},
-       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
-       {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
-       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
-       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
-       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
-       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652},
-       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
-       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
-       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+static const u32 ar9285Modes_XE2_0_high_power[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8},
+       {0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b},
+       {0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e},
+       {0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443},
+       {0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe},
+       {0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c},
+       {0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7},
+       {0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
+       {0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7},
 };
 
 static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
@@ -1760,50 +1771,51 @@ static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
        {0x00004044, 0x00000000},
 };
 
-static const u32 ar9287Modes_9287_1_1[][6] = {
-       {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
-       {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
-       {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a},
-       {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880},
-       {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e},
-       {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001},
-       {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e},
-       {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0},
-       {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
-       {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e},
-       {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18},
-       {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881},
-       {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
-       {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010},
-       {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
-       {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010},
-       {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210},
-       {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce},
-       {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c},
-       {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444},
-       {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000},
-       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
-       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+static const u32 ar9287Modes_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300},
+       {0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200},
+       {0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001},
+       {0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0},
+       {0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2},
+       {0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e},
+       {0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20},
+       {0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881},
+       {0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898},
+       {0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d},
+       {0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+       {0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210},
+       {0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce},
+       {0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c},
+       {0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4},
+       {0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444},
+       {0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
+       {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
 static const u32 ar9287Common_9287_1_1[][2] = {
@@ -2189,313 +2201,315 @@ static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = {
        {0x0000a1fc, 0xca9228ee},
 };
 
-static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a},
-       {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b},
-       {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a},
-       {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a},
-       {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a},
-       {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
-       {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a},
-       {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a},
-       {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c},
-       {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc},
-       {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4},
-       {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc},
-       {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede},
-       {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
-       {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e},
-       {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e},
-       {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062},
-       {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064},
-       {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4},
-       {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa},
-       {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac},
-       {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4},
-       {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4},
-       {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134},
-       {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174},
-       {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c},
-       {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e},
-       {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be},
-       {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe},
-       {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000},
+static const u32 ar9287Modes_tx_gain_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b},
+       {0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a},
+       {0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a},
+       {0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a},
+       {0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c},
+       {0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc},
+       {0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4},
+       {0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc},
+       {0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede},
+       {0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e},
+       {0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e},
+       {0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e},
+       {0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062},
+       {0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064},
+       {0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4},
+       {0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa},
+       {0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac},
+       {0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4},
+       {0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4},
+       {0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134},
+       {0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174},
+       {0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c},
+       {0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e},
+       {0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be},
+       {0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe},
+       {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000},
 };
 
-static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = {
-       {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
-       {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
-       {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
-       {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
-       {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
-       {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
-       {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
-       {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
-       {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
-       {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
-       {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
-       {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
-       {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
-       {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
-       {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
-       {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
-       {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
-       {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
-       {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
-       {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
-       {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
-       {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
-       {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
-       {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
-       {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
-       {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
-       {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
-       {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
-       {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
-       {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
-       {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
-       {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
-       {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
-       {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
-       {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
-       {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
-       {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
-       {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
-       {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
-       {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
-       {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
-       {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
-       {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
-       {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
-       {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
-       {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
-       {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
-       {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
-       {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
-       {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
-       {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
-       {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
-       {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
-       {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
-       {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
-       {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
-       {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
-       {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
-       {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
-       {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
-       {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
-       {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
-       {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
-       {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
-       {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
-       {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
-       {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
-       {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
-       {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
-       {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
-       {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
-       {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
-       {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
-       {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
-       {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
-       {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
-       {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
-       {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
-       {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
-       {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
-       {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
-       {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
-       {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
-       {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
-       {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
-       {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
-       {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
-       {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
-       {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
-       {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
-       {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
-       {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
-       {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
-       {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
-       {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
-       {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
-       {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
-       {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
-       {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
-       {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
-       {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
-       {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
-       {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
-       {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120},
-       {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124},
-       {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128},
-       {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c},
-       {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130},
-       {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194},
-       {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198},
-       {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c},
-       {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210},
-       {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284},
-       {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288},
-       {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c},
-       {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290},
-       {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294},
-       {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0},
-       {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4},
-       {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8},
-       {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac},
-       {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0},
-       {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4},
-       {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8},
-       {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4},
-       {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708},
-       {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c},
-       {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710},
-       {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04},
-       {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08},
-       {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c},
-       {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10},
-       {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14},
-       {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18},
-       {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c},
-       {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90},
-       {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94},
-       {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98},
-       {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4},
-       {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8},
-       {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04},
-       {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08},
-       {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c},
-       {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10},
-       {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14},
-       {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18},
-       {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c},
-       {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90},
-       {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18},
-       {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24},
-       {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28},
-       {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314},
-       {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318},
-       {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c},
-       {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390},
-       {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394},
-       {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398},
-       {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4},
-       {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8},
-       {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac},
-       {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0},
-       {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380},
-       {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384},
-       {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388},
-       {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710},
-       {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714},
-       {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718},
-       {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10},
-       {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14},
-       {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18},
-       {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c},
-       {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90},
-       {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94},
-       {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c},
-       {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90},
-       {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94},
-       {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0},
-       {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4},
-       {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8},
-       {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac},
-       {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0},
-       {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4},
-       {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1},
-       {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5},
-       {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9},
-       {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad},
-       {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1},
-       {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5},
-       {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9},
-       {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5},
-       {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9},
-       {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd},
-       {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1},
-       {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5},
-       {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2},
-       {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6},
-       {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca},
-       {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce},
-       {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2},
-       {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6},
-       {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda},
-       {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7},
-       {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb},
-       {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf},
-       {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3},
-       {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7},
-       {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb},
-       {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
-       {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067},
+static const u32 ar9287Modes_rx_gain_9287_1_1[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+       {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+       {0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+       {0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+       {0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+       {0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+       {0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+       {0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+       {0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+       {0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+       {0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+       {0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+       {0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+       {0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+       {0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+       {0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+       {0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+       {0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+       {0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+       {0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+       {0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+       {0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+       {0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+       {0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+       {0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+       {0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+       {0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+       {0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+       {0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+       {0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+       {0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+       {0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+       {0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+       {0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+       {0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+       {0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+       {0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+       {0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+       {0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+       {0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+       {0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+       {0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+       {0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+       {0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+       {0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+       {0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+       {0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+       {0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+       {0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+       {0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+       {0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+       {0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+       {0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+       {0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+       {0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+       {0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+       {0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+       {0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+       {0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+       {0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+       {0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+       {0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb},
+       {0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
+       {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067},
 };
 
 static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {
@@ -2526,310 +2540,311 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
        {0x00004044, 0x00000000},
 };
 
-static const u32 ar9271Modes_9271[][6] = {
-       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
-       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
-       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
-       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
-       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
-       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
-       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
-       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
-       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
-       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
-       {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
-       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
-       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
-       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0},
-       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
-       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059},
-       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
-       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
-       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
-       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
-       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
-       {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
-       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
-       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
-       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
-       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010},
-       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
-       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
-       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
-       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
-       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
-       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
-       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
-       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
-       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
-       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
-       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
-       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
-       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
-       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
-       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
-       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
-       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
-       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
-       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
-       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
-       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
-       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
-       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
-       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
-       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
-       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
-       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
-       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
-       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
-       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
-       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
-       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
-       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
-       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
-       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
-       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
-       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
-       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
-       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
-       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
-       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
-       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
-       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
-       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
-       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
-       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
-       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
-       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
-       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
-       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
-       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
-       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
-       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
-       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
-       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
-       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
-       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
-       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
-       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
-       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
-       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
-       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
-       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
-       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
-       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
-       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
-       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
-       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
-       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
-       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
-       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
-       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
-       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
-       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
-       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
-       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
-       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
-       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
-       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
-       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
-       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
-       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
-       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
-       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
-       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
-       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
-       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
-       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
-       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
-       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
-       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
-       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
-       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
-       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
-       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000},
-       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000},
-       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000},
-       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000},
-       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000},
-       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000},
-       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000},
-       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000},
-       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000},
-       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000},
-       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000},
-       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000},
-       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000},
-       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000},
-       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000},
-       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000},
-       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000},
-       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000},
-       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000},
-       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000},
-       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000},
-       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000},
-       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000},
-       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000},
-       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000},
-       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000},
-       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000},
-       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000},
-       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000},
-       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000},
-       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000},
-       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000},
-       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000},
-       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000},
-       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000},
-       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000},
-       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000},
-       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000},
-       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000},
-       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000},
-       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000},
-       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000},
-       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000},
-       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000},
-       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000},
-       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000},
-       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000},
-       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000},
-       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000},
-       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000},
-       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000},
-       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000},
-       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000},
-       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000},
-       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000},
-       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000},
-       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000},
-       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000},
-       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000},
-       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000},
-       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000},
-       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000},
-       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000},
-       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000},
-       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000},
-       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000},
-       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000},
-       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000},
-       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000},
-       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000},
-       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000},
-       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000},
-       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000},
-       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000},
-       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000},
-       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000},
-       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000},
-       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000},
-       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000},
-       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000},
-       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000},
-       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000},
-       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000},
-       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000},
-       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000},
-       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000},
-       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000},
-       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000},
-       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000},
-       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000},
-       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
-       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
-       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000},
-       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
-       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
-       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000},
-       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+static const u32 ar9271Modes_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+       {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
+       {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001},
+       {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+       {0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e},
+       {0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620},
+       {0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053},
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
+       {0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310},
+       {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020},
+       {0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c},
+       {0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+       {0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f},
+       {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+       {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+       {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084},
+       {0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088},
+       {0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c},
+       {0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100},
+       {0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104},
+       {0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108},
+       {0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c},
+       {0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110},
+       {0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114},
+       {0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180},
+       {0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184},
+       {0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188},
+       {0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c},
+       {0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190},
+       {0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194},
+       {0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0},
+       {0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c},
+       {0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8},
+       {0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284},
+       {0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288},
+       {0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224},
+       {0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290},
+       {0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300},
+       {0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304},
+       {0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308},
+       {0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c},
+       {0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380},
+       {0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384},
+       {0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700},
+       {0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704},
+       {0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708},
+       {0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c},
+       {0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780},
+       {0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784},
+       {0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00},
+       {0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04},
+       {0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08},
+       {0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c},
+       {0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80},
+       {0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84},
+       {0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88},
+       {0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c},
+       {0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90},
+       {0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80},
+       {0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84},
+       {0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88},
+       {0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c},
+       {0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90},
+       {0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c},
+       {0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310},
+       {0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384},
+       {0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388},
+       {0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324},
+       {0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704},
+       {0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4},
+       {0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8},
+       {0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710},
+       {0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714},
+       {0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720},
+       {0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724},
+       {0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728},
+       {0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c},
+       {0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0},
+       {0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4},
+       {0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8},
+       {0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0},
+       {0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4},
+       {0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8},
+       {0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5},
+       {0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9},
+       {0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad},
+       {0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1},
+       {0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5},
+       {0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9},
+       {0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5},
+       {0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9},
+       {0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1},
+       {0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5},
+       {0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9},
+       {0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6},
+       {0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca},
+       {0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce},
+       {0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2},
+       {0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6},
+       {0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3},
+       {0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7},
+       {0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb},
+       {0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf},
+       {0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7},
+       {0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db},
+       {0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004},
+       {0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000},
+       {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+       {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000},
+       {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e},
 };
 
 static const u32 ar9271Common_9271[][2] = {
@@ -3175,91 +3190,95 @@ static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = {
        {0x0000a1fc, 0xca9228ee},
 };
 
-static const u32 ar9271Modes_9271_1_0_only[][6] = {
-       {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
-       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+static const u32 ar9271Modes_9271_1_0_only[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
+       {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
 };
 
-static const u32 ar9271Modes_9271_ANI_reg[][6] = {
-       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
-       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e},
-       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
-       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
-       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d},
-       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+static const u32 ar9271Modes_9271_ANI_reg[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},
+       {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e},
+       {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x0000986c, 0x06903881, 0x06903881, 0x06903881, 0x06903881},
+       {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x0000a208, 0x803e68c8, 0x803e68c8, 0x803e68c8, 0x803e68c8},
+       {0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d},
+       {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
 };
 
-static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000},
-       {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
-       {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
-       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
-       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
-       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652},
-       {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
-       {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
-       {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
-       {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
-       {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
-       {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+static const u32 ar9271Modes_normal_power_tx_gain_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610},
+       {0x0000a314, 0x00000000, 0x00000000, 0x00024650, 0x00024650},
+       {0x0000a318, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x000316d2, 0x000316d2},
+       {0x0000a320, 0x00000000, 0x00000000, 0x00039758, 0x00039758},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759},
+       {0x0000a328, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e},
+       {0x0000a334, 0x000368de, 0x000368de, 0x0004979f, 0x0004979f},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0004d7df, 0x0004d7df},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007838, 0x00000029, 0x00000029, 0x00000029, 0x00000029},
+       {0x00007824, 0x00d8abff, 0x00d8abff, 0x00d8abff, 0x00d8abff},
+       {0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4},
+       {0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04},
+       {0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21c652, 0x0a21c652},
+       {0x0000a278, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a27c, 0x050e83bd, 0x050e83bd, 0x050e83bd, 0x050e83bd},
+       {0x0000a394, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a398, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
+       {0x0000a3dc, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd, 0x3bdef7bd},
+       {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd},
 };
 
-static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {
-       {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000},
-       {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000},
-       {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000},
-       {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240, 0x00000000},
-       {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241, 0x00000000},
-       {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600, 0x00000000},
-       {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800, 0x00000000},
-       {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802, 0x00000000},
-       {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805, 0x00000000},
-       {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41, 0x00000000},
-       {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00, 0x00000000},
-       {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40, 0x00000000},
-       {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80, 0x00000000},
-       {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000},
-       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000},
-       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000},
-       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000},
-       {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
-       {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
-       {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6},
-       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
-       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652},
-       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
-       {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063},
-       {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
-       {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
-       {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
-       {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+static const u32 ar9271Modes_high_power_tx_gain_9271[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000},
+       {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200},
+       {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201},
+       {0x0000a30c, 0x00000000, 0x00000000, 0x0001b240, 0x0001b240},
+       {0x0000a310, 0x00000000, 0x00000000, 0x0001d241, 0x0001d241},
+       {0x0000a314, 0x00000000, 0x00000000, 0x0001f600, 0x0001f600},
+       {0x0000a318, 0x00000000, 0x00000000, 0x00022800, 0x00022800},
+       {0x0000a31c, 0x00000000, 0x00000000, 0x00026802, 0x00026802},
+       {0x0000a320, 0x00000000, 0x00000000, 0x0002b805, 0x0002b805},
+       {0x0000a324, 0x00000000, 0x00000000, 0x0002ea41, 0x0002ea41},
+       {0x0000a328, 0x00000000, 0x00000000, 0x00038b00, 0x00038b00},
+       {0x0000a32c, 0x00000000, 0x00000000, 0x0003ab40, 0x0003ab40},
+       {0x0000a330, 0x00000000, 0x00000000, 0x0003cd80, 0x0003cd80},
+       {0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de},
+       {0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e},
+       {0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e},
+       {0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df},
+       {0x00007838, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b},
+       {0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff},
+       {0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba},
+       {0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00},
+       {0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652},
+       {0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7},
+       {0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063},
+       {0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+       {0x0000a398, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
+       {0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63},
+       {0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063},
 };
 
index 33deb0d574b088e27c6fd7b8d1a5f89947a33145..f7d8e516a2a9ee4770243b49b8d36a802461bd34 100644 (file)
@@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
        return true;
 }
 
-static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
-                                 bool is_firstseg, bool is_lastseg,
-                                 const void *ds0, dma_addr_t buf_addr,
-                                 unsigned int qcu)
+static void
+ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
 {
        struct ar5416_desc *ads = AR5416DESC(ds);
+       u32 ctl1, ctl6;
 
-       ads->ds_data = buf_addr;
-
-       if (is_firstseg) {
-               ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
-       } else if (is_lastseg) {
-               ads->ds_ctl0 = 0;
-               ads->ds_ctl1 = seglen;
-               ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
-               ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
-       } else {
-               ads->ds_ctl0 = 0;
-               ads->ds_ctl1 = seglen | AR_TxMore;
-               ads->ds_ctl2 = 0;
-               ads->ds_ctl3 = 0;
-       }
        ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
        ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
        ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
        ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
        ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+       ACCESS_ONCE(ads->ds_link) = i->link;
+       ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
+
+       ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
+       ctl6 = SM(i->keytype, AR_EncrType);
+
+       if (AR_SREV_9285(ah)) {
+               ads->ds_ctl8 = 0;
+               ads->ds_ctl9 = 0;
+               ads->ds_ctl10 = 0;
+               ads->ds_ctl11 = 0;
+       }
+
+       if ((i->is_first || i->is_last) &&
+           i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
+               ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
+                       | set11nTries(i->rates, 1)
+                       | set11nTries(i->rates, 2)
+                       | set11nTries(i->rates, 3)
+                       | (i->dur_update ? AR_DurUpdateEna : 0)
+                       | SM(0, AR_BurstDur);
+
+               ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
+                       | set11nRate(i->rates, 1)
+                       | set11nRate(i->rates, 2)
+                       | set11nRate(i->rates, 3);
+       } else {
+               ACCESS_ONCE(ads->ds_ctl2) = 0;
+               ACCESS_ONCE(ads->ds_ctl3) = 0;
+       }
+
+       if (!i->is_first) {
+               ACCESS_ONCE(ads->ds_ctl0) = 0;
+               ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+               ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+               return;
+       }
+
+       ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
+               | SM(i->type, AR_FrameType)
+               | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+       switch (i->aggr) {
+       case AGGR_BUF_FIRST:
+               ctl6 |= SM(i->aggr_len, AR_AggrLen);
+               /* fall through */
+       case AGGR_BUF_MIDDLE:
+               ctl1 |= AR_IsAggr | AR_MoreAggr;
+               ctl6 |= SM(i->ndelim, AR_PadDelim);
+               break;
+       case AGGR_BUF_LAST:
+               ctl1 |= AR_IsAggr;
+               break;
+       case AGGR_BUF_NONE:
+               break;
+       }
+
+       ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
+               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+               | SM(i->txpower, AR_XmitPower)
+               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+               | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+               | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+               | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+                  (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+       ACCESS_ONCE(ads->ds_ctl1) = ctl1;
+       ACCESS_ONCE(ads->ds_ctl6) = ctl6;
+
+       if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
+               return;
+
+       ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
+               | set11nPktDurRTSCTS(i->rates, 1);
+
+       ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
+               | set11nPktDurRTSCTS(i->rates, 3);
+
+       ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
+               | set11nRateFlags(i->rates, 1)
+               | set11nRateFlags(i->rates, 2)
+               | set11nRateFlags(i->rates, 3)
+               | SM(i->rtscts_rate, AR_RTSCTSRate);
 }
 
 static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
@@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
        return 0;
 }
 
-static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-                                   u32 pktLen, enum ath9k_pkt_type type,
-                                   u32 txPower, u8 keyIx,
-                                   enum ath9k_key_type keyType, u32 flags)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       if (txPower > 63)
-               txPower = 63;
-
-       ads->ds_ctl0 = (pktLen & AR_FrameLen)
-               | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-               | SM(txPower, AR_XmitPower)
-               | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-               | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
-               | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
-       ads->ds_ctl1 =
-               (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-               | SM(type, AR_FrameType)
-               | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-               | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-               | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
-       ads->ds_ctl6 = SM(keyType, AR_EncrType);
-
-       if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
-               ads->ds_ctl8 = 0;
-               ads->ds_ctl9 = 0;
-               ads->ds_ctl10 = 0;
-               ads->ds_ctl11 = 0;
-       }
-}
-
-static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       if (val)
-               ads->ds_ctl0 |= AR_ClrDestMask;
-       else
-               ads->ds_ctl0 &= ~AR_ClrDestMask;
-}
-
-static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-                                         void *lastds,
-                                         u32 durUpdateEn, u32 rtsctsRate,
-                                         u32 rtsctsDuration,
-                                         struct ath9k_11n_rate_series series[],
-                                         u32 nseries, u32 flags)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-       struct ar5416_desc *last_ads = AR5416DESC(lastds);
-       u32 ds_ctl0;
-
-       if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-               ds_ctl0 = ads->ds_ctl0;
-
-               if (flags & ATH9K_TXDESC_RTSENA) {
-                       ds_ctl0 &= ~AR_CTSEnable;
-                       ds_ctl0 |= AR_RTSEnable;
-               } else {
-                       ds_ctl0 &= ~AR_RTSEnable;
-                       ds_ctl0 |= AR_CTSEnable;
-               }
-
-               ads->ds_ctl0 = ds_ctl0;
-       } else {
-               ads->ds_ctl0 =
-                       (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
-       }
-
-       ads->ds_ctl2 = set11nTries(series, 0)
-               | set11nTries(series, 1)
-               | set11nTries(series, 2)
-               | set11nTries(series, 3)
-               | (durUpdateEn ? AR_DurUpdateEna : 0)
-               | SM(0, AR_BurstDur);
-
-       ads->ds_ctl3 = set11nRate(series, 0)
-               | set11nRate(series, 1)
-               | set11nRate(series, 2)
-               | set11nRate(series, 3);
-
-       ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
-               | set11nPktDurRTSCTS(series, 1);
-
-       ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
-               | set11nPktDurRTSCTS(series, 3);
-
-       ads->ds_ctl7 = set11nRateFlags(series, 0)
-               | set11nRateFlags(series, 1)
-               | set11nRateFlags(series, 2)
-               | set11nRateFlags(series, 3)
-               | SM(rtsctsRate, AR_RTSCTSRate);
-       last_ads->ds_ctl2 = ads->ds_ctl2;
-       last_ads->ds_ctl3 = ads->ds_ctl3;
-}
-
-static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-                                       u32 aggrLen)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-       ads->ds_ctl6 &= ~AR_AggrLen;
-       ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
-
-static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-                                        u32 numDelims)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-       unsigned int ctl6;
-
-       ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
-       ctl6 = ads->ds_ctl6;
-       ctl6 &= ~AR_PadDelim;
-       ctl6 |= SM(numDelims, AR_PadDelim);
-       ads->ds_ctl6 = ctl6;
-}
-
-static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       ads->ds_ctl1 |= AR_IsAggr;
-       ads->ds_ctl1 &= ~AR_MoreAggr;
-       ads->ds_ctl6 &= ~AR_PadDelim;
-}
-
-static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
 void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
                          u32 size, u32 flags)
 {
@@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
        ops->rx_enable = ar9002_hw_rx_enable;
        ops->set_desc_link = ar9002_hw_set_desc_link;
        ops->get_isr = ar9002_hw_get_isr;
-       ops->fill_txdesc = ar9002_hw_fill_txdesc;
+       ops->set_txdesc = ar9002_set_txdesc;
        ops->proc_txdesc = ar9002_hw_proc_txdesc;
-       ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
-       ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
-       ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
-       ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
-       ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
-       ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
-       ops->set_clrdmask = ar9002_hw_set_clrdmask;
 }
index fa35a0235f44b2ef2e0ce267cc8099bc6e108a9f..e4b1a83008547cbe053b18af6f2119bd95486e58 100644 (file)
@@ -615,11 +615,10 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 {
        int mp_max = -64, max_idx = 0;
        int mp_min = 63, min_idx = 0;
-       int mp_avg = 0, i, outlier_idx = 0;
+       int mp_avg = 0, i, outlier_idx = 0, mp_count = 0;
 
        /* find min/max mismatch across all calibrated gains */
        for (i = 0; i < nmeasurement; i++) {
-               mp_avg += mp_coeff[i];
                if (mp_coeff[i] > mp_max) {
                        mp_max = mp_coeff[i];
                        max_idx = i;
@@ -632,10 +631,20 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
        /* find average (exclude max abs value) */
        for (i = 0; i < nmeasurement; i++) {
                if ((abs(mp_coeff[i]) < abs(mp_max)) ||
-                   (abs(mp_coeff[i]) < abs(mp_min)))
+                   (abs(mp_coeff[i]) < abs(mp_min))) {
                        mp_avg += mp_coeff[i];
+                       mp_count++;
+               }
        }
-       mp_avg /= (nmeasurement - 1);
+
+       /*
+        * finding mean magnitude/phase if possible, otherwise
+        * just use the last value as the mean
+        */
+       if (mp_count)
+               mp_avg /= mp_count;
+       else
+               mp_avg = mp_coeff[nmeasurement - 1];
 
        /* detect outlier */
        if (abs(mp_max - mp_min) > max_delta) {
@@ -643,8 +652,9 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
                        outlier_idx = max_idx;
                else
                        outlier_idx = min_idx;
+
+               mp_coeff[outlier_idx] = mp_avg;
        }
-       mp_coeff[outlier_idx] = mp_avg;
 }
 
 static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
@@ -875,6 +885,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
        if (txiqcal_done)
                ar9003_hw_tx_iq_cal_post_proc(ah);
 
+       ath9k_hw_loadnf(ah, chan);
        ath9k_hw_start_nfcal(ah, true);
 
        /* Initialize list pointers */
index cb4c32eaef61249e061a2c2c5b1f4970d3c9161d..51398f0063e21c16edced8a93d30f1d081f6f5c8 100644 (file)
 #define COMP_HDR_LEN 4
 #define COMP_CKSUM_LEN 2
 
-#define AR_CH0_TOP (0x00016288)
-#define AR_CH0_TOP_XPABIASLVL (0x300)
-#define AR_CH0_TOP_XPABIASLVL_S (8)
-
-#define AR_CH0_THERM (0x00016290)
-#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
-#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
-#define AR_CH0_THERM_XPASHORT2GND 0x4
-#define AR_CH0_THERM_XPASHORT2GND_S 2
-
-#define AR_SWITCH_TABLE_COM_ALL (0xffff)
-#define AR_SWITCH_TABLE_COM_ALL_S (0)
-
-#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
-#define AR_SWITCH_TABLE_COM2_ALL_S (0)
-
-#define AR_SWITCH_TABLE_ALL (0xfff)
-#define AR_SWITCH_TABLE_ALL_S (0)
-
 #define LE16(x) __constant_cpu_to_le16(x)
 #define LE32(x) __constant_cpu_to_le32(x)
 
@@ -69,7 +50,7 @@ static int ar9003_hw_power_interpolate(int32_t x,
 static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
-       .macAddr = {1, 2, 3, 4, 5, 6},
+       .macAddr = {0, 2, 3, 4, 5, 6},
        .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        .baseEepHeader = {
@@ -158,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = {
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
        .base_ext1 = {
@@ -307,7 +288,7 @@ static const struct ar9300_eeprom ar9300_default = {
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -360,7 +341,7 @@ static const struct ar9300_eeprom ar9300_default = {
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
        .base_ext2 = {
@@ -735,7 +716,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
         .base_ext1 = {
@@ -884,7 +865,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -937,7 +918,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
        .base_ext2 = {
@@ -1313,7 +1294,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
                .papdRateMaskHt20 = LE32(0x80c080),
                .papdRateMaskHt40 = LE32(0x80c080),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
        },
        .base_ext1 = {
@@ -1515,7 +1496,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
        },
        .base_ext2 = {
@@ -1891,7 +1872,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                .papdRateMaskHt20 = LE32(0x0c80c080),
                .papdRateMaskHt40 = LE32(0x0080c080),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
        },
        .base_ext1 = {
@@ -2040,7 +2021,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-               { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -2093,7 +2074,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
        },
        .base_ext2 = {
@@ -2468,7 +2449,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
                .papdRateMaskHt20 = LE32(0x0c80C080),
                .papdRateMaskHt40 = LE32(0x0080C080),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
         .base_ext1 = {
@@ -2670,7 +2651,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
                .papdRateMaskHt20 = LE32(0x0cf0e0e0),
                .papdRateMaskHt40 = LE32(0x6cf0e0e0),
                .futureModal = {
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0,
                },
         },
        .base_ext2 = {
@@ -3573,6 +3554,8 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
 
        if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
                REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
+       else if (AR_SREV_9480(ah))
+               REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
        else {
                REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
                REG_RMW_FIELD(ah, AR_CH0_THERM,
@@ -3583,6 +3566,19 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
        }
 }
 
+static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
+{
+       struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+       __le32 val;
+
+       if (is_2ghz)
+               val = eep->modalHeader2G.switchcomspdt;
+       else
+               val = eep->modalHeader5G.switchcomspdt;
+       return le32_to_cpu(val);
+}
+
+
 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
 {
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@@ -3637,7 +3633,36 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 
        u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
 
-       REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
+       if (AR_SREV_9480(ah)) {
+               if (AR_SREV_9480_10(ah)) {
+                       value &= ~AR_SWITCH_TABLE_COM_SPDT;
+                       value |= 0x00100000;
+               }
+               REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+                               AR_SWITCH_TABLE_COM_AR9480_ALL, value);
+       } else
+               REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+                             AR_SWITCH_TABLE_COM_ALL, value);
+
+
+       /*
+        *   AR9480 defines new switch table for BT/WLAN,
+        *       here's new field name in XXX.ref for both 2G and 5G.
+        *   Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
+        *   15:12   R/W     SWITCH_TABLE_COM_SPDT_WLAN_RX
+        * SWITCH_TABLE_COM_SPDT_WLAN_RX
+        *
+        *   11:8     R/W     SWITCH_TABLE_COM_SPDT_WLAN_TX
+        * SWITCH_TABLE_COM_SPDT_WLAN_TX
+        *
+        *   7:4 R/W  SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+        * SWITCH_TABLE_COM_SPDT_WLAN_IDLE
+        */
+       if (AR_SREV_9480_20_OR_LATER(ah)) {
+               value = ar9003_switch_com_spdt_get(ah, is2ghz);
+               REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
+                               AR_SWITCH_TABLE_COM_SPDT_ALL, value);
+       }
 
        value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
        REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@@ -3837,6 +3862,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 {
        int internal_regulator =
                ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
+       u32 reg_val;
 
        if (internal_regulator) {
                if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
@@ -3861,7 +3887,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                                }
                        } else {
                                reg_pmu_set = (5 << 1) | (7 << 4) |
-                                             (1 << 8) | (2 << 14) |
+                                             (2 << 8) | (2 << 14) |
                                              (6 << 17) | (1 << 20) |
                                              (3 << 24) | (1 << 28);
                        }
@@ -3881,13 +3907,16 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                        REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
                        if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
                                return;
+               } else if (AR_SREV_9480(ah)) {
+                       reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+                       REG_WRITE(ah, AR_PHY_PMU1, reg_val);
                } else {
                        /* Internal regulator is ON. Write swreg register. */
-                       int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+                       reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
                        REG_WRITE(ah, AR_RTC_REG_CONTROL1,
                                  REG_READ(ah, AR_RTC_REG_CONTROL1) &
                                  (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
-                       REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL0, reg_val);
                        /* Set REG_CONTROL1.SWREG_PROGRAM */
                        REG_WRITE(ah, AR_RTC_REG_CONTROL1,
                                  REG_READ(ah,
@@ -3898,22 +3927,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
                        REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
                        while (REG_READ_FIELD(ah, AR_PHY_PMU2,
-                                             AR_PHY_PMU2_PGM))
+                                               AR_PHY_PMU2_PGM))
                                udelay(10);
 
                        REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
                        while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
-                                              AR_PHY_PMU1_PWD))
+                                               AR_PHY_PMU1_PWD))
                                udelay(10);
                        REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
                        while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
-                                             AR_PHY_PMU2_PGM))
+                                               AR_PHY_PMU2_PGM))
                                udelay(10);
-               } else
-                       REG_WRITE(ah, AR_RTC_SLEEP_CLK,
-                                 (REG_READ(ah,
-                                  AR_RTC_SLEEP_CLK) |
-                                  AR_RTC_FORCE_SWREG_PRD));
+               } else if (AR_SREV_9480(ah))
+                       REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+               else {
+                       reg_val = REG_READ(ah, AR_RTC_SLEEP_CLK) |
+                               AR_RTC_FORCE_SWREG_PRD;
+                       REG_WRITE(ah, AR_RTC_SLEEP_CLK, reg_val);
+               }
        }
 
 }
@@ -4493,6 +4524,12 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
                tempSlope = eep->modalHeader5G.tempSlope;
 
        REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
+
+       if (AR_SREV_9480_20(ah))
+               REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
+                             AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
+
+
        REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
                      temperature[0]);
 
index ab21a49159811c8ccaa587aef294e37dd95e84cd..6335a867527e13db33598f15efe63df3581909c7 100644 (file)
@@ -233,7 +233,8 @@ struct ar9300_modal_eep_header {
        u8 thresh62;
        __le32 papdRateMaskHt20;
        __le32 papdRateMaskHt40;
-       u8 futureModal[10];
+       __le16 switchcomspdt;
+       u8 futureModal[8];
 } __packed;
 
 struct ar9300_cal_data_per_freq_op_loop {
index b6839e695270999bcd1ef1665d3e533c80a444af..901f417bb036a6dc721106bba077944e31033d2f 100644 (file)
@@ -22,6 +22,8 @@
 #include "ar9330_1p1_initvals.h"
 #include "ar9330_1p2_initvals.h"
 #include "ar9580_1p0_initvals.h"
+#include "ar9480_1p0_initvals.h"
+#include "ar9480_2p0_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
+#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
+               ar9480_pciephy_pll_on_clkreq_disable_L1_2p0
+
+#define AR9480_BB_CTX_COEFJ(x) \
+               ar9480_##x##_baseband_core_txfir_coeff_japan_2484
+
+#define AR9480_BBC_TXIFR_COEFFJ \
+               ar9480_2p0_baseband_core_txfir_coeff_japan_2484
        if (AR_SREV_9330_11(ah)) {
                /* mac */
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -254,6 +264,132 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                                ar9485_1_1_pcie_phy_clkreq_disable_L1,
                                ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
                                2);
+       } else if (AR_SREV_9480_10(ah)) {
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9480_1p0_mac_core,
+                               ARRAY_SIZE(ar9480_1p0_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9480_1p0_mac_postamble,
+                               ARRAY_SIZE(ar9480_1p0_mac_postamble),
+                               5);
+
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9480_1p0_baseband_core,
+                               ARRAY_SIZE(ar9480_1p0_baseband_core),
+                               2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9480_1p0_baseband_postamble,
+                               ARRAY_SIZE(ar9480_1p0_baseband_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9480_1p0_radio_core,
+                               ARRAY_SIZE(ar9480_1p0_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9480_1p0_radio_postamble,
+                               ARRAY_SIZE(ar9480_1p0_radio_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9480_1p0_soc_preamble,
+                               ARRAY_SIZE(ar9480_1p0_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9480_1p0_soc_postamble,
+                               ARRAY_SIZE(ar9480_1p0_soc_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9480_common_rx_gain_table_1p0,
+                               ARRAY_SIZE(ar9480_common_rx_gain_table_1p0), 2);
+
+               /* Awake -> Sleep Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                       ar9480_pcie_phy_clkreq_disable_L1_1p0,
+                       ARRAY_SIZE(ar9480_pcie_phy_clkreq_disable_L1_1p0),
+                       2);
+
+               /* Sleep -> Awake Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                       ar9480_pcie_phy_clkreq_disable_L1_1p0,
+                       ARRAY_SIZE(ar9480_pcie_phy_clkreq_disable_L1_1p0),
+                       2);
+
+               INIT_INI_ARRAY(&ah->iniModesAdditional,
+                               ar9480_modes_fast_clock_1p0,
+                               ARRAY_SIZE(ar9480_modes_fast_clock_1p0), 3);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                               AR9480_BB_CTX_COEFJ(1p0),
+                               ARRAY_SIZE(AR9480_BB_CTX_COEFJ(1p0)), 2);
+
+       } else if (AR_SREV_9480_20(ah)) {
+
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9480_2p0_mac_core,
+                               ARRAY_SIZE(ar9480_2p0_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9480_2p0_mac_postamble,
+                               ARRAY_SIZE(ar9480_2p0_mac_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9480_2p0_baseband_core,
+                               ARRAY_SIZE(ar9480_2p0_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9480_2p0_baseband_postamble,
+                               ARRAY_SIZE(ar9480_2p0_baseband_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9480_2p0_radio_core,
+                               ARRAY_SIZE(ar9480_2p0_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                               ar9480_2p0_radio_postamble,
+                               ARRAY_SIZE(ar9480_2p0_radio_postamble), 5);
+               INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
+                               ar9480_2p0_radio_postamble_sys2ant,
+                               ARRAY_SIZE(ar9480_2p0_radio_postamble_sys2ant),
+                               5);
+
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9480_2p0_soc_preamble,
+                               ARRAY_SIZE(ar9480_2p0_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9480_2p0_soc_postamble,
+                               ARRAY_SIZE(ar9480_2p0_soc_postamble), 5);
+
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9480_common_rx_gain_table_2p0,
+                               ARRAY_SIZE(ar9480_common_rx_gain_table_2p0), 2);
+
+               INIT_INI_ARRAY(&ah->ini_BTCOEX_MAX_TXPWR,
+                               ar9480_2p0_BTCOEX_MAX_TXPWR_table,
+                               ARRAY_SIZE(ar9480_2p0_BTCOEX_MAX_TXPWR_table),
+                               2);
+
+               /* Awake -> Sleep Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                               PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+                               ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+                               2);
+               /* Sleep -> Awake Setting */
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                               PCIE_PLL_ON_CREQ_DIS_L1_2P0,
+                               ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+                               2);
+
+               /* Fast clock modal settings */
+               INIT_INI_ARRAY(&ah->iniModesAdditional,
+                               ar9480_modes_fast_clock_2p0,
+                               ARRAY_SIZE(ar9480_modes_fast_clock_2p0), 3);
+
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                               AR9480_BB_CTX_COEFJ(2p0),
+                               ARRAY_SIZE(AR9480_BB_CTX_COEFJ(2p0)), 2);
+
+               INIT_INI_ARRAY(&ah->ini_japan2484, AR9480_BBC_TXIFR_COEFFJ,
+                               ARRAY_SIZE(AR9480_BBC_TXIFR_COEFFJ), 2);
+
        } else if (AR_SREV_9580(ah)) {
                /* mac */
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -374,208 +510,293 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
        }
 }
 
+static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485_modes_lowest_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_lowest_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
+                       5);
+       else if (AR_SREV_9480_10(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9480_modes_low_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9480_modes_low_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9480_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9480_modes_low_ob_db_tx_gain_table_2p0,
+                       ARRAY_SIZE(ar9480_modes_low_ob_db_tx_gain_table_2p0),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_high_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_high_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
+                       5);
+       else if (AR_SREV_9480_10(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9480_modes_high_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9480_modes_high_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9480_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9480_modes_high_ob_db_tx_gain_table_2p0,
+                       ARRAY_SIZE(ar9480_modes_high_ob_db_tx_gain_table_2p0),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_high_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_low_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_low_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_low_ob_db_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_low_ob_db_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_low_ob_db_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+                       5);
+}
+
+static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_power_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+                       5);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_high_power_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+                       5);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
+                       5);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9485Modes_high_power_tx_gain_1_1,
+                       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+                       5);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9580_1p0_high_power_tx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
+                       5);
+       else
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9300Modes_high_power_tx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
+                       5);
+}
+
 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 {
        switch (ar9003_hw_get_tx_gain_idx(ah)) {
        case 0:
        default:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_lowest_ob_db_tx_gain_1p2,
-                               ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
-                               5);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_lowest_ob_db_tx_gain_1p1,
-                               ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
-                               5);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
-                                      5);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9485_modes_lowest_ob_db_tx_gain_1_1,
-                                      ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
-                                      5);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                             ar9580_1p0_lowest_ob_db_tx_gain_table,
-                             ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
-                             5);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
-                                      5);
+               ar9003_tx_gain_table_mode0(ah);
                break;
        case 1:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_high_ob_db_tx_gain_1p2,
-                               ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
-                               5);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_high_ob_db_tx_gain_1p1,
-                               ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
-                               5);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
-                                      5);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9485Modes_high_ob_db_tx_gain_1_1,
-                                      ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
-                                      5);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9580_1p0_high_ob_db_tx_gain_table,
-                               ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
-                                      5);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9300Modes_high_ob_db_tx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
-                                      5);
+               ar9003_tx_gain_table_mode1(ah);
                break;
        case 2:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_low_ob_db_tx_gain_1p2,
-                               ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
-                               5);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_low_ob_db_tx_gain_1p1,
-                               ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
-                               5);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
-                                      5);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9485Modes_low_ob_db_tx_gain_1_1,
-                                      ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
-                                      5);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                ar9580_1p0_low_ob_db_tx_gain_table,
-                                ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
-                                5);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9300Modes_low_ob_db_tx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
-                                      5);
+               ar9003_tx_gain_table_mode2(ah);
                break;
        case 3:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_high_power_tx_gain_1p2,
-                               ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
-                               5);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9331_modes_high_power_tx_gain_1p1,
-                               ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
-                               5);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                       ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
-                                      5);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9485Modes_high_power_tx_gain_1_1,
-                                      ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
-                                      5);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                               ar9580_1p0_high_power_tx_gain_table,
-                               ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
-                               5);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                                      ar9300Modes_high_power_tx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
-                                      5);
+               ar9003_tx_gain_table_mode3(ah);
                break;
        }
 }
 
+static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p2,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+                               2);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p1,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+                               2);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9340Common_rx_gain_table_1p0,
+                               ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
+                               2);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9485Common_wo_xlna_rx_gain_1_1,
+                               ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+                               2);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9580_1p0_rx_gain_table,
+                               ARRAY_SIZE(ar9580_1p0_rx_gain_table),
+                               2);
+       else if (AR_SREV_9480_10(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9480_common_rx_gain_table_1p0,
+                               ARRAY_SIZE(ar9480_common_rx_gain_table_1p0),
+                               2);
+       else if (AR_SREV_9480_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9480_common_rx_gain_table_2p0,
+                               ARRAY_SIZE(ar9480_common_rx_gain_table_2p0),
+                               2);
+       else
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9300Common_rx_gain_table_2p2,
+                               ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+                               2);
+}
+
+static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
+{
+       if (AR_SREV_9330_12(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9331_common_wo_xlna_rx_gain_1p2,
+                       ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+                       2);
+       else if (AR_SREV_9330_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9331_common_wo_xlna_rx_gain_1p1,
+                       ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+                       2);
+       else if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9340Common_wo_xlna_rx_gain_table_1p0,
+                       ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
+                       2);
+       else if (AR_SREV_9485_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9485Common_wo_xlna_rx_gain_1_1,
+                       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+                       2);
+       else if (AR_SREV_9480_10(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9480_common_wo_xlna_rx_gain_table_1p0,
+                       ARRAY_SIZE(ar9480_common_wo_xlna_rx_gain_table_1p0),
+                       2);
+       else if (AR_SREV_9480_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9480_common_wo_xlna_rx_gain_table_2p0,
+                       ARRAY_SIZE(ar9480_common_wo_xlna_rx_gain_table_2p0),
+                       2);
+       else if (AR_SREV_9580(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9580_1p0_wo_xlna_rx_gain_table,
+                       ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
+                       2);
+       else
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9300Common_wo_xlna_rx_gain_table_2p2,
+                       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+                       2);
+}
+
+static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
+{
+       if (AR_SREV_9480_10(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9480_common_mixed_rx_gain_table_1p0,
+                       ARRAY_SIZE(ar9480_common_mixed_rx_gain_table_1p0), 2);
+       else if (AR_SREV_9480_20(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                       ar9480_common_mixed_rx_gain_table_2p0,
+                       ARRAY_SIZE(ar9480_common_mixed_rx_gain_table_2p0), 2);
+}
+
 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
 {
        switch (ar9003_hw_get_rx_gain_idx(ah)) {
        case 0:
        default:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                       ar9331_common_rx_gain_1p2,
-                                       ARRAY_SIZE(ar9331_common_rx_gain_1p2),
-                                       2);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                       ar9331_common_rx_gain_1p1,
-                                       ARRAY_SIZE(ar9331_common_rx_gain_1p1),
-                                       2);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9340Common_rx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
-                                      2);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9485Common_wo_xlna_rx_gain_1_1,
-                                      ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
-                                      2);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9580_1p0_rx_gain_table,
-                                      ARRAY_SIZE(ar9580_1p0_rx_gain_table),
-                                      2);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9300Common_rx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
-                                      2);
+               ar9003_rx_gain_table_mode0(ah);
                break;
        case 1:
-               if (AR_SREV_9330_12(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                               ar9331_common_wo_xlna_rx_gain_1p2,
-                               ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
-                               2);
-               else if (AR_SREV_9330_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                               ar9331_common_wo_xlna_rx_gain_1p1,
-                               ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
-                               2);
-               else if (AR_SREV_9340(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9340Common_wo_xlna_rx_gain_table_1p0,
-                                      ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
-                                      2);
-               else if (AR_SREV_9485_11(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9485Common_wo_xlna_rx_gain_1_1,
-                                      ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
-                                      2);
-               else if (AR_SREV_9580(ah))
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                  ar9580_1p0_wo_xlna_rx_gain_table,
-                                  ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
-                                  2);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                                      ar9300Common_wo_xlna_rx_gain_table_2p2,
-                                      ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
-                                      2);
+               ar9003_rx_gain_table_mode1(ah);
+               break;
+       case 2:
+               ar9003_rx_gain_table_mode2(ah);
                break;
        }
 }
index d08ab930e430311663861025cf36794749c0e313..6cabc85bf61b3c9214b3e8ba94c6c8e6b51b646b 100644 (file)
@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct ath_hw *hw)
        REG_WRITE(hw, AR_CR, 0);
 }
 
+static void
+ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
+{
+       struct ar9003_txc *ads = ds;
+       int checksum = 0;
+       u32 val, ctl12, ctl17;
+
+       val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
+             (1 << AR_TxRxDesc_S) |
+             (1 << AR_CtrlStat_S) |
+             (i->qcu << AR_TxQcuNum_S) | 0x17;
+
+       checksum += val;
+       ACCESS_ONCE(ads->info) = val;
+
+       checksum += i->link;
+       ACCESS_ONCE(ads->link) = i->link;
+
+       checksum += i->buf_addr[0];
+       ACCESS_ONCE(ads->data0) = i->buf_addr[0];
+       checksum += i->buf_addr[1];
+       ACCESS_ONCE(ads->data1) = i->buf_addr[1];
+       checksum += i->buf_addr[2];
+       ACCESS_ONCE(ads->data2) = i->buf_addr[2];
+       checksum += i->buf_addr[3];
+       ACCESS_ONCE(ads->data3) = i->buf_addr[3];
+
+       checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl3) = val;
+       checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl5) = val;
+       checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl7) = val;
+       checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
+       ACCESS_ONCE(ads->ctl9) = val;
+
+       checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
+       ACCESS_ONCE(ads->ctl10) = checksum;
+
+       if (i->is_first || i->is_last) {
+               ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
+                       | set11nTries(i->rates, 1)
+                       | set11nTries(i->rates, 2)
+                       | set11nTries(i->rates, 3)
+                       | (i->dur_update ? AR_DurUpdateEna : 0)
+                       | SM(0, AR_BurstDur);
+
+               ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
+                       | set11nRate(i->rates, 1)
+                       | set11nRate(i->rates, 2)
+                       | set11nRate(i->rates, 3);
+       } else {
+               ACCESS_ONCE(ads->ctl13) = 0;
+               ACCESS_ONCE(ads->ctl14) = 0;
+       }
+
+       ads->ctl20 = 0;
+       ads->ctl21 = 0;
+       ads->ctl22 = 0;
+
+       ctl17 = SM(i->keytype, AR_EncrType);
+       if (!i->is_first) {
+               ACCESS_ONCE(ads->ctl11) = 0;
+               ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
+               ACCESS_ONCE(ads->ctl15) = 0;
+               ACCESS_ONCE(ads->ctl16) = 0;
+               ACCESS_ONCE(ads->ctl17) = ctl17;
+               ACCESS_ONCE(ads->ctl18) = 0;
+               ACCESS_ONCE(ads->ctl19) = 0;
+               return;
+       }
+
+       ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
+               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+               | SM(i->txpower, AR_XmitPower)
+               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+               | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
+               | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
+               | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+               | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
+                  (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
+
+       ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
+                SM(i->keyix, AR_DestIdx) : 0)
+               | SM(i->type, AR_FrameType)
+               | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+               | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+       ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
+       switch (i->aggr) {
+       case AGGR_BUF_FIRST:
+               ctl17 |= SM(i->aggr_len, AR_AggrLen);
+               /* fall through */
+       case AGGR_BUF_MIDDLE:
+               ctl12 |= AR_IsAggr | AR_MoreAggr;
+               ctl17 |= SM(i->ndelim, AR_PadDelim);
+               break;
+       case AGGR_BUF_LAST:
+               ctl12 |= AR_IsAggr;
+               break;
+       case AGGR_BUF_NONE:
+               break;
+       }
+
+       val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
+       ctl12 |= SM(val, AR_PAPRDChainMask);
+
+       ACCESS_ONCE(ads->ctl12) = ctl12;
+       ACCESS_ONCE(ads->ctl17) = ctl17;
+
+       ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
+               | set11nPktDurRTSCTS(i->rates, 1);
+
+       ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
+               | set11nPktDurRTSCTS(i->rates, 3);
+
+       ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
+               | set11nRateFlags(i->rates, 1)
+               | set11nRateFlags(i->rates, 2)
+               | set11nRateFlags(i->rates, 3)
+               | SM(i->rtscts_rate, AR_RTSCTSRate);
+
+       ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+}
+
 static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
 {
        int checksum;
@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
        return true;
 }
 
-static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
-                                 bool is_firstseg, bool is_lastseg,
-                                 const void *ds0, dma_addr_t buf_addr,
-                                 unsigned int qcu)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-       unsigned int descid = 0;
-
-       ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
-                                    (1 << AR_TxRxDesc_S) |
-                                    (1 << AR_CtrlStat_S) |
-                                    (qcu << AR_TxQcuNum_S) | 0x17;
-
-       ads->data0 = buf_addr;
-       ads->data1 = 0;
-       ads->data2 = 0;
-       ads->data3 = 0;
-
-       ads->ctl3 = (seglen << AR_BufLen_S);
-       ads->ctl3 &= AR_BufLen;
-
-       /* Fill in pointer checksum and descriptor id */
-       ads->ctl10 = ar9003_calc_ptr_chksum(ads);
-       ads->ctl10 |= (descid << AR_TxDescId_S);
-
-       if (is_firstseg) {
-               ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
-       } else if (is_lastseg) {
-               ads->ctl11 = 0;
-               ads->ctl12 = 0;
-               ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
-               ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
-       } else {
-               /* XXX Intermediate descriptor in a multi-descriptor frame.*/
-               ads->ctl11 = 0;
-               ads->ctl12 = AR_TxMore;
-               ads->ctl13 = 0;
-               ads->ctl14 = 0;
-       }
-}
-
 static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
                                 struct ath_tx_status *ts)
 {
@@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
        return 0;
 }
 
-static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-               u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
-               u8 keyIx, enum ath9k_key_type keyType, u32 flags)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
-       if (txpower > ah->txpower_limit)
-               txpower = ah->txpower_limit;
-
-       if (txpower > 63)
-               txpower = 63;
-
-       ads->ctl11 = (pktlen & AR_FrameLen)
-               | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-               | SM(txpower, AR_XmitPower)
-               | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-               | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
-               | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
-
-       ads->ctl12 =
-               (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-               | SM(type, AR_FrameType)
-               | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-               | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-               | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
-       ads->ctl17 = SM(keyType, AR_EncrType) |
-                    (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
-       ads->ctl18 = 0;
-       ads->ctl19 = AR_Not_Sounding;
-
-       ads->ctl20 = 0;
-       ads->ctl21 = 0;
-       ads->ctl22 = 0;
-}
-
-static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
-       if (val)
-               ads->ctl11 |= AR_ClrDestMask;
-       else
-               ads->ctl11 &= ~AR_ClrDestMask;
-}
-
-static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-                                         void *lastds,
-                                         u32 durUpdateEn, u32 rtsctsRate,
-                                         u32 rtsctsDuration,
-                                         struct ath9k_11n_rate_series series[],
-                                         u32 nseries, u32 flags)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-       struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
-       u_int32_t ctl11;
-
-       if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-               ctl11 = ads->ctl11;
-
-               if (flags & ATH9K_TXDESC_RTSENA) {
-                       ctl11 &= ~AR_CTSEnable;
-                       ctl11 |= AR_RTSEnable;
-               } else {
-                       ctl11 &= ~AR_RTSEnable;
-                       ctl11 |= AR_CTSEnable;
-               }
-
-               ads->ctl11 = ctl11;
-       } else {
-               ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
-       }
-
-       ads->ctl13 = set11nTries(series, 0)
-               |  set11nTries(series, 1)
-               |  set11nTries(series, 2)
-               |  set11nTries(series, 3)
-               |  (durUpdateEn ? AR_DurUpdateEna : 0)
-               |  SM(0, AR_BurstDur);
-
-       ads->ctl14 = set11nRate(series, 0)
-               |  set11nRate(series, 1)
-               |  set11nRate(series, 2)
-               |  set11nRate(series, 3);
-
-       ads->ctl15 = set11nPktDurRTSCTS(series, 0)
-               |  set11nPktDurRTSCTS(series, 1);
-
-       ads->ctl16 = set11nPktDurRTSCTS(series, 2)
-               |  set11nPktDurRTSCTS(series, 3);
-
-       ads->ctl18 = set11nRateFlags(series, 0)
-               |  set11nRateFlags(series, 1)
-               |  set11nRateFlags(series, 2)
-               |  set11nRateFlags(series, 3)
-               | SM(rtsctsRate, AR_RTSCTSRate);
-       ads->ctl19 = AR_Not_Sounding;
-
-       last_ads->ctl13 = ads->ctl13;
-       last_ads->ctl14 = ads->ctl14;
-}
-
-static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-                                       u32 aggrLen)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
-       ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
-       ads->ctl17 &= ~AR_AggrLen;
-       ads->ctl17 |= SM(aggrLen, AR_AggrLen);
-}
-
-static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-                                        u32 numDelims)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-       unsigned int ctl17;
-
-       ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
-
-       /*
-        * We use a stack variable to manipulate ctl6 to reduce uncached
-        * read modify, modfiy, write.
-        */
-       ctl17 = ads->ctl17;
-       ctl17 &= ~AR_PadDelim;
-       ctl17 |= SM(numDelims, AR_PadDelim);
-       ads->ctl17 = ctl17;
-}
-
-static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
-       ads->ctl12 |= AR_IsAggr;
-       ads->ctl12 &= ~AR_MoreAggr;
-       ads->ctl17 &= ~AR_PadDelim;
-}
-
-static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
-       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-
-       ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
-void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
-{
-       struct ar9003_txc *ads = ds;
-
-       ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
-}
-EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
-
 void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
 {
        struct ath_hw_ops *ops = ath9k_hw_ops(hw);
@@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
        ops->rx_enable = ar9003_hw_rx_enable;
        ops->set_desc_link = ar9003_hw_set_desc_link;
        ops->get_isr = ar9003_hw_get_isr;
-       ops->fill_txdesc = ar9003_hw_fill_txdesc;
+       ops->set_txdesc = ar9003_set_txdesc;
        ops->proc_txdesc = ar9003_hw_proc_txdesc;
-       ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
-       ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
-       ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
-       ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
-       ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
-       ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
-       ops->set_clrdmask = ar9003_hw_set_clrdmask;
 }
 
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
index f80d1d63398011f4deb02f532d5cb8beade9eb5a..609acb2b504f301d91611b603556ffa76a5dc108 100644 (file)
@@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
        if (delta > scale)
                return -1;
 
-       switch (get_streams(common->tx_chainmask)) {
+       switch (get_streams(ah->txchainmask)) {
        case 1:
                delta = 6;
                break;
@@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
        default:
                delta = 0;
                ath_dbg(common, ATH_DBG_CALIBRATE,
-               "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+               "Invalid tx-chainmask: %u\n", ah->txchainmask);
        }
 
        power += delta;
@@ -147,7 +147,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
                AR_PHY_PAPRD_CTRL1_B2
        };
        int training_power;
-       int i;
+       int i, val;
 
        if (IS_CHAN_2GHZ(ah->curchan))
                training_power = ar9003_get_training_power_2g(ah);
@@ -207,8 +207,9 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
                      AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1,
                      AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1);
+       val = AR_SREV_9480(ah) ? 0x91 : 147;
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2,
-                     AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147);
+                     AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, val);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
@@ -217,7 +218,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
                      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1);
-       if (AR_SREV_9485(ah))
+       if (AR_SREV_9485(ah) || AR_SREV_9480(ah))
                REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                              AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
                              -3);
@@ -225,9 +226,10 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
                REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                              AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
                              -6);
+       val = AR_SREV_9480(ah) ? -10 : -15;
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE,
-                     -15);
+                     val);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
                      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4,
@@ -757,6 +759,7 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
                              training_power);
 
        if (ah->caps.tx_chainmask & BIT(2))
+               /* val AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL correct? */
                REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2,
                              AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL,
                              training_power);
index 33edb5653ca6ab850f751b8e61b399efff13a62b..7db6e8647a01ffc2bfb952ba34eedb5bb0008f5f 100644 (file)
@@ -559,6 +559,9 @@ static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 
        if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
                REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+       else if (AR_SREV_9480(ah))
+               /* xxx only when MCI support is enabled */
+               REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
        else
                REG_WRITE(ah, AR_SELFGEN_MASK, tx);
 
@@ -592,6 +595,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
        val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
        REG_WRITE(ah, AR_PCU_MISC_MODE2,
                  val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+
+       REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -658,6 +664,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
                ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
                ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
+               if (i == ATH_INI_POST && AR_SREV_9480_20(ah))
+                       ar9003_hw_prog_ini(ah,
+                                          &ah->ini_radio_post_sys2ant,
+                                          modesIndex);
        }
 
        REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
@@ -671,12 +681,15 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                REG_WRITE_ARRAY(&ah->iniModesAdditional,
                                modesIndex, regWrites);
 
-       if (AR_SREV_9300(ah))
+       if (AR_SREV_9330(ah))
                REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
 
        if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
                REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
 
+       if (AR_SREV_9480(ah))
+               ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
+
        ar9003_hw_override_ini(ah);
        ar9003_hw_set_channel_regs(ah, chan);
        ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
@@ -785,16 +798,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
        REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
 }
 
-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
-{
-       u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
-       if (value)
-               v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       else
-               v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
 static bool ar9003_hw_ani_control(struct ath_hw *ah,
                                  enum ath9k_ani_cmd cmd, int param)
 {
@@ -1277,7 +1280,6 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
        priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
        priv_ops->rfbus_req = ar9003_hw_rfbus_req;
        priv_ops->rfbus_done = ar9003_hw_rfbus_done;
-       priv_ops->set_diversity = ar9003_hw_set_diversity;
        priv_ops->ani_control = ar9003_hw_ani_control;
        priv_ops->do_getnf = ar9003_hw_do_getnf;
        priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
index 3aca9fa2d27b6468af67a70d98045b623973d31f..6cea546a15076be97fc7788f9ee3eecf6c813974 100644 (file)
 #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i)    (AR_SM_BASE + \
                                             (AR_SREV_9485(ah) ? \
                                              0x3d0 : 0x450) + ((_i) << 2))
+#define AR_PHY_RTT_CTRL                        (AR_SM_BASE + 0x380)
+#define AR_PHY_RTT_TABLE_SW_INTF_B     (AR_SM_BASE + 0x384)
+#define AR_PHY_RTT_TABLE_SW_INTF_1_B0  (AR_SM_BASE + 0x388)
 
 #define AR_PHY_WATCHDOG_STATUS      (AR_SM_BASE + 0x5c0)
 #define AR_PHY_WATCHDOG_CTL_1       (AR_SM_BASE + 0x5c4)
 #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE                0x0000ff00
 #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S      8
 
+/* AIC Registers */
+#define AR_PHY_AIC_CTRL_0_B0   (AR_SM_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B0   (AR_SM_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B0   (AR_SM_BASE + 0x4b8)
+#define AR_PHY_AIC_CTRL_3_B0   (AR_SM_BASE + 0x4bc)
+#define AR_PHY_AIC_STAT_0_B0   (AR_SM_BASE + (AR_SREV_9480_10(ah) ? \
+                                       0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B0   (AR_SM_BASE + (AR_SREV_9480_10(ah) ? \
+                                       0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B0   (AR_SM_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B0   (AR_SM_BASE + 0x4cc)
 
 #define AR_PHY_65NM_CH0_SYNTH4      0x1608c
 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   0x00000002
 #define AR_PHY_65NM_CH0_BIAS2       0x160c4
 #define AR_PHY_65NM_CH0_BIAS4       0x160cc
 #define AR_PHY_65NM_CH0_RXTX4       0x1610c
-#define AR_PHY_65NM_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 : 0x1628c)
+
+#define AR_CH0_TOP     (AR_SREV_9300(ah) ? 0x16288 : \
+                               ((AR_SREV_9480(ah) ? 0x1628c : 0x16280)))
+#define AR_CH0_TOP_XPABIASLVL (0x300)
+#define AR_CH0_TOP_XPABIASLVL_S (8)
+
+#define AR_CH0_THERM   (AR_SREV_9300(ah) ? 0x16290 : \
+                               ((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_AR9480_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM_AR9480_ALL_S (0)
+#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
+#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
+
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+
+#define AR_SWITCH_TABLE_ALL (0xfff)
+#define AR_SWITCH_TABLE_ALL_S (0)
+
+#define AR_PHY_65NM_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 :\
+                                       (AR_SREV_9485(ah) ? 0x1628c : 0x16294))
 
 #define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000
 #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
 #define AR_PHY_65NM_CH2_RXTX1       0x16900
 #define AR_PHY_65NM_CH2_RXTX2       0x16904
 
-#define AR_CH0_TOP2            (AR_SREV_9300(ah) ? 0x1628c : 0x16284)
+#define AR_CH0_TOP2            (AR_SREV_9300(ah) ? 0x1628c : \
+                                       (AR_SREV_9485(ah) ? 0x16284 : 0x16290))
 #define AR_CH0_TOP2_XPABIASLVL         0xf000
 #define AR_CH0_TOP2_XPABIASLVL_S       12
 
-#define AR_CH0_XTAL            (AR_SREV_9300(ah) ? 0x16294 : 0x16290)
+#define AR_CH0_XTAL            (AR_SREV_9300(ah) ? 0x16294 : \
+                                       (AR_SREV_9485(ah) ? 0x16290 : 0x16298))
 #define AR_CH0_XTAL_CAPINDAC   0x7f000000
 #define AR_CH0_XTAL_CAPINDAC_S 24
 #define AR_CH0_XTAL_CAPOUTDAC  0x00fe0000
 #define AR_CH0_XTAL_CAPOUTDAC_S        17
 
-#define AR_PHY_PMU1            0x16c40
+#define AR_PHY_PMU1            (AR_SREV_9480(ah) ? 0x16340 : 0x16c40)
 #define AR_PHY_PMU1_PWD                0x1
 #define AR_PHY_PMU1_PWD_S      0
 
-#define AR_PHY_PMU2            0x16c44
+#define AR_PHY_PMU2            (AR_SREV_9480(ah) ? 0x16344 : 0x16c44)
 #define AR_PHY_PMU2_PGM                0x00200000
 #define AR_PHY_PMU2_PGM_S      21
 
  */
 #define AR_SM1_BASE    0xb200
 
-#define AR_PHY_SWITCH_CHAIN_1    (AR_SM1_BASE + 0x84)
-#define AR_PHY_FCAL_2_1          (AR_SM1_BASE + 0xd0)
-#define AR_PHY_DFT_TONE_CTL_1    (AR_SM1_BASE + 0xd4)
-#define AR_PHY_CL_TAB_1          (AR_SM1_BASE + 0x100)
-#define AR_PHY_CHAN_INFO_GAIN_1  (AR_SM1_BASE + 0x180)
-#define AR_PHY_TPC_4_B1          (AR_SM1_BASE + 0x204)
-#define AR_PHY_TPC_5_B1          (AR_SM1_BASE + 0x208)
-#define AR_PHY_TPC_6_B1          (AR_SM1_BASE + 0x20c)
-#define AR_PHY_TPC_11_B1         (AR_SM1_BASE + 0x220)
-#define AR_PHY_PDADC_TAB_1       (AR_SM1_BASE + 0x240)
+#define AR_PHY_SWITCH_CHAIN_1   (AR_SM1_BASE + 0x84)
+#define AR_PHY_FCAL_2_1         (AR_SM1_BASE + 0xd0)
+#define AR_PHY_DFT_TONE_CTL_1   (AR_SM1_BASE + 0xd4)
+#define AR_PHY_CL_TAB_1         (AR_SM1_BASE + 0x100)
+#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
+#define AR_PHY_TPC_4_B1         (AR_SM1_BASE + 0x204)
+#define AR_PHY_TPC_5_B1         (AR_SM1_BASE + 0x208)
+#define AR_PHY_TPC_6_B1         (AR_SM1_BASE + 0x20c)
+#define AR_PHY_TPC_11_B1        (AR_SM1_BASE + 0x220)
+#define AR_PHY_PDADC_TAB_1     (AR_SM1_BASE + (AR_SREV_AR9300(ah) ? \
+                                       0x240 : 0x280))
+#define AR_PHY_TPC_19_B1       (AR_SM1_BASE + 0x240)
+#define AR_PHY_TPC_19_B1_ALPHA_THERM           0xff
+#define AR_PHY_TPC_19_B1_ALPHA_THERM_S         0
 #define AR_PHY_TX_IQCAL_STATUS_B1   (AR_SM1_BASE + 0x48c)
-#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM_BASE + 0x450 + ((_i) << 2))
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)    (AR_SM1_BASE + 0x450 + ((_i) << 2))
+
+/* SM 1 AIC Registers */
+
+#define AR_PHY_AIC_CTRL_0_B1   (AR_SM1_BASE + 0x4b0)
+#define AR_PHY_AIC_CTRL_1_B1   (AR_SM1_BASE + 0x4b4)
+#define AR_PHY_AIC_CTRL_2_B1   (AR_SM1_BASE + 0x4b8)
+#define AR_PHY_AIC_STAT_0_B1   (AR_SM1_BASE + (AR_SREV_9480_10(ah) ? \
+                                       0x4c0 : 0x4c4))
+#define AR_PHY_AIC_STAT_1_B1   (AR_SM1_BASE + (AR_SREV_9480_10(ah) ? \
+                                       0x4c4 : 0x4c8))
+#define AR_PHY_AIC_CTRL_4_B1   (AR_SM1_BASE + 0x4c0)
+#define AR_PHY_AIC_STAT_2_B1   (AR_SM1_BASE + 0x4cc)
+
+#define AR_PHY_AIC_SRAM_ADDR_B1        (AR_SM1_BASE + 0x5f0)
+#define AR_PHY_AIC_SRAM_DATA_B1        (AR_SM1_BASE + 0x5f4)
 
 /*
  * Channel 2 Register Map
 
 #define AR_PHY_RSSI_3            (AR_AGC3_BASE + 0x180)
 
+/* GLB Registers */
+#define AR_GLB_BASE    0x20000
+#define AR_PHY_GLB_CONTROL     (AR_GLB_BASE + 0x44)
+#define AR_GLB_SCRATCH(_ah)    (AR_GLB_BASE + \
+                                       (AR_SREV_9480_20(_ah) ? 0x4c : 0x50))
+#define AR_GLB_STATUS          (AR_GLB_BASE + 0x48)
+
 /*
  * Misc helper defines
  */
diff --git a/drivers/net/wireless/ath/ath9k/ar9480_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9480_1p0_initvals.h
new file mode 100644 (file)
index 0000000..4071bd2
--- /dev/null
@@ -0,0 +1,1833 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9480_1P0_H
+#define INITVALS_9480_1P0_H
+
+/* AR9480 1.0 */
+
+static const u32 ar9480_1p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00060085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00001810, 0x0f000003},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00080000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008050, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00005},
+       {0x000080d8, 0x00400002},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486e00},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x99c00010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x0000001f},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0xffff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9480_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9480_1p0_sys3ant[][2] = {
+       /* Addr      allmodes  */
+       {0x00063280, 0x00040807},
+       {0x00063284, 0x104ccccc},
+};
+
+static const u32 ar9480_pcie_phy_clkreq_enable_L1_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x10053e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9480_1p0_mac_core_emulation[][2] = {
+       /* Addr      allmodes  */
+       {0x00000030, 0x00060085},
+       {0x00000044, 0x00000008},
+       {0x0000805c, 0xffffc7ff},
+       {0x00008344, 0xaa4a105b},
+};
+
+static const u32 ar9480_common_rx_gain_table_ar9280_2p0_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x02000101},
+       {0x0000a004, 0x02000102},
+       {0x0000a008, 0x02000103},
+       {0x0000a00c, 0x02000104},
+       {0x0000a010, 0x02000200},
+       {0x0000a014, 0x02000201},
+       {0x0000a018, 0x02000202},
+       {0x0000a01c, 0x02000203},
+       {0x0000a020, 0x02000204},
+       {0x0000a024, 0x02000205},
+       {0x0000a028, 0x02000208},
+       {0x0000a02c, 0x02000302},
+       {0x0000a030, 0x02000303},
+       {0x0000a034, 0x02000304},
+       {0x0000a038, 0x02000400},
+       {0x0000a03c, 0x02010300},
+       {0x0000a040, 0x02010301},
+       {0x0000a044, 0x02010302},
+       {0x0000a048, 0x02000500},
+       {0x0000a04c, 0x02010400},
+       {0x0000a050, 0x02020300},
+       {0x0000a054, 0x02020301},
+       {0x0000a058, 0x02020302},
+       {0x0000a05c, 0x02020303},
+       {0x0000a060, 0x02020400},
+       {0x0000a064, 0x02030300},
+       {0x0000a068, 0x02030301},
+       {0x0000a06c, 0x02030302},
+       {0x0000a070, 0x02030303},
+       {0x0000a074, 0x02030400},
+       {0x0000a078, 0x02040300},
+       {0x0000a07c, 0x02040301},
+       {0x0000a080, 0x02040302},
+       {0x0000a084, 0x02040303},
+       {0x0000a088, 0x02030500},
+       {0x0000a08c, 0x02040400},
+       {0x0000a090, 0x02050203},
+       {0x0000a094, 0x02050204},
+       {0x0000a098, 0x02050205},
+       {0x0000a09c, 0x02040500},
+       {0x0000a0a0, 0x02050301},
+       {0x0000a0a4, 0x02050302},
+       {0x0000a0a8, 0x02050303},
+       {0x0000a0ac, 0x02050400},
+       {0x0000a0b0, 0x02050401},
+       {0x0000a0b4, 0x02050402},
+       {0x0000a0b8, 0x02050403},
+       {0x0000a0bc, 0x02050500},
+       {0x0000a0c0, 0x02050501},
+       {0x0000a0c4, 0x02050502},
+       {0x0000a0c8, 0x02050503},
+       {0x0000a0cc, 0x02050504},
+       {0x0000a0d0, 0x02050600},
+       {0x0000a0d4, 0x02050601},
+       {0x0000a0d8, 0x02050602},
+       {0x0000a0dc, 0x02050603},
+       {0x0000a0e0, 0x02050604},
+       {0x0000a0e4, 0x02050700},
+       {0x0000a0e8, 0x02050701},
+       {0x0000a0ec, 0x02050702},
+       {0x0000a0f0, 0x02050703},
+       {0x0000a0f4, 0x02050704},
+       {0x0000a0f8, 0x02050705},
+       {0x0000a0fc, 0x02050708},
+       {0x0000a100, 0x02050709},
+       {0x0000a104, 0x0205070a},
+       {0x0000a108, 0x0205070b},
+       {0x0000a10c, 0x0205070c},
+       {0x0000a110, 0x0205070d},
+       {0x0000a114, 0x02050710},
+       {0x0000a118, 0x02050711},
+       {0x0000a11c, 0x02050712},
+       {0x0000a120, 0x02050713},
+       {0x0000a124, 0x02050714},
+       {0x0000a128, 0x02050715},
+       {0x0000a12c, 0x02050730},
+       {0x0000a130, 0x02050731},
+       {0x0000a134, 0x02050732},
+       {0x0000a138, 0x02050733},
+       {0x0000a13c, 0x02050734},
+       {0x0000a140, 0x02050735},
+       {0x0000a144, 0x02050750},
+       {0x0000a148, 0x02050751},
+       {0x0000a14c, 0x02050752},
+       {0x0000a150, 0x02050753},
+       {0x0000a154, 0x02050754},
+       {0x0000a158, 0x02050755},
+       {0x0000a15c, 0x02050770},
+       {0x0000a160, 0x02050771},
+       {0x0000a164, 0x02050772},
+       {0x0000a168, 0x02050773},
+       {0x0000a16c, 0x02050774},
+       {0x0000a170, 0x02050775},
+       {0x0000a174, 0x00000776},
+       {0x0000a178, 0x00000776},
+       {0x0000a17c, 0x00000776},
+       {0x0000a180, 0x00000776},
+       {0x0000a184, 0x00000776},
+       {0x0000a188, 0x00000776},
+       {0x0000a18c, 0x00000776},
+       {0x0000a190, 0x00000776},
+       {0x0000a194, 0x00000776},
+       {0x0000a198, 0x00000776},
+       {0x0000a19c, 0x00000776},
+       {0x0000a1a0, 0x00000776},
+       {0x0000a1a4, 0x00000776},
+       {0x0000a1a8, 0x00000776},
+       {0x0000a1ac, 0x00000776},
+       {0x0000a1b0, 0x00000776},
+       {0x0000a1b4, 0x00000776},
+       {0x0000a1b8, 0x00000776},
+       {0x0000a1bc, 0x00000776},
+       {0x0000a1c0, 0x00000776},
+       {0x0000a1c4, 0x00000776},
+       {0x0000a1c8, 0x00000776},
+       {0x0000a1cc, 0x00000776},
+       {0x0000a1d0, 0x00000776},
+       {0x0000a1d4, 0x00000776},
+       {0x0000a1d8, 0x00000776},
+       {0x0000a1dc, 0x00000776},
+       {0x0000a1e0, 0x00000776},
+       {0x0000a1e4, 0x00000776},
+       {0x0000a1e8, 0x00000776},
+       {0x0000a1ec, 0x00000776},
+       {0x0000a1f0, 0x00000776},
+       {0x0000a1f4, 0x00000776},
+       {0x0000a1f8, 0x00000776},
+       {0x0000a1fc, 0x00000776},
+       {0x0000b000, 0x02000101},
+       {0x0000b004, 0x02000102},
+       {0x0000b008, 0x02000103},
+       {0x0000b00c, 0x02000104},
+       {0x0000b010, 0x02000200},
+       {0x0000b014, 0x02000201},
+       {0x0000b018, 0x02000202},
+       {0x0000b01c, 0x02000203},
+       {0x0000b020, 0x02000204},
+       {0x0000b024, 0x02000205},
+       {0x0000b028, 0x02000208},
+       {0x0000b02c, 0x02000302},
+       {0x0000b030, 0x02000303},
+       {0x0000b034, 0x02000304},
+       {0x0000b038, 0x02000400},
+       {0x0000b03c, 0x02010300},
+       {0x0000b040, 0x02010301},
+       {0x0000b044, 0x02010302},
+       {0x0000b048, 0x02000500},
+       {0x0000b04c, 0x02010400},
+       {0x0000b050, 0x02020300},
+       {0x0000b054, 0x02020301},
+       {0x0000b058, 0x02020302},
+       {0x0000b05c, 0x02020303},
+       {0x0000b060, 0x02020400},
+       {0x0000b064, 0x02030300},
+       {0x0000b068, 0x02030301},
+       {0x0000b06c, 0x02030302},
+       {0x0000b070, 0x02030303},
+       {0x0000b074, 0x02030400},
+       {0x0000b078, 0x02040300},
+       {0x0000b07c, 0x02040301},
+       {0x0000b080, 0x02040302},
+       {0x0000b084, 0x02040303},
+       {0x0000b088, 0x02030500},
+       {0x0000b08c, 0x02040400},
+       {0x0000b090, 0x02050203},
+       {0x0000b094, 0x02050204},
+       {0x0000b098, 0x02050205},
+       {0x0000b09c, 0x02040500},
+       {0x0000b0a0, 0x02050301},
+       {0x0000b0a4, 0x02050302},
+       {0x0000b0a8, 0x02050303},
+       {0x0000b0ac, 0x02050400},
+       {0x0000b0b0, 0x02050401},
+       {0x0000b0b4, 0x02050402},
+       {0x0000b0b8, 0x02050403},
+       {0x0000b0bc, 0x02050500},
+       {0x0000b0c0, 0x02050501},
+       {0x0000b0c4, 0x02050502},
+       {0x0000b0c8, 0x02050503},
+       {0x0000b0cc, 0x02050504},
+       {0x0000b0d0, 0x02050600},
+       {0x0000b0d4, 0x02050601},
+       {0x0000b0d8, 0x02050602},
+       {0x0000b0dc, 0x02050603},
+       {0x0000b0e0, 0x02050604},
+       {0x0000b0e4, 0x02050700},
+       {0x0000b0e8, 0x02050701},
+       {0x0000b0ec, 0x02050702},
+       {0x0000b0f0, 0x02050703},
+       {0x0000b0f4, 0x02050704},
+       {0x0000b0f8, 0x02050705},
+       {0x0000b0fc, 0x02050708},
+       {0x0000b100, 0x02050709},
+       {0x0000b104, 0x0205070a},
+       {0x0000b108, 0x0205070b},
+       {0x0000b10c, 0x0205070c},
+       {0x0000b110, 0x0205070d},
+       {0x0000b114, 0x02050710},
+       {0x0000b118, 0x02050711},
+       {0x0000b11c, 0x02050712},
+       {0x0000b120, 0x02050713},
+       {0x0000b124, 0x02050714},
+       {0x0000b128, 0x02050715},
+       {0x0000b12c, 0x02050730},
+       {0x0000b130, 0x02050731},
+       {0x0000b134, 0x02050732},
+       {0x0000b138, 0x02050733},
+       {0x0000b13c, 0x02050734},
+       {0x0000b140, 0x02050735},
+       {0x0000b144, 0x02050750},
+       {0x0000b148, 0x02050751},
+       {0x0000b14c, 0x02050752},
+       {0x0000b150, 0x02050753},
+       {0x0000b154, 0x02050754},
+       {0x0000b158, 0x02050755},
+       {0x0000b15c, 0x02050770},
+       {0x0000b160, 0x02050771},
+       {0x0000b164, 0x02050772},
+       {0x0000b168, 0x02050773},
+       {0x0000b16c, 0x02050774},
+       {0x0000b170, 0x02050775},
+       {0x0000b174, 0x00000776},
+       {0x0000b178, 0x00000776},
+       {0x0000b17c, 0x00000776},
+       {0x0000b180, 0x00000776},
+       {0x0000b184, 0x00000776},
+       {0x0000b188, 0x00000776},
+       {0x0000b18c, 0x00000776},
+       {0x0000b190, 0x00000776},
+       {0x0000b194, 0x00000776},
+       {0x0000b198, 0x00000776},
+       {0x0000b19c, 0x00000776},
+       {0x0000b1a0, 0x00000776},
+       {0x0000b1a4, 0x00000776},
+       {0x0000b1a8, 0x00000776},
+       {0x0000b1ac, 0x00000776},
+       {0x0000b1b0, 0x00000776},
+       {0x0000b1b4, 0x00000776},
+       {0x0000b1b8, 0x00000776},
+       {0x0000b1bc, 0x00000776},
+       {0x0000b1c0, 0x00000776},
+       {0x0000b1c4, 0x00000776},
+       {0x0000b1c8, 0x00000776},
+       {0x0000b1cc, 0x00000776},
+       {0x0000b1d0, 0x00000776},
+       {0x0000b1d4, 0x00000776},
+       {0x0000b1d8, 0x00000776},
+       {0x0000b1dc, 0x00000776},
+       {0x0000b1e0, 0x00000776},
+       {0x0000b1e4, 0x00000776},
+       {0x0000b1e8, 0x00000776},
+       {0x0000b1ec, 0x00000776},
+       {0x0000b1f0, 0x00000776},
+       {0x0000b1f4, 0x00000776},
+       {0x0000b1f8, 0x00000776},
+       {0x0000b1fc, 0x00000776},
+};
+
+static const u32 ar9200_ar9280_2p0_radio_core_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00007800, 0x00040000},
+       {0x00007804, 0xdb005012},
+       {0x00007808, 0x04924914},
+       {0x0000780c, 0x21084210},
+       {0x00007810, 0x6d801300},
+       {0x00007814, 0x0019beff},
+       {0x00007818, 0x07e41000},
+       {0x0000781c, 0x00392000},
+       {0x00007820, 0x92592480},
+       {0x00007824, 0x00040000},
+       {0x00007828, 0xdb005012},
+       {0x0000782c, 0x04924914},
+       {0x00007830, 0x21084210},
+       {0x00007834, 0x6d801300},
+       {0x00007838, 0x0019beff},
+       {0x0000783c, 0x07e40000},
+       {0x00007840, 0x00392000},
+       {0x00007844, 0x92592480},
+       {0x00007848, 0x00100000},
+       {0x0000784c, 0x773f0567},
+       {0x00007850, 0x54214514},
+       {0x00007854, 0x12035828},
+       {0x00007858, 0x92592692},
+       {0x0000785c, 0x00000000},
+       {0x00007860, 0x56400000},
+       {0x00007864, 0x0a8e370e},
+       {0x00007868, 0xc0102850},
+       {0x0000786c, 0x812d4000},
+       {0x00007870, 0x807ec400},
+       {0x00007874, 0x001b6db0},
+       {0x00007878, 0x00376b63},
+       {0x0000787c, 0x06db6db6},
+       {0x00007880, 0x006d8000},
+       {0x00007884, 0xffeffffe},
+       {0x00007888, 0xffeffffe},
+       {0x0000788c, 0x00010000},
+       {0x00007890, 0x02060aeb},
+       {0x00007894, 0x5a108000},
+};
+
+static const u32 ar9480_1p0_baseband_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e3c, 0xcf946221, 0xcf946221, 0xcf946221, 0xcf946221},
+       {0x00009e44, 0x005c0000, 0x005c0000, 0x005c0000, 0x005c0000},
+       {0x0000a258, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x0000a25c, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a28c, 0x00011111, 0x00011111, 0x00011111, 0x00011111},
+       {0x0000a2c4, 0x00148d18, 0x00148d18, 0x00148d20, 0x00148d20},
+       {0x0000a2d8, 0xf999a800, 0xf999a800, 0xf999a80c, 0xf999a80c},
+       {0x0000a50c, 0x0000c00a, 0x0000c00a, 0x0000c00a, 0x0000c00a},
+       {0x0000a538, 0x00038e8c, 0x00038e8c, 0x00038e8c, 0x00038e8c},
+       {0x0000a53c, 0x0003cecc, 0x0003cecc, 0x0003cecc, 0x0003cecc},
+       {0x0000a540, 0x00040ed4, 0x00040ed4, 0x00040ed4, 0x00040ed4},
+       {0x0000a544, 0x00044edc, 0x00044edc, 0x00044edc, 0x00044edc},
+       {0x0000a548, 0x00048ede, 0x00048ede, 0x00048ede, 0x00048ede},
+       {0x0000a54c, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
+       {0x0000a550, 0x00050f5e, 0x00050f5e, 0x00050f5e, 0x00050f5e},
+       {0x0000a554, 0x00054f9e, 0x00054f9e, 0x00054f9e, 0x00054f9e},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9480_pcie_phy_pll_on_clkreq_disable_L1_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x10012e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9480_common_rx_gain_table_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_modes_high_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+       {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+       {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+};
+
+static const u32 ar9480_common_wo_xlna_rx_gain_table_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x32323232},
+       {0x0000b084, 0x2f2f3232},
+       {0x0000b088, 0x23282a2d},
+       {0x0000b08c, 0x1c1e2123},
+       {0x0000b090, 0x14171919},
+       {0x0000b094, 0x0e0e1214},
+       {0x0000b098, 0x03050707},
+       {0x0000b09c, 0x00030303},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_1p0_mac_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9480_1p0_mac_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00008014, 0x10f810f8, 0x10f810f8, 0x10f810f8, 0x10f810f8},
+       {0x0000801c, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017},
+};
+
+static const u32 ar9480_1p0_tx_gain_table_baseband_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a410, 0x000000d5, 0x000000d5, 0x000000d5, 0x000000d5},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x00004002, 0x00004002, 0x00004002, 0x00004002},
+       {0x0000a508, 0x00008004, 0x00008004, 0x00008004, 0x00008004},
+       {0x0000a510, 0x0001000c, 0x0001000c, 0x0001000c, 0x0001000c},
+       {0x0000a514, 0x0001420b, 0x0001420b, 0x0001420b, 0x0001420b},
+       {0x0000a518, 0x0001824a, 0x0001824a, 0x0001824a, 0x0001824a},
+       {0x0000a51c, 0x0001c44a, 0x0001c44a, 0x0001c44a, 0x0001c44a},
+       {0x0000a520, 0x0002064a, 0x0002064a, 0x0002064a, 0x0002064a},
+       {0x0000a524, 0x0002484a, 0x0002484a, 0x0002484a, 0x0002484a},
+       {0x0000a528, 0x00028a4a, 0x00028a4a, 0x00028a4a, 0x00028a4a},
+       {0x0000a52c, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
+       {0x0000a530, 0x00030e4a, 0x00030e4a, 0x00030e4a, 0x00030e4a},
+       {0x0000a534, 0x00034e8a, 0x00034e8a, 0x00034e8a, 0x00034e8a},
+};
+
+static const u32 ar9480_1p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24646c08, 0x24646c08},
+       {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+       {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+static const u32 ar9480_1p0_soc_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00001133, 0x00001133, 0x00001133, 0x00001133},
+};
+
+static const u32 ar9480_1p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a290},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x0d000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098e4, 0x01ffffff},
+       {0x000098e8, 0x01ffffff},
+       {0x000098ec, 0x01ffffff},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb514},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0x64c355c7},
+       {0x00009e58, 0xfd897735},
+       {0x00009e5c, 0xe9198724},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a644, 0xbfad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a6b0, 0x0000000a},
+       {0x0000a6b4, 0x28f12c01},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+       {0x0000b6b0, 0x0000000a},
+       {0x0000b6b4, 0x00c00001},
+};
+
+static const u32 ar9480_1p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x0131b7c0, 0x0131b7c4, 0x0131b7c4, 0x0131b7c0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00100110, 0x00100110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
+};
+
+static const u32 ar9480_modes_fast_clock_1p0[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00001030, 0x00000268, 0x000004d0},
+       {0x00001070, 0x0000018c, 0x00000318},
+       {0x000010b0, 0x00000fd0, 0x00001fa0},
+       {0x00008014, 0x044c044c, 0x08980898},
+       {0x0000801c, 0x148ec02b, 0x148ec057},
+       {0x00008318, 0x000044c0, 0x00008980},
+       {0x00009e00, 0x0372131c, 0x0372131c},
+       {0x0000a230, 0x0000400b, 0x00004016},
+       {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9480_modes_low_ob_db_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+};
+
+static const u32 ar9480_1p0_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233},
+};
+
+static const u32 ar9480_common_mixed_rx_gain_table_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_pcie_phy_clkreq_disable_L1_1p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x10013e5e},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0000580c},
+};
+
+static const u32 ar9480_1p0_baseband_core_emulation[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafa68e30},
+       {0x00009884, 0x00002842},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009e50, 0x00000000},
+       {0x00009fcc, 0x00000014},
+       {0x0000a344, 0x00000010},
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x71733d01},
+       {0x0000a3a0, 0xd0ad5c12},
+       {0x0000a3c0, 0x22222220},
+       {0x0000a3c4, 0x22222222},
+       {0x0000a404, 0x00418a11},
+       {0x0000a418, 0x050001ce},
+       {0x0000a438, 0x00001800},
+       {0x0000a458, 0x01444452},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a690, 0x00000038},
+};
+
+static const u32 ar9480_1p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016010, 0x6d820001},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x2699e04f},
+       {0x00016050, 0x6db6db6c},
+       {0x00016054, 0x6db60000},
+       {0x00016058, 0x6c200000},
+       {0x00016080, 0x00040000},
+       {0x00016084, 0x9a68048c},
+       {0x00016088, 0x54214514},
+       {0x0001608c, 0x12030409},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd2888888},
+       {0x000160a0, 0x0a108ffe},
+       {0x000160a4, 0x812fc490},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92000000},
+       {0x000160b8, 0x0285dddc},
+       {0x000160bc, 0x02908888},
+       {0x000160c0, 0x00adb6d0},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x0de6c1b0},
+       {0x00016100, 0x3fffbe04},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00200400},
+       {0x00016110, 0x00000000},
+       {0x00016144, 0x02084080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x050a0001},
+       {0x00016284, 0x3d841400},
+       {0x00016288, 0x00000000},
+       {0x0001628c, 0xe3000000},
+       {0x00016290, 0xa1005080},
+       {0x00016294, 0x00000020},
+       {0x00016298, 0x50a02900},
+       {0x00016340, 0x121e4276},
+       {0x00016344, 0x00300000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016410, 0x6c800001},
+       {0x00016440, 0x7f80fff8},
+       {0x0001644c, 0x4699e04f},
+       {0x00016450, 0x6db6db6c},
+       {0x00016454, 0x6db60000},
+       {0x00016500, 0x3fffbe04},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00200400},
+       {0x00016510, 0x00000000},
+       {0x00016544, 0x02084080},
+       {0x00016548, 0x000080c0},
+};
+
+static const u32 ar9480_1p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9480_1p0_sys2ant[][2] = {
+       /* Addr      allmodes  */
+       {0x00063120, 0x00801980},
+};
+
+#endif /* INITVALS_9480_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9480_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9480_2p0_initvals.h
new file mode 100644 (file)
index 0000000..d54163d
--- /dev/null
@@ -0,0 +1,1928 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9480_2P0_H
+#define INITVALS_9480_2P0_H
+
+/* AR9480 2.0 */
+
+static const u32 ar9480_modes_fast_clock_2p0[][3] = {
+       /* Addr      5G_HT20     5G_HT40   */
+       {0x00001030, 0x00000268, 0x000004d0},
+       {0x00001070, 0x0000018c, 0x00000318},
+       {0x000010b0, 0x00000fd0, 0x00001fa0},
+       {0x00008014, 0x044c044c, 0x08980898},
+       {0x0000801c, 0x148ec02b, 0x148ec057},
+       {0x00008318, 0x000044c0, 0x00008980},
+       {0x00009e00, 0x0372131c, 0x0372131c},
+       {0x0000a230, 0x0000400b, 0x00004016},
+       {0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9480_pciephy_clkreq_enable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18253ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9480_2p0_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+       {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+       {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+       {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3039605e, 0x33795d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782},
+       {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
+       {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+       {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
+};
+
+static const u32 ar9480_2p0_mac_core_emulation[][2] = {
+       /* Addr      allmodes  */
+       {0x00000030, 0x000e0085},
+       {0x00000044, 0x00000008},
+       {0x0000805c, 0xffffc7ff},
+       {0x00008344, 0xaa4a105b},
+};
+
+static const u32 ar9480_common_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_pciephy_clkreq_disable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18213ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9480_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x00018c00, 0x18212ede},
+       {0x00018c04, 0x000801d8},
+       {0x00018c08, 0x0003580c},
+};
+
+static const u32 ar9480_2p0_sys3ant[][2] = {
+       /* Addr      allmodes  */
+       {0x00063280, 0x00040807},
+       {0x00063284, 0x104ccccc},
+};
+
+static const u32 ar9480_common_rx_gain_table_ar9280_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x02000101},
+       {0x0000a004, 0x02000102},
+       {0x0000a008, 0x02000103},
+       {0x0000a00c, 0x02000104},
+       {0x0000a010, 0x02000200},
+       {0x0000a014, 0x02000201},
+       {0x0000a018, 0x02000202},
+       {0x0000a01c, 0x02000203},
+       {0x0000a020, 0x02000204},
+       {0x0000a024, 0x02000205},
+       {0x0000a028, 0x02000208},
+       {0x0000a02c, 0x02000302},
+       {0x0000a030, 0x02000303},
+       {0x0000a034, 0x02000304},
+       {0x0000a038, 0x02000400},
+       {0x0000a03c, 0x02010300},
+       {0x0000a040, 0x02010301},
+       {0x0000a044, 0x02010302},
+       {0x0000a048, 0x02000500},
+       {0x0000a04c, 0x02010400},
+       {0x0000a050, 0x02020300},
+       {0x0000a054, 0x02020301},
+       {0x0000a058, 0x02020302},
+       {0x0000a05c, 0x02020303},
+       {0x0000a060, 0x02020400},
+       {0x0000a064, 0x02030300},
+       {0x0000a068, 0x02030301},
+       {0x0000a06c, 0x02030302},
+       {0x0000a070, 0x02030303},
+       {0x0000a074, 0x02030400},
+       {0x0000a078, 0x02040300},
+       {0x0000a07c, 0x02040301},
+       {0x0000a080, 0x02040302},
+       {0x0000a084, 0x02040303},
+       {0x0000a088, 0x02030500},
+       {0x0000a08c, 0x02040400},
+       {0x0000a090, 0x02050203},
+       {0x0000a094, 0x02050204},
+       {0x0000a098, 0x02050205},
+       {0x0000a09c, 0x02040500},
+       {0x0000a0a0, 0x02050301},
+       {0x0000a0a4, 0x02050302},
+       {0x0000a0a8, 0x02050303},
+       {0x0000a0ac, 0x02050400},
+       {0x0000a0b0, 0x02050401},
+       {0x0000a0b4, 0x02050402},
+       {0x0000a0b8, 0x02050403},
+       {0x0000a0bc, 0x02050500},
+       {0x0000a0c0, 0x02050501},
+       {0x0000a0c4, 0x02050502},
+       {0x0000a0c8, 0x02050503},
+       {0x0000a0cc, 0x02050504},
+       {0x0000a0d0, 0x02050600},
+       {0x0000a0d4, 0x02050601},
+       {0x0000a0d8, 0x02050602},
+       {0x0000a0dc, 0x02050603},
+       {0x0000a0e0, 0x02050604},
+       {0x0000a0e4, 0x02050700},
+       {0x0000a0e8, 0x02050701},
+       {0x0000a0ec, 0x02050702},
+       {0x0000a0f0, 0x02050703},
+       {0x0000a0f4, 0x02050704},
+       {0x0000a0f8, 0x02050705},
+       {0x0000a0fc, 0x02050708},
+       {0x0000a100, 0x02050709},
+       {0x0000a104, 0x0205070a},
+       {0x0000a108, 0x0205070b},
+       {0x0000a10c, 0x0205070c},
+       {0x0000a110, 0x0205070d},
+       {0x0000a114, 0x02050710},
+       {0x0000a118, 0x02050711},
+       {0x0000a11c, 0x02050712},
+       {0x0000a120, 0x02050713},
+       {0x0000a124, 0x02050714},
+       {0x0000a128, 0x02050715},
+       {0x0000a12c, 0x02050730},
+       {0x0000a130, 0x02050731},
+       {0x0000a134, 0x02050732},
+       {0x0000a138, 0x02050733},
+       {0x0000a13c, 0x02050734},
+       {0x0000a140, 0x02050735},
+       {0x0000a144, 0x02050750},
+       {0x0000a148, 0x02050751},
+       {0x0000a14c, 0x02050752},
+       {0x0000a150, 0x02050753},
+       {0x0000a154, 0x02050754},
+       {0x0000a158, 0x02050755},
+       {0x0000a15c, 0x02050770},
+       {0x0000a160, 0x02050771},
+       {0x0000a164, 0x02050772},
+       {0x0000a168, 0x02050773},
+       {0x0000a16c, 0x02050774},
+       {0x0000a170, 0x02050775},
+       {0x0000a174, 0x00000776},
+       {0x0000a178, 0x00000776},
+       {0x0000a17c, 0x00000776},
+       {0x0000a180, 0x00000776},
+       {0x0000a184, 0x00000776},
+       {0x0000a188, 0x00000776},
+       {0x0000a18c, 0x00000776},
+       {0x0000a190, 0x00000776},
+       {0x0000a194, 0x00000776},
+       {0x0000a198, 0x00000776},
+       {0x0000a19c, 0x00000776},
+       {0x0000a1a0, 0x00000776},
+       {0x0000a1a4, 0x00000776},
+       {0x0000a1a8, 0x00000776},
+       {0x0000a1ac, 0x00000776},
+       {0x0000a1b0, 0x00000776},
+       {0x0000a1b4, 0x00000776},
+       {0x0000a1b8, 0x00000776},
+       {0x0000a1bc, 0x00000776},
+       {0x0000a1c0, 0x00000776},
+       {0x0000a1c4, 0x00000776},
+       {0x0000a1c8, 0x00000776},
+       {0x0000a1cc, 0x00000776},
+       {0x0000a1d0, 0x00000776},
+       {0x0000a1d4, 0x00000776},
+       {0x0000a1d8, 0x00000776},
+       {0x0000a1dc, 0x00000776},
+       {0x0000a1e0, 0x00000776},
+       {0x0000a1e4, 0x00000776},
+       {0x0000a1e8, 0x00000776},
+       {0x0000a1ec, 0x00000776},
+       {0x0000a1f0, 0x00000776},
+       {0x0000a1f4, 0x00000776},
+       {0x0000a1f8, 0x00000776},
+       {0x0000a1fc, 0x00000776},
+       {0x0000b000, 0x02000101},
+       {0x0000b004, 0x02000102},
+       {0x0000b008, 0x02000103},
+       {0x0000b00c, 0x02000104},
+       {0x0000b010, 0x02000200},
+       {0x0000b014, 0x02000201},
+       {0x0000b018, 0x02000202},
+       {0x0000b01c, 0x02000203},
+       {0x0000b020, 0x02000204},
+       {0x0000b024, 0x02000205},
+       {0x0000b028, 0x02000208},
+       {0x0000b02c, 0x02000302},
+       {0x0000b030, 0x02000303},
+       {0x0000b034, 0x02000304},
+       {0x0000b038, 0x02000400},
+       {0x0000b03c, 0x02010300},
+       {0x0000b040, 0x02010301},
+       {0x0000b044, 0x02010302},
+       {0x0000b048, 0x02000500},
+       {0x0000b04c, 0x02010400},
+       {0x0000b050, 0x02020300},
+       {0x0000b054, 0x02020301},
+       {0x0000b058, 0x02020302},
+       {0x0000b05c, 0x02020303},
+       {0x0000b060, 0x02020400},
+       {0x0000b064, 0x02030300},
+       {0x0000b068, 0x02030301},
+       {0x0000b06c, 0x02030302},
+       {0x0000b070, 0x02030303},
+       {0x0000b074, 0x02030400},
+       {0x0000b078, 0x02040300},
+       {0x0000b07c, 0x02040301},
+       {0x0000b080, 0x02040302},
+       {0x0000b084, 0x02040303},
+       {0x0000b088, 0x02030500},
+       {0x0000b08c, 0x02040400},
+       {0x0000b090, 0x02050203},
+       {0x0000b094, 0x02050204},
+       {0x0000b098, 0x02050205},
+       {0x0000b09c, 0x02040500},
+       {0x0000b0a0, 0x02050301},
+       {0x0000b0a4, 0x02050302},
+       {0x0000b0a8, 0x02050303},
+       {0x0000b0ac, 0x02050400},
+       {0x0000b0b0, 0x02050401},
+       {0x0000b0b4, 0x02050402},
+       {0x0000b0b8, 0x02050403},
+       {0x0000b0bc, 0x02050500},
+       {0x0000b0c0, 0x02050501},
+       {0x0000b0c4, 0x02050502},
+       {0x0000b0c8, 0x02050503},
+       {0x0000b0cc, 0x02050504},
+       {0x0000b0d0, 0x02050600},
+       {0x0000b0d4, 0x02050601},
+       {0x0000b0d8, 0x02050602},
+       {0x0000b0dc, 0x02050603},
+       {0x0000b0e0, 0x02050604},
+       {0x0000b0e4, 0x02050700},
+       {0x0000b0e8, 0x02050701},
+       {0x0000b0ec, 0x02050702},
+       {0x0000b0f0, 0x02050703},
+       {0x0000b0f4, 0x02050704},
+       {0x0000b0f8, 0x02050705},
+       {0x0000b0fc, 0x02050708},
+       {0x0000b100, 0x02050709},
+       {0x0000b104, 0x0205070a},
+       {0x0000b108, 0x0205070b},
+       {0x0000b10c, 0x0205070c},
+       {0x0000b110, 0x0205070d},
+       {0x0000b114, 0x02050710},
+       {0x0000b118, 0x02050711},
+       {0x0000b11c, 0x02050712},
+       {0x0000b120, 0x02050713},
+       {0x0000b124, 0x02050714},
+       {0x0000b128, 0x02050715},
+       {0x0000b12c, 0x02050730},
+       {0x0000b130, 0x02050731},
+       {0x0000b134, 0x02050732},
+       {0x0000b138, 0x02050733},
+       {0x0000b13c, 0x02050734},
+       {0x0000b140, 0x02050735},
+       {0x0000b144, 0x02050750},
+       {0x0000b148, 0x02050751},
+       {0x0000b14c, 0x02050752},
+       {0x0000b150, 0x02050753},
+       {0x0000b154, 0x02050754},
+       {0x0000b158, 0x02050755},
+       {0x0000b15c, 0x02050770},
+       {0x0000b160, 0x02050771},
+       {0x0000b164, 0x02050772},
+       {0x0000b168, 0x02050773},
+       {0x0000b16c, 0x02050774},
+       {0x0000b170, 0x02050775},
+       {0x0000b174, 0x00000776},
+       {0x0000b178, 0x00000776},
+       {0x0000b17c, 0x00000776},
+       {0x0000b180, 0x00000776},
+       {0x0000b184, 0x00000776},
+       {0x0000b188, 0x00000776},
+       {0x0000b18c, 0x00000776},
+       {0x0000b190, 0x00000776},
+       {0x0000b194, 0x00000776},
+       {0x0000b198, 0x00000776},
+       {0x0000b19c, 0x00000776},
+       {0x0000b1a0, 0x00000776},
+       {0x0000b1a4, 0x00000776},
+       {0x0000b1a8, 0x00000776},
+       {0x0000b1ac, 0x00000776},
+       {0x0000b1b0, 0x00000776},
+       {0x0000b1b4, 0x00000776},
+       {0x0000b1b8, 0x00000776},
+       {0x0000b1bc, 0x00000776},
+       {0x0000b1c0, 0x00000776},
+       {0x0000b1c4, 0x00000776},
+       {0x0000b1c8, 0x00000776},
+       {0x0000b1cc, 0x00000776},
+       {0x0000b1d0, 0x00000776},
+       {0x0000b1d4, 0x00000776},
+       {0x0000b1d8, 0x00000776},
+       {0x0000b1dc, 0x00000776},
+       {0x0000b1e0, 0x00000776},
+       {0x0000b1e4, 0x00000776},
+       {0x0000b1e8, 0x00000776},
+       {0x0000b1ec, 0x00000776},
+       {0x0000b1f0, 0x00000776},
+       {0x0000b1f4, 0x00000776},
+       {0x0000b1f8, 0x00000776},
+       {0x0000b1fc, 0x00000776},
+};
+
+static const u32 ar9200_ar9280_2p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00007800, 0x00040000},
+       {0x00007804, 0xdb005012},
+       {0x00007808, 0x04924914},
+       {0x0000780c, 0x21084210},
+       {0x00007810, 0x6d801300},
+       {0x00007814, 0x0019beff},
+       {0x00007818, 0x07e41000},
+       {0x0000781c, 0x00392000},
+       {0x00007820, 0x92592480},
+       {0x00007824, 0x00040000},
+       {0x00007828, 0xdb005012},
+       {0x0000782c, 0x04924914},
+       {0x00007830, 0x21084210},
+       {0x00007834, 0x6d801300},
+       {0x00007838, 0x0019beff},
+       {0x0000783c, 0x07e40000},
+       {0x00007840, 0x00392000},
+       {0x00007844, 0x92592480},
+       {0x00007848, 0x00100000},
+       {0x0000784c, 0x773f0567},
+       {0x00007850, 0x54214514},
+       {0x00007854, 0x12035828},
+       {0x00007858, 0x92592692},
+       {0x0000785c, 0x00000000},
+       {0x00007860, 0x56400000},
+       {0x00007864, 0x0a8e370e},
+       {0x00007868, 0xc0102850},
+       {0x0000786c, 0x812d4000},
+       {0x00007870, 0x807ec400},
+       {0x00007874, 0x001b6db0},
+       {0x00007878, 0x00376b63},
+       {0x0000787c, 0x06db6db6},
+       {0x00007880, 0x006d8000},
+       {0x00007884, 0xffeffffe},
+       {0x00007888, 0xffeffffe},
+       {0x0000788c, 0x00010000},
+       {0x00007890, 0x02060aeb},
+       {0x00007894, 0x5a108000},
+};
+
+static const u32 ar9480_2p0_mac_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00008014, 0x10f810f8, 0x10f810f8, 0x10f810f8, 0x10f810f8},
+       {0x0000801c, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017, 0x0e8d8017},
+};
+
+static const u32 ar9480_2p0_radio_postamble_sys3ant[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+       {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+       {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+};
+
+static const u32 ar9480_2p0_baseband_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e3c, 0xcf946221, 0xcf946221, 0xcf946221, 0xcf946221},
+       {0x00009e44, 0xfc5c0000, 0xfc5c0000, 0xfc5c0000, 0xfc5c0000},
+       {0x0000a258, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+       {0x0000a25c, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a28c, 0x00011111, 0x00011111, 0x00011111, 0x00011111},
+       {0x0000a2c4, 0x00148d18, 0x00148d18, 0x00148d20, 0x00148d20},
+       {0x0000a2d8, 0xf999a800, 0xf999a800, 0xf999a80c, 0xf999a80c},
+       {0x0000a50c, 0x0000c00a, 0x0000c00a, 0x0000c00a, 0x0000c00a},
+       {0x0000a538, 0x00038e8c, 0x00038e8c, 0x00038e8c, 0x00038e8c},
+       {0x0000a53c, 0x0003cecc, 0x0003cecc, 0x0003cecc, 0x0003cecc},
+       {0x0000a540, 0x00040ed4, 0x00040ed4, 0x00040ed4, 0x00040ed4},
+       {0x0000a544, 0x00044edc, 0x00044edc, 0x00044edc, 0x00044edc},
+       {0x0000a548, 0x00048ede, 0x00048ede, 0x00048ede, 0x00048ede},
+       {0x0000a54c, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e},
+       {0x0000a550, 0x00050f5e, 0x00050f5e, 0x00050f5e, 0x00050f5e},
+       {0x0000a554, 0x00054f9e, 0x00054f9e, 0x00054f9e, 0x00054f9e},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9480_2p0_radio_postamble_sys2ant[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+       {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+       {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+};
+
+static const u32 ar9480_common_wo_xlna_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x32323232},
+       {0x0000b084, 0x2f2f3232},
+       {0x0000b088, 0x23282a2d},
+       {0x0000b08c, 0x1c1e2123},
+       {0x0000b090, 0x14171919},
+       {0x0000b094, 0x0e0e1214},
+       {0x0000b098, 0x03050707},
+       {0x0000b09c, 0x00030303},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_2p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9480_modes_low_ob_db_tx_gain_table_2p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9480_2p0_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233},
+};
+
+static const u32 ar9480_2p0_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a9f6b},
+       {0x0000980c, 0x04900000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x6400a290},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x0d000600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32440bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098e4, 0x01ffffff},
+       {0x000098e8, 0x01ffffff},
+       {0x000098ec, 0x01ffffff},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009bf0, 0x80000000},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x9883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c0040b},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x990bb515},
+       {0x00009e28, 0x0c6f0000},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009e54, 0xe4c355c7},
+       {0x00009e58, 0xfd897735},
+       {0x00009e5c, 0xe9198724},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x00009fd0, 0x01193b93},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0c9bd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00100000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x05000080},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a454, 0x07000000},
+       {0x0000a644, 0xbfad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00002037},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a6b0, 0x0000000a},
+       {0x0000a6b4, 0x00512c01},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+       {0x0000a7f0, 0x80000000},
+       {0x0000a8d0, 0x004b6a8e},
+       {0x0000a8d4, 0x00000820},
+       {0x0000a8dc, 0x00000000},
+       {0x0000a8f0, 0x00000000},
+       {0x0000a8f4, 0x00000000},
+       {0x0000abf0, 0x80000000},
+       {0x0000b2d0, 0x00000080},
+       {0x0000b2d4, 0x00000000},
+       {0x0000b2ec, 0x00000000},
+       {0x0000b2f0, 0x00000000},
+       {0x0000b2f4, 0x00000000},
+       {0x0000b2f8, 0x00000000},
+       {0x0000b408, 0x0e79e5c0},
+       {0x0000b40c, 0x00820820},
+       {0x0000b420, 0x00000000},
+       {0x0000b6b0, 0x0000000a},
+       {0x0000b6b4, 0x00000001},
+};
+
+static const u32 ar9480_2p0_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+       {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+       {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+       {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
+};
+
+static const u32 ar9480_modes_high_ob_db_tx_gain_table_2p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+       {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+       {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9480_2p0_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73f00000},
+       {0x0001600c, 0x00000000},
+       {0x00016010, 0x6d820001},
+       {0x00016040, 0x7f80fff8},
+       {0x0001604c, 0x2699e04f},
+       {0x00016050, 0x6db6db6c},
+       {0x00016058, 0x6c200000},
+       {0x00016080, 0x00040000},
+       {0x00016084, 0x9a68048c},
+       {0x00016088, 0x54214514},
+       {0x0001608c, 0x1203040b},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd2888888},
+       {0x000160a0, 0x0a108ffe},
+       {0x000160a4, 0x812fc491},
+       {0x000160a8, 0x423c8000},
+       {0x000160b4, 0x92000000},
+       {0x000160b8, 0x0285dddc},
+       {0x000160bc, 0x02908888},
+       {0x000160c0, 0x00adb6d0},
+       {0x000160c4, 0x6db6db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x0de6c1b0},
+       {0x00016100, 0x3fffbe04},
+       {0x00016104, 0xfff80000},
+       {0x00016108, 0x00200400},
+       {0x00016110, 0x00000000},
+       {0x00016144, 0x02084080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x050a0001},
+       {0x00016284, 0x3d841400},
+       {0x00016288, 0x00000000},
+       {0x0001628c, 0xe3000000},
+       {0x00016290, 0xa1005080},
+       {0x00016294, 0x00000020},
+       {0x00016298, 0x54a82900},
+       {0x00016340, 0x121e4276},
+       {0x00016344, 0x00300000},
+       {0x00016400, 0x36db6db6},
+       {0x00016404, 0x6db6db40},
+       {0x00016408, 0x73f00000},
+       {0x0001640c, 0x00000000},
+       {0x00016410, 0x6c800001},
+       {0x00016440, 0x7f80fff8},
+       {0x0001644c, 0x4699e04f},
+       {0x00016450, 0x6db6db6c},
+       {0x00016500, 0x3fffbe04},
+       {0x00016504, 0xfff80000},
+       {0x00016508, 0x00200400},
+       {0x00016510, 0x00000000},
+       {0x00016544, 0x02084080},
+       {0x00016548, 0x000080c0},
+};
+
+static const u32 ar9480_2p0_tx_gain_table_baseband_postamble_emulation[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a410, 0x000000d5, 0x000000d5, 0x000000d5, 0x000000d5},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x00004002, 0x00004002, 0x00004002, 0x00004002},
+       {0x0000a508, 0x00008004, 0x00008004, 0x00008004, 0x00008004},
+       {0x0000a510, 0x0001000c, 0x0001000c, 0x0001000c, 0x0001000c},
+       {0x0000a514, 0x0001420b, 0x0001420b, 0x0001420b, 0x0001420b},
+       {0x0000a518, 0x0001824a, 0x0001824a, 0x0001824a, 0x0001824a},
+       {0x0000a51c, 0x0001c44a, 0x0001c44a, 0x0001c44a, 0x0001c44a},
+       {0x0000a520, 0x0002064a, 0x0002064a, 0x0002064a, 0x0002064a},
+       {0x0000a524, 0x0002484a, 0x0002484a, 0x0002484a, 0x0002484a},
+       {0x0000a528, 0x00028a4a, 0x00028a4a, 0x00028a4a, 0x00028a4a},
+       {0x0000a52c, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a},
+       {0x0000a530, 0x00030e4a, 0x00030e4a, 0x00030e4a, 0x00030e4a},
+       {0x0000a534, 0x00034e8a, 0x00034e8a, 0x00034e8a, 0x00034e8a},
+};
+
+static const u32 ar9480_2p0_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000004c2},
+};
+
+static const u32 ar9480_2p0_sys2ant[][2] = {
+       /* Addr      allmodes  */
+       {0x00063120, 0x00801980},
+};
+
+static const u32 ar9480_2p0_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x000e0085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00001810, 0x0f000003},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00080000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008050, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00b00005},
+       {0x000080d8, 0x00400002},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486e00},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008244, 0x0010f400},
+       {0x00008248, 0x00000800},
+       {0x0000824c, 0x0001e800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x99c00010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x0000001f},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0xffff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9480_2p0_mac_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9480_common_mixed_rx_gain_table_2p0[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x03820190},
+       {0x0000a030, 0x03840383},
+       {0x0000a034, 0x03880385},
+       {0x0000a038, 0x038a0389},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x29292929},
+       {0x0000a084, 0x29292929},
+       {0x0000a088, 0x29292929},
+       {0x0000a08c, 0x29292929},
+       {0x0000a090, 0x22292929},
+       {0x0000a094, 0x1d1d2222},
+       {0x0000a098, 0x0c111117},
+       {0x0000a09c, 0x00030303},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x2a2d2f32},
+       {0x0000b084, 0x21232328},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
+};
+
+static const u32 ar9480_modes_green_ob_db_tx_gain_table_2p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+       {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
+       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
+       {0x00016054, 0x6db60180, 0x6db60180, 0x6db60180, 0x6db60180},
+       {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
+       {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
+       {0x00016454, 0x6db60180, 0x6db60180, 0x6db60180, 0x6db60180},
+};
+
+static const u32 ar9480_2p0_BTCOEX_MAX_TXPWR_table[][2] = {
+       /* Addr      allmodes  */
+       {0x000018c0, 0x10101010},
+       {0x000018c4, 0x10101010},
+       {0x000018c8, 0x10101010},
+       {0x000018cc, 0x10101010},
+       {0x000018d0, 0x10101010},
+       {0x000018d4, 0x10101010},
+       {0x000018d8, 0x10101010},
+       {0x000018dc, 0x10101010},
+};
+
+static const u32 ar9480_2p0_baseband_core_emulation[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafa68e30},
+       {0x00009884, 0x00002842},
+       {0x00009c04, 0xff55ff55},
+       {0x00009c08, 0x0320ff55},
+       {0x00009e50, 0x00000000},
+       {0x00009fcc, 0x00000014},
+       {0x0000a344, 0x00000010},
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x71733d01},
+       {0x0000a3a0, 0xd0ad5c12},
+       {0x0000a3c0, 0x22222220},
+       {0x0000a3c4, 0x22222222},
+       {0x0000a404, 0x00418a11},
+       {0x0000a418, 0x050001ce},
+       {0x0000a438, 0x00001800},
+       {0x0000a458, 0x01444452},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a690, 0x00000038},
+};
+
+#endif /* INITVALS_9480_2P0_H */
index 5d9a9aabe476bb5fc5e85b1829703a1eaf844b42..94d887b65e6993a778c12dd3ca47d55426a013dd 100644 (file)
@@ -87,17 +87,14 @@ struct ath_config {
  * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
  * @BUF_AGGR: Indicates whether the buffer can be aggregated
  *     (used in aggregation scheduling)
- * @BUF_XRETRY: To denote excessive retries of the buffer
  */
 enum buffer_type {
        BUF_AMPDU               = BIT(0),
        BUF_AGGR                = BIT(1),
-       BUF_XRETRY              = BIT(2),
 };
 
 #define bf_isampdu(bf)         (bf->bf_state.bf_type & BUF_AMPDU)
 #define bf_isaggr(bf)          (bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isxretried(bf)      (bf->bf_state.bf_type & BUF_XRETRY)
 
 #define ATH_TXSTATUS_RING_SIZE 64
 
@@ -216,6 +213,7 @@ struct ath_frame_info {
 struct ath_buf_state {
        u8 bf_type;
        u8 bfs_paprd;
+       u8 ndelim;
        u16 seqno;
        unsigned long bfs_paprd_timestamp;
 };
@@ -230,7 +228,6 @@ struct ath_buf {
        dma_addr_t bf_daddr;            /* physical addr of desc */
        dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
        bool bf_stale;
-       u16 bf_flags;
        struct ath_buf_state bf_state;
 };
 
@@ -277,8 +274,7 @@ struct ath_tx_control {
 };
 
 #define ATH_TX_ERROR        0x01
-#define ATH_TX_XRETRY       0x02
-#define ATH_TX_BAR          0x04
+#define ATH_TX_BAR          0x02
 
 /**
  * @txq_map:  Index is mac80211 queue number.  This is
@@ -425,6 +421,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
 
 #define ATH_PAPRD_TIMEOUT      100 /* msecs */
 
+void ath_reset_work(struct work_struct *work);
 void ath_hw_check(struct work_struct *work);
 void ath_hw_pll_work(struct work_struct *work);
 void ath_paprd_calibrate(struct work_struct *work);
@@ -460,6 +457,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
 #define ATH_LED_PIN_9287               8
 #define ATH_LED_PIN_9300               10
 #define ATH_LED_PIN_9485               6
+#define ATH_LED_PIN_9480               0
 
 #ifdef CONFIG_MAC80211_LEDS
 void ath_init_leds(struct ath_softc *sc);
@@ -604,6 +602,7 @@ struct ath_softc {
        struct mutex mutex;
        struct work_struct paprd_work;
        struct work_struct hw_check_work;
+       struct work_struct hw_reset_work;
        struct completion paprd_complete;
 
        unsigned int hw_busy_count;
@@ -647,10 +646,10 @@ struct ath_softc {
        struct ath_descdma txsdma;
 
        struct ath_ant_comb ant_comb;
+       u8 ant_tx, ant_rx;
 };
 
 void ath9k_tasklet(unsigned long data);
-int ath_reset(struct ath_softc *sc, bool retry_tx);
 int ath_cabq_update(struct ath_softc *);
 
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -668,6 +667,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath9k_reload_chainmask_settings(struct ath_softc *sc);
 
 void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
 bool ath9k_uses_beacons(int type);
index 086c9c816bf78b0e0210869936c3feed40772ee1..9cdeaebc844f4b0064d5edabd0c8d419b4eedc5a 100644 (file)
@@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
        struct sk_buff *skb = bf->bf_mpdu;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       struct ath_desc *ds;
-       struct ath9k_11n_rate_series series[4];
-       int flags, ctsrate = 0, ctsduration = 0;
+       struct ath_tx_info info;
        struct ieee80211_supported_band *sband;
+       u8 chainmask = ah->txchainmask;
        u8 rate = 0;
 
        ath9k_reset_beacon_status(sc);
 
-       ds = bf->bf_desc;
-       flags = ATH9K_TXDESC_NOACK;
-
-       ds->ds_link = 0;
-
        sband = &sc->sbands[common->hw->conf.channel->band];
        rate = sband->bitrates[rateidx].hw_value;
        if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
                rate |= sband->bitrates[rateidx].hw_value_short;
 
-       ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
-                              ATH9K_PKT_TYPE_BEACON,
-                              MAX_RATE_POWER,
-                              ATH9K_TXKEYIX_INVALID,
-                              ATH9K_KEY_TYPE_CLEAR,
-                              flags);
-
-       /* NB: beacon's BufLen must be a multiple of 4 bytes */
-       ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
-                           true, true, ds, bf->bf_buf_addr,
-                           sc->beacon.beaconq);
-
-       memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-       series[0].Tries = 1;
-       series[0].Rate = rate;
-       series[0].ChSel = ath_txchainmask_reduction(sc,
-                       common->tx_chainmask, series[0].Rate);
-       series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
-       ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
-                                    series, 4, 0);
+       memset(&info, 0, sizeof(info));
+       info.pkt_len = skb->len + FCS_LEN;
+       info.type = ATH9K_PKT_TYPE_BEACON;
+       info.txpower = MAX_RATE_POWER;
+       info.keyix = ATH9K_TXKEYIX_INVALID;
+       info.keytype = ATH9K_KEY_TYPE_CLEAR;
+       info.flags = ATH9K_TXDESC_NOACK;
+
+       info.buf_addr[0] = bf->bf_buf_addr;
+       info.buf_len[0] = roundup(skb->len, 4);
+
+       info.is_first = true;
+       info.is_last = true;
+
+       info.qcu = sc->beacon.beaconq;
+
+       info.rates[0].Tries = 1;
+       info.rates[0].Rate = rate;
+       info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
+
+       ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
 }
 
 static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -386,9 +381,7 @@ void ath_beacon_tasklet(unsigned long data)
                        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);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
                }
 
                return;
@@ -519,6 +512,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
        /* Set the computed AP beacon timers */
 
        ath9k_hw_disable_interrupts(ah);
+       sc->sc_flags |= SC_OP_TSF_RESET;
        ath9k_beacon_init(sc, nexttbtt, intval);
        sc->beacon.bmisscnt = 0;
        ath9k_hw_set_interrupts(ah, ah->imask);
index 727e8de22fda111803af1aaeb742734ef2fae9e7..179da20992703fc99af3840d6e51349de5c5c5a3 100644 (file)
@@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
                             size_t count, loff_t *ppos)
 {
        struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
        char buf[32];
        unsigned int len;
 
-       len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
+       len = sprintf(buf, "0x%08x\n", ah->txchainmask);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
                             size_t count, loff_t *ppos)
 {
        struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
        unsigned long mask;
        char buf[32];
        ssize_t len;
@@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
        if (strict_strtoul(buf, 0, &mask))
                return -EINVAL;
 
-       common->tx_chainmask = mask;
-       sc->sc_ah->caps.tx_chainmask = mask;
+       ah->txchainmask = mask;
+       ah->caps.tx_chainmask = mask;
        return count;
 }
 
@@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
                             size_t count, loff_t *ppos)
 {
        struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
        char buf[32];
        unsigned int len;
 
-       len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
+       len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
@@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
                             size_t count, loff_t *ppos)
 {
        struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
        unsigned long mask;
        char buf[32];
        ssize_t len;
@@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
        if (strict_strtoul(buf, 0, &mask))
                return -EINVAL;
 
-       common->rx_chainmask = mask;
-       sc->sc_ah->caps.rx_chainmask = mask;
+       ah->rxchainmask = mask;
+       ah->caps.rx_chainmask = mask;
        return count;
 }
 
@@ -826,7 +826,8 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 }
 
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-                      struct ath_tx_status *ts, struct ath_txq *txq)
+                      struct ath_tx_status *ts, struct ath_txq *txq,
+                      unsigned int flags)
 {
 #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
                        [sc->debug.tsidx].c)
@@ -836,12 +837,12 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
        sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
 
        if (bf_isampdu(bf)) {
-               if (bf_isxretried(bf))
+               if (flags & ATH_TX_BAR)
                        TX_STAT_INC(qnum, a_xretries);
                else
                        TX_STAT_INC(qnum, a_completed);
        } else {
-               if (bf_isxretried(bf))
+               if (ts->ts_status & ATH9K_TXERR_XRETRY)
                        TX_STAT_INC(qnum, xretries);
                else
                        TX_STAT_INC(qnum, completed);
@@ -1323,16 +1324,17 @@ void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
 
        ath9k_ps_wakeup(sc);
 
+       spin_lock_bh(&sc->debug.samp_lock);
+
        spin_lock_irqsave(&common->cc_lock, flags);
        ath_hw_cycle_counters_update(common);
-       spin_unlock_irqrestore(&common->cc_lock, flags);
-
-       spin_lock_bh(&sc->debug.samp_lock);
 
        ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
        ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
        ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
        ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
        ATH_SAMP_DBG(noise) = ah->noise;
 
        REG_WRITE_D(ah, AR_MACMISC,
@@ -1373,6 +1375,9 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
        u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
        u8 nread;
 
+       if (sc->sc_flags & SC_OP_INVALID)
+               return -EAGAIN;
+
        buf = vmalloc(size);
        if (!buf)
                return -ENOMEM;
@@ -1381,10 +1386,14 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
                vfree(buf);
                return -ENOMEM;
        }
+       /* Account the current state too */
+       ath9k_debug_samp_bb_mac(sc);
 
        spin_lock_bh(&sc->debug.samp_lock);
        memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
                        sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
+       len += snprintf(buf + len, size - len,
+                       "Current Sample Index: %d\n", sc->debug.sampidx);
        spin_unlock_bh(&sc->debug.samp_lock);
 
        len += snprintf(buf + len, size - len,
index 95f85bdc8db7e2035266f86944b2fae9eb7b40a0..39f89bc9abcddfcf45ad6615425ddcafbf48f06b 100644 (file)
@@ -230,7 +230,8 @@ int ath9k_init_debug(struct ath_hw *ah);
 void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-                      struct ath_tx_status *ts, struct ath_txq *txq);
+                      struct ath_tx_status *ts, struct ath_txq *txq,
+                      unsigned int flags);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 
 #else
@@ -252,7 +253,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
                                     struct ath_buf *bf,
                                     struct ath_tx_status *ts,
-                                    struct ath_txq *txq)
+                                    struct ath_txq *txq,
+                                    unsigned int flags)
 {
 }
 
index e61404dda8c59b36be9766dada75b3c16ae3560e..e46f751ab50818d1c30d31a6f271c67409192eef 100644 (file)
@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
                pPdGainBoundaries[i] =
                        min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
 
-               if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-                       minDelta = pPdGainBoundaries[0] - 23;
-                       pPdGainBoundaries[0] = 23;
-               } else {
-                       minDelta = 0;
-               }
+               minDelta = 0;
 
                if (i == 0) {
                        if (AR_SREV_9280_20_OR_LATER(ah))
index ea658e794cbdf70f8dc8c1f016afb96a59f5d106..303560e49ac88f399f4a25f197bc7609d9e7065e 100644 (file)
@@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
        REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
 
        for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
-               if (AR_SREV_5416_20_OR_LATER(ah) &&
-                   (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
-                   (i != 0)) {
-                       regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-               } else
-                       regChainOffset = i * 0x1000;
+               regChainOffset = i * 0x1000;
 
                if (pEepData->baseEepHeader.txMask & (1 << i)) {
                        pRawDataset = pEepData->calPierData2G[i];
@@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
 
                        ENABLE_REGWRITE_BUFFER(ah);
 
-                       if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-                               REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
-                                         SM(pdGainOverlap_t2,
-                                            AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
-                                         | SM(gainBoundaries[0],
-                                              AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
-                                         | SM(gainBoundaries[1],
-                                              AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
-                                         | SM(gainBoundaries[2],
-                                              AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
-                                         | SM(gainBoundaries[3],
-                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
-                       }
+                       REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+                                 SM(pdGainOverlap_t2,
+                                    AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+                                 | SM(gainBoundaries[0],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+                                 | SM(gainBoundaries[1],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+                                 | SM(gainBoundaries[2],
+                                      AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+                                 | SM(gainBoundaries[3],
+                              AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
 
                        regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
                        for (j = 0; j < 32; j++) {
@@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
        if (test)
            return;
 
-       if (AR_SREV_9280_20_OR_LATER(ah)) {
-               for (i = 0; i < Ar5416RateSize; i++)
-                       ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
-       }
+       for (i = 0; i < Ar5416RateSize; i++)
+               ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
 
        ENABLE_REGWRITE_BUFFER(ah);
 
@@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
        REGWRITE_BUFFER_FLUSH(ah);
 }
 
-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
-                                 struct ath9k_channel *chan)
-{
-       struct modal_eep_4k_header *pModal;
-       struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-       u8 biaslevel;
-
-       if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
-               return;
-
-       if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
-               return;
-
-       pModal = &eep->modalHeader;
-
-       if (pModal->xpaBiasLvl != 0xff) {
-               biaslevel = pModal->xpaBiasLvl;
-               INI_RA(&ah->iniAddac, 7, 1) =
-                 (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
-       }
-}
-
 static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
                                 struct modal_eep_4k_header *pModal,
                                 struct ar5416_eeprom_4k *eep,
@@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
        u8 txRxAttenLocal;
        u8 ob[5], db1[5], db2[5];
        u8 ant_div_control1, ant_div_control2;
+       u8 bb_desired_scale;
        u32 regVal;
 
        pModal = &eep->modalHeader;
@@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
                                      AR_PHY_SETTLING_SWITCH,
                                      pModal->swSettleHt40);
        }
-       if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
-               u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
-                               EEP_4K_BB_DESIRED_SCALE_MASK);
-               if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
-                       u32 pwrctrl, mask, clr;
-
-                       mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
-                       pwrctrl = mask * bb_desired_scale;
-                       clr = mask * 0x1f;
-                       REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
-                       REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
-                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
-
-                       mask = BIT(0)|BIT(5)|BIT(15);
-                       pwrctrl = mask * bb_desired_scale;
-                       clr = mask * 0x1f;
-                       REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
-
-                       mask = BIT(0)|BIT(5);
-                       pwrctrl = mask * bb_desired_scale;
-                       clr = mask * 0x1f;
-                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
-                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
-               }
+
+       bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+                       EEP_4K_BB_DESIRED_SCALE_MASK);
+       if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+               u32 pwrctrl, mask, clr;
+
+               mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+               mask = BIT(0)|BIT(5)|BIT(15);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+               mask = BIT(0)|BIT(5);
+               pwrctrl = mask * bb_desired_scale;
+               clr = mask * 0x1f;
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+               REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
        }
 }
 
@@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = {
        .get_eeprom_ver         = ath9k_hw_4k_get_eeprom_ver,
        .get_eeprom_rev         = ath9k_hw_4k_get_eeprom_rev,
        .set_board_values       = ath9k_hw_4k_set_board_values,
-       .set_addac              = ath9k_hw_4k_set_addac,
        .set_txpower            = ath9k_hw_4k_set_txpower,
        .get_spur_channel       = ath9k_hw_4k_get_spur_channel
 };
index 21f180db23810dddf52ffd2eed2364d75e3cb82d..6698b722b604e8a4c9b5f1c29b50ec8a6584c7a1 100644 (file)
@@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
        if (test)
                return;
 
-       if (AR_SREV_9280_20_OR_LATER(ah)) {
-               for (i = 0; i < Ar5416RateSize; i++)
-                       ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
-       }
+       for (i = 0; i < Ar5416RateSize; i++)
+               ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
 
        ENABLE_REGWRITE_BUFFER(ah);
 
@@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
        REGWRITE_BUFFER_FLUSH(ah);
 }
 
-static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
-                                     struct ath9k_channel *chan)
-{
-}
-
 static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
                                             struct ath9k_channel *chan)
 {
@@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops = {
        .get_eeprom_ver         = ath9k_hw_ar9287_get_eeprom_ver,
        .get_eeprom_rev         = ath9k_hw_ar9287_get_eeprom_rev,
        .set_board_values       = ath9k_hw_ar9287_set_board_values,
-       .set_addac              = ath9k_hw_ar9287_set_addac,
        .set_txpower            = ath9k_hw_ar9287_set_txpower,
        .get_spur_channel       = ath9k_hw_ar9287_get_spur_channel
 };
index e7e84be8beed32d2768d08888a7083427338997b..eda681fc7ba6d8bd00283bea564b263305d2a2aa 100644 (file)
@@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
                                break;
                }
 
-               if (AR_SREV_5416_20_OR_LATER(ah) &&
-                   (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+               if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
                        regChainOffset = (i == 1) ? 0x2000 : 0x1000;
                else
                        regChainOffset = i * 0x1000;
@@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
                          SM(pModal->iqCalQCh[i],
                             AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
 
-               if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
-                       ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
-                                             regChainOffset, i);
+               ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+                                     regChainOffset, i);
        }
 
        if (AR_SREV_9280_20_OR_LATER(ah)) {
@@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
                      xpdGainValues[2]);
 
        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-               if (AR_SREV_5416_20_OR_LATER(ah) &&
-                   (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+               if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
                    (i != 0)) {
                        regChainOffset = (i == 1) ? 0x2000 : 0x1000;
                } else
@@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
 
                        ENABLE_REGWRITE_BUFFER(ah);
 
-                       if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-                               if (OLC_FOR_AR9280_20_LATER) {
-                                       REG_WRITE(ah,
-                                               AR_PHY_TPCRG5 + regChainOffset,
-                                               SM(0x6,
-                                               AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
-                                               SM_PD_GAIN(1) | SM_PD_GAIN(2) |
-                                               SM_PD_GAIN(3) | SM_PD_GAIN(4));
-                               } else {
-                                       REG_WRITE(ah,
-                                               AR_PHY_TPCRG5 + regChainOffset,
-                                               SM(pdGainOverlap_t2,
-                                               AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
-                                               SM_PDGAIN_B(0, 1) |
-                                               SM_PDGAIN_B(1, 2) |
-                                               SM_PDGAIN_B(2, 3) |
-                                               SM_PDGAIN_B(3, 4));
-                               }
+                       if (OLC_FOR_AR9280_20_LATER) {
+                               REG_WRITE(ah,
+                                       AR_PHY_TPCRG5 + regChainOffset,
+                                       SM(0x6,
+                                       AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+                                       SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+                                       SM_PD_GAIN(3) | SM_PD_GAIN(4));
+                       } else {
+                               REG_WRITE(ah,
+                                       AR_PHY_TPCRG5 + regChainOffset,
+                                       SM(pdGainOverlap_t2,
+                                       AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+                                       SM_PDGAIN_B(0, 1) |
+                                       SM_PDGAIN_B(1, 2) |
+                                       SM_PDGAIN_B(2, 3) |
+                                       SM_PDGAIN_B(3, 4));
                        }
 
-
                        ath9k_adjust_pdadc_values(ah, pwr_table_offset,
                                                  diff, pdadcValues);
 
index 5113dd80c99fb707946f69e073f59fbcc0f6613e..afbf5400a52a55f46fd1a815a46aed93bade7565 100644 (file)
@@ -48,6 +48,8 @@ void ath_init_leds(struct ath_softc *sc)
                        sc->sc_ah->led_pin = ATH_LED_PIN_9485;
                else if (AR_SREV_9300(sc->sc_ah))
                        sc->sc_ah->led_pin = ATH_LED_PIN_9300;
+               else if (AR_SREV_9480(sc->sc_ah))
+                       sc->sc_ah->led_pin = ATH_LED_PIN_9480;
                else
                        sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
        }
index 9cf42f6973aaffe80170301add79c0f29c055730..966661c9e58697f2040f2ba1e94e20817dd9a166 100644 (file)
@@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
        memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
 
        /* ath9k_htc supports only 1 or 2 stream devices */
-       tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
-       rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
+       tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
+       rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
 
        ath_dbg(common, ATH_DBG_CONFIG,
                "TX streams %d, RX streams: %d\n",
@@ -601,9 +601,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
 
-       common->tx_chainmask = priv->ah->caps.tx_chainmask;
-       common->rx_chainmask = priv->ah->caps.rx_chainmask;
-
        memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
 
        priv->ah->opmode = NL80211_IFTYPE_STATION;
index b9de1511add96928ade0a7696a70a5d7bc018b70..495fdf680a6c5269245ef49672c85a52b5bc057b 100644 (file)
@@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
                if (longcal || shortcal)
                        common->ani.caldone =
                                ath9k_hw_calibrate(ah, ah->curchan,
-                                                  common->rx_chainmask,
-                                                  longcal);
+                                                  ah->rxchainmask, longcal);
 
                ath9k_htc_ps_restore(priv);
        }
index dd9003ee123bfbe6701eedd519cdb749c643960a..e9782d164962ab450474a4a9475d8f9a757534b6 100644 (file)
@@ -54,13 +54,10 @@ static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
        return ath9k_hw_ops(ah)->get_isr(ah, masked);
 }
 
-static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
-                                 bool is_firstseg, bool is_lastseg,
-                                 const void *ds0, dma_addr_t buf_addr,
-                                 unsigned int qcu)
+static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
+                                      struct ath_tx_info *i)
 {
-       ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
-                                     ds0, buf_addr, qcu);
+       return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
 }
 
 static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
@@ -69,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
        return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
 }
 
-static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-                                         u32 pktLen, enum ath9k_pkt_type type,
-                                         u32 txPower, u32 keyIx,
-                                         enum ath9k_key_type keyType,
-                                         u32 flags)
-{
-       ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
-                                     keyType, flags);
-}
-
-static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-                                       void *lastds,
-                                       u32 durUpdateEn, u32 rtsctsRate,
-                                       u32 rtsctsDuration,
-                                       struct ath9k_11n_rate_series series[],
-                                       u32 nseries, u32 flags)
-{
-       ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
-                                           rtsctsRate, rtsctsDuration, series,
-                                           nseries, flags);
-}
-
-static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-                                       u32 aggrLen)
-{
-       ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
-}
-
-static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-                                              u32 numDelims)
-{
-       ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
-}
-
-static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
-{
-       ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
-}
-
-static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
-{
-       ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
-}
-
-static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
-{
-       ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
-}
-
 static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
                struct ath_hw_antcomb_conf *antconf)
 {
@@ -233,11 +181,6 @@ static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
        return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
 }
 
-static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
-{
-       return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
-}
-
 static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
                                        enum ath9k_ani_cmd cmd, int param)
 {
index 3a16ba256ef9456785692eb3607441c36222d199..f2de7ee047ce5566853e23396c441b59d3f75ffc 100644 (file)
@@ -580,6 +580,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        case AR_SREV_VERSION_9330:
        case AR_SREV_VERSION_9485:
        case AR_SREV_VERSION_9340:
+       case AR_SREV_VERSION_9480:
                break;
        default:
                ath_err(common,
@@ -664,6 +665,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR9300_DEVID_AR9330:
        case AR9300_DEVID_AR9340:
        case AR9300_DEVID_AR9580:
+       case AR9300_DEVID_AR9480:
                break;
        default:
                if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -960,7 +962,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        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 acktimeout, ctstimeout;
        int slottime;
        int sifstime;
        int rx_lat = 0, tx_lat = 0, eifs = 0;
@@ -975,7 +977,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        if (ah->misc_mode != 0)
                REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
 
-       rx_lat = 37;
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rx_lat = 41;
+       else
+               rx_lat = 37;
        tx_lat = 54;
 
        if (IS_CHAN_HALF_RATE(chan)) {
@@ -989,7 +994,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
                sifstime = 32;
        } else if (IS_CHAN_QUARTER_RATE(chan)) {
                eifs = 340;
-               rx_lat *= 4;
+               rx_lat = (rx_lat * 4) - 1;
                tx_lat *= 4;
                if (IS_CHAN_A_FAST_CLOCK(ah, chan))
                    tx_lat += 22;
@@ -1017,6 +1022,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
 
        /* As defined by IEEE 802.11-2007 17.3.8.6 */
        acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+       ctstimeout = acktimeout;
 
        /*
         * Workaround for early ACK timeouts, add an offset to match the
@@ -1031,7 +1037,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        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);
+       ath9k_hw_set_cts_timeout(ah, ctstimeout);
        if (ah->globaltxtimeout != (u32) -1)
                ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
 
@@ -1336,6 +1342,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
 {
+
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                REG_WRITE(ah, AR_WA, ah->WARegVal);
                udelay(10);
@@ -1475,9 +1482,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        u64 tsf = 0;
        int i, r;
 
-       ah->txchainmask = common->tx_chainmask;
-       ah->rxchainmask = common->rx_chainmask;
-
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
 
@@ -1495,14 +1499,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        }
        ah->noise = ath9k_hw_getchan_noise(ah, chan);
 
+       if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) ||
+           (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
+               bChannelChange = false;
+
        if (bChannelChange &&
            (ah->chip_fullsleep != true) &&
            (ah->curchan != NULL) &&
            (chan->channel != ah->curchan->channel) &&
            ((chan->channelFlags & CHANNEL_ALL) ==
-            (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-           (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
-
+            (ah->curchan->channelFlags & CHANNEL_ALL))) {
                if (ath9k_hw_channel_change(ah, chan)) {
                        ath9k_hw_loadnf(ah, ah->curchan);
                        ath9k_hw_start_nfcal(ah, true);
@@ -1742,25 +1748,41 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
 {
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
        if (setChip) {
+               if (AR_SREV_9480(ah)) {
+                       REG_WRITE(ah, AR_TIMER_MODE,
+                                 REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
+                       REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah,
+                                 AR_NDP2_TIMER_MODE) & 0xFFFFFF00);
+                       REG_WRITE(ah, AR_SLP32_INC,
+                                 REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
+                       /* xxx Required for WLAN only case ? */
+                       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+                       udelay(100);
+               }
+
                /*
                 * Clear the RTC force wake bit to allow the
                 * mac to go to sleep.
                 */
-               REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-                           AR_RTC_FORCE_WAKE_EN);
+               REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+               if (AR_SREV_9480(ah))
+                       udelay(100);
+
                if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
 
                /* Shutdown chip. Active low */
-               if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
-                       REG_CLR_BIT(ah, (AR_RTC_RESET),
-                                   AR_RTC_RESET_EN);
+               if (!AR_SREV_5416(ah) &&
+                               !AR_SREV_9271(ah) && !AR_SREV_9480_10(ah)) {
+                       REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+                       udelay(2);
+               }
        }
 
        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
-       if (AR_SREV_9300_20_OR_LATER(ah))
-               REG_WRITE(ah, AR_WA,
-                         ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+       if (!AR_SREV_9480(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 /*
@@ -1770,6 +1792,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
  */
 static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
 {
+       u32 val;
+
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
        if (setChip) {
                struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -1779,12 +1803,30 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
                        REG_WRITE(ah, AR_RTC_FORCE_WAKE,
                                  AR_RTC_FORCE_WAKE_ON_INT);
                } else {
+
+                       /* When chip goes into network sleep, it could be waken
+                        * up by MCI_INT interrupt caused by BT's HW messages
+                        * (LNA_xxx, CONT_xxx) which chould be in a very fast
+                        * rate (~100us). This will cause chip to leave and
+                        * re-enter network sleep mode frequently, which in
+                        * consequence will have WLAN MCI HW to generate lots of
+                        * SYS_WAKING and SYS_SLEEPING messages which will make
+                        * BT CPU to busy to process.
+                        */
+                       if (AR_SREV_9480(ah)) {
+                               val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
+                                       ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK;
+                               REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val);
+                       }
                        /*
                         * Clear the RTC force wake bit to allow the
                         * mac to go to sleep.
                         */
                        REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
                                    AR_RTC_FORCE_WAKE_EN);
+
+                       if (AR_SREV_9480(ah))
+                               udelay(30);
                }
        }
 
@@ -2091,6 +2133,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 
        pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
        pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+       ah->txchainmask = pCap->tx_chainmask;
+       ah->rxchainmask = pCap->rx_chainmask;
 
        ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
@@ -2401,6 +2445,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
 
        ENABLE_REGWRITE_BUFFER(ah);
 
+       if (AR_SREV_9480(ah))
+               bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
        REG_WRITE(ah, AR_RX_FILTER, bits);
 
        phybits = 0;
@@ -2447,13 +2494,13 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
        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 reg_pwr = min_t(int, MAX_RATE_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);
+       regulatory->power_limit = reg_pwr;
 
        ah->eep_ops->set_txpower(ah, chan,
                                 ath9k_regd_get_ctl(regulatory, chan),
@@ -2657,6 +2704,20 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
        REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
                    gen_tmr_configuration[timer->index].mode_mask);
 
+       if (AR_SREV_9480(ah)) {
+               /*
+                * Starting from AR9480, each generic timer can select which tsf
+                * to use. But we still follow the old rule, 0 - 7 use tsf and
+                * 8 - 15  use tsf2.
+                */
+               if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
+                       REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+               else
+                       REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+       }
+
        /* Enable both trigger and thresh interrupt masks */
        REG_SET_BIT(ah, AR_IMR_S5,
                (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@@ -2762,6 +2823,7 @@ static struct {
        { AR_SREV_VERSION_9330,         "9330" },
        { AR_SREV_VERSION_9340,         "9340" },
        { AR_SREV_VERSION_9485,         "9485" },
+       { AR_SREV_VERSION_9480,         "9480" },
 };
 
 /* For devices with external radios */
index c8af86c795e55d18d6d03daa993db465eae08292..24889f78a0536426d593ed0da3bd950e99f358f0 100644 (file)
@@ -46,6 +46,7 @@
 #define AR9300_DEVID_AR9340    0x0031
 #define AR9300_DEVID_AR9485_PCIE 0x0032
 #define AR9300_DEVID_AR9580    0x0033
+#define AR9300_DEVID_AR9480    0x0034
 #define AR9300_DEVID_AR9330    0x0035
 
 #define AR5416_AR9100_DEVID    0x000b
@@ -583,7 +584,6 @@ struct ath_hw_private_ops {
        bool (*rfbus_req)(struct ath_hw *ah);
        void (*rfbus_done)(struct ath_hw *ah);
        void (*restore_chainmask)(struct ath_hw *ah);
-       void (*set_diversity)(struct ath_hw *ah, bool value);
        u32 (*compute_pll_control)(struct ath_hw *ah,
                                   struct ath9k_channel *chan);
        bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
@@ -615,30 +615,10 @@ struct ath_hw_ops {
                          u8 rxchainmask,
                          bool longcal);
        bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
-       void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
-                           bool is_firstseg, bool is_is_lastseg,
-                           const void *ds0, dma_addr_t buf_addr,
-                           unsigned int qcu);
+       void (*set_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_info *i);
        int (*proc_txdesc)(struct ath_hw *ah, void *ds,
                           struct ath_tx_status *ts);
-       void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
-                             u32 pktLen, enum ath9k_pkt_type type,
-                             u32 txPower, u8 keyIx,
-                             enum ath9k_key_type keyType,
-                             u32 flags);
-       void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
-                               void *lastds,
-                               u32 durUpdateEn, u32 rtsctsRate,
-                               u32 rtsctsDuration,
-                               struct ath9k_11n_rate_series series[],
-                               u32 nseries, u32 flags);
-       void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
-                                 u32 aggrLen);
-       void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
-                                  u32 numDelims);
-       void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
-       void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
-       void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
        void (*antdiv_comb_conf_get)(struct ath_hw *ah,
                        struct ath_hw_antcomb_conf *antconf);
        void (*antdiv_comb_conf_set)(struct ath_hw *ah,
@@ -827,11 +807,14 @@ struct ath_hw {
        struct ar5416IniArray iniModes_9271_1_0_only;
        struct ar5416IniArray iniCckfirNormal;
        struct ar5416IniArray iniCckfirJapan2484;
+       struct ar5416IniArray ini_japan2484;
        struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
        struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
        struct ar5416IniArray iniModes_9271_ANI_reg;
        struct ar5416IniArray iniModes_high_power_tx_gain_9271;
        struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
+       struct ar5416IniArray ini_radio_post_sys2ant;
+       struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
 
        struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
        struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
index dd71a5f775165e60f04bc262bbaab8ff4fb36c9c..39514de044efea39f966e2a6d111600e8fb3344d 100644 (file)
@@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_softc *sc,
 
        /* set up supported mcs set */
        memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-       tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
-       rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
+       tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
+       rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
 
        ath_dbg(common, ATH_DBG_CONFIG,
                "TX streams %d, RX streams: %d\n",
@@ -506,10 +506,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
                sc->sc_flags |= SC_OP_RXAGGR;
        }
 
-       common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
-       common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-
-       ath9k_hw_set_diversity(sc->sc_ah, true);
        sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
 
        memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
@@ -646,10 +642,8 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
 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)
@@ -658,9 +652,22 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
        ah->curchan = curchan;
 }
 
+void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+{
+       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
+               return;
+
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+}
+
+
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
 
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
                IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
@@ -698,6 +705,16 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->sta_data_size = sizeof(struct ath_node);
        hw->vif_data_size = sizeof(struct ath_vif);
 
+       hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+       hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+
+       /* single chain devices with rx diversity */
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+               hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
+
+       sc->ant_rx = hw->wiphy->available_antennas_rx;
+       sc->ant_tx = hw->wiphy->available_antennas_tx;
+
 #ifdef CONFIG_ATH9K_RATE_CONTROL
        hw->rate_control_algorithm = "ath9k_rate_control";
 #endif
@@ -709,12 +726,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &sc->sbands[IEEE80211_BAND_5GHZ];
 
-       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-               if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
-                       setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
-               if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
-                       setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
-       }
+       ath9k_reload_chainmask_settings(sc);
 
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
 }
@@ -782,6 +794,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
                        goto error_world;
        }
 
+       INIT_WORK(&sc->hw_reset_work, ath_reset_work);
        INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
        INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
index 7ce9b320f0d9758a7c8c6c393e98e9546f9078bd..22f23eafe8bac12f132c501eb43674ef245cab02 100644 (file)
@@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
 }
 EXPORT_SYMBOL(ath9k_hw_txstart);
 
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
-{
-       struct ar5416_desc *ads = AR5416DESC(ds);
-
-       ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-       ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-       ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-       ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-       ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
-EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
-
 u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
 {
        u32 npend;
@@ -596,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
        else
                rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
 
-       rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
+       rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
        rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
 
        rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
index acb83bfd05a08b24d71aff41a1e411172e4e9374..91c96546c0cde73c395646819e552a65272bcab6 100644 (file)
 #ifndef MAC_H
 #define MAC_H
 
-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ?         \
-                               MS(ads->ds_rxstatus0, AR_RxRate) :      \
-                               (ads->ds_rxstatus3 >> 2) & 0xFF)
-
 #define set11nTries(_series, _index) \
        (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
 
@@ -263,7 +259,11 @@ struct ath_desc {
 #define ATH9K_TXDESC_VMF               0x0100
 #define ATH9K_TXDESC_FRAG_IS_ON        0x0200
 #define ATH9K_TXDESC_LOWRXCHAIN                0x0400
-#define ATH9K_TXDESC_LDPC              0x00010000
+#define ATH9K_TXDESC_LDPC              0x0800
+#define ATH9K_TXDESC_CLRDMASK          0x1000
+
+#define ATH9K_TXDESC_PAPRD             0x70000
+#define ATH9K_TXDESC_PAPRD_S           16
 
 #define ATH9K_RXDESC_INTREQ            0x0020
 
@@ -644,6 +644,7 @@ enum ath9k_rx_filter {
        ATH9K_RX_FILTER_PSPOLL = 0x00004000,
        ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
        ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+       ATH9K_RX_FILTER_CONTROL_WRAPPER = 0x00080000,
 };
 
 #define ATH9K_RATESERIES_RTS_CTS  0x0001
@@ -659,6 +660,13 @@ struct ath9k_11n_rate_series {
        u32 RateFlags;
 };
 
+enum aggr_type {
+       AGGR_BUF_NONE,
+       AGGR_BUF_FIRST,
+       AGGR_BUF_MIDDLE,
+       AGGR_BUF_LAST,
+};
+
 enum ath9k_key_type {
        ATH9K_KEY_TYPE_CLEAR,
        ATH9K_KEY_TYPE_WEP,
@@ -666,6 +674,33 @@ enum ath9k_key_type {
        ATH9K_KEY_TYPE_TKIP,
 };
 
+struct ath_tx_info {
+       u8 qcu;
+
+       bool is_first;
+       bool is_last;
+
+       enum aggr_type aggr;
+       u8 ndelim;
+       u16 aggr_len;
+
+       dma_addr_t link;
+       int pkt_len;
+       u32 flags;
+
+       dma_addr_t buf_addr[4];
+       int buf_len[4];
+
+       struct ath9k_11n_rate_series rates[4];
+       u8 rtscts_rate;
+       bool dur_update;
+
+       enum ath9k_pkt_type type;
+       enum ath9k_key_type keytype;
+       u8 keyix;
+       u8 txpower;
+};
+
 struct ath_hw;
 struct ath9k_channel;
 enum ath9k_int;
@@ -673,7 +708,6 @@ enum ath9k_int;
 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
 void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
 void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
 u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
 bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
index 7b7864dfab751d3d36083026be3f827ebfbcdd57..ee39702da5d854632db82a7228d0997e1e55ea91 100644 (file)
@@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
 void ath9k_ps_restore(struct ath_softc *sc)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       enum ath9k_power_mode mode;
        unsigned long flags;
 
        spin_lock_irqsave(&sc->sc_pm_lock, flags);
        if (--sc->ps_usecount != 0)
                goto unlock;
 
-       spin_lock(&common->cc_lock);
-       ath_hw_cycle_counters_update(common);
-       spin_unlock(&common->cc_lock);
-
        if (sc->ps_idle)
-               ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+               mode = ATH9K_PM_FULL_SLEEP;
        else if (sc->ps_enabled &&
                 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                              PS_WAIT_FOR_CAB |
                              PS_WAIT_FOR_PSPOLL_DATA |
                              PS_WAIT_FOR_TX_ACK)))
-               ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+               mode = ATH9K_PM_NETWORK_SLEEP;
+       else
+               goto unlock;
+
+       spin_lock(&common->cc_lock);
+       ath_hw_cycle_counters_update(common);
+       spin_unlock(&common->cc_lock);
+
+       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
 
  unlock:
        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
@@ -212,83 +217,58 @@ static int ath_update_survey_stats(struct ath_softc *sc)
        return ret;
 }
 
-/*
- * Set/change channels.  If the channel is really being changed, it's done
- * by reseting the chip.  To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
-                   struct ath9k_channel *hchan)
+static void __ath_cancel_work(struct ath_softc *sc)
 {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_conf *conf = &common->hw->conf;
-       bool fastcc = true, stopped;
-       struct ieee80211_channel *channel = hw->conf.channel;
-       struct ath9k_hw_cal_data *caldata = NULL;
-       int r;
-
-       if (sc->sc_flags & SC_OP_INVALID)
-               return -EIO;
-
-       sc->hw_busy_count = 0;
-
-       del_timer_sync(&common->ani.timer);
        cancel_work_sync(&sc->paprd_work);
        cancel_work_sync(&sc->hw_check_work);
        cancel_delayed_work_sync(&sc->tx_complete_work);
        cancel_delayed_work_sync(&sc->hw_pll_work);
+}
 
-       ath9k_ps_wakeup(sc);
+static void ath_cancel_work(struct ath_softc *sc)
+{
+       __ath_cancel_work(sc);
+       cancel_work_sync(&sc->hw_reset_work);
+}
 
-       spin_lock_bh(&sc->sc_pcu_lock);
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       bool ret;
 
-       /*
-        * This is only performed if the channel settings have
-        * actually changed.
-        *
-        * To switch channels clear any pending DMA operations;
-        * wait long enough for the RX fifo to drain, reset the
-        * hardware at the new frequency, and then re-enable
-        * the relevant bits of the h/w.
-        */
-       ath9k_hw_disable_interrupts(ah);
-       stopped = ath_drain_all_txq(sc, false);
+       ieee80211_stop_queues(sc->hw);
 
-       if (!ath_stoprecv(sc))
-               stopped = false;
+       sc->hw_busy_count = 0;
+       del_timer_sync(&common->ani.timer);
 
-       if (!ath9k_hw_check_alive(ah))
-               stopped = false;
+       ath9k_debug_samp_bb_mac(sc);
+       ath9k_hw_disable_interrupts(ah);
 
-       /* XXX: do not flush receive queue here. We don't want
-        * to flush data frames already in queue because of
-        * changing channel. */
+       ret = ath_drain_all_txq(sc, retry_tx);
 
-       if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
-               fastcc = false;
+       if (!ath_stoprecv(sc))
+               ret = false;
 
-       if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
-               caldata = &sc->caldata;
+       if (!flush) {
+               if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+                       ath_rx_tasklet(sc, 1, true);
+               ath_rx_tasklet(sc, 1, false);
+       } else {
+               ath_flushrecv(sc);
+       }
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
-               sc->sc_ah->curchan->channel,
-               channel->center_freq, conf_is_ht40(conf),
-               fastcc);
+       return ret;
+}
 
-       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
-       if (r) {
-               ath_err(common,
-                       "Unable to reset channel (%u MHz), reset status %d\n",
-                       channel->center_freq, r);
-               goto ps_restore;
-       }
+static bool ath_complete_reset(struct ath_softc *sc, bool start)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
 
        if (ath_startrecv(sc) != 0) {
                ath_err(common, "Unable to restart recv logic\n");
-               r = -EIO;
-               goto ps_restore;
+               return false;
        }
 
        ath9k_cmn_update_txpow(ah, sc->curtxpow,
@@ -296,21 +276,109 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
        ath9k_hw_set_interrupts(ah, ah->imask);
        ath9k_hw_enable_interrupts(ah);
 
-       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
+       if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
                if (sc->sc_flags & SC_OP_BEACONS)
                        ath_set_beacon(sc);
+
                ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
                ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
                if (!common->disable_ani)
                        ath_start_ani(common);
        }
 
- ps_restore:
-       ieee80211_wake_queues(hw);
+       if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
+               struct ath_hw_antcomb_conf div_ant_conf;
+               u8 lna_conf;
+
+               ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
+
+               if (sc->ant_rx == 1)
+                       lna_conf = ATH_ANT_DIV_COMB_LNA1;
+               else
+                       lna_conf = ATH_ANT_DIV_COMB_LNA2;
+               div_ant_conf.main_lna_conf = lna_conf;
+               div_ant_conf.alt_lna_conf = lna_conf;
+
+               ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
+       }
+
+       ieee80211_wake_queues(sc->hw);
+
+       return true;
+}
+
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
+                             bool retry_tx)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_cal_data *caldata = NULL;
+       bool fastcc = true;
+       bool flush = false;
+       int r;
+
+       __ath_cancel_work(sc);
+
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
+               fastcc = false;
+               caldata = &sc->caldata;
+       }
+
+       if (!hchan) {
+               fastcc = false;
+               flush = true;
+               hchan = ah->curchan;
+       }
 
+       if (fastcc && !ath9k_hw_check_alive(ah))
+               fastcc = false;
+
+       if (!ath_prepare_reset(sc, retry_tx, flush))
+               fastcc = false;
+
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "Reset to %u MHz, HT40: %d fastcc: %d\n",
+               hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
+                                                         CHANNEL_HT40PLUS)),
+               fastcc);
+
+       r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+       if (r) {
+               ath_err(common,
+                       "Unable to reset channel, reset status %d\n", r);
+               goto out;
+       }
+
+       if (!ath_complete_reset(sc, true))
+               r = -EIO;
+
+out:
        spin_unlock_bh(&sc->sc_pcu_lock);
+       return r;
+}
+
+
+/*
+ * Set/change channels.  If the channel is really being changed, it's done
+ * by reseting the chip.  To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+                   struct ath9k_channel *hchan)
+{
+       int r;
+
+       if (sc->sc_flags & SC_OP_INVALID)
+               return -EIO;
+
+       ath9k_ps_wakeup(sc);
+
+       r = ath_reset_internal(sc, hchan, false);
 
        ath9k_ps_restore(sc);
+
        return r;
 }
 
@@ -318,7 +386,6 @@ static void ath_paprd_activate(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_cal_data *caldata = ah->caldata;
-       struct ath_common *common = ath9k_hw_common(ah);
        int chain;
 
        if (!caldata || !caldata->paprd_done)
@@ -327,7 +394,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
        ath9k_ps_wakeup(sc);
        ar9003_paprd_enable(ah, false);
        for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
-               if (!(common->tx_chainmask & BIT(chain)))
+               if (!(ah->txchainmask & BIT(chain)))
                        continue;
 
                ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -414,7 +481,7 @@ void ath_paprd_calibrate(struct work_struct *work)
        memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 
        for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
-               if (!(common->tx_chainmask & BIT(chain)))
+               if (!(ah->txchainmask & BIT(chain)))
                        continue;
 
                chain_ok = 0;
@@ -535,7 +602,7 @@ void ath_ani_calibrate(unsigned long data)
        if (longcal || shortcal) {
                common->ani.caldone =
                        ath9k_hw_calibrate(ah, ah->curchan,
-                                               common->rx_chainmask, longcal);
+                                               ah->rxchainmask, longcal);
        }
 
        ath9k_ps_restore(sc);
@@ -597,74 +664,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
                ath_tx_node_cleanup(sc, an);
 }
 
-void ath_hw_check(struct work_struct *work)
-{
-       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       unsigned long flags;
-       int busy;
-
-       ath9k_ps_wakeup(sc);
-       if (ath9k_hw_check_alive(sc->sc_ah))
-               goto out;
-
-       spin_lock_irqsave(&common->cc_lock, flags);
-       busy = ath_update_survey_stats(sc);
-       spin_unlock_irqrestore(&common->cc_lock, flags);
-
-       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) {
-                       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;
-
-out:
-       ath9k_ps_restore(sc);
-}
-
-static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
-{
-       static int count;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
-       if (pll_sqsum >= 0x40000) {
-               count++;
-               if (count == 3) {
-                       /* 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
-               count = 0;
-}
-
-void ath_hw_pll_work(struct work_struct *work)
-{
-       struct ath_softc *sc = container_of(work, struct ath_softc,
-                                           hw_pll_work.work);
-       u32 pll_sqsum;
-
-       if (AR_SREV_9485(sc->sc_ah)) {
-
-               ath9k_ps_wakeup(sc);
-               pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
-               ath9k_ps_restore(sc);
-
-               ath_hw_pll_rx_hang_check(sc, pll_sqsum);
-
-               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
-       }
-}
-
 
 void ath9k_tasklet(unsigned long data)
 {
@@ -675,17 +674,15 @@ void ath9k_tasklet(unsigned long data)
        u32 status = sc->intrstatus;
        u32 rxmask;
 
+       ath9k_ps_wakeup(sc);
+       spin_lock(&sc->sc_pcu_lock);
+
        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;
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               goto out;
        }
 
-       ath9k_ps_wakeup(sc);
-       spin_lock(&sc->sc_pcu_lock);
-
        /*
         * Only run the baseband hang check if beacons stop working in AP or
         * IBSS mode, because it has a high false positive rate. For station
@@ -733,6 +730,7 @@ void ath9k_tasklet(unsigned long data)
                if (status & ATH9K_INT_GENTIMER)
                        ath_gen_timer_isr(sc->sc_ah);
 
+out:
        /* re-enable hardware interrupt */
        ath9k_hw_enable_interrupts(ah);
 
@@ -895,28 +893,13 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
                        channel->center_freq, r);
        }
 
-       ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                              sc->config.txpowlimit, &sc->curtxpow);
-       if (ath_startrecv(sc) != 0) {
-               ath_err(common, "Unable to restart recv logic\n");
-               goto out;
-       }
-       if (sc->sc_flags & SC_OP_BEACONS)
-               ath_set_beacon(sc);     /* restart beacons */
-
-       /* Re-Enable  interrupts */
-       ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_hw_enable_interrupts(ah);
+       ath_complete_reset(sc, true);
 
        /* Enable LED */
        ath9k_hw_cfg_output(ah, ah->led_pin,
                            AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
        ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
-       ieee80211_wake_queues(hw);
-       ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
-
-out:
        spin_unlock_bh(&sc->sc_pcu_lock);
 
        ath9k_ps_restore(sc);
@@ -929,11 +912,10 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
        int r;
 
        ath9k_ps_wakeup(sc);
-       cancel_delayed_work_sync(&sc->hw_pll_work);
 
-       spin_lock_bh(&sc->sc_pcu_lock);
+       ath_cancel_work(sc);
 
-       ieee80211_stop_queues(hw);
+       spin_lock_bh(&sc->sc_pcu_lock);
 
        /*
         * Keep the LED on when the radio is disabled
@@ -944,13 +926,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
                ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
        }
 
-       /* Disable interrupts */
-       ath9k_hw_disable_interrupts(ah);
-
-       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
-
-       ath_stoprecv(sc);               /* turn off frame recv */
-       ath_flushrecv(sc);              /* flush recv queue */
+       ath_prepare_reset(sc, false, true);
 
        if (!ah->curchan)
                ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
@@ -970,51 +946,13 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
        ath9k_ps_restore(sc);
 }
 
-int ath_reset(struct ath_softc *sc, bool retry_tx)
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
 {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_hw *hw = sc->hw;
        int r;
 
-       sc->hw_busy_count = 0;
-
-       ath9k_debug_samp_bb_mac(sc);
-       /* Stop ANI */
-
-       del_timer_sync(&common->ani.timer);
-
        ath9k_ps_wakeup(sc);
 
-       ieee80211_stop_queues(hw);
-
-       ath9k_hw_disable_interrupts(ah);
-       ath_drain_all_txq(sc, retry_tx);
-
-       ath_stoprecv(sc);
-       ath_flushrecv(sc);
-
-       r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
-       if (r)
-               ath_err(common,
-                       "Unable to reset hardware; reset status %d\n", r);
-
-       if (ath_startrecv(sc) != 0)
-               ath_err(common, "Unable to start recv logic\n");
-
-       /*
-        * We may be doing a reset in response to a request
-        * that changes the channel so update any state that
-        * might change as a result.
-        */
-       ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                              sc->config.txpowlimit, &sc->curtxpow);
-
-       if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
-               ath_set_beacon(sc);     /* restart beacons */
-
-       ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_hw_enable_interrupts(ah);
+       r = ath_reset_internal(sc, NULL, retry_tx);
 
        if (retry_tx) {
                int i;
@@ -1027,15 +965,80 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
                }
        }
 
-       ieee80211_wake_queues(hw);
+       ath9k_ps_restore(sc);
+
+       return r;
+}
+
+void ath_reset_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
 
-       /* Start ANI */
-       if (!common->disable_ani)
-               ath_start_ani(common);
+       ath_reset(sc, true);
+}
+
+void ath_hw_check(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long flags;
+       int busy;
 
+       ath9k_ps_wakeup(sc);
+       if (ath9k_hw_check_alive(sc->sc_ah))
+               goto out;
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       busy = ath_update_survey_stats(sc);
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       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)
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+
+       } else if (busy >= 0)
+               sc->hw_busy_count = 0;
+
+out:
        ath9k_ps_restore(sc);
+}
 
-       return r;
+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+{
+       static int count;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+       if (pll_sqsum >= 0x40000) {
+               count++;
+               if (count == 3) {
+                       /* Rx is hung for more than 500ms. Reset it */
+                       ath_dbg(common, ATH_DBG_RESET,
+                               "Possible RX hang, resetting");
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+                       count = 0;
+               }
+       } else
+               count = 0;
+}
+
+void ath_hw_pll_work(struct work_struct *work)
+{
+       struct ath_softc *sc = container_of(work, struct ath_softc,
+                                           hw_pll_work.work);
+       u32 pll_sqsum;
+
+       if (AR_SREV_9485(sc->sc_ah)) {
+
+               ath9k_ps_wakeup(sc);
+               pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+               ath9k_ps_restore(sc);
+
+               ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+
+               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+       }
 }
 
 /**********************/
@@ -1084,28 +1087,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
                goto mutex_unlock;
        }
 
-       /*
-        * This is needed only to setup initial state
-        * but it's best done after a reset.
-        */
-       ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                       sc->config.txpowlimit, &sc->curtxpow);
-
-       /*
-        * Setup the hardware after reset:
-        * The receive engine is set going.
-        * Frame transmit is handled entirely
-        * in the frame output path; there's nothing to do
-        * here except setup the interrupt mask.
-        */
-       if (ath_startrecv(sc) != 0) {
-               ath_err(common, "Unable to start recv logic\n");
-               r = -EIO;
-               spin_unlock_bh(&sc->sc_pcu_lock);
-               goto mutex_unlock;
-       }
-       spin_unlock_bh(&sc->sc_pcu_lock);
-
        /* Setup our intr mask. */
        ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
                    ATH9K_INT_RXORN | ATH9K_INT_FATAL |
@@ -1128,12 +1109,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
        /* Disable BMISS interrupt when we're not associated */
        ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-       ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_hw_enable_interrupts(ah);
 
-       ieee80211_wake_queues(hw);
+       if (!ath_complete_reset(sc, false)) {
+               r = -EIO;
+               spin_unlock_bh(&sc->sc_pcu_lock);
+               goto mutex_unlock;
+       }
 
-       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+       spin_unlock_bh(&sc->sc_pcu_lock);
 
        if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
            !ah->btcoex_hw.enabled) {
@@ -1226,10 +1209,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        mutex_lock(&sc->mutex);
 
-       cancel_delayed_work_sync(&sc->tx_complete_work);
-       cancel_delayed_work_sync(&sc->hw_pll_work);
-       cancel_work_sync(&sc->paprd_work);
-       cancel_work_sync(&sc->hw_check_work);
+       ath_cancel_work(sc);
 
        if (sc->sc_flags & SC_OP_INVALID) {
                ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
@@ -2041,6 +2021,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
                /* Stop ANI */
                sc->sc_flags &= ~SC_OP_ANI_RUN;
                del_timer_sync(&common->ani.timer);
+               memset(&sc->caldata, 0, sizeof(sc->caldata));
        }
 }
 
@@ -2292,7 +2273,11 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 
        mutex_lock(&sc->mutex);
        ah->coverage_class = coverage_class;
+
+       ath9k_ps_wakeup(sc);
        ath9k_hw_init_global_settings(ah);
+       ath9k_ps_restore(sc);
+
        mutex_unlock(&sc->mutex);
 }
 
@@ -2308,6 +2293,12 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
        mutex_lock(&sc->mutex);
        cancel_delayed_work_sync(&sc->tx_complete_work);
 
+       if (ah->ah_flags & AH_UNPLUGGED) {
+               ath_dbg(common, ATH_DBG_ANY, "Device has been unplugged!\n");
+               mutex_unlock(&sc->mutex);
+               return;
+       }
+
        if (sc->sc_flags & SC_OP_INVALID) {
                ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
                mutex_unlock(&sc->mutex);
@@ -2340,9 +2331,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
        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);
 
@@ -2419,6 +2412,59 @@ static int ath9k_get_stats(struct ieee80211_hw *hw,
        return 0;
 }
 
+static u32 fill_chainmask(u32 cap, u32 new)
+{
+       u32 filled = 0;
+       int i;
+
+       for (i = 0; cap && new; i++, cap >>= 1) {
+               if (!(cap & BIT(0)))
+                       continue;
+
+               if (new & BIT(0))
+                       filled |= BIT(i);
+
+               new >>= 1;
+       }
+
+       return filled;
+}
+
+static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+
+       if (!rx_ant || !tx_ant)
+               return -EINVAL;
+
+       sc->ant_rx = rx_ant;
+       sc->ant_tx = tx_ant;
+
+       if (ah->caps.rx_chainmask == 1)
+               return 0;
+
+       /* AR9100 runs into calibration issues if not all rx chains are enabled */
+       if (AR_SREV_9100(ah))
+               ah->rxchainmask = 0x7;
+       else
+               ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
+
+       ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
+       ath9k_reload_chainmask_settings(sc);
+
+       return 0;
+}
+
+static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+       struct ath_softc *sc = hw->priv;
+
+       *tx_ant = sc->ant_tx;
+       *rx_ant = sc->ant_rx;
+       return 0;
+}
+
 struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -2445,4 +2491,6 @@ struct ieee80211_ops ath9k_ops = {
        .tx_frames_pending  = ath9k_tx_frames_pending,
        .tx_last_beacon     = ath9k_tx_last_beacon,
        .get_stats          = ath9k_get_stats,
+       .set_antenna        = ath9k_set_antenna,
+       .get_antenna        = ath9k_get_antenna,
 };
index 891661a61513cdb65e0a4f5390a5d70f1abc3557..d67d6eee395422269fec4c38766452530c8bc962 100644 (file)
@@ -33,6 +33,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
        { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
        { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
        { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
+       { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E  AR9480 */
        { 0 }
 };
 
@@ -332,16 +333,16 @@ static int ath_pci_resume(struct device *device)
        if ((val & 0x0000ff00) != 0)
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
+       ath9k_ps_wakeup(sc);
        /* Enable LED */
        ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
                            AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-       ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+       ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
 
          /*
           * Reset key cache to sane defaults (all entries cleared) instead of
           * semi-random values after suspend/resume.
           */
-       ath9k_ps_wakeup(sc);
        ath9k_cmn_init_crypto(sc->sc_ah);
        ath9k_ps_restore(sc);
 
index 9c7f905f3871b6e4ac76ce542f7306ddb317c08c..bcc0b222ec18b7a0091fc913b6269510e3f3d14c 100644 (file)
@@ -1839,7 +1839,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                 * If we're asked to flush receive queue, directly
                 * chain it back at the queue without processing it.
                 */
-               if (flush)
+               if (sc->sc_flags & SC_OP_RXFLUSH)
                        goto requeue_drop_frag;
 
                retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
@@ -1950,7 +1950,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                        ath_rx_ps(sc, skb);
                spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
-               if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+               if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
                        ath_ant_comb_scan(sc, &rs);
 
                ieee80211_rx(hw, skb);
@@ -1967,7 +1967,8 @@ requeue:
                } else {
                        list_move_tail(&bf->list, &sc->rx.rxbuf);
                        ath_rx_buf_link(sc, bf);
-                       ath9k_hw_rxena(ah);
+                       if (!flush)
+                               ath9k_hw_rxena(ah);
                }
        } while (1);
 
index 17a272f4d8d6aa230a85eb09af75164cf2ef9687..b76c49d9c503937fa2bf3a15e41e6405428a7657 100644 (file)
 #define AR_SREV_VERSION_9340           0x300
 #define AR_SREV_VERSION_9580           0x1C0
 #define AR_SREV_REVISION_9580_10       4 /* AR9580 1.0 */
+#define AR_SREV_VERSION_9480           0x280
+#define AR_SREV_REVISION_9480_10       0
+#define AR_SREV_REVISION_9480_20       2
 
 #define AR_SREV_5416(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
         ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
-#define AR_SREV_5416_20_OR_LATER(_ah) \
-       (((AR_SREV_5416(_ah)) && \
-        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
-        ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
 #define AR_SREV_5416_22_OR_LATER(_ah) \
        (((AR_SREV_5416(_ah)) && \
         ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
     (AR_SREV_9285_12_OR_LATER(_ah) && \
      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
 
+#define AR_SREV_9480(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480))
+
+#define AR_SREV_9480_10(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
+       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9480_10))
+
+#define AR_SREV_9480_20(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
+       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9480_20))
+
+#define AR_SREV_9480_20_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9480) && \
+       ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9480_20))
+
 #define AR_SREV_9580(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
@@ -1132,7 +1146,7 @@ enum {
 #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
 #define AR_ENT_OTP               0x40d8
 #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
-#define AR_ENT_OTP_MPSD                0x00800000
+#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE                0x00800000
 
 #define AR_CH0_BB_DPLL1                 0x16180
 #define AR_CH0_BB_DPLL1_REFDIV  0xF8000000
@@ -1779,6 +1793,7 @@ enum {
 #define AR_TXOP_12_15  0x81fc
 
 #define AR_NEXT_NDP2_TIMER                  0x8180
+#define AR_GEN_TIMER_BANK_1_LEN                        8
 #define AR_FIRST_NDP_TIMER                  7
 #define AR_NDP2_PERIOD                      0x81a0
 #define AR_NDP2_TIMER_MODE                  0x81c0
@@ -1867,9 +1882,10 @@ enum {
 #define AR_PCU_MISC_MODE2_HWWAR2                       0x02000000
 #define AR_PCU_MISC_MODE2_RESERVED2                    0xFFFE0000
 
-#define AR_MAC_PCU_ASYNC_FIFO_REG3                     0x8358
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL        0x00000400
-#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET          0x80000000
+#define AR_MAC_PCU_ASYNC_FIFO_REG3                     0x8358
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL                0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET          0x80000000
+#define AR_MAC_PCU_GEN_TIMER_TSF_SEL                   0x83d8
 
 
 #define AR_AES_MUTE_MASK0       0x805c
@@ -1920,4 +1936,38 @@ enum {
 #define AR_PHY_AGC_CONTROL_YCOK_MAX            0x000003c0
 #define AR_PHY_AGC_CONTROL_YCOK_MAX_S          6
 
+/* MCI Registers */
+#define AR_MCI_INTERRUPT_RX_MSG_EN             0x183c
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET    0x00000001
+#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S  0
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL     0x00000002
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S   1
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK       0x00000004
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S     2
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO       0x00000008
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S     3
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST        0x00000010
+#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S      4
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO       0x00000020
+#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S     5
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT         0x00000040
+#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S       6
+#define AR_MCI_INTERRUPT_RX_MSG_GPM             0x00000100
+#define AR_MCI_INTERRUPT_RX_MSG_GPM_S           8
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO        0x00000200
+#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S      9
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING    0x00000400
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S  10
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING      0x00000800
+#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S    11
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE        0x00001000
+#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S      12
+#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK        (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \
+                                         AR_MCI_INTERRUPT_RX_MSG_LNA_INFO   | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_NACK  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_INFO  | \
+                                         AR_MCI_INTERRUPT_RX_MSG_CONT_RST)
+
+
 #endif
index 68066c56e4e57c2c1938a1b2ca59fa4b02d04747..fa3dcfdf71743255771dd4c6f314687ff2ca0b0b 100644 (file)
@@ -56,10 +56,9 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                                struct ath_tx_status *ts, int txok, int sendbar);
 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);
 static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
                             struct ath_tx_status *ts, int nframes, int nbad,
-                            int txok, bool update_rc);
+                            int txok);
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
                              int seqno);
 static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
@@ -263,6 +262,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
                             struct sk_buff *skb)
 {
        struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_buf *bf = fi->bf;
        struct ieee80211_hdr *hdr;
 
        TX_STAT_INC(txq->axq_qnum, a_retries);
@@ -271,6 +271,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
 
        hdr = (struct ieee80211_hdr *)skb->data;
        hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+               sizeof(*hdr), DMA_TO_DEVICE);
 }
 
 static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
@@ -390,11 +392,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                while (bf) {
                        bf_next = bf->bf_next;
 
-                       bf->bf_state.bf_type |= BUF_XRETRY;
                        if (!bf->bf_stale || bf_next != NULL)
                                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);
 
@@ -470,7 +470,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                                clear_filter = true;
                                txpending = 1;
                        } else {
-                               bf->bf_state.bf_type |= BUF_XRETRY;
                                txfail = 1;
                                sendbar = 1;
                                txfail_cnt++;
@@ -497,17 +496,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
                        if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
                                memcpy(tx_info->control.rates, rates, sizeof(rates));
-                               ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
+                               ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
                                rc_update = false;
-                       } else {
-                               ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
                        }
 
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
                                !txfail, sendbar);
                } else {
                        /* retry the un-acked ones */
-                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
                        if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
                                if (bf->bf_next == NULL && bf_last->bf_stale) {
                                        struct ath_buf *tbf;
@@ -523,26 +519,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                                                ath_tx_update_baw(sc, tid, seqno);
                                                spin_unlock_bh(&txq->axq_lock);
 
-                                               bf->bf_state.bf_type |=
-                                                       BUF_XRETRY;
-                                               ath_tx_rc_status(sc, bf, ts, nframes,
-                                                               nbad, 0, false);
                                                ath_tx_complete_buf(sc, bf, txq,
                                                                    &bf_head,
-                                                                   ts, 0, 0);
+                                                                   ts, 0, 1);
                                                break;
                                        }
 
-                                       ath9k_hw_cleartxdesc(sc->sc_ah,
-                                                            tbf->bf_desc);
                                        fi->bf = tbf;
-                               } else {
-                                       /*
-                                        * Clear descriptor status words for
-                                        * software retry
-                                        */
-                                       ath9k_hw_cleartxdesc(sc->sc_ah,
-                                                            bf->bf_desc);
                                }
                        }
 
@@ -582,7 +565,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        rcu_read_unlock();
 
        if (needreset)
-               ath_reset(sc, false);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
 }
 
 static bool ath_lookup_legacy(struct ath_buf *bf)
@@ -709,7 +692,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
         * Add delimiter when using RTS/CTS with aggregation
         * and non enterprise AR9003 card
         */
-       if (first_subfrm)
+       if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
+           (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
                ndelim = max(ndelim, FIRST_DESC_NDELIMS);
 
        /*
@@ -777,7 +761,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
                if (!bf)
                        continue;
 
-               bf->bf_state.bf_type |= BUF_AMPDU;
+               bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
                seqno = bf->bf_state.seqno;
                if (!bf_first)
                        bf_first = bf;
@@ -804,8 +788,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
                }
 
                tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-               if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
-                       !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
+               if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
                        break;
 
                /* do not exceed subframe limit */
@@ -827,20 +810,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
 
                nframes++;
                bf->bf_next = NULL;
-               ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
 
                /* link buffers of this frame to the aggregate */
                if (!fi->retries)
                        ath_tx_addto_baw(sc, tid, seqno);
-               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+               bf->bf_state.ndelim = ndelim;
 
                __skb_unlink(skb, &tid->buf_q);
                list_add_tail(&bf->list, bf_q);
-               if (bf_prev) {
+               if (bf_prev)
                        bf_prev->bf_next = bf;
-                       ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
-                                              bf->bf_daddr);
-               }
+
                bf_prev = bf;
 
        } while (!skb_queue_empty(&tid->buf_q));
@@ -851,12 +831,231 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
 #undef PADBYTES
 }
 
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * width  - 0 for 20 MHz, 1 for 40 MHz
+ * half_gi - to use 4us v/s 3.6 us for symbol time
+ */
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+                           int width, int half_gi, bool shortPreamble)
+{
+       u32 nbits, nsymbits, duration, nsymbols;
+       int streams;
+
+       /* find number of symbols: PLCP + data */
+       streams = HT_RC_2_STREAMS(rix);
+       nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+       nsymbits = bits_per_symbol[rix % 8][width] * streams;
+       nsymbols = (nbits + nsymbits - 1) / nsymbits;
+
+       if (!half_gi)
+               duration = SYMBOL_TIME(nsymbols);
+       else
+               duration = SYMBOL_TIME_HALFGI(nsymbols);
+
+       /* addup duration for legacy/ht training and signal fields */
+       duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
+       return duration;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_info *info, int len)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rates;
+       const struct ieee80211_rate *rate;
+       struct ieee80211_hdr *hdr;
+       int i;
+       u8 rix = 0;
+
+       skb = bf->bf_mpdu;
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+       hdr = (struct ieee80211_hdr *)skb->data;
+
+       /* set dur_update_en for l-sig computation except for PS-Poll frames */
+       info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
+
+       /*
+        * We check if Short Preamble is needed for the CTS rate by
+        * checking the BSS's global flag.
+        * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+        */
+       rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
+       info->rtscts_rate = rate->hw_value;
+       if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+               info->rtscts_rate |= rate->hw_value_short;
+
+       for (i = 0; i < 4; i++) {
+               bool is_40, is_sgi, is_sp;
+               int phy;
+
+               if (!rates[i].count || (rates[i].idx < 0))
+                       continue;
+
+               rix = rates[i].idx;
+               info->rates[i].Tries = rates[i].count;
+
+                   if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       info->flags |= ATH9K_TXDESC_RTSENA;
+               } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+                       info->flags |= ATH9K_TXDESC_CTSENA;
+               }
+
+               if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
+               if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+                       info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+
+               is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
+               is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
+               is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+
+               if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+                       /* MCS rates */
+                       info->rates[i].Rate = rix | 0x80;
+                       info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+                                       ah->txchainmask, info->rates[i].Rate);
+                       info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
+                                is_40, is_sgi, is_sp);
+                       if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
+                               info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+                       continue;
+               }
+
+               /* legacy rates */
+               if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
+                   !(rate->flags & IEEE80211_RATE_ERP_G))
+                       phy = WLAN_RC_PHY_CCK;
+               else
+                       phy = WLAN_RC_PHY_OFDM;
+
+               rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
+               info->rates[i].Rate = rate->hw_value;
+               if (rate->hw_value_short) {
+                       if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                               info->rates[i].Rate |= rate->hw_value_short;
+               } else {
+                       is_sp = false;
+               }
+
+               if (bf->bf_state.bfs_paprd)
+                       info->rates[i].ChSel = ah->txchainmask;
+               else
+                       info->rates[i].ChSel = ath_txchainmask_reduction(sc,
+                                       ah->txchainmask, info->rates[i].Rate);
+
+               info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+                       phy, rate->bitrate * 100, len, rix, is_sp);
+       }
+
+       /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+       if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
+               info->flags &= ~ATH9K_TXDESC_RTSENA;
+
+       /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
+       if (info->flags & ATH9K_TXDESC_RTSENA)
+               info->flags &= ~ATH9K_TXDESC_CTSENA;
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr;
+       enum ath9k_pkt_type htype;
+       __le16 fc;
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       fc = hdr->frame_control;
+
+       if (ieee80211_is_beacon(fc))
+               htype = ATH9K_PKT_TYPE_BEACON;
+       else if (ieee80211_is_probe_resp(fc))
+               htype = ATH9K_PKT_TYPE_PROBE_RESP;
+       else if (ieee80211_is_atim(fc))
+               htype = ATH9K_PKT_TYPE_ATIM;
+       else if (ieee80211_is_pspoll(fc))
+               htype = ATH9K_PKT_TYPE_PSPOLL;
+       else
+               htype = ATH9K_PKT_TYPE_NORMAL;
+
+       return htype;
+}
+
+static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_txq *txq, int len)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
+       struct ath_buf *bf_first = bf;
+       struct ath_tx_info info;
+       bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
+
+       memset(&info, 0, sizeof(info));
+       info.is_first = true;
+       info.is_last = true;
+       info.txpower = MAX_RATE_POWER;
+       info.qcu = txq->axq_qnum;
+
+       info.flags = ATH9K_TXDESC_INTREQ;
+       if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+               info.flags |= ATH9K_TXDESC_NOACK;
+       if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
+               info.flags |= ATH9K_TXDESC_LDPC;
+
+       ath_buf_set_rate(sc, bf, &info, len);
+
+       if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+               info.flags |= ATH9K_TXDESC_CLRDMASK;
+
+       if (bf->bf_state.bfs_paprd)
+               info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
+
+
+       while (bf) {
+               struct sk_buff *skb = bf->bf_mpdu;
+               struct ath_frame_info *fi = get_frame_info(skb);
+
+               info.type = get_hw_packet_type(skb);
+               if (bf->bf_next)
+                       info.link = bf->bf_next->bf_daddr;
+               else
+                       info.link = 0;
+
+               info.buf_addr[0] = bf->bf_buf_addr;
+               info.buf_len[0] = skb->len;
+               info.pkt_len = fi->framelen;
+               info.keyix = fi->keyix;
+               info.keytype = fi->keytype;
+
+               if (aggr) {
+                       if (bf == bf_first)
+                               info.aggr = AGGR_BUF_FIRST;
+                       else if (!bf->bf_next)
+                               info.aggr = AGGR_BUF_LAST;
+                       else
+                               info.aggr = AGGR_BUF_MIDDLE;
+
+                       info.ndelim = bf->bf_state.ndelim;
+                       info.aggr_len = len;
+               }
+
+               ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+               bf = bf->bf_next;
+       }
+}
+
 static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
                              struct ath_atx_tid *tid)
 {
        struct ath_buf *bf;
        enum ATH_AGGR_STATUS status;
-       struct ath_frame_info *fi;
+       struct ieee80211_tx_info *tx_info;
        struct list_head bf_q;
        int aggr_len;
 
@@ -877,34 +1076,25 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
                bf = list_first_entry(&bf_q, struct ath_buf, list);
                bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
+               tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
 
                if (tid->ac->clear_ps_filter) {
                        tid->ac->clear_ps_filter = false;
-                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+                       tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               } else {
+                       tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
                }
 
                /* if only one frame, send as non-aggregate */
                if (bf == bf->bf_lastbf) {
-                       fi = get_frame_info(bf->bf_mpdu);
-
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
-                       ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
-                       ath_buf_set_rate(sc, bf, fi->framelen);
-                       ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-                       continue;
+                       aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
+                       bf->bf_state.bf_type = BUF_AMPDU;
+               } else {
+                       TX_STAT_INC(txq->axq_qnum, a_aggr);
                }
 
-               /* setup first desc of aggregate */
-               bf->bf_state.bf_type |= BUF_AGGR;
-               ath_buf_set_rate(sc, bf, aggr_len);
-               ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
-
-               /* anchor last desc of aggregate */
-               ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
-
+               ath_tx_fill_desc(sc, bf, txq, aggr_len);
                ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-               TX_STAT_INC(txq->axq_qnum, a_aggr);
-
        } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
                 status != ATH_AGGR_BAW_CLOSED);
 }
@@ -1332,7 +1522,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
        struct ath_atx_ac *ac, *ac_tmp, *last_ac;
        struct ath_atx_tid *tid, *last_tid;
 
-       if (list_empty(&txq->axq_acq) ||
+       if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
            txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
                return;
 
@@ -1482,7 +1672,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
        if (!bf)
                return;
 
-       bf->bf_state.bf_type |= BUF_AMPDU;
+       bf->bf_state.bf_type = BUF_AMPDU;
        INIT_LIST_HEAD(&bf_head);
        list_add(&bf->list, &bf_head);
 
@@ -1492,7 +1682,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
        /* Queue to h/w without aggregation */
        TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
        bf->bf_lastbf = bf;
-       ath_buf_set_rate(sc, bf, fi->framelen);
+       ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
 }
 
@@ -1512,41 +1702,18 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
 
        INIT_LIST_HEAD(&bf_head);
        list_add_tail(&bf->list, &bf_head);
-       bf->bf_state.bf_type &= ~BUF_AMPDU;
+       bf->bf_state.bf_type = 0;
 
        /* update starting sequence number for subsequent ADDBA request */
        if (tid)
                INCR(tid->seq_start, IEEE80211_SEQ_MAX);
 
        bf->bf_lastbf = bf;
-       ath_buf_set_rate(sc, bf, fi->framelen);
+       ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
        TX_STAT_INC(txq->axq_qnum, queued);
 }
 
-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-{
-       struct ieee80211_hdr *hdr;
-       enum ath9k_pkt_type htype;
-       __le16 fc;
-
-       hdr = (struct ieee80211_hdr *)skb->data;
-       fc = hdr->frame_control;
-
-       if (ieee80211_is_beacon(fc))
-               htype = ATH9K_PKT_TYPE_BEACON;
-       else if (ieee80211_is_probe_resp(fc))
-               htype = ATH9K_PKT_TYPE_PROBE_RESP;
-       else if (ieee80211_is_atim(fc))
-               htype = ATH9K_PKT_TYPE_ATIM;
-       else if (ieee80211_is_pspoll(fc))
-               htype = ATH9K_PKT_TYPE_PSPOLL;
-       else
-               htype = ATH9K_PKT_TYPE_NORMAL;
-
-       return htype;
-}
-
 static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
                             int framelen)
 {
@@ -1574,51 +1741,6 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
        fi->framelen = framelen;
 }
 
-static int setup_tx_flags(struct sk_buff *skb)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       int flags = 0;
-
-       flags |= ATH9K_TXDESC_INTREQ;
-
-       if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-               flags |= ATH9K_TXDESC_NOACK;
-
-       if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
-               flags |= ATH9K_TXDESC_LDPC;
-
-       return flags;
-}
-
-/*
- * rix - rate index
- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
- * width  - 0 for 20 MHz, 1 for 40 MHz
- * half_gi - to use 4us v/s 3.6 us for symbol time
- */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
-                           int width, int half_gi, bool shortPreamble)
-{
-       u32 nbits, nsymbits, duration, nsymbols;
-       int streams;
-
-       /* find number of symbols: PLCP + data */
-       streams = HT_RC_2_STREAMS(rix);
-       nbits = (pktlen << 3) + OFDM_PLCP_BITS;
-       nsymbits = bits_per_symbol[rix % 8][width] * streams;
-       nsymbols = (nbits + nsymbits - 1) / nsymbits;
-
-       if (!half_gi)
-               duration = SYMBOL_TIME(nsymbols);
-       else
-               duration = SYMBOL_TIME_HALFGI(nsymbols);
-
-       /* addup duration for legacy/ht training and signal fields */
-       duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
-
-       return duration;
-}
-
 u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
 {
        struct ath_hw *ah = sc->sc_ah;
@@ -1631,118 +1753,6 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
                return chainmask;
 }
 
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
-{
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath9k_11n_rate_series series[4];
-       struct sk_buff *skb;
-       struct ieee80211_tx_info *tx_info;
-       struct ieee80211_tx_rate *rates;
-       const struct ieee80211_rate *rate;
-       struct ieee80211_hdr *hdr;
-       int i, flags = 0;
-       u8 rix = 0, ctsrate = 0;
-       bool is_pspoll;
-
-       memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-
-       skb = bf->bf_mpdu;
-       tx_info = IEEE80211_SKB_CB(skb);
-       rates = tx_info->control.rates;
-       hdr = (struct ieee80211_hdr *)skb->data;
-       is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
-
-       /*
-        * We check if Short Preamble is needed for the CTS rate by
-        * checking the BSS's global flag.
-        * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
-        */
-       rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
-       ctsrate = rate->hw_value;
-       if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
-               ctsrate |= rate->hw_value_short;
-
-       for (i = 0; i < 4; i++) {
-               bool is_40, is_sgi, is_sp;
-               int phy;
-
-               if (!rates[i].count || (rates[i].idx < 0))
-                       continue;
-
-               rix = rates[i].idx;
-               series[i].Tries = rates[i].count;
-
-                   if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-                       series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-                       flags |= ATH9K_TXDESC_RTSENA;
-               } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-                       series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-                       flags |= ATH9K_TXDESC_CTSENA;
-               }
-
-               if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-                       series[i].RateFlags |= ATH9K_RATESERIES_2040;
-               if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
-                       series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
-
-               is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
-               is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
-               is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
-
-               if (rates[i].flags & IEEE80211_TX_RC_MCS) {
-                       /* MCS rates */
-                       series[i].Rate = rix | 0x80;
-                       series[i].ChSel = ath_txchainmask_reduction(sc,
-                                       common->tx_chainmask, series[i].Rate);
-                       series[i].PktDuration = ath_pkt_duration(sc, rix, len,
-                                is_40, is_sgi, is_sp);
-                       if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
-                               series[i].RateFlags |= ATH9K_RATESERIES_STBC;
-                       continue;
-               }
-
-               /* legacy rates */
-               if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
-                   !(rate->flags & IEEE80211_RATE_ERP_G))
-                       phy = WLAN_RC_PHY_CCK;
-               else
-                       phy = WLAN_RC_PHY_OFDM;
-
-               rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
-               series[i].Rate = rate->hw_value;
-               if (rate->hw_value_short) {
-                       if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                               series[i].Rate |= rate->hw_value_short;
-               } else {
-                       is_sp = false;
-               }
-
-               if (bf->bf_state.bfs_paprd)
-                       series[i].ChSel = common->tx_chainmask;
-               else
-                       series[i].ChSel = ath_txchainmask_reduction(sc,
-                                       common->tx_chainmask, series[i].Rate);
-
-               series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
-                       phy, rate->bitrate * 100, len, rix, is_sp);
-       }
-
-       /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-       if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
-               flags &= ~ATH9K_TXDESC_RTSENA;
-
-       /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
-       if (flags & ATH9K_TXDESC_RTSENA)
-               flags &= ~ATH9K_TXDESC_CTSENA;
-
-       /* set dur_update_en for l-sig computation except for PS-Poll frames */
-       ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
-                                    bf->bf_lastbf->bf_desc,
-                                    !is_pspoll, ctsrate,
-                                    0, series, 4, flags);
-
-}
-
 /*
  * Assign a descriptor (and sequence number if necessary,
  * and map buffer for DMA. Frees skb on error
@@ -1752,13 +1762,10 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                                           struct ath_atx_tid *tid,
                                           struct sk_buff *skb)
 {
-       struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_frame_info *fi = get_frame_info(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ath_buf *bf;
-       struct ath_desc *ds;
-       int frm_type;
        u16 seqno;
 
        bf = ath_tx_get_buffer(sc);
@@ -1776,7 +1783,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                bf->bf_state.seqno = seqno;
        }
 
-       bf->bf_flags = setup_tx_flags(skb);
        bf->bf_mpdu = skb;
 
        bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@@ -1790,22 +1796,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
                goto error;
        }
 
-       frm_type = get_hw_packet_type(skb);
-
-       ds = bf->bf_desc;
-       ath9k_hw_set_desc_link(ah, ds, 0);
-
-       ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
-                              fi->keyix, fi->keytype, bf->bf_flags);
-
-       ath9k_hw_filltxdesc(ah, ds,
-                           skb->len,   /* segment length */
-                           true,       /* first segment */
-                           true,       /* last segment */
-                           ds,         /* first descriptor */
-                           bf->bf_buf_addr,
-                           txq->axq_qnum);
-
        fi->bf = bf;
 
        return bf;
@@ -1848,16 +1838,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
 
                bf->bf_state.bfs_paprd = txctl->paprd;
 
-               if (bf->bf_state.bfs_paprd)
-                       ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
-                                                  bf->bf_state.bfs_paprd);
-
                if (txctl->paprd)
                        bf->bf_state.bfs_paprd_timestamp = jiffies;
 
-               if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
-
                ath_tx_send_normal(sc, txctl->txq, tid, skb);
        }
 
@@ -1907,6 +1890,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 
                skb_push(skb, padsize);
                memmove(skb->data, skb->data + padsize, padpos);
+               hdr = (struct ieee80211_hdr *) skb->data;
        }
 
        if ((vif && vif->type != NL80211_IFTYPE_AP &&
@@ -1952,10 +1936,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *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))) {
+       if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
                tx_info->flags |= IEEE80211_TX_STAT_ACK;
-       }
 
        padpos = ath9k_cmn_padpos(hdr->frame_control);
        padsize = padpos & 3;
@@ -1999,18 +1982,18 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                                struct ath_tx_status *ts, int txok, int sendbar)
 {
        struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        unsigned long flags;
        int tx_flags = 0;
 
        if (sendbar)
                tx_flags = ATH_TX_BAR;
 
-       if (!txok) {
+       if (!txok)
                tx_flags |= ATH_TX_ERROR;
 
-               if (bf_isxretried(bf))
-                       tx_flags |= ATH_TX_XRETRY;
-       }
+       if (ts->ts_status & ATH9K_TXERR_FILT)
+               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 
        dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
        bf->bf_buf_addr = 0;
@@ -2023,7 +2006,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                else
                        complete(&sc->paprd_complete);
        } else {
-               ath_debug_stat_tx(sc, bf, ts, txq);
+               ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
                ath_tx_complete(sc, skb, tx_flags, txq);
        }
        /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
@@ -2041,7 +2024,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 
 static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
                             struct ath_tx_status *ts, int nframes, int nbad,
-                            int txok, bool update_rc)
+                            int txok)
 {
        struct sk_buff *skb = bf->bf_mpdu;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -2056,9 +2039,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
        tx_rateindex = ts->ts_rateindex;
        WARN_ON(tx_rateindex >= hw->max_rates);
 
-       if (ts->ts_status & ATH9K_TXERR_FILT)
-               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
+       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
                tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 
                BUG_ON(nbad > nframes);
@@ -2068,7 +2049,7 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
        }
 
        if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
-           (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+           (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
                /*
                 * If an underrun error is seen assume it as an excessive
                 * retry only if max frame trigger level has been reached
@@ -2081,9 +2062,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
                 * successfully by eventually preferring slower rates.
                 * This itself should also alleviate congestion on the bus.
                 */
-               if (ieee80211_is_data(hdr->frame_control) &&
-                   (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
-                                    ATH9K_TX_DELIM_UNDERRUN)) &&
+               if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+                                            ATH9K_TX_DELIM_UNDERRUN)) &&
+                   ieee80211_is_data(hdr->frame_control) &&
                    ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
                        tx_info->status.rates[tx_rateindex].count =
                                hw->max_rate_tries;
@@ -2114,13 +2095,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
        spin_unlock_bh(&txq->axq_lock);
 
        if (!bf_isampdu(bf)) {
-               /*
-                * This frame is sent out as a single frame.
-                * Use hardware retry status for this frame.
-                */
-               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_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
                ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
        } else
                ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
@@ -2147,6 +2122,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 
        spin_lock_bh(&txq->axq_lock);
        for (;;) {
+               if (work_pending(&sc->hw_reset_work))
+                       break;
+
                if (list_empty(&txq->axq_q)) {
                        txq->axq_link = NULL;
                        if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2234,9 +2212,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
        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);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
        }
 
        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2269,6 +2245,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
        int status;
 
        for (;;) {
+               if (work_pending(&sc->hw_reset_work))
+                       break;
+
                status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
                if (status == -EINPROGRESS)
                        break;
index 782b8f3ae58f3ac408c43a6deea388a1cc962340..af351ecd87c40810ad2c0102b9a3a112a5cbea6d 100644 (file)
@@ -1115,8 +1115,10 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
         * the high througput speed in 802.11n networks.
         */
 
-       if (!is_main_vif(ar, vif))
+       if (!is_main_vif(ar, vif)) {
+               mutex_lock(&ar->mutex);
                goto err_softw;
+       }
 
        /*
         * While the hardware supports *catch-all* key, for offloading
index 8ff706289b5db6b8886c1559528ae23e575acde3..f8615cdf1075b7102403a1f352821ef756adb505 100644 (file)
 #define B43_MMIO_TSF_CFP_START_LOW     0x604
 #define B43_MMIO_TSF_CFP_START_HIGH    0x606
 #define B43_MMIO_TSF_CFP_PRETBTT       0x612
+#define B43_MMIO_TSF_CLK_FRAC_LOW      0x62E
+#define B43_MMIO_TSF_CLK_FRAC_HIGH     0x630
 #define B43_MMIO_TSF_0                 0x632   /* core rev < 3 only */
 #define B43_MMIO_TSF_1                 0x634   /* core rev < 3 only */
 #define B43_MMIO_TSF_2                 0x636   /* core rev < 3 only */
index 05f6c7bff6ab683836c9614bbe4797e5fdd2d2ad..424692df239d40232f6da1e0849a875064087ecd 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   Bus abstraction layer
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
index 975d960405488b6ea2cf3db429688098247103da..5e45604f0f5d2c95b86b364ab354769fd126d24f 100644 (file)
@@ -817,9 +817,23 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
        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);
index 172294170df8e7777938b429257c334b0cad8856..56fa3a3648c43dbc32a015ece857a0f3f5bcaeac 100644 (file)
@@ -7,6 +7,7 @@
   Copyright (c) 2005-2009 Michael Buesch <[email protected]>
   Copyright (c) 2005 Danny van Dyk <[email protected]>
   Copyright (c) 2005 Andreas Jaggi <[email protected]>
+  Copyright (c) 2010-2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
 
   SDIO support
   Copyright (c) 2009 Albert Herranz <[email protected]>
@@ -64,6 +65,7 @@ MODULE_AUTHOR("Martin Langer");
 MODULE_AUTHOR("Stefano Brivio");
 MODULE_AUTHOR("Michael Buesch");
 MODULE_AUTHOR("Gábor Stefanik");
+MODULE_AUTHOR("RafaÅ‚ MiÅ‚ecki");
 MODULE_LICENSE("GPL");
 
 MODULE_FIRMWARE("b43/ucode11.fw");
@@ -1635,7 +1637,8 @@ static void handle_irq_beacon(struct b43_wldev *dev)
        u32 cmd, beacon0_valid, beacon1_valid;
 
        if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
-           !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
+           !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) &&
+           !b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
                return;
 
        /* This is the bottom half of the asynchronous beacon update. */
@@ -2953,6 +2956,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
        case B43_PHYTYPE_N:
        case B43_PHYTYPE_LP:
        case B43_PHYTYPE_HT:
+       case B43_PHYTYPE_LCN:
                b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
                b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
                b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
index 4d6345e8ee6bb7fc4aca143610ab23939da5e5e1..7416c5e9154d6a734ece86a5d071ca57f7be485a 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n HT-PHY support
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
index 4b2cd6d24ce9573696057f36fbb6a09af23b8c54..bffeb44b4a4088c3ff22765e55cfd2be81b45871 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n LCN-PHY support
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
   Boston, MA 02110-1301, USA.
 
+  This file incorporates work covered by the following copyright and
+  permission notice:
+
+      Copyright (c) 2010 Broadcom Corporation
+
+      Permission to use, copy, modify, and/or distribute this software for any
+      purpose with or without fee is hereby granted, provided that the above
+      copyright notice and this permission notice appear in all copies.
 */
 
 #include <linux/slab.h>
 #include "tables_phy_lcn.h"
 #include "main.h"
 
+struct lcn_tx_gains {
+       u16 gm_gain;
+       u16 pga_gain;
+       u16 pad_gain;
+       u16 dac_gain;
+};
+
+struct lcn_tx_iir_filter {
+       u8 type;
+       u16 values[16];
+};
+
+enum lcn_sense_type {
+       B43_SENSE_TEMP,
+       B43_SENSE_VBAT,
+};
+
+/* In theory it's PHY common function, move if needed */
+/* brcms_b_switch_macfreq */
+static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
+{
+       if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
+               switch (spurmode) {
+               case 2:         /* 126 Mhz */
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+                       break;
+               case 1:         /* 123 Mhz */
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+                       break;
+               default:        /* 120 Mhz */
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+                       break;
+               }
+       } else if (dev->phy.type == B43_PHYTYPE_LCN) {
+               switch (spurmode) {
+               case 1:         /* 82 Mhz */
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+                       break;
+               default:        /* 80 Mhz */
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+                       break;
+               }
+       }
+}
+
 /**************************************************
  * Radio 2064.
  **************************************************/
 
+/* wlc_lcnphy_radio_2064_channel_tune_4313 */
+static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
+{
+       u16 save[2];
+
+       b43_radio_set(dev, 0x09d, 0x4);
+       b43_radio_write(dev, 0x09e, 0xf);
+
+       /* Channel specific values in theory, in practice always the same */
+       b43_radio_write(dev, 0x02a, 0xb);
+       b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
+       b43_radio_maskset(dev, 0x091, ~0x3, 0);
+       b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
+       b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
+       b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
+       b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
+       b43_radio_write(dev, 0x06c, 0x80);
+
+       save[0] = b43_radio_read(dev, 0x044);
+       save[1] = b43_radio_read(dev, 0x12b);
+
+       b43_radio_set(dev, 0x044, 0x7);
+       b43_radio_set(dev, 0x12b, 0xe);
+
+       /* TODO */
+
+       b43_radio_write(dev, 0x040, 0xfb);
+
+       b43_radio_write(dev, 0x041, 0x9a);
+       b43_radio_write(dev, 0x042, 0xa3);
+       b43_radio_write(dev, 0x043, 0x0c);
+
+       /* TODO */
+
+       b43_radio_set(dev, 0x044, 0x0c);
+       udelay(1);
+
+       b43_radio_write(dev, 0x044, save[0]);
+       b43_radio_write(dev, 0x12b, save[1]);
+
+       if (dev->phy.rev == 1) {
+               /* brcmsmac uses outdated 0x3 for 0x038 */
+               b43_radio_write(dev, 0x038, 0x0);
+               b43_radio_write(dev, 0x091, 0x7);
+       }
+}
+
+/* wlc_radio_2064_init */
 static void b43_radio_2064_init(struct b43_wldev *dev)
 {
-       b43_radio_write(dev, 0x09c, 0x0020);
-       b43_radio_write(dev, 0x105, 0x0008);
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               b43_radio_write(dev, 0x09c, 0x0020);
+               b43_radio_write(dev, 0x105, 0x0008);
+       } else {
+               /* TODO */
+       }
        b43_radio_write(dev, 0x032, 0x0062);
        b43_radio_write(dev, 0x033, 0x0019);
        b43_radio_write(dev, 0x090, 0x0010);
        b43_radio_write(dev, 0x010, 0x0000);
-       b43_radio_write(dev, 0x060, 0x007f);
-       b43_radio_write(dev, 0x061, 0x0072);
-       b43_radio_write(dev, 0x062, 0x007f);
+       if (dev->phy.rev == 1) {
+               b43_radio_write(dev, 0x060, 0x007f);
+               b43_radio_write(dev, 0x061, 0x0072);
+               b43_radio_write(dev, 0x062, 0x007f);
+       }
        b43_radio_write(dev, 0x01d, 0x0002);
        b43_radio_write(dev, 0x01e, 0x0006);
 
        b43_phy_write(dev, 0x4ea, 0x4688);
        b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
        b43_phy_mask(dev, 0x4eb, ~0x01c0);
-       b43_phy_maskset(dev, 0x4eb, 0xff00, 0x19);
+       b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
 
        b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
 
@@ -80,6 +194,7 @@ static void b43_radio_2064_init(struct b43_wldev *dev)
  * Various PHY ops
  **************************************************/
 
+/* wlc_lcnphy_toggle_afe_pwdn */
 static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
 {
        u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
@@ -95,22 +210,40 @@ static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
        b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
 }
 
-static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev)
+/* wlc_lcnphy_get_pa_gain */
+static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
 {
-       u8 i;
+       return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
+}
+
+/* wlc_lcnphy_set_dac_gain */
+static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
+{
+       u16 dac_ctrl;
+
+       dac_ctrl = b43_phy_read(dev, 0x439);
+       dac_ctrl = dac_ctrl & 0xc7f;
+       dac_ctrl = dac_ctrl | (dac_gain << 7);
+       b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
+}
 
-       for (i = 0; i < 0x80; i++)
-               b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
+/* wlc_lcnphy_set_bbmult */
+static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
+{
+       b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
 }
 
-static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev)
+/* wlc_lcnphy_clear_tx_power_offsets */
+static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
 {
        u8 i;
 
-       b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
-       for (i = 0; i < 30; i++) {
-               b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
-               b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+       if (1) { /* FIXME */
+               b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
+               for (i = 0; i < 30; i++) {
+                       b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
+                       b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+               }
        }
 
        b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
@@ -120,6 +253,447 @@ static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev)
        }
 }
 
+/* wlc_lcnphy_rev0_baseband_init */
+static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
+{
+       b43_radio_write(dev, 0x11c, 0);
+
+       b43_phy_write(dev, 0x43b, 0);
+       b43_phy_write(dev, 0x43c, 0);
+       b43_phy_write(dev, 0x44c, 0);
+       b43_phy_write(dev, 0x4e6, 0);
+       b43_phy_write(dev, 0x4f9, 0);
+       b43_phy_write(dev, 0x4b0, 0);
+       b43_phy_write(dev, 0x938, 0);
+       b43_phy_write(dev, 0x4b0, 0);
+       b43_phy_write(dev, 0x44e, 0);
+
+       b43_phy_set(dev, 0x567, 0x03);
+
+       b43_phy_set(dev, 0x44a, 0x44);
+       b43_phy_write(dev, 0x44a, 0x80);
+
+       if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
+               ; /* TODO */
+       b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
+       if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
+               b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
+               b43_phy_write(dev, 0x910, 0x1);
+       }
+
+       b43_phy_write(dev, 0x910, 0x1);
+
+       b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
+       b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
+       b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
+}
+
+/* wlc_lcnphy_bu_tweaks */
+static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
+{
+       b43_phy_set(dev, 0x805, 0x1);
+
+       b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
+       b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
+
+       b43_phy_write(dev, 0x414, 0x1e10);
+       b43_phy_write(dev, 0x415, 0x0640);
+
+       b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
+
+       b43_phy_set(dev, 0x44a, 0x44);
+       b43_phy_write(dev, 0x44a, 0x80);
+
+       b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
+       b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
+
+       if (dev->dev->bus_sprom->board_rev >= 0x1204)
+               b43_radio_set(dev, 0x09b, 0xf0);
+
+       b43_phy_write(dev, 0x7d6, 0x0902);
+
+       b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
+       b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
+
+       if (dev->phy.rev == 1) {
+               b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
+               b43_phy_maskset(dev, 0x411, ~0xff, 1);
+               b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
+
+               /* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
+
+               b43_phy_maskset(dev, 0x656, ~0xf, 2);
+               b43_phy_set(dev, 0x44d, 4);
+
+               b43_radio_set(dev, 0x0f7, 0x4);
+               b43_radio_mask(dev, 0x0f1, ~0x3);
+               b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
+               b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
+               b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
+
+               b43_radio_set(dev, 0x11f, 0x2);
+
+               b43_phy_lcn_clear_tx_power_offsets(dev);
+
+               /* TODO: something more? */
+       }
+}
+
+/* wlc_lcnphy_vbat_temp_sense_setup */
+static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
+                                   enum lcn_sense_type sense_type)
+{
+       u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+       u16 auxpga_vmid;
+       u8 tx_pwr_idx;
+       u8 i;
+
+       u16 save_radio_regs[6][2] = {
+               { 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
+               { 0x025, 0 }, { 0x112, 0 },
+       };
+       u16 save_phy_regs[14][2] = {
+               { 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
+               { 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
+               { 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
+               { 0x40d, 0 }, { 0x4a2, 0 },
+       };
+       u16 save_radio_4a4;
+
+       msleep(1);
+
+       /* Save */
+       for (i = 0; i < 6; i++)
+               save_radio_regs[i][1] = b43_radio_read(dev,
+                                                      save_radio_regs[i][0]);
+       for (i = 0; i < 14; i++)
+               save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
+       b43_mac_suspend(dev);
+       save_radio_4a4 = b43_radio_read(dev, 0x4a4);
+       /* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
+       tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
+
+       /* Setup */
+       /* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
+       b43_radio_set(dev, 0x007, 0x1);
+       b43_radio_set(dev, 0x0ff, 0x10);
+       b43_radio_set(dev, 0x11f, 0x4);
+
+       b43_phy_mask(dev, 0x503, ~0x1);
+       b43_phy_mask(dev, 0x503, ~0x4);
+       b43_phy_mask(dev, 0x4a4, ~0x4000);
+       b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
+       b43_phy_mask(dev, 0x4d0, ~0x20);
+       b43_phy_set(dev, 0x4a5, 0xff);
+       b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
+       b43_phy_mask(dev, 0x4a5, ~0x700);
+       b43_phy_maskset(dev, 0x40d, ~0xff, 64);
+       b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
+       b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
+       b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
+       b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
+       b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
+       b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
+       b43_phy_mask(dev, 0x4da, ~0x1000);
+       b43_phy_set(dev, 0x4da, 0x2000);
+       b43_phy_set(dev, 0x4a6, 0x8000);
+
+       b43_radio_write(dev, 0x025, 0xc);
+       b43_radio_set(dev, 0x005, 0x8);
+       b43_phy_set(dev, 0x938, 0x4);
+       b43_phy_set(dev, 0x939, 0x4);
+       b43_phy_set(dev, 0x4a4, 0x1000);
+
+       /* FIXME: don't hardcode */
+       b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
+
+       switch (sense_type) {
+       case B43_SENSE_TEMP:
+               b43_phy_set(dev, 0x4d7, 0x8);
+               b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
+               auxpga_vmidcourse = 8;
+               auxpga_vmidfine = 0x4;
+               auxpga_gain = 2;
+               b43_radio_set(dev, 0x082, 0x20);
+               break;
+       case B43_SENSE_VBAT:
+               b43_phy_set(dev, 0x4d7, 0x8);
+               b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
+               auxpga_vmidcourse = 7;
+               auxpga_vmidfine = 0xa;
+               auxpga_gain = 2;
+               break;
+       }
+       auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+
+       b43_phy_set(dev, 0x4d8, 0x1);
+       b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
+       b43_phy_set(dev, 0x4d8, 0x2);
+       b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
+       b43_phy_set(dev, 0x4d0, 0x20);
+       b43_radio_write(dev, 0x112, 0x6);
+
+       /* TODO: dummy transmission? */
+       /* Wait if not done */
+       if (!(b43_phy_read(dev, 0x476) & 0x8000))
+               udelay(10);
+
+       /* Restore */
+       for (i = 0; i < 6; i++)
+               b43_radio_write(dev, save_radio_regs[i][0],
+                               save_radio_regs[i][1]);
+       for (i = 0; i < 14; i++)
+               b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
+       /* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
+       b43_radio_write(dev, 0x4a4, save_radio_4a4);
+
+       b43_mac_enable(dev);
+
+       msleep(1);
+}
+
+static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
+                                              u8 filter_type)
+{
+       int i, j;
+       u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
+                          0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
+                          0x931, 0x932 };
+       /* Table is from brcmsmac, values for type 25 were outdated, probably
+        * others need updating too */
+       struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
+               { 0,  { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
+                       1582, 64, 128, 64 } },
+               { 1,  { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
+                       1863, 93, 167, 93 } },
+               { 2,  { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
+                       778, 1582, 64, 128, 64 } },
+               { 3,  { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
+                       754, 1760, 170, 340, 170 } },
+               { 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
+                       767, 1760, 256, 185, 256 } },
+               { 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
+                       767, 1760, 256, 273, 256 } },
+               { 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
+                       767, 1760, 256, 352, 256 } },
+               { 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
+                       767, 1760, 128, 233, 128 } },
+               { 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
+                       1760, 256, 1881, 256 } },
+               { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
+                       1760, 262, 1878, 262 } },
+               /* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
+                * 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
+               { 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
+                       1864, 128, 384, 288 } },
+               { 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
+                       613, 1864, 128, 384, 288 } },
+               { 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
+                       754, 1760, 170, 340, 170 } },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
+               if (tx_iir_filters_cck[i].type == filter_type) {
+                       for (j = 0; j < 16; j++)
+                               b43_phy_write(dev, phy_regs[j],
+                                             tx_iir_filters_cck[i].values[j]);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
+                                               u8 filter_type)
+{
+       int i, j;
+       u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
+                          0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
+                          0x90d, 0x90e };
+       struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
+               { 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
+                      0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
+               { 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
+                      0xFE2B, 212, 0xFFCE, 212 } },
+               { 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+                      0xFEF2, 128, 0xFFE2, 128 } },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
+               if (tx_iir_filters_ofdm[i].type == filter_type) {
+                       for (j = 0; j < 16; j++)
+                               b43_phy_write(dev, phy_regs[j],
+                                             tx_iir_filters_ofdm[i].values[j]);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+/* wlc_lcnphy_set_tx_gain_override */
+static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
+{
+       b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
+       b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
+       b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
+}
+
+/* wlc_lcnphy_set_tx_gain */
+static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
+                                   struct lcn_tx_gains *target_gains)
+{
+       u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
+
+       b43_phy_write(dev, 0x4b5,
+                     (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+       b43_phy_maskset(dev, 0x4fb, ~0x7fff,
+                       (target_gains->pad_gain | (pa_gain << 8)));
+       b43_phy_write(dev, 0x4fc,
+                     (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+       b43_phy_maskset(dev, 0x4fd, ~0x7fff,
+                       (target_gains->pad_gain | (pa_gain << 8)));
+
+       b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
+       b43_phy_lcn_set_tx_gain_override(dev, true);
+}
+
+/* wlc_lcnphy_tx_pwr_ctrl_init */
+static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
+{
+       struct lcn_tx_gains tx_gains;
+       u8 bbmult;
+
+       b43_mac_suspend(dev);
+
+       if (!dev->phy.lcn->hw_pwr_ctl_capable) {
+               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+                       tx_gains.gm_gain = 4;
+                       tx_gains.pga_gain = 12;
+                       tx_gains.pad_gain = 12;
+                       tx_gains.dac_gain = 0;
+                       bbmult = 150;
+               } else {
+                       tx_gains.gm_gain = 7;
+                       tx_gains.pga_gain = 15;
+                       tx_gains.pad_gain = 14;
+                       tx_gains.dac_gain = 0;
+                       bbmult = 150;
+               }
+               b43_phy_lcn_set_tx_gain(dev, &tx_gains);
+               b43_phy_lcn_set_bbmult(dev, bbmult);
+               b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
+       } else {
+               b43err(dev->wl, "TX power control not supported for this HW\n");
+       }
+
+       b43_mac_enable(dev);
+}
+
+/* wlc_lcnphy_txrx_spur_avoidance_mode */
+static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
+                                                bool enable)
+{
+       if (enable) {
+               b43_phy_write(dev, 0x942, 0x7);
+               b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
+               b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
+
+               b43_phy_write(dev, 0x44a, 0x084);
+               b43_phy_write(dev, 0x44a, 0x080);
+               b43_phy_write(dev, 0x6d3, 0x2222);
+               b43_phy_write(dev, 0x6d3, 0x2220);
+       } else {
+               b43_phy_write(dev, 0x942, 0x0);
+               b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
+               b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
+       }
+       b43_phy_switch_macfreq(dev, enable);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+/* wlc_lcnphy_set_chanspec_tweaks */
+static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
+{
+       struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
+       b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
+
+       if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
+           channel == 9 || channel == 10 || channel == 11 || channel == 12) {
+               bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
+               bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
+               bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
+
+               bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+               b43_phy_write(dev, 0x942, 0);
+
+               b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
+               b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
+               b43_phy_write(dev, 0x425, 0x5907);
+       } else {
+               bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
+               bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
+               bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
+
+               bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+               b43_phy_write(dev, 0x942, 0);
+
+               b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
+               b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
+               b43_phy_write(dev, 0x425, 0x590a);
+       }
+
+       b43_phy_set(dev, 0x44a, 0x44);
+       b43_phy_write(dev, 0x44a, 0x80);
+}
+
+/* wlc_phy_chanspec_set_lcnphy */
+static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
+                                  struct ieee80211_channel *channel,
+                                  enum nl80211_channel_type channel_type)
+{
+       static const u16 sfo_cfg[14][2] = {
+               {965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
+               {975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
+               {985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
+       };
+
+       b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
+
+       b43_phy_set(dev, 0x44a, 0x44);
+       b43_phy_write(dev, 0x44a, 0x80);
+
+       b43_radio_2064_channel_setup(dev);
+       mdelay(1);
+
+       b43_phy_lcn_afe_set_unset(dev);
+
+       b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
+       b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
+
+       if (channel->hw_value == 14) {
+               b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
+               b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
+       } else {
+               b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
+               /* brcmsmac uses filter_type 2, we follow wl with 25 */
+               b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
+       }
+       /* brcmsmac uses filter_type 2, we follow wl with 0 */
+       b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
+
+       b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
+
+       return 0;
+}
+
 /**************************************************
  * Basic PHY ops.
  **************************************************/
@@ -153,8 +727,11 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
        memset(phy_lcn, 0, sizeof(*phy_lcn));
 }
 
+/* wlc_phy_init_lcnphy */
 static int b43_phy_lcn_op_init(struct b43_wldev *dev)
 {
+       struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
        b43_phy_set(dev, 0x44a, 0x80);
        b43_phy_mask(dev, 0x44a, 0x7f);
        b43_phy_set(dev, 0x6d1, 0x80);
@@ -167,18 +744,31 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev)
        b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
 
        b43_phy_lcn_tables_init(dev);
-       /* TODO: various tables ops here */
-       b43_phy_lcn_clean_0x18_table(dev);
-
-       /* TODO: some ops here */
 
-       b43_phy_lcn_clear_0x07_table(dev);
+       b43_phy_lcn_rev0_baseband_init(dev);
+       b43_phy_lcn_bu_tweaks(dev);
 
        if (dev->phy.radio_ver == 0x2064)
                b43_radio_2064_init(dev);
        else
                B43_WARN_ON(1);
 
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+               b43_phy_lcn_tx_pwr_ctl_init(dev);
+
+       b43_switch_channel(dev, dev->phy.channel);
+
+       bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
+       bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
+
+       /* TODO */
+
+       b43_phy_set(dev, 0x448, 0x4000);
+       udelay(100);
+       b43_phy_mask(dev, 0x448, ~0x4000);
+
+       /* TODO */
+
        return 0;
 }
 
@@ -215,6 +805,22 @@ static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
        }
 }
 
+static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
+                                       unsigned int new_channel)
+{
+       struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+       enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               if ((new_channel < 1) || (new_channel > 14))
+                       return -EINVAL;
+       } else {
+               return -EINVAL;
+       }
+
+       return b43_phy_lcn_set_channel(dev, channel, channel_type);
+}
+
 static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
 {
        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -232,6 +838,46 @@ static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
 {
 }
 
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+                                  u16 set)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA,
+                   (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+       /* LCN-PHY needs 0x200 for read access */
+       reg |= 0x200;
+
+       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
+                                      u16 value)
+{
+       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
 /**************************************************
  * PHY ops struct.
  **************************************************/
@@ -241,18 +887,14 @@ const struct b43_phy_operations b43_phyops_lcn = {
        .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,
index 25f06e8d453186e73aaa1d7939c6a3c4eb549b1c..6a7092e13fff95244bbc9c11ff688f9d5686f38f 100644 (file)
@@ -19,6 +19,9 @@
 
 
 struct b43_phy_lcn {
+       bool hw_pwr_ctl;
+       bool hw_pwr_ctl_capable;
+       u8 tx_pwr_curr_idx;
 };
 
 
index 2eadadf5f4fc375ced006719086846a624182a04..b17d9b6c33a51e5a5946c5a9f3b12bdab3541e50 100644 (file)
@@ -4,6 +4,7 @@
   IEEE 802.11n PHY support
 
   Copyright (c) 2008 Michael Buesch <[email protected]>
+  Copyright (c) 2010-2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
 
   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
@@ -77,6 +78,7 @@ enum b43_nphy_rssi_type {
        B43_NPHY_RSSI_TBD,
 };
 
+/* TODO: reorder functions */
 static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
                                                bool enable);
 static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
@@ -87,6 +89,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
                                                u16 value, u8 core, bool off);
 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
                                                u16 value, u8 core);
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev);
+
+static inline bool b43_nphy_ipa(struct b43_wldev *dev)
+{
+       enum ieee80211_band band = b43_current_band(dev->wl);
+       return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
+               (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
+}
 
 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
 {//TODO
@@ -248,15 +258,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
 {
        struct b43_phy_n *nphy = dev->phy.n;
        u8 i;
-       u16 tmp;
+       u16 bmask, val, tmp;
+       enum ieee80211_band band = b43_current_band(dev->wl);
 
        if (nphy->hang_avoid)
                b43_nphy_stay_in_carrier_search(dev, 1);
 
        nphy->txpwrctrl = enable;
        if (!enable) {
-               if (dev->phy.rev >= 3)
-                       ; /* TODO */
+               if (dev->phy.rev >= 3 &&
+                   (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
+                    (B43_NPHY_TXPCTL_CMD_COEFF |
+                     B43_NPHY_TXPCTL_CMD_HWPCTLEN |
+                     B43_NPHY_TXPCTL_CMD_PCTLEN))) {
+                       /* We disable enabled TX pwr ctl, save it's state */
+                       nphy->tx_pwr_idx[0] = b43_phy_read(dev,
+                                               B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
+                       nphy->tx_pwr_idx[1] = b43_phy_read(dev,
+                                               B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
+               }
 
                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
                for (i = 0; i < 84; i++)
@@ -285,10 +305,67 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
                        b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
                                ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
 
-               if (dev->phy.rev < 2 && 0)
-                       ; /* TODO */
+               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+                       b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
        } else {
-               b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n");
+               b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
+                                   nphy->adj_pwr_tbl);
+               b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
+                                   nphy->adj_pwr_tbl);
+
+               bmask = B43_NPHY_TXPCTL_CMD_COEFF |
+                       B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+               /* wl does useless check for "enable" param here */
+               val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+               if (dev->phy.rev >= 3) {
+                       bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+                       if (val)
+                               val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+               }
+               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
+
+               if (band == IEEE80211_BAND_5GHZ) {
+                       b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+                                       ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
+                       if (dev->phy.rev > 1)
+                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+                                               ~B43_NPHY_TXPCTL_INIT_PIDXI1,
+                                               0x64);
+               }
+
+               if (dev->phy.rev >= 3) {
+                       if (nphy->tx_pwr_idx[0] != 128 &&
+                           nphy->tx_pwr_idx[1] != 128) {
+                               /* Recover TX pwr ctl state */
+                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+                                               ~B43_NPHY_TXPCTL_CMD_INIT,
+                                               nphy->tx_pwr_idx[0]);
+                               if (dev->phy.rev > 1)
+                                       b43_phy_maskset(dev,
+                                               B43_NPHY_TXPCTL_INIT,
+                                               ~0xff, nphy->tx_pwr_idx[1]);
+                       }
+               }
+
+               if (dev->phy.rev >= 3) {
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
+               } else {
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
+               }
+
+               if (dev->phy.rev == 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
+               else if (dev->phy.rev < 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
+
+               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+                       b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
+
+               if (b43_nphy_ipa(dev)) {
+                       b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
+                       b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
+               }
        }
 
        if (nphy->hang_avoid)
@@ -369,22 +446,23 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
                else
                        b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
 
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i);
-               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
-
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
-               tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+               b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
 
+               tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
                if (i == 0)
                        tmp = (tmp & 0x00FF) | (bbmult << 8);
                else
                        tmp = (tmp & 0xFF00) | bbmult;
-
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
-               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp);
-
-               if (0)
-                       ; /* TODO */
+               b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
+
+               if (b43_nphy_ipa(dev)) {
+                       u32 tmp32;
+                       u16 reg = (i == 0) ?
+                               B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
+                       tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
+                       b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
+                       b43_phy_set(dev, reg, 0x4);
+               }
        }
 
        b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
@@ -393,6 +471,57 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
                b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+{
+       struct b43_phy *phy = &dev->phy;
+
+       const u32 *table = NULL;
+#if 0
+       TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
+       u32 rfpwr_offset;
+       u8 pga_gain;
+       int i;
+#endif
+
+       if (phy->rev >= 3) {
+               if (b43_nphy_ipa(dev)) {
+                       table = b43_nphy_get_ipa_gain_table(dev);
+               } else {
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+                               if (phy->rev == 3)
+                                       table = b43_ntab_tx_gain_rev3_5ghz;
+                               if (phy->rev == 4)
+                                       table = b43_ntab_tx_gain_rev4_5ghz;
+                               else
+                                       table = b43_ntab_tx_gain_rev5plus_5ghz;
+                       } else {
+                               table = b43_ntab_tx_gain_rev3plus_2ghz;
+                       }
+               }
+       } else {
+               table = b43_ntab_tx_gain_rev0_1_2;
+       }
+       b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
+       b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+
+       if (phy->rev >= 3) {
+#if 0
+               nphy->gmval = (table[0] >> 16) & 0x7000;
+
+               for (i = 0; i < 128; i++) {
+                       pga_gain = (table[i] >> 24) & 0xF;
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+                       else
+                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
+                       b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
+                                      rfpwr_offset);
+                       b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
+                                      rfpwr_offset);
+               }
+#endif
+       }
+}
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
 static void b43_radio_2055_setup(struct b43_wldev *dev,
@@ -581,14 +710,10 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
 static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
        u16 tmp;
-       enum ieee80211_band band = b43_current_band(dev->wl);
-       bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
-                       (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
 
        if (dev->phy.rev >= 3) {
-               if (ipa) {
+               if (b43_nphy_ipa(dev)) {
                        tmp = 4;
                        b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
                              (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
@@ -899,11 +1024,7 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
 static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
 {
        u16 array[4];
-       int i;
-
-       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
-       for (i = 0; i < 4; i++)
-               array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+       b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
 
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
@@ -1366,180 +1487,220 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
        }
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
-static void b43_nphy_workarounds(struct b43_wldev *dev)
+static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
 {
+       struct b43_phy_n *nphy = dev->phy.n;
        struct ssb_sprom *sprom = dev->dev->bus_sprom;
-       struct b43_phy *phy = &dev->phy;
-       struct b43_phy_n *nphy = phy->n;
 
-       u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
-       u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
-
-       u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
-       u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
+       /* TX to RX */
+       u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
+       u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+       /* RX to TX */
+       u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
+                                       0x1F };
+       u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+       u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
+       u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
 
        u16 tmp16;
        u32 tmp32;
 
-       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
-               b43_nphy_classifier(dev, 1, 0);
-       else
-               b43_nphy_classifier(dev, 1, 1);
+       tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+       tmp32 &= 0xffffff;
+       b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+       b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+       b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+       b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+       b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
+       b43_phy_write(dev, 0x2AE, 0x000C);
+
+       /* TX to RX */
+       b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
+
+       /* RX to TX */
+       if (b43_nphy_ipa(dev))
+               b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
+                                        rx2tx_delays_ipa, 9);
+       if (nphy->hw_phyrxchain != 3 &&
+           nphy->hw_phyrxchain != nphy->hw_phytxchain) {
+               if (b43_nphy_ipa(dev)) {
+                       rx2tx_delays[5] = 59;
+                       rx2tx_delays[6] = 1;
+                       rx2tx_events[7] = 0x1F;
+               }
+               b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
+       }
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
+       tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
+               0x2 : 0x9C40;
+       b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
 
-       b43_phy_set(dev, B43_NPHY_IQFLIP,
-                   B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+       b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
 
-       if (dev->phy.rev >= 3) {
-               tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
-               tmp32 &= 0xffffff;
-               b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+       b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+       b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
 
-               b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
-               b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
-               b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+       b43_nphy_gain_ctrl_workarounds(dev);
 
-               b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
-               b43_phy_write(dev, 0x2AE, 0x000C);
+       b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
+       b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
 
-               /* TODO */
+       /* TODO */
 
-               tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
-                       0x2 : 0x9C40;
-               b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+       /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+       if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+            b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
+           (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+            b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
+               tmp32 = 0x00088888;
+       else
+               tmp32 = 0x88888888;
+       b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+       b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+       b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+       if (dev->phy.rev == 4 &&
+               b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+               b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+                               0x70);
+               b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+                               0x70);
+       }
 
-               b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+       b43_phy_write(dev, 0x224, 0x039C);
+       b43_phy_write(dev, 0x225, 0x0357);
+       b43_phy_write(dev, 0x226, 0x0317);
+       b43_phy_write(dev, 0x227, 0x02D7);
+       b43_phy_write(dev, 0x228, 0x039C);
+       b43_phy_write(dev, 0x229, 0x0357);
+       b43_phy_write(dev, 0x22A, 0x0317);
+       b43_phy_write(dev, 0x22B, 0x02D7);
+       b43_phy_write(dev, 0x22C, 0x039C);
+       b43_phy_write(dev, 0x22D, 0x0357);
+       b43_phy_write(dev, 0x22E, 0x0317);
+       b43_phy_write(dev, 0x22F, 0x02D7);
+}
 
-               b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
-               b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
+{
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+       struct b43_phy *phy = &dev->phy;
+       struct b43_phy_n *nphy = phy->n;
 
-               b43_nphy_gain_ctrl_workarounds(dev);
+       u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
+       u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
 
-               b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
-               b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+       u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
+       u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
 
-               /* TODO */
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
+           nphy->band5g_pwrgain) {
+               b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
+               b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
+       } else {
+               b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+               b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
+       }
 
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
-
-               /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
-
-               if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
-                   b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
-                   (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
-                   b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
-                       tmp32 = 0x00088888;
-               else
-                       tmp32 = 0x88888888;
-               b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
-               b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
-               b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
-
-               if (dev->phy.rev == 4 &&
-                   b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-                       b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
-                                       0x70);
-                       b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
-                                       0x70);
-               }
+       b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
+       b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
+       b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+       b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
 
-               b43_phy_write(dev, 0x224, 0x039C);
-               b43_phy_write(dev, 0x225, 0x0357);
-               b43_phy_write(dev, 0x226, 0x0317);
-               b43_phy_write(dev, 0x227, 0x02D7);
-               b43_phy_write(dev, 0x228, 0x039C);
-               b43_phy_write(dev, 0x229, 0x0357);
-               b43_phy_write(dev, 0x22A, 0x0317);
-               b43_phy_write(dev, 0x22B, 0x02D7);
-               b43_phy_write(dev, 0x22C, 0x039C);
-               b43_phy_write(dev, 0x22D, 0x0357);
-               b43_phy_write(dev, 0x22E, 0x0317);
-               b43_phy_write(dev, 0x22F, 0x02D7);
-       } else {
-               if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
-                   nphy->band5g_pwrgain) {
-                       b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
-                       b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
-               } else {
-                       b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
-                       b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
-               }
+       if (dev->phy.rev < 2) {
+               b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
+               b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
+               b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+               b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+               b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
+               b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
+       }
 
-               b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
-               b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
-               b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
-               b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
 
-               if (dev->phy.rev < 2) {
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
-                       b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
-               }
+       if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
+           dev->dev->board_type == 0x8B) {
+               delays1[0] = 0x1;
+               delays1[5] = 0x14;
+       }
+       b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
+       b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
 
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+       b43_nphy_gain_ctrl_workarounds(dev);
 
-               if (sprom->boardflags2_lo & 0x100 &&
-                   dev->dev->board_type == 0x8B) {
-                       delays1[0] = 0x1;
-                       delays1[5] = 0x14;
-               }
-               b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
-               b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
+       if (dev->phy.rev < 2) {
+               if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
+                       b43_hf_write(dev, b43_hf_read(dev) |
+                                       B43_HF_MLADVW);
+       } else if (dev->phy.rev == 2) {
+               b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
+               b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
+       }
 
-               b43_nphy_gain_ctrl_workarounds(dev);
+       if (dev->phy.rev < 2)
+               b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+                               ~B43_NPHY_SCRAM_SIGCTL_SCM);
+
+       /* Set phase track alpha and beta */
+       b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+       b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+       b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+       b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+
+       b43_phy_mask(dev, B43_NPHY_PIL_DW1,
+                       ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
+       b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
+       b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
+       b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+
+       if (dev->phy.rev == 2)
+               b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
+                               B43_NPHY_FINERX2_CGC_DECGC);
+}
 
-               if (dev->phy.rev < 2) {
-                       if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
-                               b43_hf_write(dev, b43_hf_read(dev) |
-                                               B43_HF_MLADVW);
-               } else if (dev->phy.rev == 2) {
-                       b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
-                       b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
-               }
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
+static void b43_nphy_workarounds(struct b43_wldev *dev)
+{
+       struct b43_phy *phy = &dev->phy;
+       struct b43_phy_n *nphy = phy->n;
 
-               if (dev->phy.rev < 2)
-                       b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
-                                       ~B43_NPHY_SCRAM_SIGCTL_SCM);
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+               b43_nphy_classifier(dev, 1, 0);
+       else
+               b43_nphy_classifier(dev, 1, 1);
 
-               /* Set phase track alpha and beta */
-               b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
-               b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
-               b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
-               b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 1);
 
-               b43_phy_mask(dev, B43_NPHY_PIL_DW1,
-                               ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
-               b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
-               b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
-               b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+       b43_phy_set(dev, B43_NPHY_IQFLIP,
+                   B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
 
-               if (dev->phy.rev == 2)
-                       b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
-                                       B43_NPHY_FINERX2_CGC_DECGC);
-       }
+       if (dev->phy.rev >= 3)
+               b43_nphy_workarounds_rev3plus(dev);
+       else
+               b43_nphy_workarounds_rev1_2(dev);
 
        if (nphy->hang_avoid)
                b43_nphy_stay_in_carrier_search(dev, 0);
@@ -2135,7 +2296,6 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
 
 static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
        u8 i;
        u16 reg, val;
 
@@ -2199,10 +2359,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
                                        enum ieee80211_band band =
                                                b43_current_band(dev->wl);
 
-                                       if ((nphy->ipa2g_on &&
-                                               band == IEEE80211_BAND_2GHZ) ||
-                                               (nphy->ipa5g_on &&
-                                               band == IEEE80211_BAND_5GHZ))
+                                       if (b43_nphy_ipa(dev))
                                                val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
                                        else
                                                val = 0x11;
@@ -2577,8 +2734,8 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
 {
        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
                if (dev->phy.rev >= 6) {
-                       /* TODO If the chip is 47162
-                               return txpwrctrl_tx_gain_ipa_rev5 */
+                       if (dev->dev->chip_id == 47162)
+                               return txpwrctrl_tx_gain_ipa_rev5;
                        return txpwrctrl_tx_gain_ipa_rev6;
                } else if (dev->phy.rev >= 5) {
                        return txpwrctrl_tx_gain_ipa_rev5;
@@ -2828,10 +2985,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
                                enum ieee80211_band band =
                                        b43_current_band(dev->wl);
 
-                               if ((nphy->ipa2g_on &&
-                                    band == IEEE80211_BAND_2GHZ) ||
-                                   (nphy->ipa5g_on &&
-                                    band == IEEE80211_BAND_5GHZ)) {
+                               if (b43_nphy_ipa(dev)) {
                                        table = b43_nphy_get_ipa_gain_table(dev);
                                } else {
                                        if (band == IEEE80211_BAND_5GHZ) {
@@ -3648,7 +3802,7 @@ int b43_phy_initn(struct b43_wldev *dev)
        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
 
-       if (sprom->boardflags2_lo & 0x100 ||
+       if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
            (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
             dev->dev->board_type == 0x8B))
                b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
@@ -3667,8 +3821,7 @@ int b43_phy_initn(struct b43_wldev *dev)
        }
 
        tmp2 = b43_current_band(dev->wl);
-       if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
-           (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
+       if (b43_nphy_ipa(dev)) {
                b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
                b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
                                nphy->papd_epsilon_offset[0] << 7);
@@ -3706,15 +3859,7 @@ int b43_phy_initn(struct b43_wldev *dev)
        b43_nphy_tx_power_fix(dev);
        /* TODO N PHY TX Power Control Idle TSSI */
        /* TODO N PHY TX Power Control Setup */
-
-       if (phy->rev >= 3) {
-               /* TODO */
-       } else {
-               b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
-                                       b43_ntab_tx_gain_rev0_1_2);
-               b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
-                                       b43_ntab_tx_gain_rev0_1_2);
-       }
+       b43_nphy_tx_gain_table_upload(dev);
 
        if (nphy->phyrxchain != 3)
                b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
@@ -3918,6 +4063,10 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
        nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
        nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
        nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
+       /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
+        * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
+       nphy->tx_pwr_idx[0] = 128;
+       nphy->tx_pwr_idx[1] = 128;
 }
 
 static void b43_nphy_op_free(struct b43_wldev *dev)
index e789a89f1047f7f7bc8544702bb1e8fd78ff1fd9..fbf520285bd1788008b87c6290e7cf0926cf136f 100644 (file)
@@ -764,6 +764,8 @@ struct b43_phy_n {
        u8 cal_orig_pwr_idx[2];
        u8 measure_hold;
        u8 phyrxchain;
+       u8 hw_phyrxchain;
+       u8 hw_phytxchain;
        u8 perical;
        u32 deaf_count;
        u32 rxcalparams;
@@ -783,6 +785,8 @@ struct b43_phy_n {
        u16 mphase_txcal_bestcoeffs[11];
 
        bool txpwrctrl;
+       u8 tx_pwr_idx[2];
+       u16 adj_pwr_tbl[84];
        u16 txcal_bbmult;
        u16 txiqlocal_bestc[11];
        bool txiqlocal_coeffsvalid;
index 93643f18c2b3ab5706808f5e99cf50a0d630d64c..5289a18ddd8c7d2d976e42643801ea07cddb7e8f 100644 (file)
@@ -4,6 +4,7 @@
   IEEE 802.11n PHY and radio device data tables
 
   Copyright (c) 2008 Michael Buesch <[email protected]>
+  Copyright (c) 2010 RafaÅ‚ MiÅ‚ecki <[email protected]>
 
   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
index 8890df06702939b5396a142c7d6ea79b76d41f67..a01f776ca4de92a0a3b54ff9dfda066d1f05240d 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n 2056 radio device data tables
 
+  Copyright (c) 2010 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
index d52df6be705a6e5732dca3ebee40e89d5280013b..a7159d8578be8d6db37a649dcc04fa8ad6ed849e 100644 (file)
@@ -1,29 +1,3 @@
-/*
-
-  Broadcom B43 wireless driver
-
-  Copyright (c) 2010 RafaÅ‚ MiÅ‚ecki <[email protected]>
-
-  Some parts of the code in this file are derived from the brcm80211
-  driver  Copyright (c) 2010 Broadcom Corporation
-
-  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.
-
-*/
-
 #ifndef B43_RADIO_2056_H_
 #define B43_RADIO_2056_H_
 
index f029f6e1f5d1c879abdbeea625a841aa87582ff3..d4ce8a12ff9a05a9bb988b0a47fb888c0b9c123d 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n 2059 radio device data tables
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
index 916f238a71dfbe307991364caff6f6879de32580..7b326f2efdc9e912e8d47fb6fa3cd6da9e06af62 100644 (file)
@@ -4,6 +4,7 @@
   IEEE 802.11n PHY data tables
 
   Copyright (c) 2008 Michael Buesch <[email protected]>
+  Copyright (c) 2010 RafaÅ‚ MiÅ‚ecki <[email protected]>
 
   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
index 677d217b5fb32f1bef2ba9120c44a68a9f956932..176c49d74ef4e4ec5f98ea015e3b511b809a3f62 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n HT-PHY data tables
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
index 0a5842808a78229dd3670cba9aa861544dd2687a..9d484e2f79bfd96f5ad2dd60b25c1334ce173e7f 100644 (file)
@@ -3,6 +3,8 @@
   Broadcom B43 wireless driver
   IEEE 802.11n LCN-PHY data tables
 
+  Copyright (c) 2011 RafaÅ‚ MiÅ‚ecki <[email protected]>
+
   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
 #include "phy_common.h"
 #include "phy_lcn.h"
 
+struct b43_lcntab_tx_gain_tbl_entry {
+       u8 gm;
+       u8 pga;
+       u8 pad;
+       u8 dac;
+       u8 bb_mult;
+};
+
+/**************************************************
+ * Static tables.
+ **************************************************/
+
 static const u16 b43_lcntab_0x02[] = {
        0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
        0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
@@ -295,6 +309,160 @@ static const u32 b43_lcntab_0x18[] = {
        0x00080000, 0x00080000, 0x00080000, 0x00080000,
 };
 
+/**************************************************
+ * TX gain.
+ **************************************************/
+
+const struct b43_lcntab_tx_gain_tbl_entry
+       b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
+       { 0x03, 0x00, 0x1f, 0x0, 0x48 },
+       { 0x03, 0x00, 0x1f, 0x0, 0x46 },
+       { 0x03, 0x00, 0x1f, 0x0, 0x44 },
+       { 0x03, 0x00, 0x1e, 0x0, 0x43 },
+       { 0x03, 0x00, 0x1d, 0x0, 0x44 },
+       { 0x03, 0x00, 0x1c, 0x0, 0x44 },
+       { 0x03, 0x00, 0x1b, 0x0, 0x45 },
+       { 0x03, 0x00, 0x1a, 0x0, 0x46 },
+       { 0x03, 0x00, 0x19, 0x0, 0x46 },
+       { 0x03, 0x00, 0x18, 0x0, 0x47 },
+       { 0x03, 0x00, 0x17, 0x0, 0x48 },
+       { 0x03, 0x00, 0x17, 0x0, 0x46 },
+       { 0x03, 0x00, 0x16, 0x0, 0x47 },
+       { 0x03, 0x00, 0x15, 0x0, 0x48 },
+       { 0x03, 0x00, 0x15, 0x0, 0x46 },
+       { 0x03, 0x00, 0x15, 0x0, 0x44 },
+       { 0x03, 0x00, 0x15, 0x0, 0x42 },
+       { 0x03, 0x00, 0x15, 0x0, 0x40 },
+       { 0x03, 0x00, 0x15, 0x0, 0x3f },
+       { 0x03, 0x00, 0x14, 0x0, 0x40 },
+       { 0x03, 0x00, 0x13, 0x0, 0x41 },
+       { 0x03, 0x00, 0x13, 0x0, 0x40 },
+       { 0x03, 0x00, 0x12, 0x0, 0x41 },
+       { 0x03, 0x00, 0x12, 0x0, 0x40 },
+       { 0x03, 0x00, 0x11, 0x0, 0x41 },
+       { 0x03, 0x00, 0x11, 0x0, 0x40 },
+       { 0x03, 0x00, 0x10, 0x0, 0x41 },
+       { 0x03, 0x00, 0x10, 0x0, 0x40 },
+       { 0x03, 0x00, 0x10, 0x0, 0x3e },
+       { 0x03, 0x00, 0x10, 0x0, 0x3c },
+       { 0x03, 0x00, 0x10, 0x0, 0x3a },
+       { 0x03, 0x00, 0x0f, 0x0, 0x3d },
+       { 0x03, 0x00, 0x0f, 0x0, 0x3b },
+       { 0x03, 0x00, 0x0e, 0x0, 0x3d },
+       { 0x03, 0x00, 0x0e, 0x0, 0x3c },
+       { 0x03, 0x00, 0x0e, 0x0, 0x3a },
+       { 0x03, 0x00, 0x0d, 0x0, 0x3c },
+       { 0x03, 0x00, 0x0d, 0x0, 0x3b },
+       { 0x03, 0x00, 0x0c, 0x0, 0x3e },
+       { 0x03, 0x00, 0x0c, 0x0, 0x3c },
+       { 0x03, 0x00, 0x0c, 0x0, 0x3a },
+       { 0x03, 0x00, 0x0b, 0x0, 0x3e },
+       { 0x03, 0x00, 0x0b, 0x0, 0x3c },
+       { 0x03, 0x00, 0x0b, 0x0, 0x3b },
+       { 0x03, 0x00, 0x0b, 0x0, 0x39 },
+       { 0x03, 0x00, 0x0a, 0x0, 0x3d },
+       { 0x03, 0x00, 0x0a, 0x0, 0x3b },
+       { 0x03, 0x00, 0x0a, 0x0, 0x39 },
+       { 0x03, 0x00, 0x09, 0x0, 0x3e },
+       { 0x03, 0x00, 0x09, 0x0, 0x3c },
+       { 0x03, 0x00, 0x09, 0x0, 0x3a },
+       { 0x03, 0x00, 0x09, 0x0, 0x39 },
+       { 0x03, 0x00, 0x08, 0x0, 0x3e },
+       { 0x03, 0x00, 0x08, 0x0, 0x3c },
+       { 0x03, 0x00, 0x08, 0x0, 0x3a },
+       { 0x03, 0x00, 0x08, 0x0, 0x39 },
+       { 0x03, 0x00, 0x08, 0x0, 0x37 },
+       { 0x03, 0x00, 0x07, 0x0, 0x3d },
+       { 0x03, 0x00, 0x07, 0x0, 0x3c },
+       { 0x03, 0x00, 0x07, 0x0, 0x3a },
+       { 0x03, 0x00, 0x07, 0x0, 0x38 },
+       { 0x03, 0x00, 0x07, 0x0, 0x37 },
+       { 0x03, 0x00, 0x06, 0x0, 0x3e },
+       { 0x03, 0x00, 0x06, 0x0, 0x3c },
+       { 0x03, 0x00, 0x06, 0x0, 0x3a },
+       { 0x03, 0x00, 0x06, 0x0, 0x39 },
+       { 0x03, 0x00, 0x06, 0x0, 0x37 },
+       { 0x03, 0x00, 0x06, 0x0, 0x36 },
+       { 0x03, 0x00, 0x06, 0x0, 0x34 },
+       { 0x03, 0x00, 0x05, 0x0, 0x3d },
+       { 0x03, 0x00, 0x05, 0x0, 0x3b },
+       { 0x03, 0x00, 0x05, 0x0, 0x39 },
+       { 0x03, 0x00, 0x05, 0x0, 0x38 },
+       { 0x03, 0x00, 0x05, 0x0, 0x36 },
+       { 0x03, 0x00, 0x05, 0x0, 0x35 },
+       { 0x03, 0x00, 0x05, 0x0, 0x33 },
+       { 0x03, 0x00, 0x04, 0x0, 0x3e },
+       { 0x03, 0x00, 0x04, 0x0, 0x3c },
+       { 0x03, 0x00, 0x04, 0x0, 0x3a },
+       { 0x03, 0x00, 0x04, 0x0, 0x39 },
+       { 0x03, 0x00, 0x04, 0x0, 0x37 },
+       { 0x03, 0x00, 0x04, 0x0, 0x36 },
+       { 0x03, 0x00, 0x04, 0x0, 0x34 },
+       { 0x03, 0x00, 0x04, 0x0, 0x33 },
+       { 0x03, 0x00, 0x04, 0x0, 0x31 },
+       { 0x03, 0x00, 0x04, 0x0, 0x30 },
+       { 0x03, 0x00, 0x04, 0x0, 0x2e },
+       { 0x03, 0x00, 0x03, 0x0, 0x3c },
+       { 0x03, 0x00, 0x03, 0x0, 0x3a },
+       { 0x03, 0x00, 0x03, 0x0, 0x39 },
+       { 0x03, 0x00, 0x03, 0x0, 0x37 },
+       { 0x03, 0x00, 0x03, 0x0, 0x36 },
+       { 0x03, 0x00, 0x03, 0x0, 0x34 },
+       { 0x03, 0x00, 0x03, 0x0, 0x33 },
+       { 0x03, 0x00, 0x03, 0x0, 0x31 },
+       { 0x03, 0x00, 0x03, 0x0, 0x30 },
+       { 0x03, 0x00, 0x03, 0x0, 0x2e },
+       { 0x03, 0x00, 0x03, 0x0, 0x2d },
+       { 0x03, 0x00, 0x03, 0x0, 0x2c },
+       { 0x03, 0x00, 0x03, 0x0, 0x2b },
+       { 0x03, 0x00, 0x03, 0x0, 0x29 },
+       { 0x03, 0x00, 0x02, 0x0, 0x3d },
+       { 0x03, 0x00, 0x02, 0x0, 0x3b },
+       { 0x03, 0x00, 0x02, 0x0, 0x39 },
+       { 0x03, 0x00, 0x02, 0x0, 0x38 },
+       { 0x03, 0x00, 0x02, 0x0, 0x36 },
+       { 0x03, 0x00, 0x02, 0x0, 0x35 },
+       { 0x03, 0x00, 0x02, 0x0, 0x33 },
+       { 0x03, 0x00, 0x02, 0x0, 0x32 },
+       { 0x03, 0x00, 0x02, 0x0, 0x30 },
+       { 0x03, 0x00, 0x02, 0x0, 0x2f },
+       { 0x03, 0x00, 0x02, 0x0, 0x2e },
+       { 0x03, 0x00, 0x02, 0x0, 0x2c },
+       { 0x03, 0x00, 0x02, 0x0, 0x2b },
+       { 0x03, 0x00, 0x02, 0x0, 0x2a },
+       { 0x03, 0x00, 0x02, 0x0, 0x29 },
+       { 0x03, 0x00, 0x02, 0x0, 0x27 },
+       { 0x03, 0x00, 0x02, 0x0, 0x26 },
+       { 0x03, 0x00, 0x02, 0x0, 0x25 },
+       { 0x03, 0x00, 0x02, 0x0, 0x24 },
+       { 0x03, 0x00, 0x02, 0x0, 0x23 },
+       { 0x03, 0x00, 0x02, 0x0, 0x22 },
+       { 0x03, 0x00, 0x02, 0x0, 0x21 },
+       { 0x03, 0x00, 0x02, 0x0, 0x20 },
+       { 0x03, 0x00, 0x01, 0x0, 0x3f },
+       { 0x03, 0x00, 0x01, 0x0, 0x3d },
+       { 0x03, 0x00, 0x01, 0x0, 0x3b },
+       { 0x03, 0x00, 0x01, 0x0, 0x39 },
+};
+
+/**************************************************
+ * SW control.
+ **************************************************/
+
+const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
+       0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+       0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+       0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+       0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+       0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+       0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+       0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+       0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+       0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+       0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+       0x0002, 0x0008, 0x0004, 0x0001,
+};
+
 /**************************************************
  * R/W ops.
  **************************************************/
@@ -318,9 +486,8 @@ u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
                break;
        case B43_LCNTAB_32BIT:
                b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
-               value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI);
-               value <<= 16;
-               value |= b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+               value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+               value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
                break;
        default:
                B43_WARN_ON(1);
@@ -357,10 +524,9 @@ void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
                        break;
                case B43_LCNTAB_32BIT:
                        *((u32 *)data) = b43_phy_read(dev,
-                                                     B43_PHY_LCN_TABLE_DATAHI);
-                       *((u32 *)data) <<= 16;
-                       *((u32 *)data) |= b43_phy_read(dev,
                                                B43_PHY_LCN_TABLE_DATALO);
+                       *((u32 *)data) |= (b43_phy_read(dev,
+                                          B43_PHY_LCN_TABLE_DATAHI) << 16);
                        data += 4;
                        break;
                default:
@@ -447,7 +613,7 @@ void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
 #define lcntab_upload(dev, offset, data) do { \
                b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
        } while (0)
-void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
 {
        lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
        lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
@@ -464,3 +630,78 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev)
        lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
        lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
 }
+
+void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
+                       const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
+{
+       u32 i;
+       u32 val;
+
+       u16 pa_gain = 0x70;
+       if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
+               pa_gain = 0x10;
+
+       for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
+               val = ((pa_gain << 24) |
+                      (gain_table[i].pad << 16) |
+                      (gain_table[i].pga << 8) |
+                       gain_table[i].gm);
+               b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
+
+               /* brcmsmac doesn't maskset, we follow newer wl here */
+               val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
+               val &= 0x000fffff;
+               val |= ((gain_table[i].dac << 28) |
+                       (gain_table[i].bb_mult << 20));
+               b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
+       }
+}
+
+/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
+static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev)
+{
+       int i;
+       u32 tmp;
+       for (i = 0; i < 128; i++) {
+               tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
+               b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
+       }
+}
+
+/* wlc_lcnphy_clear_papd_comptable */
+static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
+{
+       u8 i;
+
+       for (i = 0; i < 0x80; i++)
+               b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
+}
+
+/* wlc_lcnphy_tbl_init */
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+       b43_phy_lcn_upload_static_tables(dev);
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               if (sprom->boardflags_lo & B43_BFL_EXTLNA)
+                       b43_phy_lcn_load_tx_gain_tab(dev,
+                               b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
+               else
+                       b43err(dev->wl,
+                              "TX gain table unknown for this card\n");
+       }
+
+       if (sprom->boardflags_lo & B43_BFL_FEM &&
+           !(sprom->boardflags_hi & B43_BFH_FEM_BT))
+               b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
+                       ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
+                       b43_lcntab_sw_ctl_4313_epa_rev0);
+       else
+               b43err(dev->wl, "SW ctl table is unknown for this card\n");
+
+       /* TODO: various tables ops here */
+       b43_phy_lcn_rewrite_tables(dev);
+       b43_phy_lcn_clean_papd_comp_table(dev);
+}
index b6471e89c36f1a3fce2e05b3b54953148948b297..caff9db6831fb39e82570c90e87cf8cb96d2f151 100644 (file)
@@ -10,6 +10,8 @@
 #define B43_LCNTAB16(table, offset)    (((table) << 10) | (offset) | B43_LCNTAB_16BIT)
 #define B43_LCNTAB32(table, offset)    (((table) << 10) | (offset) | B43_LCNTAB_32BIT)
 
+#define B43_LCNTAB_TX_GAIN_SIZE                128
+
 u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
 void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
                          unsigned int nr_elements, void *_data);
index 3774dd034746286815af04f0322e7d4e778d6f32..ef9ad79d1bfd14191f26f77a9ecbe0f2289fcb25 100644 (file)
@@ -1901,17 +1901,19 @@ static void ipw2100_down(struct ipw2100_priv *priv)
 
 /* Called by register_netdev() */
 static int ipw2100_net_init(struct net_device *dev)
+{
+       struct ipw2100_priv *priv = libipw_priv(dev);
+
+       return ipw2100_up(priv, 1);
+}
+
+static int ipw2100_wdev_init(struct net_device *dev)
 {
        struct ipw2100_priv *priv = libipw_priv(dev);
        const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
        struct wireless_dev *wdev = &priv->ieee->wdev;
-       int ret;
        int i;
 
-       ret = ipw2100_up(priv, 1);
-       if (ret)
-               return ret;
-
        memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
 
        /* fill-out priv->ieee->bg_band */
@@ -6350,9 +6352,13 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
                       "Error calling register_netdev.\n");
                goto fail;
        }
+       registered = 1;
+
+       err = ipw2100_wdev_init(dev);
+       if (err)
+               goto fail;
 
        mutex_lock(&priv->action_mutex);
-       registered = 1;
 
        IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev));
 
@@ -6389,7 +6395,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
 
       fail_unlock:
        mutex_unlock(&priv->action_mutex);
-
+       wiphy_unregister(priv->ieee->wdev.wiphy);
+       kfree(priv->ieee->bg_band.channels);
       fail:
        if (dev) {
                if (registered)
index 4395977d536969c208ab148957b04eaf3441369e..1d546668b2eed551123676f6b8eb55a7c61cc7d3 100644 (file)
@@ -11425,17 +11425,24 @@ static void ipw_bg_down(struct work_struct *work)
 
 /* Called by register_netdev() */
 static int ipw_net_init(struct net_device *dev)
+{
+       int rc = 0;
+       struct ipw_priv *priv = libipw_priv(dev);
+
+       mutex_lock(&priv->mutex);
+       if (ipw_up(priv))
+               rc = -EIO;
+       mutex_unlock(&priv->mutex);
+
+       return rc;
+}
+
+static int ipw_wdev_init(struct net_device *dev)
 {
        int i, rc = 0;
        struct ipw_priv *priv = libipw_priv(dev);
        const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
        struct wireless_dev *wdev = &priv->ieee->wdev;
-       mutex_lock(&priv->mutex);
-
-       if (ipw_up(priv)) {
-               rc = -EIO;
-               goto out;
-       }
 
        memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
 
@@ -11520,13 +11527,9 @@ static int ipw_net_init(struct net_device *dev)
        set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
 
        /* With that information in place, we can now register the wiphy... */
-       if (wiphy_register(wdev->wiphy)) {
+       if (wiphy_register(wdev->wiphy))
                rc = -EIO;
-               goto out;
-       }
-
 out:
-       mutex_unlock(&priv->mutex);
        return rc;
 }
 
@@ -11833,14 +11836,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
                goto out_remove_sysfs;
        }
 
+       err = ipw_wdev_init(net_dev);
+       if (err) {
+               IPW_ERROR("failed to register wireless device\n");
+               goto out_unregister_netdev;
+       }
+
 #ifdef CONFIG_IPW2200_PROMISCUOUS
        if (rtap_iface) {
                err = ipw_prom_alloc(priv);
                if (err) {
                        IPW_ERROR("Failed to register promiscuous network "
                                  "device (error %d).\n", err);
-                       unregister_netdev(priv->net_dev);
-                       goto out_remove_sysfs;
+                       wiphy_unregister(priv->ieee->wdev.wiphy);
+                       kfree(priv->ieee->a_band.channels);
+                       kfree(priv->ieee->bg_band.channels);
+                       goto out_unregister_netdev;
                }
        }
 #endif
@@ -11852,6 +11863,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
 
        return 0;
 
+      out_unregister_netdev:
+       unregister_netdev(priv->net_dev);
       out_remove_sysfs:
        sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
       out_release_irq:
index 0cc5177d738df9f9370cbf8ef325dddab7a8e556..8faeaf2dddeca0e70cb95bbb91ce45d48e275ea4 100644 (file)
@@ -821,12 +821,15 @@ static void iwl3945_rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
 
  out:
 
-       rs_sta->last_txrate_idx = index;
-       if (sband->band == IEEE80211_BAND_5GHZ)
-               info->control.rates[0].idx = rs_sta->last_txrate_idx -
-                               IWL_FIRST_OFDM_RATE;
-       else
+       if (sband->band == IEEE80211_BAND_5GHZ) {
+               if (WARN_ON_ONCE(index < IWL_FIRST_OFDM_RATE))
+                       index = IWL_FIRST_OFDM_RATE;
+               rs_sta->last_txrate_idx = index;
+               info->control.rates[0].idx = index - IWL_FIRST_OFDM_RATE;
+       } else {
+               rs_sta->last_txrate_idx = index;
                info->control.rates[0].idx = rs_sta->last_txrate_idx;
+       }
 
        IWL_DEBUG_RATE(priv, "leave: %d\n", index);
 }
index 48ab9142af387437858498166154182d48dc19ed..8fa59cdb3b49992e6a0380d655fb7f68d94ea006 100644 (file)
@@ -3,18 +3,19 @@ obj-$(CONFIG_IWLAGN)  += iwlagn.o
 iwlagn-objs            := iwl-agn.o iwl-agn-rs.o
 iwlagn-objs            += iwl-agn-ucode.o iwl-agn-tx.o
 iwlagn-objs            += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
-iwlagn-objs            += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
+iwlagn-objs            += iwl-agn-tt.o iwl-agn-sta.o
 
-iwlagn-objs            += iwl-core.o iwl-eeprom.o iwl-power.o
-iwlagn-objs            += iwl-rx.o iwl-sta.o
-iwlagn-objs            += iwl-scan.o iwl-led.o
-iwlagn-objs             += iwl-agn-rxon.o
-iwlagn-objs             += iwl-5000.o
-iwlagn-objs             += iwl-6000.o
-iwlagn-objs             += iwl-1000.o
-iwlagn-objs             += iwl-2000.o
-iwlagn-objs             += iwl-pci.o
-iwlagn-objs             += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o
+iwlagn-objs            += iwl-core.o iwl-eeprom.o iwl-power.o
+iwlagn-objs            += iwl-rx.o iwl-sta.o
+iwlagn-objs            += iwl-scan.o iwl-led.o
+iwlagn-objs            += iwl-agn-rxon.o
+iwlagn-objs            += iwl-5000.o
+iwlagn-objs            += iwl-6000.o
+iwlagn-objs            += iwl-1000.o
+iwlagn-objs            += iwl-2000.o
+iwlagn-objs            += iwl-pci.o
+iwlagn-objs            += iwl-trans.o
+iwlagn-objs            += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
 
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
index 4766c3a1a2f6669c890fa8beadc33ab4e3a1a8aa..887f9ac434c2797afd903bca340a3e5fcf2a04b0 100644 (file)
@@ -44,7 +44,7 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-shared.h"
-#include "iwl-pci.h"
+#include "iwl-cfg.h"
 
 /* Highest firmware API version supported */
 #define IWL1000_UCODE_API_MAX 6
@@ -161,8 +161,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
        if (priv->cfg->need_dc_calib)
                hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
 
-       hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
        return 0;
 }
 
@@ -191,7 +189,6 @@ static struct iwl_base_params iwl1000_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_1000,
        .shadow_ram_support = false,
        .led_compensation = 51,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
index 764d3104e12822e2f08676d1f4e24c955f5089df..db889581c0e5dabe3d47e2f3d9a54bd234b93b82 100644 (file)
@@ -45,7 +45,7 @@
 #include "iwl-agn-hw.h"
 #include "iwl-6000-hw.h"
 #include "iwl-shared.h"
-#include "iwl-pci.h"
+#include "iwl-cfg.h"
 
 /* Highest firmware API version supported */
 #define IWL2030_UCODE_API_MAX 6
@@ -75,7 +75,7 @@
 #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
 
 #define IWL135_FW_PRE "iwlwifi-135-"
-#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"
+#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode"
 
 static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -159,8 +159,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
        if (priv->cfg->need_temp_offset_calib)
                hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
 
-       hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
        return 0;
 }
 
@@ -211,7 +209,6 @@ static struct iwl_base_params iwl2000_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_2x00,
        .shadow_ram_support = true,
        .led_compensation = 51,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -231,7 +228,6 @@ static struct iwl_base_params iwl2030_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_2x00,
        .shadow_ram_support = true,
        .led_compensation = 57,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -268,6 +264,7 @@ static struct iwl_bt_params iwl2030_bt_params = {
        .base_params = &iwl2000_base_params,                    \
        .need_dc_calib = true,                                  \
        .need_temp_offset_calib = true,                         \
+       .temp_offset_v2 = true,                                 \
        .led_mode = IWL_LED_RF_STATE,                           \
        .iq_invert = true                                       \
 
@@ -285,6 +282,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
 struct iwl_cfg iwl2000_2bgn_d_cfg = {
        .name = "2000D Series 2x2 BGN",
        IWL_DEVICE_2000,
+       .ht_params = &iwl2000_ht_params,
 };
 
 #define IWL_DEVICE_2030                                                \
@@ -299,6 +297,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
        .bt_params = &iwl2030_bt_params,                        \
        .need_dc_calib = true,                                  \
        .need_temp_offset_calib = true,                         \
+       .temp_offset_v2 = true,                                 \
        .led_mode = IWL_LED_RF_STATE,                           \
        .adv_pm = true,                                         \
        .iq_invert = true                                       \
@@ -325,6 +324,7 @@ struct iwl_cfg iwl2030_2bg_cfg = {
        .base_params = &iwl2000_base_params,                    \
        .need_dc_calib = true,                                  \
        .need_temp_offset_calib = true,                         \
+       .temp_offset_v2 = true,                                 \
        .led_mode = IWL_LED_RF_STATE,                           \
        .adv_pm = true,                                         \
        .rx_with_siso_diversity = true,                         \
@@ -353,6 +353,7 @@ struct iwl_cfg iwl105_bgn_cfg = {
        .bt_params = &iwl2030_bt_params,                        \
        .need_dc_calib = true,                                  \
        .need_temp_offset_calib = true,                         \
+       .temp_offset_v2 = true,                                 \
        .led_mode = IWL_LED_RF_STATE,                           \
        .adv_pm = true,                                         \
        .rx_with_siso_diversity = true,                         \
index f9630a3c79fe996c26093954f2938129cd6e2a89..c0135988e777140ff6ef1770bd74a580c3d55a8f 100644 (file)
@@ -74,8 +74,8 @@
 static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
 {
        u16 temperature, voltage;
-       __le16 *temp_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+       __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
+                               EEPROM_KELVIN_TEMPERATURE);
 
        temperature = le16_to_cpu(temp_calib[0]);
        voltage = le16_to_cpu(temp_calib[1]);
index 7cb4d69e0c37a8d872d604dabec2a2b4a601f521..290701620f03dd8c73cf350b45afc46de673a153 100644 (file)
@@ -47,7 +47,7 @@
 #include "iwl-5000-hw.h"
 #include "iwl-trans.h"
 #include "iwl-shared.h"
-#include "iwl-pci.h"
+#include "iwl-cfg.h"
 
 /* Highest firmware API version supported */
 #define IWL5000_UCODE_API_MAX 5
@@ -184,8 +184,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
                BIT(IWL_CALIB_TX_IQ_PERD)       |
                BIT(IWL_CALIB_BASE_BAND);
 
-       hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
        return 0;
 }
 
@@ -223,8 +221,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
        if (priv->cfg->need_dc_calib)
                hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
 
-       hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
        return 0;
 }
 
@@ -353,7 +349,6 @@ static struct iwl_base_params iwl5000_base_params = {
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
        .led_compensation = 51,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_LONG_WD_TIMEOUT,
index 2a98e65ca84cb8eebf4119342a4f90ceaca6d97f..37837f7b6990cfe0b0d74e15b511cf2e15d1b41b 100644 (file)
@@ -46,7 +46,7 @@
 #include "iwl-6000-hw.h"
 #include "iwl-trans.h"
 #include "iwl-shared.h"
-#include "iwl-pci.h"
+#include "iwl-cfg.h"
 
 /* Highest firmware API version supported */
 #define IWL6000_UCODE_API_MAX 4
@@ -180,8 +180,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
        if (priv->cfg->need_temp_offset_calib)
                hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
 
-       hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
        return 0;
 }
 
@@ -305,7 +303,6 @@ static struct iwl_base_params iwl6000_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
        .shadow_ram_support = true,
        .led_compensation = 51,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -323,7 +320,6 @@ static struct iwl_base_params iwl6050_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
        .shadow_ram_support = true,
        .led_compensation = 51,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -340,7 +336,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
        .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
        .shadow_ram_support = true,
        .led_compensation = 57,
-       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
index b725f6970dee81883416b0d95ff8d0d5f43d59be..03bac48558b25be81e810963f6c82f32dc9b89d7 100644 (file)
@@ -766,12 +766,9 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
        u8 first_chain;
        u16 i = 0;
 
-       average_sig[0] = data->chain_signal_a /
-                        priv->cfg->base_params->chain_noise_num_beacons;
-       average_sig[1] = data->chain_signal_b /
-                        priv->cfg->base_params->chain_noise_num_beacons;
-       average_sig[2] = data->chain_signal_c /
-                        priv->cfg->base_params->chain_noise_num_beacons;
+       average_sig[0] = data->chain_signal_a / IWL_CAL_NUM_BEACONS;
+       average_sig[1] = data->chain_signal_b / IWL_CAL_NUM_BEACONS;
+       average_sig[2] = data->chain_signal_c / IWL_CAL_NUM_BEACONS;
 
        if (average_sig[0] >= average_sig[1]) {
                max_average_sig = average_sig[0];
@@ -1038,8 +1035,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
        /* If this is the "chain_noise_num_beacons", determine:
         * 1)  Disconnected antennas (using signal strengths)
         * 2)  Differential gain (using silence noise) to balance receivers */
-       if (data->beacon_count !=
-               priv->cfg->base_params->chain_noise_num_beacons)
+       if (data->beacon_count != IWL_CAL_NUM_BEACONS)
                return;
 
        /* Analyze signal for disconnected antenna */
@@ -1055,12 +1051,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
                iwl_find_disconn_antenna(priv, average_sig, data);
 
        /* Analyze noise for rx balance */
-       average_noise[0] = data->chain_noise_a /
-                          priv->cfg->base_params->chain_noise_num_beacons;
-       average_noise[1] = data->chain_noise_b /
-                          priv->cfg->base_params->chain_noise_num_beacons;
-       average_noise[2] = data->chain_noise_c /
-                          priv->cfg->base_params->chain_noise_num_beacons;
+       average_noise[0] = data->chain_noise_a / IWL_CAL_NUM_BEACONS;
+       average_noise[1] = data->chain_noise_b / IWL_CAL_NUM_BEACONS;
+       average_noise[2] = data->chain_noise_c / IWL_CAL_NUM_BEACONS;
 
        for (i = 0; i < NUM_RX_CHAINS; i++) {
                if (!(data->disconn_array[i]) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
deleted file mode 100644 (file)
index c62ddc2..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <[email protected]>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-#include "iwl-agn.h"
-#include "iwl-io.h"
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
-******************************************************************************/
-
-int iwl_eeprom_check_version(struct iwl_priv *priv)
-{
-       u16 eeprom_ver;
-       u16 calib_ver;
-
-       eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-       calib_ver = iwlagn_eeprom_calib_version(priv);
-
-       if (eeprom_ver < priv->cfg->eeprom_ver ||
-           calib_ver < priv->cfg->eeprom_calib_ver)
-               goto err;
-
-       IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
-                eeprom_ver, calib_ver);
-
-       return 0;
-err:
-       IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
-                 "CALIB=0x%x < 0x%x\n",
-                 eeprom_ver, priv->cfg->eeprom_ver,
-                 calib_ver,  priv->cfg->eeprom_calib_ver);
-       return -EINVAL;
-
-}
-
-int iwl_eeprom_check_sku(struct iwl_priv *priv)
-{
-       u16 radio_cfg;
-
-       if (!priv->cfg->sku) {
-               /* not using sku overwrite */
-               priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
-               if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
-                   !priv->cfg->ht_params) {
-                       IWL_ERR(priv, "Invalid 11n configuration\n");
-                       return -EINVAL;
-               }
-       }
-       if (!priv->cfg->sku) {
-               IWL_ERR(priv, "Invalid device sku\n");
-               return -EINVAL;
-       }
-
-       IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
-
-       if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
-               /* not using .cfg overwrite */
-               radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-               priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
-               priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
-               if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
-                       IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
-                               priv->cfg->valid_tx_ant,
-                               priv->cfg->valid_rx_ant);
-                       return -EINVAL;
-               }
-               IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
-                        priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
-       }
-       /*
-        * for some special cases,
-        * EEPROM did not reflect the correct antenna setting
-        * so overwrite the valid tx/rx antenna from .cfg
-        */
-       return 0;
-}
-
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
-       const u8 *addr = iwl_eeprom_query_addr(priv,
-                                       EEPROM_MAC_ADDRESS);
-       memcpy(mac, addr, ETH_ALEN);
-}
-
-/**
- * iwl_get_max_txpower_avg - get the highest tx power from all chains.
- *     find the highest tx power from all chains for the channel
- */
-static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
-               struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-               int element, s8 *max_txpower_in_half_dbm)
-{
-       s8 max_txpower_avg = 0; /* (dBm) */
-
-       /* Take the highest tx power from any valid chains */
-       if ((priv->cfg->valid_tx_ant & ANT_A) &&
-           (enhanced_txpower[element].chain_a_max > max_txpower_avg))
-               max_txpower_avg = enhanced_txpower[element].chain_a_max;
-       if ((priv->cfg->valid_tx_ant & ANT_B) &&
-           (enhanced_txpower[element].chain_b_max > max_txpower_avg))
-               max_txpower_avg = enhanced_txpower[element].chain_b_max;
-       if ((priv->cfg->valid_tx_ant & ANT_C) &&
-           (enhanced_txpower[element].chain_c_max > max_txpower_avg))
-               max_txpower_avg = enhanced_txpower[element].chain_c_max;
-       if (((priv->cfg->valid_tx_ant == ANT_AB) |
-           (priv->cfg->valid_tx_ant == ANT_BC) |
-           (priv->cfg->valid_tx_ant == ANT_AC)) &&
-           (enhanced_txpower[element].mimo2_max > max_txpower_avg))
-               max_txpower_avg =  enhanced_txpower[element].mimo2_max;
-       if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
-           (enhanced_txpower[element].mimo3_max > max_txpower_avg))
-               max_txpower_avg = enhanced_txpower[element].mimo3_max;
-
-       /*
-        * max. tx power in EEPROM is in 1/2 dBm format
-        * convert from 1/2 dBm to dBm (round-up convert)
-        * but we also do not want to loss 1/2 dBm resolution which
-        * will impact performance
-        */
-       *max_txpower_in_half_dbm = max_txpower_avg;
-       return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
-}
-
-static void
-iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
-                                   struct iwl_eeprom_enhanced_txpwr *txp,
-                                   s8 max_txpower_avg)
-{
-       int ch_idx;
-       bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
-       enum ieee80211_band band;
-
-       band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
-               IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
-
-       for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
-               struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
-
-               /* update matching channel or from common data only */
-               if (txp->channel != 0 && ch_info->channel != txp->channel)
-                       continue;
-
-               /* update matching band only */
-               if (band != ch_info->band)
-                       continue;
-
-               if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
-                       ch_info->max_power_avg = max_txpower_avg;
-                       ch_info->curr_txpow = max_txpower_avg;
-                       ch_info->scan_power = max_txpower_avg;
-               }
-
-               if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
-                       ch_info->ht40_max_power_avg = max_txpower_avg;
-       }
-}
-
-#define EEPROM_TXP_OFFS        (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
-#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
-#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
-
-#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
-                           ? # x " " : "")
-
-void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
-       struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
-       int idx, entries;
-       __le16 *txp_len;
-       s8 max_txp_avg, max_txp_avg_halfdbm;
-
-       BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
-
-       /* the length is in 16-bit words, but we want entries */
-       txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
-       entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
-
-       txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
-
-       for (idx = 0; idx < entries; idx++) {
-               txp = &txp_array[idx];
-               /* skip invalid entries */
-               if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
-                       continue;
-
-               IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
-                                (txp->channel && (txp->flags &
-                                       IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
-                                       "Common " : (txp->channel) ?
-                                       "Channel" : "Common",
-                                (txp->channel),
-                                TXP_CHECK_AND_PRINT(VALID),
-                                TXP_CHECK_AND_PRINT(BAND_52G),
-                                TXP_CHECK_AND_PRINT(OFDM),
-                                TXP_CHECK_AND_PRINT(40MHZ),
-                                TXP_CHECK_AND_PRINT(HT_AP),
-                                TXP_CHECK_AND_PRINT(RES1),
-                                TXP_CHECK_AND_PRINT(RES2),
-                                TXP_CHECK_AND_PRINT(COMMON_TYPE),
-                                txp->flags);
-               IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
-                                "chain_B: 0X%02x chain_C: 0X%02x\n",
-                                txp->chain_a_max, txp->chain_b_max,
-                                txp->chain_c_max);
-               IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
-                                "MIMO3: 0x%02x High 20_on_40: 0x%02x "
-                                "Low 20_on_40: 0x%02x\n",
-                                txp->mimo2_max, txp->mimo3_max,
-                                ((txp->delta_20_in_40 & 0xf0) >> 4),
-                                (txp->delta_20_in_40 & 0x0f));
-
-               max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
-                                                     &max_txp_avg_halfdbm);
-
-               /*
-                * Update the user limit values values to the highest
-                * power supported by any channel
-                */
-               if (max_txp_avg > priv->tx_power_user_lmt)
-                       priv->tx_power_user_lmt = max_txp_avg;
-               if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
-                       priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
-
-               iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
-       }
-}
index 7c036b9c2b30e9bdc262a679457b3ede4ef6d528..d30714be515b38249028337f59d6238b7deff305 100644 (file)
@@ -96,11 +96,7 @@ void iwlagn_temperature(struct iwl_priv *priv)
 
 u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
 {
-       struct iwl_eeprom_calib_hdr {
-               u8 version;
-               u8 pa_type;
-               u16 voltage;
-       } *hdr;
+       struct iwl_eeprom_calib_hdr *hdr;
 
        hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
                                                        EEPROM_CALIB_ALL);
@@ -194,433 +190,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
        return -1;
 }
 
-static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
-                                          struct ieee80211_vif *vif,
-                                          enum ieee80211_band band,
-                                          struct iwl_scan_channel *scan_ch)
-{
-       const struct ieee80211_supported_band *sband;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added = 0;
-       u16 channel = 0;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband) {
-               IWL_ERR(priv, "invalid band\n");
-               return added;
-       }
-
-       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
-       passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-       channel = iwl_get_single_channel_number(priv, band);
-       if (channel) {
-               scan_ch->channel = cpu_to_le16(channel);
-               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-               /* Set txpower levels to defaults */
-               scan_ch->dsp_atten = 110;
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-               added++;
-       } else
-               IWL_ERR(priv, "no valid channel found\n");
-       return added;
-}
-
-static int iwl_get_channels_for_scan(struct iwl_priv *priv,
-                                    struct ieee80211_vif *vif,
-                                    enum ieee80211_band band,
-                                    u8 is_active, u8 n_probes,
-                                    struct iwl_scan_channel *scan_ch)
-{
-       struct ieee80211_channel *chan;
-       const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added, i;
-       u16 channel;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband)
-               return 0;
-
-       active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
-       passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-       for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-               chan = priv->scan_request->channels[i];
-
-               if (chan->band != band)
-                       continue;
-
-               channel = chan->hw_value;
-               scan_ch->channel = cpu_to_le16(channel);
-
-               ch_info = iwl_get_channel_info(priv, band, channel);
-               if (!is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
-                                       channel);
-                       continue;
-               }
-
-               if (!is_active || is_channel_passive(ch_info) ||
-                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
-                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               else
-                       scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
-
-               if (n_probes)
-                       scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-
-               /* Set txpower levels to defaults */
-               scan_ch->dsp_atten = 110;
-
-               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
-                * power level:
-                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-                */
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-
-               IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
-                              channel, le32_to_cpu(scan_ch->type),
-                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-                               "ACTIVE" : "PASSIVE",
-                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
-                              active_dwell : passive_dwell);
-
-               scan_ch++;
-               added++;
-       }
-
-       IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
-       return added;
-}
-
-int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_SCAN_CMD,
-               .len = { sizeof(struct iwl_scan_cmd), },
-               .flags = CMD_SYNC,
-       };
-       struct iwl_scan_cmd *scan;
-       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       u32 rate_flags = 0;
-       u16 cmd_len;
-       u16 rx_chain = 0;
-       enum ieee80211_band band;
-       u8 n_probes = 0;
-       u8 rx_ant = hw_params(priv).valid_rx_ant;
-       u8 rate;
-       bool is_active = false;
-       int  chan_mod;
-       u8 active_chains;
-       u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
-       int ret;
-
-       lockdep_assert_held(&priv->shrd->mutex);
-
-       if (vif)
-               ctx = iwl_rxon_ctx_from_vif(vif);
-
-       if (!priv->scan_cmd) {
-               priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
-                                        IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-               if (!priv->scan_cmd) {
-                       IWL_DEBUG_SCAN(priv,
-                                      "fail to allocate memory for scan\n");
-                       return -ENOMEM;
-               }
-       }
-       scan = priv->scan_cmd;
-       memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
-       scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-       scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-       if (priv->scan_type != IWL_SCAN_ROC &&
-           iwl_is_any_associated(priv)) {
-               u16 interval = 0;
-               u32 extra;
-               u32 suspend_time = 100;
-               u32 scan_suspend_time = 100;
-
-               IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-               switch (priv->scan_type) {
-               case IWL_SCAN_ROC:
-                       WARN_ON(1);
-                       break;
-               case IWL_SCAN_RADIO_RESET:
-                       interval = 0;
-                       break;
-               case IWL_SCAN_NORMAL:
-                       interval = vif->bss_conf.beacon_int;
-                       break;
-               }
-
-               scan->suspend_time = 0;
-               scan->max_out_time = cpu_to_le32(200 * 1024);
-               if (!interval)
-                       interval = suspend_time;
-
-               extra = (suspend_time / interval) << 22;
-               scan_suspend_time = (extra |
-                   ((suspend_time % interval) * 1024));
-               scan->suspend_time = cpu_to_le32(scan_suspend_time);
-               IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
-                              scan_suspend_time, interval);
-       } else if (priv->scan_type == IWL_SCAN_ROC) {
-               scan->suspend_time = 0;
-               scan->max_out_time = 0;
-               scan->quiet_time = 0;
-               scan->quiet_plcp_th = 0;
-       }
-
-       switch (priv->scan_type) {
-       case IWL_SCAN_RADIO_RESET:
-               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-               break;
-       case IWL_SCAN_NORMAL:
-               if (priv->scan_request->n_ssids) {
-                       int i, p = 0;
-                       IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-                       for (i = 0; i < priv->scan_request->n_ssids; i++) {
-                               /* always does wildcard anyway */
-                               if (!priv->scan_request->ssids[i].ssid_len)
-                                       continue;
-                               scan->direct_scan[p].id = WLAN_EID_SSID;
-                               scan->direct_scan[p].len =
-                                       priv->scan_request->ssids[i].ssid_len;
-                               memcpy(scan->direct_scan[p].ssid,
-                                      priv->scan_request->ssids[i].ssid,
-                                      priv->scan_request->ssids[i].ssid_len);
-                               n_probes++;
-                               p++;
-                       }
-                       is_active = true;
-               } else
-                       IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
-               break;
-       case IWL_SCAN_ROC:
-               IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
-               break;
-       }
-
-       scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-       scan->tx_cmd.sta_id = ctx->bcast_sta_id;
-       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-       switch (priv->scan_band) {
-       case IEEE80211_BAND_2GHZ:
-               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-               chan_mod = le32_to_cpu(
-                       priv->contexts[IWL_RXON_CTX_BSS].active.flags &
-                                               RXON_FLG_CHANNEL_MODE_MSK)
-                                      >> RXON_FLG_CHANNEL_MODE_POS;
-               if (chan_mod == CHANNEL_MODE_PURE_40) {
-                       rate = IWL_RATE_6M_PLCP;
-               } else {
-                       rate = IWL_RATE_1M_PLCP;
-                       rate_flags = RATE_MCS_CCK_MSK;
-               }
-               /*
-                * Internal scans are passive, so we can indiscriminately set
-                * the BT ignore flag on 2.4 GHz since it applies to TX only.
-                */
-               if (priv->cfg->bt_params &&
-                   priv->cfg->bt_params->advanced_bt_coexist)
-                       scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
-               break;
-       case IEEE80211_BAND_5GHZ:
-               rate = IWL_RATE_6M_PLCP;
-               break;
-       default:
-               IWL_WARN(priv, "Invalid scan band\n");
-               return -EIO;
-       }
-
-       /*
-        * If active scanning is requested but a certain channel is
-        * marked passive, we can do active scanning if we detect
-        * transmissions.
-        *
-        * There is an issue with some firmware versions that triggers
-        * a sysassert on a "good CRC threshold" of zero (== disabled),
-        * on a radar channel even though this means that we should NOT
-        * send probes.
-        *
-        * The "good CRC threshold" is the number of frames that we
-        * need to receive during our dwell time on a channel before
-        * sending out probes -- setting this to a huge value will
-        * mean we never reach it, but at the same time work around
-        * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
-        * here instead of IWL_GOOD_CRC_TH_DISABLED.
-        *
-        * This was fixed in later versions along with some other
-        * scan changes, and the threshold behaves as a flag in those
-        * versions.
-        */
-       if (priv->new_scan_threshold_behaviour)
-               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-                                               IWL_GOOD_CRC_TH_DISABLED;
-       else
-               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-                                               IWL_GOOD_CRC_TH_NEVER;
-
-       band = priv->scan_band;
-
-       if (priv->cfg->scan_rx_antennas[band])
-               rx_ant = priv->cfg->scan_rx_antennas[band];
-
-       if (band == IEEE80211_BAND_2GHZ &&
-           priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
-               /* transmit 2.4 GHz probes only on first antenna */
-               scan_tx_antennas = first_antenna(scan_tx_antennas);
-       }
-
-       priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
-                                                   scan_tx_antennas);
-       rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
-       scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
-
-       /* In power save mode use one chain, otherwise use all chains */
-       if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) {
-               /* rx_ant has been set to all valid chains previously */
-               active_chains = rx_ant &
-                               ((u8)(priv->chain_noise_data.active_chains));
-               if (!active_chains)
-                       active_chains = rx_ant;
-
-               IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
-                               priv->chain_noise_data.active_chains);
-
-               rx_ant = first_antenna(active_chains);
-       }
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist &&
-           priv->bt_full_concurrent) {
-               /* operated as 1x1 in full concurrency mode */
-               rx_ant = first_antenna(rx_ant);
-       }
-
-       /* MIMO is not used here, but value is required */
-       rx_chain |=
-               hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
-       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
-       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
-       rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
-       scan->rx_chain = cpu_to_le16(rx_chain);
-       switch (priv->scan_type) {
-       case IWL_SCAN_NORMAL:
-               cmd_len = iwl_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       vif->addr,
-                                       priv->scan_request->ie,
-                                       priv->scan_request->ie_len,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-               break;
-       case IWL_SCAN_RADIO_RESET:
-       case IWL_SCAN_ROC:
-               /* use bcast addr, will not be transmitted but must be valid */
-               cmd_len = iwl_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       iwl_bcast_addr, NULL, 0,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-               break;
-       default:
-               BUG();
-       }
-       scan->tx_cmd.len = cpu_to_le16(cmd_len);
-
-       scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
-                              RXON_FILTER_BCON_AWARE_MSK);
-
-       switch (priv->scan_type) {
-       case IWL_SCAN_RADIO_RESET:
-               scan->channel_count =
-                       iwl_get_single_channel_for_scan(priv, vif, band,
-                               (void *)&scan->data[cmd_len]);
-               break;
-       case IWL_SCAN_NORMAL:
-               scan->channel_count =
-                       iwl_get_channels_for_scan(priv, vif, band,
-                               is_active, n_probes,
-                               (void *)&scan->data[cmd_len]);
-               break;
-       case IWL_SCAN_ROC: {
-               struct iwl_scan_channel *scan_ch;
-
-               scan->channel_count = 1;
-
-               scan_ch = (void *)&scan->data[cmd_len];
-               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               scan_ch->channel =
-                       cpu_to_le16(priv->hw_roc_channel->hw_value);
-               scan_ch->active_dwell =
-               scan_ch->passive_dwell =
-                       cpu_to_le16(priv->hw_roc_duration);
-
-               /* Set txpower levels to defaults */
-               scan_ch->dsp_atten = 110;
-
-               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
-                * power level:
-                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-                */
-               if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-               }
-               break;
-       }
-
-       if (scan->channel_count == 0) {
-               IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-               return -EIO;
-       }
-
-       cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
-           scan->channel_count * sizeof(struct iwl_scan_channel);
-       cmd.data[0] = scan;
-       cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-       scan->len = cpu_to_le16(cmd.len[0]);
-
-       /* set scan bit here for PAN params */
-       set_bit(STATUS_SCAN_HW, &priv->shrd->status);
-
-       ret = iwlagn_set_pan_params(priv);
-       if (ret)
-               return ret;
-
-       ret = iwl_trans_send_cmd(trans(priv), &cmd);
-       if (ret) {
-               clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
-               iwlagn_set_pan_params(priv);
-       }
-
-       return ret;
-}
-
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
                               struct ieee80211_vif *vif, bool add)
 {
@@ -659,7 +228,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
                                 IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
                                 IWL_SCD_MGMT_MSK;
        if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
-           (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+           (priv->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
                flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
                                IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
                                IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
@@ -1136,8 +705,9 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
        }
 }
 
-void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
-                                            struct iwl_rx_mem_buffer *rxb)
+int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+                                 struct iwl_rx_mem_buffer *rxb,
+                                 struct iwl_device_cmd *cmd)
 {
        unsigned long flags;
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -1146,7 +716,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 
        if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
                /* bt coex disabled */
-               return;
+               return 0;
        }
 
        IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
@@ -1188,6 +758,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
        spin_lock_irqsave(&priv->shrd->lock, flags);
        priv->bt_ci_compliance = coex->bt_ci_compliance;
        spin_unlock_irqrestore(&priv->shrd->lock, flags);
+       return 0;
 }
 
 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
index ffee15ba06a8a53abf6c051713d6950f4011cad2..c14f8d6fd7d8d36878f071ba907ebe0661f5c848 100644 (file)
@@ -346,7 +346,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
 {
        struct iwl_station_priv *sta_priv =
                container_of(lq_sta, struct iwl_station_priv, lq_sta);
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
        lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
@@ -710,7 +710,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
 static bool rs_use_green(struct ieee80211_sta *sta)
 {
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
                !(ctx->ht.non_gf_sta_present);
@@ -917,7 +917,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
        struct iwl_scale_tbl_info tbl_type;
        struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
 
@@ -1283,7 +1283,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
        s32 rate;
        s8 is_green = lq_sta->is_green;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
                return -1;
@@ -1339,7 +1339,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
        s32 rate;
        s8 is_green = lq_sta->is_green;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
                return -1;
@@ -1396,7 +1396,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
        u8 is_green = lq_sta->is_green;
        s32 rate;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
                return -1;
@@ -2263,7 +2263,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        u8 tid = IWL_MAX_TID_COUNT;
        struct iwl_tid_data *tid_data;
        struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+       struct iwl_rxon_context *ctx = sta_priv->ctx;
 
        IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
 
@@ -2706,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
                return;
 
        sta_priv = (void *)sta->drv_priv;
-       ctx = sta_priv->common.ctx;
+       ctx = sta_priv->ctx;
 
        i = lq_sta->last_txrate_idx;
 
index 1af276739d875f522d43ef0dad29d91889381c67..00e6fc59e4590967625ef963c5ab58d4325b210b 100644 (file)
@@ -311,7 +311,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
        int slot0 = 300, slot1 = 0;
        int ret;
 
-       if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+       if (priv->shrd->valid_contexts == BIT(IWL_RXON_CTX_BSS))
                return 0;
 
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
@@ -456,7 +456,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
        else
                ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 
-       iwl_print_rx_config_cmd(priv, ctx);
+       iwl_print_rx_config_cmd(priv, ctx->ctxid);
        ret = iwl_check_rxon_cmd(priv, ctx);
        if (ret) {
                IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
index 92ba8cd0ecd50f12196def3916a6df7e3a2119c0..495f936647414b8ceaf38b74ea5bc7d26cd15a95 100644 (file)
@@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
 {
        if (stop) {
                IWL_DEBUG_TEMP(priv, "Stop all queues\n");
-               if (priv->shrd->mac80211_registered)
+               if (priv->mac80211_registered)
                        ieee80211_stop_queues(priv->hw);
                IWL_DEBUG_TEMP(priv,
                                "Schedule 5 seconds CT_KILL Timer\n");
@@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
                          jiffies + CT_KILL_EXIT_DURATION * HZ);
        } else {
                IWL_DEBUG_TEMP(priv, "Wake all queues\n");
-               if (priv->shrd->mac80211_registered)
+               if (priv->mac80211_registered)
                        ieee80211_wake_queues(priv->hw);
        }
 }
index d118ed29bf3f86319fd427a98d74678b53a0889c..7282a23e8f1ce3faab9e3cf78080323a65b9a453 100644 (file)
@@ -117,7 +117,6 @@ struct iwl_tt_mgmt {
 u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
 bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
 bool iwl_ht_enabled(struct iwl_priv *priv);
-bool iwl_check_for_ct_kill(struct iwl_priv *priv);
 enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
 enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
 void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
index f8a4bcf0a34bbd76587791b4f8af62622246bbd5..8c0f07f56149bf07ea2208e7dace8ad542baf7ef 100644 (file)
@@ -313,6 +313,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
        }
 
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               is_agg = true;
+
        /* irqs already disabled/saved above when locking priv->shrd->lock */
        spin_lock(&priv->shrd->sta_lock);
 
@@ -322,7 +325,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                goto drop_unlock_sta;
 
        memset(dev_cmd, 0, sizeof(*dev_cmd));
-       tx_cmd = &dev_cmd->cmd.tx;
+       tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
 
        /* Copy MAC header from skb into command buffer */
        memcpy(tx_cmd->hdr, hdr, hdr_len);
@@ -736,12 +739,13 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
        }
 }
 
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
        int txq_id = SEQ_TO_QUEUE(sequence);
-       int cmd_index = SEQ_TO_INDEX(sequence);
+       int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
        struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        struct ieee80211_hdr *hdr;
        u32 status = le16_to_cpu(tx_resp->status.status);
@@ -824,6 +828,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 
        iwl_check_abort_status(priv, tx_resp->frame_count, status);
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }
 
 /**
@@ -832,8 +837,9 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
  * Handles block-acknowledge notification from device, which reports success
  * of frames sent via aggregation.
  */
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-                                          struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+                                  struct iwl_rx_mem_buffer *rxb,
+                                  struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
@@ -857,7 +863,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        if (scd_flow >= hw_params(priv).max_txq_num) {
                IWL_ERR(priv,
                        "BUG_ON scd_flow is bigger than number of queues\n");
-               return;
+               return 0;
        }
 
        sta_id = ba_resp->sta_id;
@@ -877,14 +883,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                        "BA scd_flow %d does not match txq_id %d\n",
                        scd_flow, agg->txq_id);
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        if (unlikely(!agg->wait_for_ba)) {
                if (unlikely(ba_resp->bitmap))
                        IWL_ERR(priv, "Received BA when not expected\n");
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
@@ -901,7 +907,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           ba_resp->scd_ssn);
 
        /* Mark that the expected block-ack response arrived */
-       agg->wait_for_ba = 0;
+       agg->wait_for_ba = false;
 
        /* Sanity check values reported by uCode */
        if (ba_resp->txed_2_done > ba_resp->txed) {
@@ -955,4 +961,5 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        }
 
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }
index ddb255a575dfc6f05f8a7cc7efd75f65134aa841..b4e1e7c4c3148af02c1405bec1fe21003b2003d1 100644 (file)
@@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
                FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
        IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
-       ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-                                       priv->ucode_write_complete, 5 * HZ);
-       if (ret == -ERESTARTSYS) {
-               IWL_ERR(priv, "Could not load the %s uCode section due "
-                       "to interrupt\n", name);
-               return ret;
-       }
+       ret = wait_event_timeout(priv->shrd->wait_command_queue,
+                                priv->ucode_write_complete, 5 * HZ);
        if (!ret) {
                IWL_ERR(priv, "Could not load the %s uCode section\n",
                        name);
@@ -164,11 +159,11 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
 {
        struct iwl_calib_temperature_offset_cmd cmd;
        __le16 *offset_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
 
        memset(&cmd, 0, sizeof(cmd));
        iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
-       memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib));
+       memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib));
        if (!(cmd.radio_sensor_offset))
                cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
 
@@ -178,6 +173,42 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
                             (u8 *)&cmd, sizeof(cmd));
 }
 
+static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
+{
+       struct iwl_calib_temperature_offset_v2_cmd cmd;
+       __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
+                                    EEPROM_KELVIN_TEMPERATURE);
+       __le16 *offset_calib_low =
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
+       struct iwl_eeprom_calib_hdr *hdr;
+
+       memset(&cmd, 0, sizeof(cmd));
+       iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
+       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
+                                                       EEPROM_CALIB_ALL);
+       memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
+               sizeof(*offset_calib_high));
+       memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
+               sizeof(*offset_calib_low));
+       if (!(cmd.radio_sensor_offset_low)) {
+               IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
+               cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
+               cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
+       }
+       memcpy(&cmd.burntVoltageRef, &hdr->voltage,
+               sizeof(hdr->voltage));
+
+       IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
+                       le16_to_cpu(cmd.radio_sensor_offset_high));
+       IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
+                       le16_to_cpu(cmd.radio_sensor_offset_low));
+       IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
+                       le16_to_cpu(cmd.burntVoltageRef));
+
+       return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
+                            (u8 *)&cmd, sizeof(cmd));
+}
+
 static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
 {
        struct iwl_calib_cfg_cmd calib_cfg_cmd;
@@ -197,8 +228,9 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
        return iwl_trans_send_cmd(trans(priv), &cmd);
 }
 
-void iwlagn_rx_calib_result(struct iwl_priv *priv,
-                            struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_calib_result(struct iwl_priv *priv,
+                           struct iwl_rx_mem_buffer *rxb,
+                           struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
@@ -231,9 +263,10 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
        default:
                IWL_ERR(priv, "Unknown calibration notification %d\n",
                          hdr->op_code);
-               return;
+               return -1;
        }
        iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
+       return 0;
 }
 
 int iwlagn_init_alive_start(struct iwl_priv *priv)
@@ -263,8 +296,12 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
         * temperature offset calibration is only needed for runtime ucode,
         * so prepare the value now.
         */
-       if (priv->cfg->need_temp_offset_calib)
-               return iwlagn_set_temperature_offset_calib(priv);
+       if (priv->cfg->need_temp_offset_calib) {
+               if (priv->cfg->temp_offset_v2)
+                       return iwlagn_set_temperature_offset_calib_v2(priv);
+               else
+                       return iwlagn_set_temperature_offset_calib(priv);
+       }
 
        return 0;
 }
@@ -349,6 +386,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
 
 static int iwlagn_alive_notify(struct iwl_priv *priv)
 {
+       struct iwl_rxon_context *ctx;
        int ret;
 
        if (!priv->tx_cmd_pool)
@@ -361,6 +399,8 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
                return -ENOMEM;
 
        iwl_trans_tx_start(trans(priv));
+       for_each_context(priv, ctx)
+               ctx->last_tx_rejected = false;
 
        ret = iwlagn_send_wimax_coex(priv);
        if (ret)
index 8113fbe770a3da676a0dec2ef95077b2dd3c4851..baaf48616cc7afc11e4e9131e8ad2482f53f8996 100644 (file)
@@ -453,122 +453,6 @@ static void iwl_bg_tx_flush(struct work_struct *work)
        iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_shared *shrd = dev_get_drvdata(d);
-       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd));
-}
-static ssize_t store_debug_level(struct device *d,
-                               struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_shared *shrd = dev_get_drvdata(d);
-       struct iwl_priv *priv = shrd->priv;
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 0, &val);
-       if (ret)
-               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
-       else {
-               shrd->dbg_level_dev = val;
-               if (iwl_alloc_traffic_mem(priv))
-                       IWL_ERR(shrd->priv,
-                               "Not enough memory to generate traffic log\n");
-       }
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                       show_debug_level, store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-
-static ssize_t show_temperature(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_shared *shrd = dev_get_drvdata(d);
-       struct iwl_priv *priv = shrd->priv;
-
-       if (!iwl_is_alive(priv->shrd))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_is_ready_rf(priv->shrd))
-               return sprintf(buf, "off\n");
-       else
-               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
-       else {
-               ret = iwl_set_tx_power(priv, val, false);
-               if (ret)
-                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
-                               ret);
-               else
-                       ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_temperature.attr,
-       &dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
-       &dev_attr_debug_level.attr,
-#endif
-       NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
-       .name = NULL,           /* put in device directory */
-       .attrs = iwl_sysfs_entries,
-};
-
 /******************************************************************************
  *
  * uCode download functions
@@ -623,9 +507,9 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
         * The default context is always valid,
         * the PAN context depends on uCode.
         */
-       priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+       priv->shrd->valid_contexts = BIT(IWL_RXON_CTX_BSS);
        if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
-               priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
+               priv->shrd->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
 
        for (i = 0; i < NUM_IWL_RXON_CTX; i++)
                priv->contexts[i].ctxid = i;
@@ -1259,13 +1143,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-       err = sysfs_create_group(&(priv->bus->dev->kobj),
-                                       &iwl_attribute_group);
-       if (err) {
-               IWL_ERR(priv, "failed to create sysfs device attributes\n");
-               goto out_unbind;
-       }
-
        /* We have our copies now, allow OS release its copies */
        release_firmware(ucode_raw);
        complete(&priv->firmware_loading_complete);
@@ -1519,9 +1396,11 @@ static void __iwl_down(struct iwl_priv *priv)
        if (!exit_pending)
                clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
 
-       if (priv->shrd->mac80211_registered)
+       if (priv->mac80211_registered)
                ieee80211_stop_queues(priv->hw);
 
+       iwl_trans_stop_device(trans(priv));
+
        /* Clear out all status bits but a few that are stable across reset */
        priv->shrd->status &=
                        test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
@@ -1533,8 +1412,6 @@ static void __iwl_down(struct iwl_priv *priv)
                        test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
                                STATUS_EXIT_PENDING;
 
-       iwl_trans_stop_device(trans(priv));
-
        dev_kfree_skb(priv->beacon_skb);
        priv->beacon_skb = NULL;
 }
@@ -1780,7 +1657,12 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                    IEEE80211_HW_SPECTRUM_MGMT |
                    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
+       /*
+        * Including the following line will crash some AP's.  This
+        * workaround removes the stimulus which causes the crash until
+        * the AP software can be fixed.
        hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+        */
 
        hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
@@ -1863,7 +1745,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
                return ret;
        }
-       priv->shrd->mac80211_registered = 1;
+       priv->mac80211_registered = 1;
 
        return 0;
 }
@@ -1919,7 +1801,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int iwlagn_send_patterns(struct iwl_priv *priv,
                                struct cfg80211_wowlan *wowlan)
 {
@@ -1994,7 +1876,7 @@ struct wowlan_key_data {
        bool error, use_rsc_tsc, use_tkip;
 };
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
 {
        int i;
@@ -2631,7 +2513,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        mutex_lock(&priv->shrd->mutex);
        IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
                        sta->addr);
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
+       sta_priv->sta_id = IWL_INVALID_STATION;
 
        atomic_set(&sta_priv->pending_frames, 0);
        if (vif->type == NL80211_IFTYPE_AP)
@@ -2647,7 +2529,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
                return ret;
        }
 
-       sta_priv->common.sta_id = sta_id;
+       sta_priv->sta_id = sta_id;
 
        /* Initialize rate scaling */
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
@@ -2880,7 +2762,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
        int err = 0;
 
-       if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+       if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
                return -EOPNOTSUPP;
 
        if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
@@ -2888,15 +2770,6 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->shrd->mutex);
 
-       /*
-        * TODO: Remove this hack! Firmware needs to be updated
-        * to allow longer off-channel periods in scanning for
-        * this use case, based on a flag (and we'll need an API
-        * flag in the firmware when it has that).
-        */
-       if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80)
-               duration = 80;
-
        if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
                err = -EBUSY;
                goto out;
@@ -2905,6 +2778,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
        priv->hw_roc_channel = channel;
        priv->hw_roc_chantype = channel_type;
        priv->hw_roc_duration = duration;
+       priv->hw_roc_start_notified = false;
        cancel_delayed_work(&priv->hw_roc_disable_work);
 
        if (!ctx->is_active) {
@@ -2945,7 +2819,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
 {
        struct iwl_priv *priv = hw->priv;
 
-       if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+       if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
                return -EOPNOTSUPP;
 
        mutex_lock(&priv->shrd->mutex);
@@ -3032,7 +2906,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 {
        priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
 
-       init_waitqueue_head(&priv->wait_command_queue);
+       init_waitqueue_head(&priv->shrd->wait_command_queue);
 
        INIT_WORK(&priv->restart, iwl_bg_restart);
        INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -3203,7 +3077,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
        .tx = iwlagn_mac_tx,
        .start = iwlagn_mac_start,
        .stop = iwlagn_mac_stop,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        .suspend = iwlagn_mac_suspend,
        .resume = iwlagn_mac_resume,
 #endif
@@ -3309,10 +3183,9 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        priv = hw->priv;
        priv->bus = bus;
        priv->shrd = &priv->_shrd;
+       bus->shrd = priv->shrd;
        priv->shrd->bus = bus;
        priv->shrd->priv = priv;
-       priv->shrd->hw = hw;
-       bus_set_drv_data(priv->bus, priv->shrd);
 
        priv->shrd->trans = trans_ops->alloc(priv->shrd);
        if (priv->shrd->trans == NULL) {
@@ -3475,8 +3348,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
        iwl_dbgfs_unregister(priv);
-       sysfs_remove_group(&priv->bus->dev->kobj,
-                          &iwl_attribute_group);
 
        /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
         * to be called and iwl_down since we are removing the device
@@ -3487,9 +3358,9 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        iwl_testmode_cleanup(priv);
        iwl_leds_exit(priv);
 
-       if (priv->shrd->mac80211_registered) {
+       if (priv->mac80211_registered) {
                ieee80211_unregister_hw(priv->hw);
-               priv->shrd->mac80211_registered = 0;
+               priv->mac80211_registered = 0;
        }
 
        iwl_tt_exit(priv);
@@ -3513,8 +3384,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
 
        iwl_trans_free(trans(priv));
 
-       bus_set_drv_data(priv->bus, NULL);
-
        iwl_uninit_drv(priv);
 
        dev_kfree_skb(priv->beacon_skb);
index a7b4948e43da21749989f64715ef70c38bfb8598..2a297d1e6bc7b0db59051036590a421fe4ac7a27 100644 (file)
@@ -88,8 +88,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
                             u32 changes);
 
 /* uCode */
-void iwlagn_rx_calib_result(struct iwl_priv *priv,
-                        struct iwl_rx_mem_buffer *rxb);
+int iwlagn_rx_calib_result(struct iwl_priv *priv,
+                           struct iwl_rx_mem_buffer *rxb,
+                           struct iwl_device_cmd *cmd);
 int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
 void iwlagn_send_prio_tbl(struct iwl_priv *priv);
 int iwlagn_run_init_ucode(struct iwl_priv *priv);
@@ -98,7 +99,6 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                                 enum iwlagn_ucode_type ucode_type);
 
 /* lib */
-int iwlagn_hw_valid_rtc_data_addr(u32 addr);
 int iwlagn_send_tx_power(struct iwl_priv *priv);
 void iwlagn_temperature(struct iwl_priv *priv);
 u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
@@ -109,7 +109,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
 /* rx */
 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
 void iwl_setup_rx_handlers(struct iwl_priv *priv);
-void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 
 
 /* tx */
@@ -118,9 +117,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn);
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta, u16 tid);
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb);
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+                                  struct iwl_rx_mem_buffer *rxb,
+                                  struct iwl_device_cmd *cmd);
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd);
 
 static inline u32 iwl_tx_status_to_mac80211(u32 status)
 {
@@ -148,7 +149,6 @@ static inline bool iwl_is_tx_success(u32 status)
 u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
 
 /* scan */
-int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwlagn_post_scan(struct iwl_priv *priv);
 void iwlagn_disable_roc(struct iwl_priv *priv);
 
@@ -158,8 +158,9 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 
 /* bt coex */
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
-void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
-                                 struct iwl_rx_mem_buffer *rxb);
+int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+                                 struct iwl_rx_mem_buffer *rxb,
+                                 struct iwl_device_cmd *cmd);
 void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
 void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
 void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
index 83aed46673e17d0ad6f9b51ec5e4ef541f15a7a5..08b97594e3057c303237fda4846ea3b92240ee43 100644 (file)
 #ifndef __iwl_bus_h__
 #define __iwl_bus_h__
 
-/*This file includes the declaration that are exported from the bus layer */
-
 #include <linux/types.h>
 #include <linux/spinlock.h>
 
+/**
+ * DOC: Bus layer - role and goal
+ *
+ * iwl-bus.h defines the API to the bus layer of the iwlwifi driver.
+ * The bus layer is responsible for doing very basic bus operations that are
+ * listed in the iwl_bus_ops structure.
+ * The bus layer registers to the bus driver, advertises the supported HW and
+ * gets notifications about enumeration, suspend, resume.
+ * For the moment, the bus layer is not a linux kernel module as itself, and
+ * the module_init function of the driver must call the bus specific
+ * registration functions. These functions are listed at the end of this file.
+ * For the moment, there is only one implementation of this interface: PCI-e.
+ * This implementation is iwl-pci.c
+ */
+
+/**
+ * DOC: encapsulation and type safety
+ *
+ * The iwl_bus describes the data that is shared amongst all the bus layer
+ * implementations. This data is visible to other layers. Data in the bus
+ * specific area is not visible outside the bus specific implementation.
+ * iwl_bus holds a pointer to iwl_shared which holds pointer to all the other
+ * layers of the driver (iwl_priv, iwl_trans). In fact, this is the way to go
+ * when the transport layer needs to call a function of another layer.
+ *
+ * In order to achieve encapsulation, iwl_priv cannot be dereferenced from the
+ * bus layer. Type safety is still kept since functions that gets iwl_priv gets
+ * a typed pointer (as opposed to void *).
+ */
+
+/**
+ * DOC: probe flow
+ *
+ * The module_init calls the bus specific registration function. The
+ * registration to the bus layer will trigger an enumeration of the bus which
+ * will call the bus specific probe function.
+ * The first thing this function must do is to allocate the memory needed by
+ * iwl_bus + the bus_specific data.
+ * Once the bus specific probe function has configured the hardware, it
+ * chooses the appropriate transport layer and calls iwl_probe that will run
+ * the bus independent probe flow.
+ *
+ * Note: The bus specific code must set the following data in iwl_bus before it
+ *       calls iwl_probe:
+ *     * bus->dev
+ *     * bus->irq
+ *     * bus->ops
+ */
+
 struct iwl_shared;
 struct iwl_bus;
 
 /**
  * struct iwl_bus_ops - bus specific operations
  * @get_pm_support: must returns true if the bus can go to sleep
- * @apm_config: will be called during the config of the APM configuration
- * @set_drv_data: set the shared data pointer to the bus layer
+ * @apm_config: will be called during the config of the APM
  * @get_hw_id: prints the hw_id in the provided buffer
  * @write8: write a byte to register at offset ofs
  * @write32: write a dword to register at offset ofs
@@ -84,7 +130,6 @@ struct iwl_bus;
 struct iwl_bus_ops {
        bool (*get_pm_support)(struct iwl_bus *bus);
        void (*apm_config)(struct iwl_bus *bus);
-       void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd);
        void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
        void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
        void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
@@ -93,14 +138,18 @@ struct iwl_bus_ops {
 
 /**
  * struct iwl_bus - bus common data
- * @dev - pointer to struct device * that represent the device
+ *
+ * This data is common to all bus layer implementations.
+ *
+ * @dev - pointer to struct device * that represents the device
  * @ops - pointer to iwl_bus_ops
  * @shrd - pointer to iwl_shared which holds shared data from the upper layer
+ *     NB: for the time being this needs to be set by the upper layer since
+ *     it allocates the shared data
  * @irq - the irq number for the device
  * @reg_lock - protect hw register access
  */
 struct iwl_bus {
-       /* Common data to all buses */
        struct device *dev;
        const struct iwl_bus_ops *ops;
        struct iwl_shared *shrd;
@@ -123,12 +172,6 @@ static inline void bus_apm_config(struct iwl_bus *bus)
        bus->ops->apm_config(bus);
 }
 
-static inline void bus_set_drv_data(struct iwl_bus *bus,
-                               struct iwl_shared *shrd)
-{
-       bus->ops->set_drv_data(bus, shrd);
-}
-
 static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
 {
        bus->ops->get_hw_id(bus, buf, buf_len);
@@ -149,6 +192,9 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
        return bus->ops->read32(bus, ofs);
 }
 
+/*****************************************************
+* Bus layer registration functions
+******************************************************/
 int __must_check iwl_pci_register_driver(void);
 void iwl_pci_unregister_driver(void);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h
new file mode 100644 (file)
index 0000000..d4f317c
--- /dev/null
@@ -0,0 +1,115 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_pci_h__
+#define __iwl_pci_h__
+
+
+/*
+ * This file declares the config structures for all devices.
+ */
+
+extern struct iwl_cfg iwl5300_agn_cfg;
+extern struct iwl_cfg iwl5100_agn_cfg;
+extern struct iwl_cfg iwl5350_agn_cfg;
+extern struct iwl_cfg iwl5100_bgn_cfg;
+extern struct iwl_cfg iwl5100_abg_cfg;
+extern struct iwl_cfg iwl5150_agn_cfg;
+extern struct iwl_cfg iwl5150_abg_cfg;
+extern struct iwl_cfg iwl6005_2agn_cfg;
+extern struct iwl_cfg iwl6005_2abg_cfg;
+extern struct iwl_cfg iwl6005_2bg_cfg;
+extern struct iwl_cfg iwl6005_2agn_sff_cfg;
+extern struct iwl_cfg iwl1030_bgn_cfg;
+extern struct iwl_cfg iwl1030_bg_cfg;
+extern struct iwl_cfg iwl6030_2agn_cfg;
+extern struct iwl_cfg iwl6030_2abg_cfg;
+extern struct iwl_cfg iwl6030_2bgn_cfg;
+extern struct iwl_cfg iwl6030_2bg_cfg;
+extern struct iwl_cfg iwl6000i_2agn_cfg;
+extern struct iwl_cfg iwl6000i_2abg_cfg;
+extern struct iwl_cfg iwl6000i_2bg_cfg;
+extern struct iwl_cfg iwl6000_3agn_cfg;
+extern struct iwl_cfg iwl6050_2agn_cfg;
+extern struct iwl_cfg iwl6050_2abg_cfg;
+extern struct iwl_cfg iwl6150_bgn_cfg;
+extern struct iwl_cfg iwl6150_bg_cfg;
+extern struct iwl_cfg iwl1000_bgn_cfg;
+extern struct iwl_cfg iwl1000_bg_cfg;
+extern struct iwl_cfg iwl100_bgn_cfg;
+extern struct iwl_cfg iwl100_bg_cfg;
+extern struct iwl_cfg iwl130_bgn_cfg;
+extern struct iwl_cfg iwl130_bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_cfg;
+extern struct iwl_cfg iwl2000_2bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_d_cfg;
+extern struct iwl_cfg iwl2030_2bgn_cfg;
+extern struct iwl_cfg iwl2030_2bg_cfg;
+extern struct iwl_cfg iwl6035_2agn_cfg;
+extern struct iwl_cfg iwl6035_2abg_cfg;
+extern struct iwl_cfg iwl6035_2bg_cfg;
+extern struct iwl_cfg iwl105_bg_cfg;
+extern struct iwl_cfg iwl105_bgn_cfg;
+extern struct iwl_cfg iwl135_bg_cfg;
+extern struct iwl_cfg iwl135_bgn_cfg;
+
+#endif /* __iwl_pci_h__ */
index cb06196e0e8034cd7563e173c5d3a2962f9d7854..64593aa03ad6892b0ff5ce10374beeecce233c6f 100644 (file)
@@ -3213,12 +3213,7 @@ enum iwl_ucode_calib_cfg {
                                        IWL_CALIB_CFG_LO_IDX |          \
                                        IWL_CALIB_CFG_TX_IQ_IDX |       \
                                        IWL_CALIB_CFG_RX_IQ_IDX |       \
-                                       IWL_CALIB_CFG_NOISE_IDX |       \
-                                       IWL_CALIB_CFG_CRYSTAL_IDX |     \
-                                       IWL_CALIB_CFG_TEMPERATURE_IDX | \
-                                       IWL_CALIB_CFG_PAPD_IDX |        \
-                                       IWL_CALIB_CFG_SENSITIVITY_IDX | \
-                                       IWL_CALIB_CFG_TX_PWR_IDX)
+                                       IWL_CALIB_CFG_CRYSTAL_IDX)
 
 #define IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK      cpu_to_le32(BIT(0))
 
@@ -3268,6 +3263,14 @@ struct iwl_calib_temperature_offset_cmd {
        __le16 reserved;
 } __packed;
 
+struct iwl_calib_temperature_offset_v2_cmd {
+       struct iwl_calib_hdr hdr;
+       __le16 radio_sensor_offset_high;
+       __le16 radio_sensor_offset_low;
+       __le16 burntVoltageRef;
+       __le16 reserved;
+} __packed;
+
 /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
 struct iwl_calib_chain_noise_reset_cmd {
        struct iwl_calib_hdr hdr;
index 20dd1a5506ed82762bac0011c9c9919426fd9562..cea6520fafdb27789de270af3357e7b8739409d5 100644 (file)
@@ -818,8 +818,9 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 void iwl_print_rx_config_cmd(struct iwl_priv *priv,
-                            struct iwl_rxon_context *ctx)
+                            enum iwl_rxon_context_id ctxid)
 {
+       struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
        struct iwl_rxon_cmd *rxon = &ctx->staging;
 
        IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
@@ -868,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
         * commands by clearing the ready bit */
        clear_bit(STATUS_READY, &priv->shrd->status);
 
-       wake_up_interruptible(&priv->wait_command_queue);
+       wake_up(&priv->shrd->wait_command_queue);
 
        if (!ondemand) {
                /*
@@ -1327,7 +1328,13 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->shrd->mutex);
 
-       WARN_ON(ctx->vif != vif);
+       if (WARN_ON(ctx->vif != vif)) {
+               struct iwl_rxon_context *tmp;
+               IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
+               for_each_context(priv, tmp)
+                       IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
+                               tmp->ctxid, tmp, tmp->vif);
+       }
        ctx->vif = NULL;
 
        iwl_teardown_interface(priv, vif, false);
@@ -1802,13 +1809,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
                return 0;
 
        quot = (usec / interval) &
-               (iwl_beacon_time_mask_high(priv,
-               hw_params(priv).beacon_time_tsf_bits) >>
-               hw_params(priv).beacon_time_tsf_bits);
+               (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
+               IWLAGN_EXT_BEACON_TIME_POS);
        rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
-                                  hw_params(priv).beacon_time_tsf_bits);
+                                  IWLAGN_EXT_BEACON_TIME_POS);
 
-       return (quot << hw_params(priv).beacon_time_tsf_bits) + rem;
+       return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
 }
 
 /* base is usually what we get from ucode with each received frame,
@@ -1818,22 +1824,22 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
                           u32 addon, u32 beacon_interval)
 {
        u32 base_low = base & iwl_beacon_time_mask_low(priv,
-                               hw_params(priv).beacon_time_tsf_bits);
+                               IWLAGN_EXT_BEACON_TIME_POS);
        u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
-                               hw_params(priv).beacon_time_tsf_bits);
+                               IWLAGN_EXT_BEACON_TIME_POS);
        u32 interval = beacon_interval * TIME_UNIT;
        u32 res = (base & iwl_beacon_time_mask_high(priv,
-                               hw_params(priv).beacon_time_tsf_bits)) +
+                               IWLAGN_EXT_BEACON_TIME_POS)) +
                                (addon & iwl_beacon_time_mask_high(priv,
-                               hw_params(priv).beacon_time_tsf_bits));
+                               IWLAGN_EXT_BEACON_TIME_POS));
 
        if (base_low > addon_low)
                res += base_low - addon_low;
        else if (base_low < addon_low) {
                res += interval + base_low - addon_low;
-               res += (1 << hw_params(priv).beacon_time_tsf_bits);
+               res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
        } else
-               res += (1 << hw_params(priv).beacon_time_tsf_bits);
+               res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
 
        return cpu_to_le32(res);
 }
@@ -1842,7 +1848,7 @@ void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
                                 enum iwl_rxon_context_id ctx,
                                 u8 sta_id, u8 tid)
 {
-       struct ieee80211_vif *vif = priv->contexts[ctx].vif;
+       struct ieee80211_vif *vif;
        u8 *addr = priv->stations[sta_id].sta.sta.addr;
 
        if (ctx == NUM_IWL_RXON_CTX)
@@ -1865,3 +1871,33 @@ void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
 
        ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
 }
+
+void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
+{
+       wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
+}
+
+void iwl_nic_config(struct iwl_priv *priv)
+{
+       priv->cfg->lib->nic_config(priv);
+
+}
+
+void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info;
+
+       info = IEEE80211_SKB_CB(skb);
+       kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+       dev_kfree_skb_any(skb);
+}
+
+void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac)
+{
+       ieee80211_stop_queue(priv->hw, ac);
+}
+
+void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac)
+{
+       ieee80211_wake_queue(priv->hw, ac);
+}
index 2ea8a2e0dfbc57268767bc6e2a5bc87b6d277636..74d4cff09faec02b3bb3bfed7c9d731d4f4d0e30 100644 (file)
@@ -73,8 +73,6 @@ struct iwl_cmd;
 
 #define TIME_UNIT              1024
 
-#define IWL_CMD(x) case x: return #x
-
 struct iwl_lib_ops {
        /* set hw dependent parameters */
        int (*set_hw_params)(struct iwl_priv *priv);
@@ -126,7 +124,6 @@ struct iwl_base_params {
        const u16 max_ll_items;
        const bool shadow_ram_support;
        u16 led_compensation;
-       int chain_noise_num_beacons;
        bool adv_thermal_throttle;
        bool support_ct_kill_exit;
        const bool support_wimax_coexist;
@@ -196,6 +193,7 @@ struct iwl_ht_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @iq_invert: I/Q inversion
+ * @temp_offset_v2: support v2 of temperature offset calibration
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -233,6 +231,7 @@ struct iwl_cfg {
        const bool rx_with_siso_diversity;
        const bool internal_wimax_coex;
        const bool iq_invert;
+       const bool temp_offset_v2;
 };
 
 /***************************
@@ -271,7 +270,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw,
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
-void iwl_reset_traffic_log(struct iwl_priv *priv);
 void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
                                u16 length, struct ieee80211_hdr *header);
 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
@@ -332,12 +330,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
                       const u8 *ta, const u8 *ie, int ie_len, int left);
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
-u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
-                             enum ieee80211_band band,
-                             u8 n_probes);
-u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
-                              enum ieee80211_band band,
-                              struct ieee80211_vif *vif);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
 int __must_check iwl_scan_initiate(struct iwl_priv *priv,
@@ -360,26 +352,12 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
  *   S e n d i n g     H o s t     C o m m a n d s   *
  *****************************************************/
 
-const char *get_cmd_string(u8 cmd);
 void iwl_bg_watchdog(unsigned long data);
 u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
 __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
                           u32 addon, u32 beacon_interval);
 
 
-/*****************************************************
-*  Error Handling Debugging
-******************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv,
-                            struct iwl_rxon_context *ctx);
-#else
-static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
-                                          struct iwl_rxon_context *ctx)
-{
-}
-#endif
-
 /*****************************************************
 *  GEOS
 ******************************************************/
@@ -389,8 +367,6 @@ void iwl_free_geos(struct iwl_priv *priv);
 extern void iwl_send_bt_config(struct iwl_priv *priv);
 extern int iwl_send_statistics_request(struct iwl_priv *priv,
                                       u8 flags, bool clear);
-void iwl_apm_stop(struct iwl_priv *priv);
-int iwl_apm_init(struct iwl_priv *priv);
 
 int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 
@@ -408,7 +384,4 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
 
 extern bool bt_siso_mode;
 
-
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
-
 #endif /* __iwl_core_h__ */
index d6dbb04230453a3c1595f28673fc8fabf8d8179a..b9f3267e720cb3c9b9d14b75fa6331555576823e 100644 (file)
  */
 #define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
 
+/**********************************************************
+ * CSR values
+ **********************************************************/
+ /*
+ * host interrupt timeout value
+ * used with setting interrupt coalescing timer
+ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
+ *
+ * default interrupt coalescing timer is 64 x 32 = 2048 usecs
+ * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
+ */
+#define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
+#define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
+#define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
+#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
+
 #endif /* !__iwl_csr_h__ */
index e320cc10167ed06c772f538009d86485c549a4ab..bf2a678970a9a08ada4efe209a53d491fece370b 100644 (file)
                goto err;                                               \
 } while (0)
 
+#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do {                  \
+       struct dentry *__tmp;                                           \
+       __tmp = debugfs_create_u32(#name, mode,                         \
+                                  parent, ptr);                        \
+       if (IS_ERR(__tmp) || !__tmp)                                    \
+               goto err;                                               \
+} while (0)
+
 /* file operation */
 #define DEBUGFS_READ_FUNC(name)                                         \
 static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
@@ -804,6 +812,89 @@ DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
 DEBUGFS_READ_FILE_OPS(current_sleep_command);
 
+static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       int pos = 0, ofs = 0;
+       int cnt = 0, entry;
+
+       char *buf;
+       int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+               (hw_params(priv).max_txq_num * 32 * 8) + 400;
+       const u8 *ptr;
+       ssize_t ret;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IWL_ERR(priv, "Can not allocate buffer\n");
+               return -ENOMEM;
+       }
+       if (priv->tx_traffic &&
+               (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
+               ptr = priv->tx_traffic;
+               pos += scnprintf(buf + pos, bufsz - pos,
+                               "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
+               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+                            entry++,  ofs += 16) {
+                               pos += scnprintf(buf + pos, bufsz - pos,
+                                               "0x%.4x ", ofs);
+                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+                                                  buf + pos, bufsz - pos, 0);
+                               pos += strlen(buf + pos);
+                               if (bufsz - pos > 0)
+                                       buf[pos++] = '\n';
+                       }
+               }
+       }
+
+       if (priv->rx_traffic &&
+               (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
+               ptr = priv->rx_traffic;
+               pos += scnprintf(buf + pos, bufsz - pos,
+                               "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
+               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+                            entry++,  ofs += 16) {
+                               pos += scnprintf(buf + pos, bufsz - pos,
+                                               "0x%.4x ", ofs);
+                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+                                                  buf + pos, bufsz - pos, 0);
+                               pos += strlen(buf + pos);
+                               if (bufsz - pos > 0)
+                                       buf[pos++] = '\n';
+                       }
+               }
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       char buf[8];
+       int buf_size;
+       int traffic_log;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &traffic_log) != 1)
+               return -EFAULT;
+       if (traffic_log == 0)
+               iwl_reset_traffic_log(priv);
+
+       return count;
+}
+
 static const char *fmt_value = "  %-30s %10u\n";
 static const char *fmt_hex   = "  %-30s       0x%02X\n";
 static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
@@ -2146,8 +2237,8 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
 
 static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
                                        char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
+                                       size_t count, loff_t *ppos)
+{
        struct iwl_priv *priv = file->private_data;
        int i, pos = 0;
        char buf[300];
@@ -2226,8 +2317,8 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
 
 static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
                                        const char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
+                                       size_t count, loff_t *ppos)
+{
        struct iwl_priv *priv = file->private_data;
        char buf[8];
        int buf_size;
@@ -2340,6 +2431,7 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
 
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
 DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
 DEBUGFS_READ_FILE_OPS(ucode_general_stats);
@@ -2361,6 +2453,52 @@ DEBUGFS_READ_FILE_OPS(bt_traffic);
 DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
 DEBUGFS_READ_FILE_OPS(reply_tx_error);
 
+#ifdef CONFIG_IWLWIFI_DEBUG
+static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
+                                         char __user *user_buf,
+                                         size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       struct iwl_shared *shrd = priv->shrd;
+       char buf[11];
+       int len;
+
+       len = scnprintf(buf, sizeof(buf), "0x%.8x",
+                       iwl_get_debug_level(shrd));
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
+                                          const char __user *user_buf,
+                                          size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       struct iwl_shared *shrd = priv->shrd;
+       char buf[11];
+       unsigned long val;
+       int ret;
+
+       if (count > sizeof(buf))
+               return -EINVAL;
+
+       memset(buf, 0, sizeof(buf));
+       if (copy_from_user(buf, user_buf, count))
+               return -EFAULT;
+
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       shrd->dbg_level_dev = val;
+       if (iwl_alloc_traffic_mem(priv))
+               IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+       return count;
+}
+DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
 /*
  * Create the debugfs files and directories
  *
@@ -2398,8 +2536,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_U32(temperature, dir_data, &priv->temperature, S_IRUSR);
+
        DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
@@ -2411,7 +2552,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
-
        DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
@@ -2422,6 +2562,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
        if (iwl_advanced_bt_coexist(priv))
                DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
+#ifdef CONFIG_IWLWIFI_DEBUG
+       DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
+#endif
+
        DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
                         &priv->disable_sens_cal);
        DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
@@ -2449,6 +2593,3 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
        debugfs_remove_recursive(priv->debugfs_dir);
        priv->debugfs_dir = NULL;
 }
-
-
-
index 1e54293532b0f1f0d4aac3925af1c86d5a7fe69a..4ddaf2c63f50071c06f28a08452b1036f602ab24 100644 (file)
@@ -32,7 +32,6 @@
 #define __iwl_dev_h__
 
 #include <linux/interrupt.h>
-#include <linux/pci.h> /* for struct pci_device_id */
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/leds.h>
@@ -89,100 +88,6 @@ struct iwl_tx_queue;
 #define        DEFAULT_SHORT_RETRY_LIMIT 7U
 #define        DEFAULT_LONG_RETRY_LIMIT  4U
 
-/* defined below */
-struct iwl_device_cmd;
-
-struct iwl_cmd_meta {
-       /* only for SYNC commands, iff the reply skb is wanted */
-       struct iwl_host_cmd *source;
-       /*
-        * only for ASYNC commands
-        * (which is somewhat stupid -- look at iwl-sta.c for instance
-        * which duplicates a bunch of code because the callback isn't
-        * invoked for SYNC commands, if it were and its result passed
-        * through it would be simpler...)
-        */
-       void (*callback)(struct iwl_priv *priv,
-                        struct iwl_device_cmd *cmd,
-                        struct iwl_rx_packet *pkt);
-
-       u32 flags;
-
-       DEFINE_DMA_UNMAP_ADDR(mapping);
-       DEFINE_DMA_UNMAP_LEN(len);
-};
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues.
- *
- * Note the difference between n_bd and n_window: the hardware
- * always assumes 256 descriptors, so n_bd is always 256 (unless
- * there might be HW changes in the future). For the normal TX
- * queues, n_window, which is the size of the software queue data
- * is also 256; however, for the command queue, n_window is only
- * 32 since we don't need so many commands pending. Since the HW
- * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
- * the software buffers (in the variables @meta, @txb in struct
- * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
- * in the same struct) have 256.
- * This means that we end up with the following:
- *  HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
- *  SW entries:           | 0      | ... | 31          |
- * where N is a number between 0 and 7. This means that the SW
- * data is a window overlayed over the HW queue.
- */
-struct iwl_queue {
-       int n_bd;              /* number of BDs in this queue */
-       int write_ptr;       /* 1-st empty entry (index) host_w*/
-       int read_ptr;         /* last used entry (index) host_r*/
-       /* use for monitoring and recovering the stuck queue */
-       dma_addr_t dma_addr;   /* physical addr for BD's */
-       int n_window;          /* safe queue window */
-       u32 id;
-       int low_mark;          /* low watermark, resume queue if free
-                               * space more than this */
-       int high_mark;         /* high watermark, stop queue if free
-                               * space less than this */
-};
-
-/**
- * struct iwl_tx_queue - Tx Queue for DMA
- * @q: generic Rx/Tx queue descriptor
- * @bd: base of circular buffer of TFDs
- * @cmd: array of command/TX buffer pointers
- * @meta: array of meta data for each command/tx buffer
- * @dma_addr_cmd: physical address of cmd/tx buffer array
- * @txb: array of per-TFD driver data
- * @time_stamp: time (in jiffies) of last read_ptr change
- * @need_update: indicates need to update read/write index
- * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
- * @sta_id: valid if sched_retry is set
- * @tid: valid if sched_retry is set
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- */
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-struct iwl_tx_queue {
-       struct iwl_queue q;
-       struct iwl_tfd *tfds;
-       struct iwl_device_cmd **cmd;
-       struct iwl_cmd_meta *meta;
-       struct sk_buff **skbs;
-       unsigned long time_stamp;
-       u8 need_update;
-       u8 sched_retry;
-       u8 active;
-       u8 swq_id;
-
-       u16 sta_id;
-       u16 tid;
-};
-
 #define IWL_NUM_SCAN_RATES         (2)
 
 /*
@@ -212,21 +117,6 @@ struct iwl_channel_info {
        u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
 };
 
-#define IWL_TX_FIFO_BK         0       /* shared */
-#define IWL_TX_FIFO_BE         1
-#define IWL_TX_FIFO_VI         2       /* shared */
-#define IWL_TX_FIFO_VO         3
-#define IWL_TX_FIFO_BK_IPAN    IWL_TX_FIFO_BK
-#define IWL_TX_FIFO_BE_IPAN    4
-#define IWL_TX_FIFO_VI_IPAN    IWL_TX_FIFO_VI
-#define IWL_TX_FIFO_VO_IPAN    5
-/* re-uses the VO FIFO, uCode will properly flush/schedule */
-#define IWL_TX_FIFO_AUX                5
-#define IWL_TX_FIFO_UNUSED     -1
-
-/* AUX (TX during scan dwell) queue */
-#define IWL_AUX_QUEUE          10
-
 /*
  * Minimum number of queues. MAX_NUM is defined in hw specific files.
  * Set the minimum to accommodate
@@ -249,70 +139,6 @@ struct iwl_channel_info {
 #define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
 #define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
 
-
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-enum {
-       CMD_SYNC = 0,
-       CMD_ASYNC = BIT(0),
-       CMD_WANT_SKB = BIT(1),
-       CMD_ON_DEMAND = BIT(2),
-};
-
-#define DEF_CMD_PAYLOAD_SIZE 320
-
-/**
- * struct iwl_device_cmd
- *
- * For allocation of the command and tx queues, this establishes the overall
- * size of the largest command we send to uCode, except for commands that
- * aren't fully copied and use other TFD space.
- */
-struct iwl_device_cmd {
-       struct iwl_cmd_header hdr;      /* uCode API */
-       union {
-               u32 flags;
-               u8 val8;
-               u16 val16;
-               u32 val32;
-               struct iwl_tx_cmd tx;
-               struct iwl6000_channel_switch_cmd chswitch;
-               u8 payload[DEF_CMD_PAYLOAD_SIZE];
-       } __packed cmd;
-} __packed;
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
-
-#define IWL_MAX_CMD_TFDS       2
-
-enum iwl_hcmd_dataflag {
-       IWL_HCMD_DFL_NOCOPY     = BIT(0),
-};
-
-/**
- * struct iwl_host_cmd - Host command to the uCode
- * @data: array of chunks that composes the data of the host command
- * @reply_page: pointer to the page that holds the response to the host command
- * @callback:
- * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
- * @len: array of the lenths of the chunks in data
- * @dataflags:
- * @id: id of the host command
- */
-struct iwl_host_cmd {
-       const void *data[IWL_MAX_CMD_TFDS];
-       unsigned long reply_page;
-       void (*callback)(struct iwl_priv *priv,
-                        struct iwl_device_cmd *cmd,
-                        struct iwl_rx_packet *pkt);
-       u32 flags;
-       u16 len[IWL_MAX_CMD_TFDS];
-       u8 dataflags[IWL_MAX_CMD_TFDS];
-       u8 id;
-};
-
 #define SUP_RATE_11A_MAX_NUM_CHANNELS  8
 #define SUP_RATE_11B_MAX_NUM_CHANNELS  4
 #define SUP_RATE_11G_MAX_NUM_CHANNELS  12
@@ -376,11 +202,6 @@ struct iwl_station_entry {
        struct iwl_link_quality_cmd *lq;
 };
 
-struct iwl_station_priv_common {
-       struct iwl_rxon_context *ctx;
-       u8 sta_id;
-};
-
 /*
  * iwl_station_priv: Driver's private station information
  *
@@ -389,12 +210,13 @@ struct iwl_station_priv_common {
  * space.
  */
 struct iwl_station_priv {
-       struct iwl_station_priv_common common;
+       struct iwl_rxon_context *ctx;
        struct iwl_lq_sta lq_sta;
        atomic_t pending_frames;
        bool client;
        bool asleep;
        u8 max_agg_bufsize;
+       u8 sta_id;
 };
 
 /**
@@ -580,9 +402,6 @@ extern const u8 iwl_bcast_addr[ETH_ALEN];
 #define IWL_OPERATION_MODE_MIXED    2
 #define IWL_OPERATION_MODE_20MHZ    3
 
-#define IWL_TX_CRC_SIZE 4
-#define IWL_TX_DELIMITER_SIZE 4
-
 #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
 
 /* Sensitivity and chain noise calibration */
@@ -706,9 +525,6 @@ struct iwl_chain_noise_data {
 #define        EEPROM_SEM_TIMEOUT 10           /* milliseconds */
 #define EEPROM_SEM_RETRY_LIMIT 1000    /* number of attempts (not time) */
 
-#define IWL_TRAFFIC_ENTRIES    (256)
-#define IWL_TRAFFIC_ENTRY_SIZE  (64)
-
 enum {
        MEASUREMENT_READY = (1 << 0),
        MEASUREMENT_ACTIVE = (1 << 1),
@@ -849,21 +665,6 @@ struct iwl_event_log {
        int wraps_more_count;
 };
 
-/*
- * host interrupt timeout value
- * used with setting interrupt coalescing timer
- * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
- *
- * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
- */
-#define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
-#define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
-#define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
-
 /*
  * This is the threshold value of plcp error rate per 100mSecs.  It is
  * used to set and check for the validity of plcp_delta.
@@ -1040,8 +841,9 @@ struct iwl_priv {
 
        void (*pre_rx_handler)(struct iwl_priv *priv,
                               struct iwl_rx_mem_buffer *rxb);
-       void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
-                                      struct iwl_rx_mem_buffer *rxb);
+       int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+                                      struct iwl_rx_mem_buffer *rxb,
+                                      struct iwl_device_cmd *cmd);
 
        struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
 
@@ -1095,9 +897,6 @@ struct iwl_priv {
        /*TODO: remove these pointers - use bus(priv) instead */
        struct iwl_bus *bus;    /* bus specific data */
 
-       /* microcode/device supports multiple contexts */
-       u8 valid_contexts;
-
        /* max number of station keys */
        u8 sta_key_max_num;
 
@@ -1142,8 +941,6 @@ struct iwl_priv {
        /* Rate scaling data */
        u8 retry_rate;
 
-       wait_queue_head_t wait_command_queue;
-
        int activity_timer_active;
 
        /* counts mgmt, ctl, and data packets */
@@ -1158,6 +955,8 @@ struct iwl_priv {
        struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
        unsigned long ucode_key_table;
 
+       u8 mac80211_registered;
+
        /* Indication if ieee80211_ops->open has been called */
        u8 is_open;
 
@@ -1231,7 +1030,7 @@ struct iwl_priv {
        struct delayed_work hw_roc_disable_work;
        enum nl80211_channel_type hw_roc_chantype;
        int hw_roc_duration;
-       bool hw_roc_setup;
+       bool hw_roc_setup, hw_roc_start_notified;
 
        /* bt coex */
        u8 bt_enable_flag;
@@ -1327,7 +1126,7 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
 #define for_each_context(priv, ctx)                            \
        for (ctx = &priv->contexts[IWL_RXON_CTX_BSS];           \
             ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++)    \
-               if (priv->valid_contexts & BIT(ctx->ctxid))
+               if (priv->shrd->valid_contexts & BIT(ctx->ctxid))
 
 static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
 {
index 80ee65be9cd19b1db9f3f395bfea2bdc40a66941..0b669417b0a604f4928f1c559af4322788e20aca 100644 (file)
@@ -72,6 +72,7 @@
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
+#include "iwl-agn.h"
 #include "iwl-eeprom.h"
 #include "iwl-io.h"
 
@@ -138,7 +139,7 @@ static const u8 iwl_eeprom_band_7[] = {       /* 5.2 ht40 channel */
 
 /******************************************************************************
  *
- * EEPROM related functions
+ * generic NVM functions
  *
 ******************************************************************************/
 
@@ -214,6 +215,93 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
        return ret;
 }
 
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+{
+       if (!priv->eeprom)
+               return 0;
+       return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+}
+
+int iwl_eeprom_check_version(struct iwl_priv *priv)
+{
+       u16 eeprom_ver;
+       u16 calib_ver;
+
+       eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+       calib_ver = iwlagn_eeprom_calib_version(priv);
+
+       if (eeprom_ver < priv->cfg->eeprom_ver ||
+           calib_ver < priv->cfg->eeprom_calib_ver)
+               goto err;
+
+       IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+                eeprom_ver, calib_ver);
+
+       return 0;
+err:
+       IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+                 "CALIB=0x%x < 0x%x\n",
+                 eeprom_ver, priv->cfg->eeprom_ver,
+                 calib_ver,  priv->cfg->eeprom_calib_ver);
+       return -EINVAL;
+
+}
+
+int iwl_eeprom_check_sku(struct iwl_priv *priv)
+{
+       u16 radio_cfg;
+
+       if (!priv->cfg->sku) {
+               /* not using sku overwrite */
+               priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+               if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+                   !priv->cfg->ht_params) {
+                       IWL_ERR(priv, "Invalid 11n configuration\n");
+                       return -EINVAL;
+               }
+       }
+       if (!priv->cfg->sku) {
+               IWL_ERR(priv, "Invalid device sku\n");
+               return -EINVAL;
+       }
+
+       IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
+
+       if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
+               /* not using .cfg overwrite */
+               radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+               priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+               priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+               if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
+                       IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
+                               priv->cfg->valid_tx_ant,
+                               priv->cfg->valid_rx_ant);
+                       return -EINVAL;
+               }
+               IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
+                        priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
+       }
+       /*
+        * for some special cases,
+        * EEPROM did not reflect the correct antenna setting
+        * so overwrite the valid tx/rx antenna from .cfg
+        */
+       return 0;
+}
+
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+       const u8 *addr = iwl_eeprom_query_addr(priv,
+                                       EEPROM_MAC_ADDRESS);
+       memcpy(mac, addr, ETH_ALEN);
+}
+
+/******************************************************************************
+ *
+ * OTP related functions
+ *
+******************************************************************************/
+
 static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
 {
        iwl_read32(bus(priv), CSR_OTP_GP_REG);
@@ -407,11 +495,152 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
        return -EINVAL;
 }
 
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+/******************************************************************************
+ *
+ * Tx Power related functions
+ *
+******************************************************************************/
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ *     find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+               struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+               int element, s8 *max_txpower_in_half_dbm)
 {
-       if (!priv->eeprom)
-               return 0;
-       return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+       s8 max_txpower_avg = 0; /* (dBm) */
+
+       /* Take the highest tx power from any valid chains */
+       if ((priv->cfg->valid_tx_ant & ANT_A) &&
+           (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+               max_txpower_avg = enhanced_txpower[element].chain_a_max;
+       if ((priv->cfg->valid_tx_ant & ANT_B) &&
+           (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+               max_txpower_avg = enhanced_txpower[element].chain_b_max;
+       if ((priv->cfg->valid_tx_ant & ANT_C) &&
+           (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+               max_txpower_avg = enhanced_txpower[element].chain_c_max;
+       if (((priv->cfg->valid_tx_ant == ANT_AB) |
+           (priv->cfg->valid_tx_ant == ANT_BC) |
+           (priv->cfg->valid_tx_ant == ANT_AC)) &&
+           (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+               max_txpower_avg =  enhanced_txpower[element].mimo2_max;
+       if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+           (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+               max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+       /*
+        * max. tx power in EEPROM is in 1/2 dBm format
+        * convert from 1/2 dBm to dBm (round-up convert)
+        * but we also do not want to loss 1/2 dBm resolution which
+        * will impact performance
+        */
+       *max_txpower_in_half_dbm = max_txpower_avg;
+       return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
+}
+
+static void
+iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
+                                   struct iwl_eeprom_enhanced_txpwr *txp,
+                                   s8 max_txpower_avg)
+{
+       int ch_idx;
+       bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
+       enum ieee80211_band band;
+
+       band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
+               IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
+
+       for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
+               struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
+
+               /* update matching channel or from common data only */
+               if (txp->channel != 0 && ch_info->channel != txp->channel)
+                       continue;
+
+               /* update matching band only */
+               if (band != ch_info->band)
+                       continue;
+
+               if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
+                       ch_info->max_power_avg = max_txpower_avg;
+                       ch_info->curr_txpow = max_txpower_avg;
+                       ch_info->scan_power = max_txpower_avg;
+               }
+
+               if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
+                       ch_info->ht40_max_power_avg = max_txpower_avg;
+       }
+}
+
+#define EEPROM_TXP_OFFS        (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
+#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
+#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
+
+#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
+                           ? # x " " : "")
+
+void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+       struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
+       int idx, entries;
+       __le16 *txp_len;
+       s8 max_txp_avg, max_txp_avg_halfdbm;
+
+       BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
+
+       /* the length is in 16-bit words, but we want entries */
+       txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+       entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
+
+       txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+
+       for (idx = 0; idx < entries; idx++) {
+               txp = &txp_array[idx];
+               /* skip invalid entries */
+               if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
+                       continue;
+
+               IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
+                                (txp->channel && (txp->flags &
+                                       IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
+                                       "Common " : (txp->channel) ?
+                                       "Channel" : "Common",
+                                (txp->channel),
+                                TXP_CHECK_AND_PRINT(VALID),
+                                TXP_CHECK_AND_PRINT(BAND_52G),
+                                TXP_CHECK_AND_PRINT(OFDM),
+                                TXP_CHECK_AND_PRINT(40MHZ),
+                                TXP_CHECK_AND_PRINT(HT_AP),
+                                TXP_CHECK_AND_PRINT(RES1),
+                                TXP_CHECK_AND_PRINT(RES2),
+                                TXP_CHECK_AND_PRINT(COMMON_TYPE),
+                                txp->flags);
+               IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
+                                "chain_B: 0X%02x chain_C: 0X%02x\n",
+                                txp->chain_a_max, txp->chain_b_max,
+                                txp->chain_c_max);
+               IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
+                                "MIMO3: 0x%02x High 20_on_40: 0x%02x "
+                                "Low 20_on_40: 0x%02x\n",
+                                txp->mimo2_max, txp->mimo3_max,
+                                ((txp->delta_20_in_40 & 0xf0) >> 4),
+                                (txp->delta_20_in_40 & 0x0f));
+
+               max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
+                                                     &max_txp_avg_halfdbm);
+
+               /*
+                * Update the user limit values values to the highest
+                * power supported by any channel
+                */
+               if (max_txp_avg > priv->tx_power_user_lmt)
+                       priv->tx_power_user_lmt = max_txp_avg;
+               if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
+                       priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
+
+               iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
+       }
 }
 
 /**
index e2b5e0ea5d9cf4dd26019a0ad8de87a8c2dcf2e1..c94747e7299e234a77b71b27af47cf73ae235495 100644 (file)
@@ -163,11 +163,19 @@ struct iwl_eeprom_enhanced_txpwr {
 } __packed;
 
 /* calibration */
+struct iwl_eeprom_calib_hdr {
+       u8 version;
+       u8 pa_type;
+       __le16 voltage;
+} __packed;
+
 #define EEPROM_CALIB_ALL       (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
 #define EEPROM_XTAL            ((2*0x128) | EEPROM_CALIB_ALL)
 
 /* temperature */
-#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+#define EEPROM_KELVIN_TEMPERATURE      ((2*0x12A) | EEPROM_CALIB_ALL)
+#define EEPROM_RAW_TEMPERATURE         ((2*0x12B) | EEPROM_CALIB_ALL)
+
 
 /* agn links */
 #define EEPROM_LINK_HOST             (2*0x64)
index d3feac9e45b403f1de8360019c926a7f9e7cd08f..968fc66e3506ebcf77487ed68afbfb6da314b700 100644 (file)
 
 #include "iwl-io.h"
 
-#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
-
-
 static inline struct ieee80211_conf *ieee80211_get_hw_conf(
        struct ieee80211_hw *hw)
 {
        return &hw->conf;
 }
 
-/**
- * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
-{
-       return ++index & (n_bd - 1);
-}
-
-/**
- * iwl_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
-{
-       return --index & (n_bd - 1);
-}
-
 static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
 {
        IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
index 7dffed186f0a5f5abf21ee4090aa5b09b458e730..f149165e801075aca13d9865bfd9b2a35ec3368f 100644 (file)
@@ -104,7 +104,6 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
                .len = { sizeof(struct iwl_led_cmd), },
                .data = { led_cmd, },
                .flags = CMD_ASYNC,
-               .callback = NULL,
        };
        u32 reg;
 
index e41f53e5c307e702924fb23b349e4d4bf9de5073..1d7bb7423f94b2ebfec2b854dff8eed3d6879f7e 100644 (file)
@@ -68,7 +68,7 @@
 #include "iwl-shared.h"
 #include "iwl-trans.h"
 #include "iwl-csr.h"
-#include "iwl-pci.h"
+#include "iwl-cfg.h"
 
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
@@ -134,12 +134,6 @@ static void iwl_pci_apm_config(struct iwl_bus *bus)
        }
 }
 
-static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd)
-{
-       bus->shrd = shrd;
-       pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd);
-}
-
 static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
                              int buf_len)
 {
@@ -168,7 +162,6 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
 static const struct iwl_bus_ops bus_ops_pci = {
        .get_pm_support = iwl_pci_is_pm_supported,
        .apm_config = iwl_pci_apm_config,
-       .set_drv_data = iwl_pci_set_drv_data,
        .get_hw_id = iwl_pci_get_hw_id,
        .write8 = iwl_pci_write8,
        .write32 = iwl_pci_write32,
@@ -260,6 +253,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
        {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
        {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
 
 /* 6x30 Series */
        {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
@@ -392,6 +386,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_bus = IWL_BUS_GET_PCI_BUS(bus);
        pci_bus->pci_dev = pdev;
 
+       pci_set_drvdata(pdev, bus);
+
        /* W/A - seems to solve weird behavior. We need to remove this if we
         * don't want to stay in L1 all the time. This wastes a lot of power */
        pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
@@ -483,27 +479,22 @@ out_no_pci:
        return err;
 }
 
-static void iwl_pci_down(struct iwl_bus *bus)
-{
-       struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific;
-
-       pci_disable_msi(pci_bus->pci_dev);
-       pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
-       pci_release_regions(pci_bus->pci_dev);
-       pci_disable_device(pci_bus->pci_dev);
-       pci_set_drvdata(pci_bus->pci_dev, NULL);
-
-       kfree(bus);
-}
-
 static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 {
-       struct iwl_shared *shrd = pci_get_drvdata(pdev);
-       struct iwl_bus *bus = shrd->bus;
+       struct iwl_bus *bus = pci_get_drvdata(pdev);
+       struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus);
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+       struct iwl_shared *shrd = bus->shrd;
 
        iwl_remove(shrd->priv);
 
-       iwl_pci_down(bus);
+       pci_disable_msi(pci_dev);
+       pci_iounmap(pci_dev, pci_bus->hw_base);
+       pci_release_regions(pci_dev);
+       pci_disable_device(pci_dev);
+       pci_set_drvdata(pci_dev, NULL);
+
+       kfree(bus);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -511,7 +502,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 static int iwl_pci_suspend(struct device *device)
 {
        struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_shared *shrd = pci_get_drvdata(pdev);
+       struct iwl_bus *bus = pci_get_drvdata(pdev);
+       struct iwl_shared *shrd = bus->shrd;
 
        /* Before you put code here, think about WoWLAN. You cannot check here
         * whether WoWLAN is enabled or not, and your code will run even if
@@ -524,7 +516,8 @@ static int iwl_pci_suspend(struct device *device)
 static int iwl_pci_resume(struct device *device)
 {
        struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_shared *shrd = pci_get_drvdata(pdev);
+       struct iwl_bus *bus = pci_get_drvdata(pdev);
+       struct iwl_shared *shrd = bus->shrd;
 
        /* Before you put code here, think about WoWLAN. You cannot check here
         * whether WoWLAN is enabled or not, and your code will run even if
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h
deleted file mode 100644 (file)
index c0aea9e..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <[email protected]>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-#ifndef __iwl_pci_h__
-#define __iwl_pci_h__
-
-
-/* This file includes the declaration that are internal to the PCI
- * implementation of the bus layer
- */
-
-/* configuration for the _agn devices */
-extern struct iwl_cfg iwl5300_agn_cfg;
-extern struct iwl_cfg iwl5100_agn_cfg;
-extern struct iwl_cfg iwl5350_agn_cfg;
-extern struct iwl_cfg iwl5100_bgn_cfg;
-extern struct iwl_cfg iwl5100_abg_cfg;
-extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl5150_abg_cfg;
-extern struct iwl_cfg iwl6005_2agn_cfg;
-extern struct iwl_cfg iwl6005_2abg_cfg;
-extern struct iwl_cfg iwl6005_2bg_cfg;
-extern struct iwl_cfg iwl6005_2agn_sff_cfg;
-extern struct iwl_cfg iwl1030_bgn_cfg;
-extern struct iwl_cfg iwl1030_bg_cfg;
-extern struct iwl_cfg iwl6030_2agn_cfg;
-extern struct iwl_cfg iwl6030_2abg_cfg;
-extern struct iwl_cfg iwl6030_2bgn_cfg;
-extern struct iwl_cfg iwl6030_2bg_cfg;
-extern struct iwl_cfg iwl6000i_2agn_cfg;
-extern struct iwl_cfg iwl6000i_2abg_cfg;
-extern struct iwl_cfg iwl6000i_2bg_cfg;
-extern struct iwl_cfg iwl6000_3agn_cfg;
-extern struct iwl_cfg iwl6050_2agn_cfg;
-extern struct iwl_cfg iwl6050_2abg_cfg;
-extern struct iwl_cfg iwl6150_bgn_cfg;
-extern struct iwl_cfg iwl6150_bg_cfg;
-extern struct iwl_cfg iwl1000_bgn_cfg;
-extern struct iwl_cfg iwl1000_bg_cfg;
-extern struct iwl_cfg iwl100_bgn_cfg;
-extern struct iwl_cfg iwl100_bg_cfg;
-extern struct iwl_cfg iwl130_bgn_cfg;
-extern struct iwl_cfg iwl130_bg_cfg;
-extern struct iwl_cfg iwl2000_2bgn_cfg;
-extern struct iwl_cfg iwl2000_2bg_cfg;
-extern struct iwl_cfg iwl2000_2bgn_d_cfg;
-extern struct iwl_cfg iwl2030_2bgn_cfg;
-extern struct iwl_cfg iwl2030_2bg_cfg;
-extern struct iwl_cfg iwl6035_2agn_cfg;
-extern struct iwl_cfg iwl6035_2abg_cfg;
-extern struct iwl_cfg iwl6035_2bg_cfg;
-extern struct iwl_cfg iwl105_bg_cfg;
-extern struct iwl_cfg iwl105_bgn_cfg;
-extern struct iwl_cfg iwl135_bg_cfg;
-extern struct iwl_cfg iwl135_bgn_cfg;
-
-#endif /* __iwl_pci_h__ */
index 8572548dd4a2f6ea24247781709c8943355225ba..bcd7f64683aa02c06ebd1af0e8650ef39d8fdd11 100644 (file)
 #include "iwl-agn.h"
 #include "iwl-shared.h"
 
+const char *get_cmd_string(u8 cmd)
+{
+       switch (cmd) {
+               IWL_CMD(REPLY_ALIVE);
+               IWL_CMD(REPLY_ERROR);
+               IWL_CMD(REPLY_RXON);
+               IWL_CMD(REPLY_RXON_ASSOC);
+               IWL_CMD(REPLY_QOS_PARAM);
+               IWL_CMD(REPLY_RXON_TIMING);
+               IWL_CMD(REPLY_ADD_STA);
+               IWL_CMD(REPLY_REMOVE_STA);
+               IWL_CMD(REPLY_REMOVE_ALL_STA);
+               IWL_CMD(REPLY_TXFIFO_FLUSH);
+               IWL_CMD(REPLY_WEPKEY);
+               IWL_CMD(REPLY_TX);
+               IWL_CMD(REPLY_LEDS_CMD);
+               IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+               IWL_CMD(COEX_PRIORITY_TABLE_CMD);
+               IWL_CMD(COEX_MEDIUM_NOTIFICATION);
+               IWL_CMD(COEX_EVENT_CMD);
+               IWL_CMD(REPLY_QUIET_CMD);
+               IWL_CMD(REPLY_CHANNEL_SWITCH);
+               IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+               IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+               IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+               IWL_CMD(POWER_TABLE_CMD);
+               IWL_CMD(PM_SLEEP_NOTIFICATION);
+               IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+               IWL_CMD(REPLY_SCAN_CMD);
+               IWL_CMD(REPLY_SCAN_ABORT_CMD);
+               IWL_CMD(SCAN_START_NOTIFICATION);
+               IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+               IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+               IWL_CMD(BEACON_NOTIFICATION);
+               IWL_CMD(REPLY_TX_BEACON);
+               IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
+               IWL_CMD(QUIET_NOTIFICATION);
+               IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+               IWL_CMD(MEASURE_ABORT_NOTIFICATION);
+               IWL_CMD(REPLY_BT_CONFIG);
+               IWL_CMD(REPLY_STATISTICS_CMD);
+               IWL_CMD(STATISTICS_NOTIFICATION);
+               IWL_CMD(REPLY_CARD_STATE_CMD);
+               IWL_CMD(CARD_STATE_NOTIFICATION);
+               IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+               IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+               IWL_CMD(SENSITIVITY_CMD);
+               IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+               IWL_CMD(REPLY_RX_PHY_CMD);
+               IWL_CMD(REPLY_RX_MPDU_CMD);
+               IWL_CMD(REPLY_RX);
+               IWL_CMD(REPLY_COMPRESSED_BA);
+               IWL_CMD(CALIBRATION_CFG_CMD);
+               IWL_CMD(CALIBRATION_RES_NOTIFICATION);
+               IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
+               IWL_CMD(REPLY_TX_POWER_DBM_CMD);
+               IWL_CMD(TEMPERATURE_NOTIFICATION);
+               IWL_CMD(TX_ANT_CONFIGURATION_CMD);
+               IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
+               IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
+               IWL_CMD(REPLY_BT_COEX_PROT_ENV);
+               IWL_CMD(REPLY_WIPAN_PARAMS);
+               IWL_CMD(REPLY_WIPAN_RXON);
+               IWL_CMD(REPLY_WIPAN_RXON_TIMING);
+               IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
+               IWL_CMD(REPLY_WIPAN_QOS_PARAM);
+               IWL_CMD(REPLY_WIPAN_WEPKEY);
+               IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
+               IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+               IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
+               IWL_CMD(REPLY_WOWLAN_PATTERNS);
+               IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
+               IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
+               IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
+               IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
+               IWL_CMD(REPLY_WOWLAN_GET_STATUS);
+       default:
+               return "UNKNOWN";
+
+       }
+}
 
 /******************************************************************************
  *
  *
  ******************************************************************************/
 
-static void iwl_rx_reply_error(struct iwl_priv *priv,
-                              struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_error(struct iwl_priv *priv,
+                              struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
@@ -61,9 +143,11 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
                pkt->u.err_resp.cmd_id,
                le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
                le32_to_cpu(pkt->u.err_resp.error_info));
+       return 0;
 }
 
-static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
@@ -75,7 +159,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
 
        if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
-               return;
+               return 0;
 
        if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
                rxon->channel = csa->channel;
@@ -88,11 +172,13 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
                        le16_to_cpu(csa->channel));
                iwl_chswitch_done(priv, false);
        }
+       return 0;
 }
 
 
-static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
-                                         struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
+                                         struct iwl_rx_mem_buffer *rxb,
+                                         struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
@@ -100,15 +186,17 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
        if (!report->state) {
                IWL_DEBUG_11H(priv,
                        "Spectrum Measure Notification: Start\n");
-               return;
+               return 0;
        }
 
        memcpy(&priv->measure_report, report, sizeof(*report));
        priv->measurement_status |= MEASUREMENT_READY;
+       return 0;
 }
 
-static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-                                 struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
+                                 struct iwl_rx_mem_buffer *rxb,
+                                 struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -116,10 +204,12 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
        IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
                     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
 #endif
+       return 0;
 }
 
-static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-                                            struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+                                            struct iwl_rx_mem_buffer *rxb,
+                                            struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        u32 __maybe_unused len =
@@ -128,10 +218,12 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
                        "notification for %s:\n", len,
                        get_cmd_string(pkt->hdr.cmd));
        iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+       return 0;
 }
 
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_beacon_notif(struct iwl_priv *priv,
+                               struct iwl_rx_mem_buffer *rxb,
+                               struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
@@ -152,6 +244,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
 
        if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
                queue_work(priv->shrd->workqueue, &priv->beacon_update);
+       return 0;
 }
 
 /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
@@ -394,8 +487,9 @@ iwl_accumulative_statistics(struct iwl_priv *priv,
 }
 #endif
 
-static void iwl_rx_statistics(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_statistics(struct iwl_priv *priv,
+                             struct iwl_rx_mem_buffer *rxb,
+                             struct iwl_device_cmd *cmd)
 {
        unsigned long stamp = jiffies;
        const int reg_recalib_period = 60;
@@ -449,7 +543,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
                WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
                          len, sizeof(struct iwl_bt_notif_statistics),
                          sizeof(struct iwl_notif_statistics));
-               return;
+               return 0;
        }
 
        change = common->temperature != priv->statistics.common.temperature ||
@@ -492,10 +586,12 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
        }
        if (priv->cfg->lib->temperature && change)
                priv->cfg->lib->temperature(priv);
+       return 0;
 }
 
-static void iwl_rx_reply_statistics(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_statistics(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb,
+                                   struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
@@ -510,13 +606,15 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,
 #endif
                IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
        }
-       iwl_rx_statistics(priv, rxb);
+       iwl_rx_statistics(priv, rxb, cmd);
+       return 0;
 }
 
 /* Handle notification from uCode that card's power state is changing
  * due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_card_state_notif(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb,
+                                   struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
@@ -563,11 +661,13 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
                wiphy_rfkill_set_hw_state(priv->hw->wiphy,
                        test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
        else
-               wake_up_interruptible(&priv->wait_command_queue);
+               wake_up(&priv->shrd->wait_command_queue);
+       return 0;
 }
 
-static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-                                      struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+                                      struct iwl_rx_mem_buffer *rxb,
+                                      struct iwl_device_cmd *cmd)
 
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -585,18 +685,21 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
                if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
                        iwl_init_sensitivity(priv);
        }
+       return 0;
 }
 
 /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
  * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_rx_phy(struct iwl_priv *priv,
+                               struct iwl_rx_mem_buffer *rxb,
+                               struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
        priv->last_phy_res_valid = true;
        memcpy(&priv->last_phy_res, pkt->u.raw,
               sizeof(struct iwl_rx_phy_res));
+       return 0;
 }
 
 /*
@@ -811,8 +914,9 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
 
 /* Called for REPLY_RX (legacy ABG frames), or
  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-static void iwl_rx_reply_rx(struct iwl_priv *priv,
-                           struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_rx(struct iwl_priv *priv,
+                           struct iwl_rx_mem_buffer *rxb,
+                           struct iwl_device_cmd *cmd)
 {
        struct ieee80211_hdr *header;
        struct ieee80211_rx_status rx_status;
@@ -845,7 +949,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
        } else {
                if (!priv->last_phy_res_valid) {
                        IWL_ERR(priv, "MPDU frame without cached PHY data\n");
-                       return;
+                       return 0;
                }
                phy_res = &priv->last_phy_res;
                amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
@@ -859,14 +963,14 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
        if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
                IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
                                phy_res->cfg_phy_cnt);
-               return;
+               return 0;
        }
 
        if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
            !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
                IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
                                le32_to_cpu(rx_pkt_status));
-               return;
+               return 0;
        }
 
        /* This will be used in several places later */
@@ -927,6 +1031,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
 
        iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
                                    rxb, &rx_status);
+       return 0;
 }
 
 /**
@@ -937,7 +1042,8 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
  */
 void iwl_setup_rx_handlers(struct iwl_priv *priv)
 {
-       void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+       int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd);
 
        handlers = priv->rx_handlers;
 
@@ -947,6 +1053,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
        handlers[PM_SLEEP_NOTIFICATION]         = iwl_rx_pm_sleep_notif;
        handlers[PM_DEBUG_STATISTIC_NOTIFIC]    = iwl_rx_pm_debug_statistics_notif;
        handlers[BEACON_NOTIFICATION]           = iwl_rx_beacon_notif;
+       handlers[REPLY_ADD_STA]                 = iwl_add_sta_callback;
 
        /*
         * The same handler is used for both the REPLY to a discrete
@@ -984,9 +1091,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
 
 }
 
-void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                    struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       int err = 0;
 
        /*
         * Do the notification wait before RX handlers so
@@ -1021,11 +1130,12 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
         *   rx_handlers table.  See iwl_setup_rx_handlers() */
        if (priv->rx_handlers[pkt->hdr.cmd]) {
                priv->rx_handlers_stats[pkt->hdr.cmd]++;
-               priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+               err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
        } else {
                /* No handling needed */
                IWL_DEBUG_RX(priv,
                        "No handler needed for %s, 0x%02x\n",
                        get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
        }
+       return err;
 }
index fc5af3475392b7bf897844afe54f241b10def001..2b6db24daf70d6b04b5a6f5fb4e6925751942a39 100644 (file)
@@ -189,8 +189,9 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
 }
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl_rx_reply_scan(struct iwl_priv *priv,
-                             struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_reply_scan(struct iwl_priv *priv,
+                             struct iwl_rx_mem_buffer *rxb,
+                             struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -199,11 +200,13 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
 
        IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
 #endif
+       return 0;
 }
 
 /* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb,
+                                   struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_scanstart_notification *notif =
@@ -218,13 +221,19 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
                       le32_to_cpu(notif->tsf_low),
                       notif->status, notif->beacon_timer);
 
-       if (priv->scan_type == IWL_SCAN_ROC)
+       if (priv->scan_type == IWL_SCAN_ROC &&
+           !priv->hw_roc_start_notified) {
                ieee80211_ready_on_channel(priv->hw);
+               priv->hw_roc_start_notified = true;
+       }
+
+       return 0;
 }
 
 /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
-                                     struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
+                                     struct iwl_rx_mem_buffer *rxb,
+                                     struct iwl_device_cmd *cmd)
 {
 #ifdef CONFIG_IWLWIFI_DEBUG
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -242,11 +251,13 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
                       le32_to_cpu(notif->statistics[0]),
                       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
 #endif
+       return 0;
 }
 
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
-                                      struct iwl_rx_mem_buffer *rxb)
+static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
+                                      struct iwl_rx_mem_buffer *rxb,
+                                      struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
@@ -286,6 +297,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
                queue_work(priv->shrd->workqueue,
                           &priv->bt_traffic_change_work);
        }
+       return 0;
 }
 
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@ -299,9 +311,8 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
                                        iwl_rx_scan_complete_notif;
 }
 
-inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
-                                    enum ieee80211_band band,
-                                    u8 n_probes)
+static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
+                                    enum ieee80211_band band, u8 n_probes)
 {
        if (band == IEEE80211_BAND_5GHZ)
                return IWL_ACTIVE_DWELL_TIME_52 +
@@ -311,35 +322,481 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
                        IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
 
-u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
-                              enum ieee80211_band band,
-                              struct ieee80211_vif *vif)
+static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
 {
        struct iwl_rxon_context *ctx;
+
+       /*
+        * If we're associated, we clamp the dwell time 98%
+        * of the smallest beacon interval (minus 2 * channel
+        * tune time)
+        */
+       for_each_context(priv, ctx) {
+               u16 value;
+
+               if (!iwl_is_associated_ctx(ctx))
+                       continue;
+               value = ctx->beacon_int;
+               if (!value)
+                       value = IWL_PASSIVE_DWELL_BASE;
+               value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+               dwell_time = min(value, dwell_time);
+       }
+
+       return dwell_time;
+}
+
+static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
+                                     enum ieee80211_band band)
+{
        u16 passive = (band == IEEE80211_BAND_2GHZ) ?
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
 
-       if (iwl_is_any_associated(priv)) {
+       return iwl_limit_dwell(priv, passive);
+}
+
+static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
+                                          struct ieee80211_vif *vif,
+                                          enum ieee80211_band band,
+                                          struct iwl_scan_channel *scan_ch)
+{
+       const struct ieee80211_supported_band *sband;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added = 0;
+       u16 channel = 0;
+
+       sband = iwl_get_hw_mode(priv, band);
+       if (!sband) {
+               IWL_ERR(priv, "invalid band\n");
+               return added;
+       }
+
+       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+       channel = iwl_get_single_channel_number(priv, band);
+       if (channel) {
+               scan_ch->channel = cpu_to_le16(channel);
+               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* Set txpower levels to defaults */
+               scan_ch->dsp_atten = 110;
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+               added++;
+       } else
+               IWL_ERR(priv, "no valid channel found\n");
+       return added;
+}
+
+static int iwl_get_channels_for_scan(struct iwl_priv *priv,
+                                    struct ieee80211_vif *vif,
+                                    enum ieee80211_band band,
+                                    u8 is_active, u8 n_probes,
+                                    struct iwl_scan_channel *scan_ch)
+{
+       struct ieee80211_channel *chan;
+       const struct ieee80211_supported_band *sband;
+       const struct iwl_channel_info *ch_info;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added, i;
+       u16 channel;
+
+       sband = iwl_get_hw_mode(priv, band);
+       if (!sband)
+               return 0;
+
+       active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+       for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+               chan = priv->scan_request->channels[i];
+
+               if (chan->band != band)
+                       continue;
+
+               channel = chan->hw_value;
+               scan_ch->channel = cpu_to_le16(channel);
+
+               ch_info = iwl_get_channel_info(priv, band, channel);
+               if (!is_channel_valid(ch_info)) {
+                       IWL_DEBUG_SCAN(priv,
+                                      "Channel %d is INVALID for this band.\n",
+                                      channel);
+                       continue;
+               }
+
+               if (!is_active || is_channel_passive(ch_info) ||
+                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+               else
+                       scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+               if (n_probes)
+                       scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+               /* Set txpower levels to defaults */
+               scan_ch->dsp_atten = 110;
+
+               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+                * power level:
+                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+                */
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+               IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
+                              channel, le32_to_cpu(scan_ch->type),
+                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+                               "ACTIVE" : "PASSIVE",
+                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+                              active_dwell : passive_dwell);
+
+               scan_ch++;
+               added++;
+       }
+
+       IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+       return added;
+}
+
+static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_SCAN_CMD,
+               .len = { sizeof(struct iwl_scan_cmd), },
+               .flags = CMD_SYNC,
+       };
+       struct iwl_scan_cmd *scan;
+       struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+       u32 rate_flags = 0;
+       u16 cmd_len;
+       u16 rx_chain = 0;
+       enum ieee80211_band band;
+       u8 n_probes = 0;
+       u8 rx_ant = hw_params(priv).valid_rx_ant;
+       u8 rate;
+       bool is_active = false;
+       int  chan_mod;
+       u8 active_chains;
+       u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
+       int ret;
+
+       lockdep_assert_held(&priv->shrd->mutex);
+
+       if (vif)
+               ctx = iwl_rxon_ctx_from_vif(vif);
+
+       if (!priv->scan_cmd) {
+               priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+                                        IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+               if (!priv->scan_cmd) {
+                       IWL_DEBUG_SCAN(priv,
+                                      "fail to allocate memory for scan\n");
+                       return -ENOMEM;
+               }
+       }
+       scan = priv->scan_cmd;
+       memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+       scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+       scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+       if (priv->scan_type != IWL_SCAN_ROC &&
+           iwl_is_any_associated(priv)) {
+               u16 interval = 0;
+               u32 extra;
+               u32 suspend_time = 100;
+               u32 scan_suspend_time = 100;
+
+               IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+               switch (priv->scan_type) {
+               case IWL_SCAN_ROC:
+                       WARN_ON(1);
+                       break;
+               case IWL_SCAN_RADIO_RESET:
+                       interval = 0;
+                       break;
+               case IWL_SCAN_NORMAL:
+                       interval = vif->bss_conf.beacon_int;
+                       break;
+               }
+
+               scan->suspend_time = 0;
+               scan->max_out_time = cpu_to_le32(200 * 1024);
+               if (!interval)
+                       interval = suspend_time;
+
+               extra = (suspend_time / interval) << 22;
+               scan_suspend_time = (extra |
+                   ((suspend_time % interval) * 1024));
+               scan->suspend_time = cpu_to_le32(scan_suspend_time);
+               IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+                              scan_suspend_time, interval);
+       } else if (priv->scan_type == IWL_SCAN_ROC) {
+               scan->suspend_time = 0;
+               scan->max_out_time = 0;
+               scan->quiet_time = 0;
+               scan->quiet_plcp_th = 0;
+       }
+
+       switch (priv->scan_type) {
+       case IWL_SCAN_RADIO_RESET:
+               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+               break;
+       case IWL_SCAN_NORMAL:
+               if (priv->scan_request->n_ssids) {
+                       int i, p = 0;
+                       IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+                       for (i = 0; i < priv->scan_request->n_ssids; i++) {
+                               /* always does wildcard anyway */
+                               if (!priv->scan_request->ssids[i].ssid_len)
+                                       continue;
+                               scan->direct_scan[p].id = WLAN_EID_SSID;
+                               scan->direct_scan[p].len =
+                                       priv->scan_request->ssids[i].ssid_len;
+                               memcpy(scan->direct_scan[p].ssid,
+                                      priv->scan_request->ssids[i].ssid,
+                                      priv->scan_request->ssids[i].ssid_len);
+                               n_probes++;
+                               p++;
+                       }
+                       is_active = true;
+               } else
+                       IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+               break;
+       case IWL_SCAN_ROC:
+               IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
+               break;
+       }
+
+       scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+       scan->tx_cmd.sta_id = ctx->bcast_sta_id;
+       scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+       switch (priv->scan_band) {
+       case IEEE80211_BAND_2GHZ:
+               scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+               chan_mod = le32_to_cpu(
+                       priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+                                               RXON_FLG_CHANNEL_MODE_MSK)
+                                      >> RXON_FLG_CHANNEL_MODE_POS;
+               if (chan_mod == CHANNEL_MODE_PURE_40) {
+                       rate = IWL_RATE_6M_PLCP;
+               } else {
+                       rate = IWL_RATE_1M_PLCP;
+                       rate_flags = RATE_MCS_CCK_MSK;
+               }
                /*
-                * If we're associated, we clamp the maximum passive
-                * dwell time to be 98% of the smallest beacon interval
-                * (minus 2 * channel tune time)
+                * Internal scans are passive, so we can indiscriminately set
+                * the BT ignore flag on 2.4 GHz since it applies to TX only.
                 */
-               for_each_context(priv, ctx) {
-                       u16 value;
-
-                       if (!iwl_is_associated_ctx(ctx))
-                               continue;
-                       value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
-                       if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
-                               value = IWL_PASSIVE_DWELL_BASE;
-                       value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
-                       passive = min(value, passive);
+               if (priv->cfg->bt_params &&
+                   priv->cfg->bt_params->advanced_bt_coexist)
+                       scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
+               break;
+       case IEEE80211_BAND_5GHZ:
+               rate = IWL_RATE_6M_PLCP;
+               break;
+       default:
+               IWL_WARN(priv, "Invalid scan band\n");
+               return -EIO;
+       }
+
+       /*
+        * If active scanning is requested but a certain channel is
+        * marked passive, we can do active scanning if we detect
+        * transmissions.
+        *
+        * There is an issue with some firmware versions that triggers
+        * a sysassert on a "good CRC threshold" of zero (== disabled),
+        * on a radar channel even though this means that we should NOT
+        * send probes.
+        *
+        * The "good CRC threshold" is the number of frames that we
+        * need to receive during our dwell time on a channel before
+        * sending out probes -- setting this to a huge value will
+        * mean we never reach it, but at the same time work around
+        * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+        * here instead of IWL_GOOD_CRC_TH_DISABLED.
+        *
+        * This was fixed in later versions along with some other
+        * scan changes, and the threshold behaves as a flag in those
+        * versions.
+        */
+       if (priv->new_scan_threshold_behaviour)
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+                                               IWL_GOOD_CRC_TH_DISABLED;
+       else
+               scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+                                               IWL_GOOD_CRC_TH_NEVER;
+
+       band = priv->scan_band;
+
+       if (priv->cfg->scan_rx_antennas[band])
+               rx_ant = priv->cfg->scan_rx_antennas[band];
+
+       if (band == IEEE80211_BAND_2GHZ &&
+           priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist) {
+               /* transmit 2.4 GHz probes only on first antenna */
+               scan_tx_antennas = first_antenna(scan_tx_antennas);
+       }
+
+       priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv,
+                                                   priv->scan_tx_ant[band],
+                                                   scan_tx_antennas);
+       rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
+       scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
+
+       /* In power save mode use one chain, otherwise use all chains */
+       if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) {
+               /* rx_ant has been set to all valid chains previously */
+               active_chains = rx_ant &
+                               ((u8)(priv->chain_noise_data.active_chains));
+               if (!active_chains)
+                       active_chains = rx_ant;
+
+               IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+                               priv->chain_noise_data.active_chains);
+
+               rx_ant = first_antenna(active_chains);
+       }
+       if (priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist &&
+           priv->bt_full_concurrent) {
+               /* operated as 1x1 in full concurrency mode */
+               rx_ant = first_antenna(rx_ant);
+       }
+
+       /* MIMO is not used here, but value is required */
+       rx_chain |=
+               hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+       rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+       rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+       scan->rx_chain = cpu_to_le16(rx_chain);
+       switch (priv->scan_type) {
+       case IWL_SCAN_NORMAL:
+               cmd_len = iwl_fill_probe_req(priv,
+                                       (struct ieee80211_mgmt *)scan->data,
+                                       vif->addr,
+                                       priv->scan_request->ie,
+                                       priv->scan_request->ie_len,
+                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
+               break;
+       case IWL_SCAN_RADIO_RESET:
+       case IWL_SCAN_ROC:
+               /* use bcast addr, will not be transmitted but must be valid */
+               cmd_len = iwl_fill_probe_req(priv,
+                                       (struct ieee80211_mgmt *)scan->data,
+                                       iwl_bcast_addr, NULL, 0,
+                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
+               break;
+       default:
+               BUG();
+       }
+       scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
+       scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
+                              RXON_FILTER_BCON_AWARE_MSK);
+
+       switch (priv->scan_type) {
+       case IWL_SCAN_RADIO_RESET:
+               scan->channel_count =
+                       iwl_get_single_channel_for_scan(priv, vif, band,
+                               (void *)&scan->data[cmd_len]);
+               break;
+       case IWL_SCAN_NORMAL:
+               scan->channel_count =
+                       iwl_get_channels_for_scan(priv, vif, band,
+                               is_active, n_probes,
+                               (void *)&scan->data[cmd_len]);
+               break;
+       case IWL_SCAN_ROC: {
+               struct iwl_scan_channel *scan_ch;
+               int n_chan, i;
+               u16 dwell;
+
+               dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
+               n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
+
+               scan->channel_count = n_chan;
+
+               scan_ch = (void *)&scan->data[cmd_len];
+
+               for (i = 0; i < n_chan; i++) {
+                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+                       scan_ch->channel =
+                               cpu_to_le16(priv->hw_roc_channel->hw_value);
+
+                       if (i == n_chan - 1)
+                               dwell = priv->hw_roc_duration - i * dwell;
+
+                       scan_ch->active_dwell =
+                       scan_ch->passive_dwell = cpu_to_le16(dwell);
+
+                       /* Set txpower levels to defaults */
+                       scan_ch->dsp_atten = 110;
+
+                       /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+                        * power level:
+                        * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+                        */
+                       if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
+                               scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+                       else
+                               scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+                       scan_ch++;
                }
+               }
+
+               break;
        }
 
-       return passive;
+       if (scan->channel_count == 0) {
+               IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+               return -EIO;
+       }
+
+       cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
+           scan->channel_count * sizeof(struct iwl_scan_channel);
+       cmd.data[0] = scan;
+       cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
+       scan->len = cpu_to_le16(cmd.len[0]);
+
+       /* set scan bit here for PAN params */
+       set_bit(STATUS_SCAN_HW, &priv->shrd->status);
+
+       ret = iwlagn_set_pan_params(priv);
+       if (ret)
+               return ret;
+
+       ret = iwl_trans_send_cmd(trans(priv), &cmd);
+       if (ret) {
+               clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
+               iwlagn_set_pan_params(priv);
+       }
+
+       return ret;
 }
 
 void iwl_init_scan_params(struct iwl_priv *priv)
index 8b8cd54a32e01d6094d88210ca5c46d137f8b33e..7abafe16de9a41527b4f2d6213938b26ad90c8cb 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/gfp.h>
+#include <linux/mm.h> /* for page_address */
 #include <net/mac80211.h>
 
 #include "iwl-commands.h"
 
-/*This files includes all the types / functions that are exported by the
- * upper layer to the bus and transport layer */
+/**
+ * DOC: shared area - role and goal
+ *
+ * The shared area contains all the data exported by the upper layer to the
+ * other layers. Since the bus and transport layer shouldn't dereference
+ * iwl_priv, all the data needed by the upper layer and the transport / bus
+ * layer must be here.
+ * The shared area also holds pointer to all the other layers. This allows a
+ * layer to call a function from another layer.
+ *
+ * NOTE: All the layers hold a pointer to the shared area which must be shrd.
+ *     A few macros assume that (_m)->shrd points to the shared area no matter
+ *     what _m is.
+ *
+ * gets notifications about enumeration, suspend, resume.
+ * For the moment, the bus layer is not a linux kernel module as itself, and
+ * the module_init function of the driver must call the bus specific
+ * registration functions. These functions are listed at the end of this file.
+ * For the moment, there is only one implementation of this interface: PCI-e.
+ * This implementation is iwl-pci.c
+ */
 
 struct iwl_cfg;
 struct iwl_bus;
@@ -89,6 +109,9 @@ extern struct iwl_mod_params iwlagn_mod_params;
 
 /**
  * struct iwl_mod_params
+ *
+ * Holds the module parameters
+ *
  * @sw_crypto: using hardware encryption, default = 0
  * @num_of_queues: number of tx queue, HW dependent
  * @disable_11n: 11n capabilities enabled, default = 0
@@ -133,20 +156,24 @@ struct iwl_mod_params {
 
 /**
  * struct iwl_hw_params
+ *
+ * Holds the module parameters
+ *
  * @max_txq_num: Max # Tx queues supported
  * @num_ampdu_queues: num of ampdu queues
- * @tx/rx_chains_num: Number of TX/RX chains
- * @valid_tx/rx_ant: usable antennas
- * @max_stations:
- * @ht40_channel: is 40MHz width possible in band 2.4
- * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
- * @sku:
+ * @tx_chains_num: Number of TX chains
+ * @rx_chains_num: Number of RX chains
+ * @valid_tx_ant: usable antennas for TX
+ * @valid_rx_ant: usable antennas for RX
+ * @max_stations: the maximal number of stations
+ * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
+ * @sku: sku read from EEPROM
  * @rx_page_order: Rx buffer page order
- * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
- * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
- * @sw_crypto: 0 for hw, 1 for sw
- * @max_xxx_size: for ucode uses
- * @ct_kill_threshold: temperature threshold
+ * @max_inst_size: for ucode use
+ * @max_data_size: for ucode use
+ * @ct_kill_threshold: temperature threshold - in hw dependent unit
+ * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
+ *     relevant for 1000, 6000 and up
  * @wd_timeout: TX queues watchdog timeout
  * @calib_init_cfg: setup initial calibrations for the hw
  * @calib_rt_cfg: setup runtime calibrations for the hw
@@ -162,14 +189,12 @@ struct iwl_hw_params {
        u8  max_stations;
        u8  ht40_channel;
        bool shadow_reg_enable;
-       u16 beacon_time_tsf_bits;
        u16 sku;
        u32 rx_page_order;
        u32 max_inst_size;
        u32 max_data_size;
-       u32 ct_kill_threshold; /* value in hw-dependent units */
-       u32 ct_kill_exit_threshold; /* value in hw-dependent units */
-                                   /* for 1000, 6000 series and up */
+       u32 ct_kill_threshold;
+       u32 ct_kill_exit_threshold;
        unsigned int wd_timeout;
 
        u32 calib_init_cfg;
@@ -178,28 +203,59 @@ struct iwl_hw_params {
 };
 
 /**
- * struct iwl_ht_agg - aggregation status while waiting for block-ack
- * @txq_id: Tx queue used for Tx attempt
- * @wait_for_ba: Expect block-ack before next Tx reply
- * @rate_n_flags: Rate at which Tx was attempted
+ * enum iwl_agg_state
+ *
+ * The state machine of the BA agreement establishment / tear down.
+ * These states relate to a specific RA / TID.
  *
- * If REPLY_TX indicates that aggregation was attempted, driver must wait
- * for block ack (REPLY_COMPRESSED_BA).  This struct stores tx reply info
- * until block ack arrives.
+ * @IWL_AGG_OFF: aggregation is not used
+ * @IWL_AGG_ON: aggregation session is up
+ * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
+ *     HW queue to be empty from packets for this RA /TID.
+ * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
+ *     HW queue to be empty from packets for this RA /TID.
+ */
+enum iwl_agg_state {
+       IWL_AGG_OFF = 0,
+       IWL_AGG_ON,
+       IWL_EMPTYING_HW_QUEUE_ADDBA,
+       IWL_EMPTYING_HW_QUEUE_DELBA,
+};
+
+/**
+ * struct iwl_ht_agg - aggregation state machine
+
+ * This structs holds the states for the BA agreement establishment and tear
+ * down. It also holds the state during the BA session itself. This struct is
+ * duplicated for each RA / TID.
+
+ * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
+ *     Tx response (REPLY_TX), and the block ack notification
+ *     (REPLY_COMPRESSED_BA).
+ * @state: state of the BA agreement establishment / tear down.
+ * @txq_id: Tx queue used by the BA session - used by the transport layer.
+ *     Needed by the upper layer for debugfs only.
+ * @wait_for_ba: Expect block-ack before next Tx reply
  */
 struct iwl_ht_agg {
-       u16 txq_id;
-       u16 wait_for_ba;
        u32 rate_n_flags;
-#define IWL_AGG_OFF 0
-#define IWL_AGG_ON 1
-#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
-#define IWL_EMPTYING_HW_QUEUE_DELBA 3
-       u8 state;
+       enum iwl_agg_state state;
+       u16 txq_id;
+       bool wait_for_ba;
 };
 
+/**
+ * struct iwl_tid_data - one for each RA / TID
+
+ * This structs holds the states for each RA / TID.
+
+ * @seq_number: the next WiFi sequence number to use
+ * @tfds_in_queue: number of packets sent to the HW queues.
+ *     Exported for debugfs only
+ * @agg: aggregation state machine
+ */
 struct iwl_tid_data {
-       u16 seq_number; /* agn only */
+       u16 seq_number;
        u16 tfds_in_queue;
        struct iwl_ht_agg agg;
 };
@@ -212,6 +268,7 @@ struct iwl_tid_data {
  * @ucode_owner: IWL_OWNERSHIP_*
  * @cmd_queue: command queue number
  * @status: STATUS_*
+ * @valid_contexts: microcode/device supports multiple contexts
  * @bus: pointer to the bus layer data
  * @priv: pointer to the upper layer data
  * @hw_params: see struct iwl_hw_params
@@ -232,6 +289,7 @@ struct iwl_shared {
        u8 cmd_queue;
        unsigned long status;
        bool wowlan;
+       u8 valid_contexts;
 
        struct iwl_bus *bus;
        struct iwl_priv *priv;
@@ -243,13 +301,9 @@ struct iwl_shared {
        spinlock_t sta_lock;
        struct mutex mutex;
 
-       /*these 2 shouldn't really be here, but they are needed for
-        * iwl_queue_stop, which is called from the upper layer too
-        */
-       u8 mac80211_registered;
-       struct ieee80211_hw *hw;
-
        struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
+
+       wait_queue_head_t wait_command_queue;
 };
 
 /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
@@ -285,6 +339,26 @@ static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
        free_pages(page, shrd->hw_params.rx_page_order);
 }
 
+/**
+ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_inc_wrap(int index, int n_bd)
+{
+       return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_queue_dec_wrap(int index, int n_bd)
+{
+       return --index & (n_bd - 1);
+}
+
 struct iwl_rx_mem_buffer {
        dma_addr_t page_dma;
        struct page *page;
@@ -346,21 +420,52 @@ enum iwl_rxon_context_id {
        NUM_IWL_RXON_CTX
 };
 
-#ifdef CONFIG_PM
-int iwl_suspend(struct iwl_priv *priv);
-int iwl_resume(struct iwl_priv *priv);
-#endif /* !CONFIG_PM */
-
 int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
                struct iwl_cfg *cfg);
 void __devexit iwl_remove(struct iwl_priv * priv);
+struct iwl_device_cmd;
+int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
+                                struct iwl_rx_mem_buffer *rxb,
+                                struct iwl_device_cmd *cmd);
 
+int iwlagn_hw_valid_rtc_data_addr(u32 addr);
 void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
                                 enum iwl_rxon_context_id ctx,
                                 u8 sta_id, u8 tid);
 void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
                                enum iwl_rxon_context_id ctx,
                                u8 sta_id, u8 tid);
+void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
+void iwl_nic_config(struct iwl_priv *priv);
+void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
+void iwl_apm_stop(struct iwl_priv *priv);
+int iwl_apm_init(struct iwl_priv *priv);
+void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
+const char *get_cmd_string(u8 cmd);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+
+void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
+void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+void iwl_reset_traffic_log(struct iwl_priv *priv);
+#endif /* CONFIG_IWLWIFI_DEBUGFS */
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+                            enum iwl_rxon_context_id ctxid);
+#else
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+                                          enum iwl_rxon_context_id ctxid)
+{
+}
+#endif
+
+#define IWL_CMD(x) case x: return #x
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+#define IWL_TRAFFIC_ENTRIES    (256)
+#define IWL_TRAFFIC_ENTRY_SIZE  (64)
 
 /*****************************************************
 * DRIVER STATUS FUNCTIONS
index 26b2bd4db6b4d6fd0823372544473de8dad22f88..580a4d702ff3c019ef7c84880ae080f272eae3eb 100644 (file)
@@ -59,8 +59,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 
 static int iwl_process_add_sta_resp(struct iwl_priv *priv,
                                    struct iwl_addsta_cmd *addsta,
-                                   struct iwl_rx_packet *pkt,
-                                   bool sync)
+                                   struct iwl_rx_packet *pkt)
 {
        u8 sta_id = addsta->sta.sta_id;
        unsigned long flags;
@@ -123,15 +122,14 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
        return ret;
 }
 
-static void iwl_add_sta_callback(struct iwl_priv *priv,
-                                struct iwl_device_cmd *cmd,
-                                struct iwl_rx_packet *pkt)
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_addsta_cmd *addsta =
-               (struct iwl_addsta_cmd *)cmd->cmd.payload;
-
-       iwl_process_add_sta_resp(priv, addsta, pkt, false);
+               (struct iwl_addsta_cmd *) cmd->payload;
 
+       return iwl_process_add_sta_resp(priv, addsta, pkt);
 }
 
 static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
@@ -147,7 +145,6 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
 int iwl_send_add_sta(struct iwl_priv *priv,
                     struct iwl_addsta_cmd *sta, u8 flags)
 {
-       struct iwl_rx_packet *pkt = NULL;
        int ret = 0;
        u8 data[sizeof(*sta)];
        struct iwl_host_cmd cmd = {
@@ -160,9 +157,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
        IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
                       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
 
-       if (flags & CMD_ASYNC)
-               cmd.callback = iwl_add_sta_callback;
-       else {
+       if (!(flags & CMD_ASYNC)) {
                cmd.flags |= CMD_WANT_SKB;
                might_sleep();
        }
@@ -172,14 +167,16 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
        if (ret || (flags & CMD_ASYNC))
                return ret;
+       /*else the command was successfully sent in SYNC mode, need to free
+        * the reply page */
 
-       if (ret == 0) {
-               pkt = (struct iwl_rx_packet *)cmd.reply_page;
-               ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
-       }
        iwl_free_pages(priv->shrd, cmd.reply_page);
 
-       return ret;
+       if (cmd.handler_status)
+               IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
+                       cmd.handler_status);
+
+       return cmd.handler_status;
 }
 
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
@@ -305,7 +302,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
        station->ctxid = ctx->ctxid;
 
        if (sta) {
-               struct iwl_station_priv_common *sta_priv;
+               struct iwl_station_priv *sta_priv;
 
                sta_priv = (void *)sta->drv_priv;
                sta_priv->ctx = ctx;
@@ -821,7 +818,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
                       struct ieee80211_sta *sta)
 {
        struct iwl_priv *priv = hw->priv;
-       struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
+       struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
        int ret;
 
        IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
@@ -829,7 +826,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
        mutex_lock(&priv->shrd->mutex);
        IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
                        sta->addr);
-       ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
+       ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
        if (ret)
                IWL_ERR(priv, "Error removing station %pM\n",
                        sta->addr);
index 9641eb6b1d0afa435fed3803c6b95fbc289376cd..1bca0dabde8d1009309a3e662db95aebca3b3b8c 100644 (file)
@@ -61,6 +61,9 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
                    struct iwl_link_quality_cmd *lq, u8 flags, bool init);
 void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd);
+
 
 /**
  * iwl_clear_driver_stations - clear knowledge of all stations from driver
@@ -102,7 +105,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
        if (WARN_ON(!sta))
                return IWL_INVALID_STATION;
 
-       return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
+       return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
 }
 
 /**
index 848fc18befc25a3768dd90860ea1b787f20eb5e4..3335d31daf89678385cc87b1c90a070029ad7277 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <net/net_namespace.h>
 #include <linux/netdevice.h>
 #include <net/cfg80211.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
deleted file mode 100644 (file)
index ec4e737..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <[email protected]>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#ifndef __iwl_trans_int_pcie_h__
-#define __iwl_trans_int_pcie_h__
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-
-#include "iwl-fh.h"
-#include "iwl-csr.h"
-#include "iwl-shared.h"
-#include "iwl-trans.h"
-#include "iwl-debug.h"
-#include "iwl-io.h"
-
-struct iwl_tx_queue;
-struct iwl_queue;
-struct iwl_host_cmd;
-
-/*This file includes the declaration that are internal to the
- * trans_pcie layer */
-
-/**
- * struct isr_statistics - interrupt statistics
- *
- */
-struct isr_statistics {
-       u32 hw;
-       u32 sw;
-       u32 err_code;
-       u32 sch;
-       u32 alive;
-       u32 rfkill;
-       u32 ctkill;
-       u32 wakeup;
-       u32 rx;
-       u32 tx;
-       u32 unhandled;
-};
-
-/**
- * struct iwl_rx_queue - Rx queue
- * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
- * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
- * @pool:
- * @queue:
- * @read: Shared index to newest available Rx buffer
- * @write: Shared index to oldest written Rx packet
- * @free_count: Number of pre-allocated buffers in rx_free
- * @write_actual:
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
- * @need_update: flag to indicate we need to update read/write index
- * @rb_stts: driver's pointer to receive buffer status
- * @rb_stts_dma: bus address of receive buffer status
- * @lock:
- *
- * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
- */
-struct iwl_rx_queue {
-       __le32 *bd;
-       dma_addr_t bd_dma;
-       struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
-       struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
-       u32 read;
-       u32 write;
-       u32 free_count;
-       u32 write_actual;
-       struct list_head rx_free;
-       struct list_head rx_used;
-       int need_update;
-       struct iwl_rb_status *rb_stts;
-       dma_addr_t rb_stts_dma;
-       spinlock_t lock;
-};
-
-struct iwl_dma_ptr {
-       dma_addr_t dma;
-       void *addr;
-       size_t size;
-};
-
-/*
- * This queue number is required for proper operation
- * because the ucode will stop/start the scheduler as
- * required.
- */
-#define IWL_IPAN_MCAST_QUEUE           8
-
-/**
- * struct iwl_trans_pcie - PCIe transport specific data
- * @rxq: all the RX queue data
- * @rx_replenish: work that will be called when buffers need to be allocated
- * @trans: pointer to the generic transport area
- * @scd_base_addr: scheduler sram base address in SRAM
- * @scd_bc_tbls: pointer to the byte count table of the scheduler
- * @kw: keep warm address
- * @ac_to_fifo: to what fifo is a specifc AC mapped ?
- * @ac_to_queue: to what tx queue  is a specifc AC mapped ?
- * @mcast_queue:
- * @txq: Tx DMA processing queues
- * @txq_ctx_active_msk: what queue is active
- * queue_stopped: tracks what queue is stopped
- * queue_stop_count: tracks what SW queue is stopped
- */
-struct iwl_trans_pcie {
-       struct iwl_rx_queue rxq;
-       struct work_struct rx_replenish;
-       struct iwl_trans *trans;
-
-       /* INT ICT Table */
-       __le32 *ict_tbl;
-       void *ict_tbl_vir;
-       dma_addr_t ict_tbl_dma;
-       dma_addr_t aligned_ict_tbl_dma;
-       int ict_index;
-       u32 inta;
-       bool use_ict;
-       struct tasklet_struct irq_tasklet;
-       struct isr_statistics isr_stats;
-
-       u32 inta_mask;
-       u32 scd_base_addr;
-       struct iwl_dma_ptr scd_bc_tbls;
-       struct iwl_dma_ptr kw;
-
-       const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
-       const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
-       u8 mcast_queue[NUM_IWL_RXON_CTX];
-
-       struct iwl_tx_queue *txq;
-       unsigned long txq_ctx_active_msk;
-#define IWL_MAX_HW_QUEUES      32
-       unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
-       atomic_t queue_stop_count[4];
-};
-
-#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
-       ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
-
-/*****************************************************
-* RX
-******************************************************/
-void iwl_bg_rx_replenish(struct work_struct *data);
-void iwl_irq_tasklet(struct iwl_trans *trans);
-void iwlagn_rx_replenish(struct iwl_trans *trans);
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
-                       struct iwl_rx_queue *q);
-
-/*****************************************************
-* ICT
-******************************************************/
-int iwl_reset_ict(struct iwl_trans *trans);
-void iwl_disable_ict(struct iwl_trans *trans);
-int iwl_alloc_isr_ict(struct iwl_trans *trans);
-void iwl_free_isr_ict(struct iwl_trans *trans);
-irqreturn_t iwl_isr_ict(int irq, void *data);
-
-/*****************************************************
-* TX / HCMD
-******************************************************/
-void iwl_txq_update_write_ptr(struct iwl_trans *trans,
-                       struct iwl_tx_queue *txq);
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
-                                struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len, u8 reset);
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
-int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id,
-                       u32 flags, u16 len, const void *data);
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
-                                          struct iwl_tx_queue *txq,
-                                          u16 byte_cnt);
-void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
-int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
-                                 enum iwl_rxon_context_id ctx, int sta_id,
-                                 int tid);
-void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
-void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
-                            struct iwl_tx_queue *txq,
-                            int tx_fifo_id, int scd_retry);
-int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
-                               enum iwl_rxon_context_id ctx, int sta_id,
-                               int tid, u16 *ssn);
-void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
-                                enum iwl_rxon_context_id ctx,
-                                int sta_id, int tid, int frame_limit);
-void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-       int index);
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
-                        struct sk_buff_head *skbs);
-int iwl_queue_space(const struct iwl_queue *q);
-
-/*****************************************************
-* Error handling
-******************************************************/
-int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
-                           char **buf, bool display);
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
-void iwl_dump_csr(struct iwl_trans *trans);
-
-/*****************************************************
-* Helpers
-******************************************************/
-static inline void iwl_disable_interrupts(struct iwl_trans *trans)
-{
-       clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
-
-       /* disable interrupts from uCode/NIC to host */
-       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
-
-       /* acknowledge/clear/reset any interrupts still pending
-        * from uCode or flow handler (Rx/Tx DMA) */
-       iwl_write32(bus(trans), CSR_INT, 0xffffffff);
-       iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff);
-       IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
-}
-
-static inline void iwl_enable_interrupts(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
-       set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
-       iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
-}
-
-/*
- * we have 8 bits used like this:
- *
- * 7 6 5 4 3 2 1 0
- * | | | | | | | |
- * | | | | | | +-+-------- AC queue (0-3)
- * | | | | | |
- * | +-+-+-+-+------------ HW queue ID
- * |
- * +---------------------- unused
- */
-static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
-{
-       BUG_ON(ac > 3);   /* only have 2 bits */
-       BUG_ON(hwq > 31); /* only use 5 bits */
-
-       txq->swq_id = (hwq << 2) | ac;
-}
-
-static inline void iwl_wake_queue(struct iwl_trans *trans,
-                                 struct iwl_tx_queue *txq)
-{
-       u8 queue = txq->swq_id;
-       u8 ac = queue & 3;
-       u8 hwq = (queue >> 2) & 0x1f;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (unlikely(!trans->shrd->mac80211_registered))
-               return;
-
-       if (test_and_clear_bit(hwq, trans_pcie->queue_stopped))
-               if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0)
-                       ieee80211_wake_queue(trans->shrd->hw, ac);
-}
-
-static inline void iwl_stop_queue(struct iwl_trans *trans,
-                                 struct iwl_tx_queue *txq)
-{
-       u8 queue = txq->swq_id;
-       u8 ac = queue & 3;
-       u8 hwq = (queue >> 2) & 0x1f;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (unlikely(!trans->shrd->mac80211_registered))
-               return;
-
-       if (!test_and_set_bit(hwq, trans_pcie->queue_stopped))
-               if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0)
-                       ieee80211_stop_queue(trans->shrd->hw, ac);
-}
-
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
-static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
-                                       int txq_id)
-{
-       set_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
-}
-
-static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie,
-                                         int txq_id)
-{
-       clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
-}
-
-static inline int iwl_queue_used(const struct iwl_queue *q, int i)
-{
-       return q->write_ptr >= q->read_ptr ?
-               (i >= q->read_ptr && i < q->write_ptr) :
-               !(i < q->read_ptr && i >= q->write_ptr);
-}
-
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
-{
-       return index & (q->n_window - 1);
-}
-
-#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
new file mode 100644 (file)
index 0000000..2b6756e
--- /dev/null
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __iwl_trans_int_pcie_h__
+#define __iwl_trans_int_pcie_h__
+
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+
+#include "iwl-fh.h"
+#include "iwl-csr.h"
+#include "iwl-shared.h"
+#include "iwl-trans.h"
+#include "iwl-debug.h"
+#include "iwl-io.h"
+
+struct iwl_tx_queue;
+struct iwl_queue;
+struct iwl_host_cmd;
+
+/*This file includes the declaration that are internal to the
+ * trans_pcie layer */
+
+/**
+ * struct isr_statistics - interrupt statistics
+ *
+ */
+struct isr_statistics {
+       u32 hw;
+       u32 sw;
+       u32 err_code;
+       u32 sch;
+       u32 alive;
+       u32 rfkill;
+       u32 ctkill;
+       u32 wakeup;
+       u32 rx;
+       u32 tx;
+       u32 unhandled;
+};
+
+/**
+ * struct iwl_rx_queue - Rx queue
+ * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
+ * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @pool:
+ * @queue:
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @write_actual:
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ * @rb_stts: driver's pointer to receive buffer status
+ * @rb_stts_dma: bus address of receive buffer status
+ * @lock:
+ *
+ * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
+ */
+struct iwl_rx_queue {
+       __le32 *bd;
+       dma_addr_t bd_dma;
+       struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+       struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+       u32 read;
+       u32 write;
+       u32 free_count;
+       u32 write_actual;
+       struct list_head rx_free;
+       struct list_head rx_used;
+       int need_update;
+       struct iwl_rb_status *rb_stts;
+       dma_addr_t rb_stts_dma;
+       spinlock_t lock;
+};
+
+struct iwl_dma_ptr {
+       dma_addr_t dma;
+       void *addr;
+       size_t size;
+};
+
+/*
+ * This queue number is required for proper operation
+ * because the ucode will stop/start the scheduler as
+ * required.
+ */
+#define IWL_IPAN_MCAST_QUEUE           8
+
+struct iwl_cmd_meta {
+       /* only for SYNC commands, iff the reply skb is wanted */
+       struct iwl_host_cmd *source;
+
+       u32 flags;
+
+       DEFINE_DMA_UNMAP_ADDR(mapping);
+       DEFINE_DMA_UNMAP_LEN(len);
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues.
+ *
+ * Note the difference between n_bd and n_window: the hardware
+ * always assumes 256 descriptors, so n_bd is always 256 (unless
+ * there might be HW changes in the future). For the normal TX
+ * queues, n_window, which is the size of the software queue data
+ * is also 256; however, for the command queue, n_window is only
+ * 32 since we don't need so many commands pending. Since the HW
+ * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
+ * the software buffers (in the variables @meta, @txb in struct
+ * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
+ * in the same struct) have 256.
+ * This means that we end up with the following:
+ *  HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
+ *  SW entries:           | 0      | ... | 31          |
+ * where N is a number between 0 and 7. This means that the SW
+ * data is a window overlayed over the HW queue.
+ */
+struct iwl_queue {
+       int n_bd;              /* number of BDs in this queue */
+       int write_ptr;       /* 1-st empty entry (index) host_w*/
+       int read_ptr;         /* last used entry (index) host_r*/
+       /* use for monitoring and recovering the stuck queue */
+       dma_addr_t dma_addr;   /* physical addr for BD's */
+       int n_window;          /* safe queue window */
+       u32 id;
+       int low_mark;          /* low watermark, resume queue if free
+                               * space more than this */
+       int high_mark;         /* high watermark, stop queue if free
+                               * space less than this */
+};
+
+/**
+ * struct iwl_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
+ * @need_update: indicates need to update read/write index
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ * @sta_id: valid if sched_retry is set
+ * @tid: valid if sched_retry is set
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+struct iwl_tx_queue {
+       struct iwl_queue q;
+       struct iwl_tfd *tfds;
+       struct iwl_device_cmd **cmd;
+       struct iwl_cmd_meta *meta;
+       struct sk_buff **skbs;
+       unsigned long time_stamp;
+       u8 need_update;
+       u8 sched_retry;
+       u8 active;
+       u8 swq_id;
+
+       u16 sta_id;
+       u16 tid;
+};
+
+/**
+ * struct iwl_trans_pcie - PCIe transport specific data
+ * @rxq: all the RX queue data
+ * @rx_replenish: work that will be called when buffers need to be allocated
+ * @trans: pointer to the generic transport area
+ * @scd_base_addr: scheduler sram base address in SRAM
+ * @scd_bc_tbls: pointer to the byte count table of the scheduler
+ * @kw: keep warm address
+ * @ac_to_fifo: to what fifo is a specifc AC mapped ?
+ * @ac_to_queue: to what tx queue  is a specifc AC mapped ?
+ * @mcast_queue:
+ * @txq: Tx DMA processing queues
+ * @txq_ctx_active_msk: what queue is active
+ * queue_stopped: tracks what queue is stopped
+ * queue_stop_count: tracks what SW queue is stopped
+ */
+struct iwl_trans_pcie {
+       struct iwl_rx_queue rxq;
+       struct work_struct rx_replenish;
+       struct iwl_trans *trans;
+
+       /* INT ICT Table */
+       __le32 *ict_tbl;
+       void *ict_tbl_vir;
+       dma_addr_t ict_tbl_dma;
+       dma_addr_t aligned_ict_tbl_dma;
+       int ict_index;
+       u32 inta;
+       bool use_ict;
+       struct tasklet_struct irq_tasklet;
+       struct isr_statistics isr_stats;
+
+       u32 inta_mask;
+       u32 scd_base_addr;
+       struct iwl_dma_ptr scd_bc_tbls;
+       struct iwl_dma_ptr kw;
+
+       const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
+       const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
+       u8 mcast_queue[NUM_IWL_RXON_CTX];
+
+       struct iwl_tx_queue *txq;
+       unsigned long txq_ctx_active_msk;
+#define IWL_MAX_HW_QUEUES      32
+       unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
+       atomic_t queue_stop_count[4];
+};
+
+#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
+       ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific))
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_bg_rx_replenish(struct work_struct *data);
+void iwl_irq_tasklet(struct iwl_trans *trans);
+void iwlagn_rx_replenish(struct iwl_trans *trans);
+void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
+                       struct iwl_rx_queue *q);
+
+/*****************************************************
+* ICT
+******************************************************/
+int iwl_reset_ict(struct iwl_trans *trans);
+void iwl_disable_ict(struct iwl_trans *trans);
+int iwl_alloc_isr_ict(struct iwl_trans *trans);
+void iwl_free_isr_ict(struct iwl_trans *trans);
+irqreturn_t iwl_isr_ict(int irq, void *data);
+
+/*****************************************************
+* TX / HCMD
+******************************************************/
+void iwl_txq_update_write_ptr(struct iwl_trans *trans,
+                       struct iwl_tx_queue *txq);
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
+                                struct iwl_tx_queue *txq,
+                                dma_addr_t addr, u16 len, u8 reset);
+int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
+int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
+void iwl_tx_cmd_complete(struct iwl_trans *trans,
+                        struct iwl_rx_mem_buffer *rxb, int handler_status);
+void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
+                                          struct iwl_tx_queue *txq,
+                                          u16 byte_cnt);
+void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
+int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
+                                 enum iwl_rxon_context_id ctx, int sta_id,
+                                 int tid);
+void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
+void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
+                            struct iwl_tx_queue *txq,
+                            int tx_fifo_id, int scd_retry);
+int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
+                               enum iwl_rxon_context_id ctx, int sta_id,
+                               int tid, u16 *ssn);
+void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
+                                enum iwl_rxon_context_id ctx,
+                                int sta_id, int tid, int frame_limit);
+void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
+       int index, enum dma_data_direction dma_dir);
+int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
+                        struct sk_buff_head *skbs);
+int iwl_queue_space(const struct iwl_queue *q);
+
+/*****************************************************
+* Error handling
+******************************************************/
+int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
+                           char **buf, bool display);
+int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
+void iwl_dump_csr(struct iwl_trans *trans);
+
+/*****************************************************
+* Helpers
+******************************************************/
+static inline void iwl_disable_interrupts(struct iwl_trans *trans)
+{
+       clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+
+       /* disable interrupts from uCode/NIC to host */
+       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
+
+       /* acknowledge/clear/reset any interrupts still pending
+        * from uCode or flow handler (Rx/Tx DMA) */
+       iwl_write32(bus(trans), CSR_INT, 0xffffffff);
+       iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff);
+       IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
+}
+
+static inline void iwl_enable_interrupts(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
+       set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
+       iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
+}
+
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
+{
+       BUG_ON(ac > 3);   /* only have 2 bits */
+       BUG_ON(hwq > 31); /* only use 5 bits */
+
+       txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void iwl_wake_queue(struct iwl_trans *trans,
+                                 struct iwl_tx_queue *txq)
+{
+       u8 queue = txq->swq_id;
+       u8 ac = queue & 3;
+       u8 hwq = (queue >> 2) & 0x1f;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (test_and_clear_bit(hwq, trans_pcie->queue_stopped))
+               if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0)
+                       iwl_wake_sw_queue(priv(trans), ac);
+}
+
+static inline void iwl_stop_queue(struct iwl_trans *trans,
+                                 struct iwl_tx_queue *txq)
+{
+       u8 queue = txq->swq_id;
+       u8 ac = queue & 3;
+       u8 hwq = (queue >> 2) & 0x1f;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (!test_and_set_bit(hwq, trans_pcie->queue_stopped))
+               if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0)
+                       iwl_stop_sw_queue(priv(trans), ac);
+}
+
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
+static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
+                                       int txq_id)
+{
+       set_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
+}
+
+static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie,
+                                         int txq_id)
+{
+       clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk);
+}
+
+static inline int iwl_queue_used(const struct iwl_queue *q, int i)
+{
+       return q->write_ptr >= q->read_ptr ?
+               (i >= q->read_ptr && i < q->write_ptr) :
+               !(i < q->read_ptr && i >= q->write_ptr);
+}
+
+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
+{
+       return index & (q->n_window - 1);
+}
+
+#define IWL_TX_FIFO_BK         0       /* shared */
+#define IWL_TX_FIFO_BE         1
+#define IWL_TX_FIFO_VI         2       /* shared */
+#define IWL_TX_FIFO_VO         3
+#define IWL_TX_FIFO_BK_IPAN    IWL_TX_FIFO_BK
+#define IWL_TX_FIFO_BE_IPAN    4
+#define IWL_TX_FIFO_VI_IPAN    IWL_TX_FIFO_VI
+#define IWL_TX_FIFO_VO_IPAN    5
+/* re-uses the VO FIFO, uCode will properly flush/schedule */
+#define IWL_TX_FIFO_AUX                5
+#define IWL_TX_FIFO_UNUSED     -1
+
+/* AUX (TX during scan dwell) queue */
+#define IWL_AUX_QUEUE          10
+
+#endif /* __iwl_trans_int_pcie_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
new file mode 100644 (file)
index 0000000..3ef9eac
--- /dev/null
@@ -0,0 +1,1433 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/gfp.h>
+
+/*TODO: Remove include to iwl-core.h*/
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-trans-pcie-int.h"
+
+/******************************************************************************
+ *
+ * RX path functions
+ *
+ ******************************************************************************/
+
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC.  These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC.  The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl_rx_queue_alloc()   Allocates rx_free
+ * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl_rx_queue_restock
+ * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_rx_queue_space - Return number of free slots available in queue.
+ */
+static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+{
+       int s = q->read - q->write;
+       if (s <= 0)
+               s += RX_QUEUE_SIZE;
+       /* keep some buffer to not confuse full and empty queue */
+       s -= 2;
+       if (s < 0)
+               s = 0;
+       return s;
+}
+
+/**
+ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
+                       struct iwl_rx_queue *q)
+{
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(&q->lock, flags);
+
+       if (q->need_update == 0)
+               goto exit_unlock;
+
+       if (hw_params(trans).shadow_reg_enable) {
+               /* shadow register enabled */
+               /* Device expects a multiple of 8 */
+               q->write_actual = (q->write & ~0x7);
+               iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual);
+       } else {
+               /* If power-saving is in use, make sure device is awake */
+               if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
+                       reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
+
+                       if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+                               IWL_DEBUG_INFO(trans,
+                                       "Rx queue requesting wakeup,"
+                                       " GP1 = 0x%x\n", reg);
+                               iwl_set_bit(bus(trans), CSR_GP_CNTRL,
+                                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                               goto exit_unlock;
+                       }
+
+                       q->write_actual = (q->write & ~0x7);
+                       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
+                                       q->write_actual);
+
+               /* Else device is assumed to be awake */
+               } else {
+                       /* Device expects a multiple of 8 */
+                       q->write_actual = (q->write & ~0x7);
+                       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
+                               q->write_actual);
+               }
+       }
+       q->need_update = 0;
+
+ exit_unlock:
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+
+/**
+ * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr)
+{
+       return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       struct list_head *element;
+       struct iwl_rx_mem_buffer *rxb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rxq->lock, flags);
+       while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+               /* The overwritten rxb must be a used one */
+               rxb = rxq->queue[rxq->write];
+               BUG_ON(rxb && rxb->page);
+
+               /* Get next free Rx buffer, remove from free list */
+               element = rxq->rx_free.next;
+               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+               list_del(element);
+
+               /* Point to Rx buffer via next RBD in circular buffer */
+               rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma);
+               rxq->queue[rxq->write] = rxb;
+               rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+               rxq->free_count--;
+       }
+       spin_unlock_irqrestore(&rxq->lock, flags);
+       /* If the pre-allocated buffer pool is dropping low, schedule to
+        * refill it */
+       if (rxq->free_count <= RX_LOW_WATERMARK)
+               queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish);
+
+
+       /* If we've added more space for the firmware to place data, tell it.
+        * Increment device's write pointer in multiples of 8. */
+       if (rxq->write_actual != (rxq->write & ~0x7)) {
+               spin_lock_irqsave(&rxq->lock, flags);
+               rxq->need_update = 1;
+               spin_unlock_irqrestore(&rxq->lock, flags);
+               iwl_rx_queue_update_write_ptr(trans, rxq);
+       }
+}
+
+/**
+ * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       struct list_head *element;
+       struct iwl_rx_mem_buffer *rxb;
+       struct page *page;
+       unsigned long flags;
+       gfp_t gfp_mask = priority;
+
+       while (1) {
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               if (rxq->free_count > RX_LOW_WATERMARK)
+                       gfp_mask |= __GFP_NOWARN;
+
+               if (hw_params(trans).rx_page_order > 0)
+                       gfp_mask |= __GFP_COMP;
+
+               /* Alloc a new receive buffer */
+               page = alloc_pages(gfp_mask,
+                                 hw_params(trans).rx_page_order);
+               if (!page) {
+                       if (net_ratelimit())
+                               IWL_DEBUG_INFO(trans, "alloc_pages failed, "
+                                          "order: %d\n",
+                                          hw_params(trans).rx_page_order);
+
+                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+                           net_ratelimit())
+                               IWL_CRIT(trans, "Failed to alloc_pages with %s."
+                                        "Only %u free buffers remaining.\n",
+                                        priority == GFP_ATOMIC ?
+                                        "GFP_ATOMIC" : "GFP_KERNEL",
+                                        rxq->free_count);
+                       /* We don't reschedule replenish work here -- we will
+                        * call the restock method and if it still needs
+                        * more buffers it will schedule replenish */
+                       return;
+               }
+
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               if (list_empty(&rxq->rx_used)) {
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, hw_params(trans).rx_page_order);
+                       return;
+               }
+               element = rxq->rx_used.next;
+               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+               list_del(element);
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               BUG_ON(rxb->page);
+               rxb->page = page;
+               /* Get physical address of the RB */
+               rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0,
+                               PAGE_SIZE << hw_params(trans).rx_page_order,
+                               DMA_FROM_DEVICE);
+               /* dma address must be no more than 36 bits */
+               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+               /* and also 256 byte aligned! */
+               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+               spin_lock_irqsave(&rxq->lock, flags);
+
+               list_add_tail(&rxb->list, &rxq->rx_free);
+               rxq->free_count++;
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+       }
+}
+
+void iwlagn_rx_replenish(struct iwl_trans *trans)
+{
+       unsigned long flags;
+
+       iwlagn_rx_allocate(trans, GFP_KERNEL);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwlagn_rx_queue_restock(trans);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
+
+static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
+{
+       iwlagn_rx_allocate(trans, GFP_ATOMIC);
+
+       iwlagn_rx_queue_restock(trans);
+}
+
+void iwl_bg_rx_replenish(struct work_struct *data)
+{
+       struct iwl_trans_pcie *trans_pcie =
+           container_of(data, struct iwl_trans_pcie, rx_replenish);
+       struct iwl_trans *trans = trans_pcie->trans;
+
+       if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
+               return;
+
+       mutex_lock(&trans->shrd->mutex);
+       iwlagn_rx_replenish(trans);
+       mutex_unlock(&trans->shrd->mutex);
+}
+
+/**
+ * iwl_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+static void iwl_rx_handle(struct iwl_trans *trans)
+{
+       struct iwl_rx_mem_buffer *rxb;
+       struct iwl_rx_packet *pkt;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
+       struct iwl_device_cmd *cmd;
+       u32 r, i;
+       int reclaim;
+       unsigned long flags;
+       u8 fill_rx = 0;
+       u32 count = 8;
+       int total_empty;
+       int index, cmd_index;
+
+       /* uCode's read index (stored in shared DRAM) indicates the last Rx
+        * buffer that the driver may process (last buffer filled by ucode). */
+       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
+       i = rxq->read;
+
+       /* Rx interrupt, but nothing sent from uCode */
+       if (i == r)
+               IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i);
+
+       /* calculate total frames need to be restock after handling RX */
+       total_empty = r - rxq->write_actual;
+       if (total_empty < 0)
+               total_empty += RX_QUEUE_SIZE;
+
+       if (total_empty > (RX_QUEUE_SIZE / 2))
+               fill_rx = 1;
+
+       while (i != r) {
+               int len, err;
+               u16 txq_id, sequence;
+
+               rxb = rxq->queue[i];
+
+               /* If an RXB doesn't have a Rx queue slot associated with it,
+                * then a bug has been introduced in the queue refilling
+                * routines -- catch it here */
+               if (WARN_ON(rxb == NULL)) {
+                       i = (i + 1) & RX_QUEUE_MASK;
+                       continue;
+               }
+
+               rxq->queue[i] = NULL;
+
+               dma_unmap_page(bus(trans)->dev, rxb->page_dma,
+                              PAGE_SIZE << hw_params(trans).rx_page_order,
+                              DMA_FROM_DEVICE);
+               pkt = rxb_addr(rxb);
+
+               IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
+                       i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+
+               len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+               len += sizeof(u32); /* account for status word */
+               trace_iwlwifi_dev_rx(priv(trans), pkt, len);
+
+               /* Reclaim a command buffer only if this packet is a response
+                *   to a (driver-originated) command.
+                * If the packet (e.g. Rx frame) originated from uCode,
+                *   there is no command buffer to reclaim.
+                * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+                *   but apparently a few don't get set; catch them here. */
+               reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+                       (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+                       (pkt->hdr.cmd != REPLY_RX) &&
+                       (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+                       (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+                       (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+                       (pkt->hdr.cmd != REPLY_TX);
+
+               sequence = le16_to_cpu(pkt->hdr.sequence);
+               index = SEQ_TO_INDEX(sequence);
+               cmd_index = get_cmd_index(&txq->q, index);
+
+               if (reclaim)
+                       cmd = txq->cmd[cmd_index];
+               else
+                       cmd = NULL;
+
+               /* warn if this is cmd response / notification and the uCode
+                * didn't set the SEQ_RX_FRAME for a frame that is
+                * uCode-originated*/
+               WARN(txq_id == trans->shrd->cmd_queue && reclaim == false &&
+                    (!(pkt->hdr.sequence & SEQ_RX_FRAME)),
+                    "reclaim is false, SEQ_RX_FRAME unset: %s\n",
+                    get_cmd_string(pkt->hdr.cmd));
+
+               err = iwl_rx_dispatch(priv(trans), rxb, cmd);
+
+               /*
+                * XXX: After here, we should always check rxb->page
+                * against NULL before touching it or its virtual
+                * memory (pkt). Because some rx_handler might have
+                * already taken or freed the pages.
+                */
+
+               if (reclaim) {
+                       /* Invoke any callbacks, transfer the buffer to caller,
+                        * and fire off the (possibly) blocking
+                        * iwl_trans_send_cmd()
+                        * as we reclaim the driver command queue */
+                       if (rxb->page)
+                               iwl_tx_cmd_complete(trans, rxb, err);
+                       else
+                               IWL_WARN(trans, "Claim null rxb?\n");
+               }
+
+               /* Reuse the page if possible. For notification packets and
+                * SKBs that fail to Rx correctly, add them back into the
+                * rx_free list for reuse later. */
+               spin_lock_irqsave(&rxq->lock, flags);
+               if (rxb->page != NULL) {
+                       rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page,
+                               0, PAGE_SIZE <<
+                                   hw_params(trans).rx_page_order,
+                               DMA_FROM_DEVICE);
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               } else
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+
+               spin_unlock_irqrestore(&rxq->lock, flags);
+
+               i = (i + 1) & RX_QUEUE_MASK;
+               /* If there are a lot of unused frames,
+                * restock the Rx queue so ucode wont assert. */
+               if (fill_rx) {
+                       count++;
+                       if (count >= 8) {
+                               rxq->read = i;
+                               iwlagn_rx_replenish_now(trans);
+                               count = 0;
+                       }
+               }
+       }
+
+       /* Backtrack one entry */
+       rxq->read = i;
+       if (fill_rx)
+               iwlagn_rx_replenish_now(trans);
+       else
+               iwlagn_rx_queue_restock(trans);
+}
+
+static const char * const desc_lookup_text[] = {
+       "OK",
+       "FAIL",
+       "BAD_PARAM",
+       "BAD_CHECKSUM",
+       "NMI_INTERRUPT_WDG",
+       "SYSASSERT",
+       "FATAL_ERROR",
+       "BAD_COMMAND",
+       "HW_ERROR_TUNE_LOCK",
+       "HW_ERROR_TEMPERATURE",
+       "ILLEGAL_CHAN_FREQ",
+       "VCC_NOT_STABLE",
+       "FH_ERROR",
+       "NMI_INTERRUPT_HOST",
+       "NMI_INTERRUPT_ACTION_PT",
+       "NMI_INTERRUPT_UNKNOWN",
+       "UCODE_VERSION_MISMATCH",
+       "HW_ERROR_ABS_LOCK",
+       "HW_ERROR_CAL_LOCK_FAIL",
+       "NMI_INTERRUPT_INST_ACTION_PT",
+       "NMI_INTERRUPT_DATA_ACTION_PT",
+       "NMI_TRM_HW_ER",
+       "NMI_INTERRUPT_TRM",
+       "NMI_INTERRUPT_BREAK_POINT",
+       "DEBUG_0",
+       "DEBUG_1",
+       "DEBUG_2",
+       "DEBUG_3",
+};
+
+static struct { char *name; u8 num; } advanced_lookup[] = {
+       { "NMI_INTERRUPT_WDG", 0x34 },
+       { "SYSASSERT", 0x35 },
+       { "UCODE_VERSION_MISMATCH", 0x37 },
+       { "BAD_COMMAND", 0x38 },
+       { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
+       { "FATAL_ERROR", 0x3D },
+       { "NMI_TRM_HW_ERR", 0x46 },
+       { "NMI_INTERRUPT_TRM", 0x4C },
+       { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
+       { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
+       { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
+       { "NMI_INTERRUPT_HOST", 0x66 },
+       { "NMI_INTERRUPT_ACTION_PT", 0x7C },
+       { "NMI_INTERRUPT_UNKNOWN", 0x84 },
+       { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
+       { "ADVANCED_SYSASSERT", 0 },
+};
+
+static const char *desc_lookup(u32 num)
+{
+       int i;
+       int max = ARRAY_SIZE(desc_lookup_text);
+
+       if (num < max)
+               return desc_lookup_text[num];
+
+       max = ARRAY_SIZE(advanced_lookup) - 1;
+       for (i = 0; i < max; i++) {
+               if (advanced_lookup[i].num == num)
+                       break;
+       }
+       return advanced_lookup[i].name;
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+static void iwl_dump_nic_error_log(struct iwl_trans *trans)
+{
+       u32 base;
+       struct iwl_error_event_table table;
+       struct iwl_priv *priv = priv(trans);
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       base = priv->device_pointers.error_event_table;
+       if (priv->ucode_type == IWL_UCODE_INIT) {
+               if (!base)
+                       base = priv->init_errlog_ptr;
+       } else {
+               if (!base)
+                       base = priv->inst_errlog_ptr;
+       }
+
+       if (!iwlagn_hw_valid_rtc_data_addr(base)) {
+               IWL_ERR(trans,
+                       "Not valid error log pointer 0x%08X for %s uCode\n",
+                       base,
+                       (priv->ucode_type == IWL_UCODE_INIT)
+                                       ? "Init" : "RT");
+               return;
+       }
+
+       iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table));
+
+       if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
+               IWL_ERR(trans, "Start IWL Error Log Dump:\n");
+               IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
+                       trans->shrd->status, table.valid);
+       }
+
+       trans_pcie->isr_stats.err_code = table.error_id;
+
+       trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
+                                     table.data1, table.data2, table.line,
+                                     table.blink1, table.blink2, table.ilink1,
+                                     table.ilink2, table.bcon_time, table.gp1,
+                                     table.gp2, table.gp3, table.ucode_ver,
+                                     table.hw_ver, table.brd_ver);
+       IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id,
+               desc_lookup(table.error_id));
+       IWL_ERR(trans, "0x%08X | uPc\n", table.pc);
+       IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1);
+       IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2);
+       IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1);
+       IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2);
+       IWL_ERR(trans, "0x%08X | data1\n", table.data1);
+       IWL_ERR(trans, "0x%08X | data2\n", table.data2);
+       IWL_ERR(trans, "0x%08X | line\n", table.line);
+       IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time);
+       IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low);
+       IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi);
+       IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1);
+       IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2);
+       IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3);
+       IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver);
+       IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver);
+       IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver);
+       IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd);
+}
+
+/**
+ * iwl_irq_handle_error - called for HW or SW error interrupt from card
+ */
+static void iwl_irq_handle_error(struct iwl_trans *trans)
+{
+       struct iwl_priv *priv = priv(trans);
+       /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
+       if (priv->cfg->internal_wimax_coex &&
+           (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
+                       APMS_CLK_VAL_MRB_FUNC_MODE) ||
+            (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
+                       APMG_PS_CTRL_VAL_RESET_REQ))) {
+               /*
+                * Keep the restart process from trying to send host
+                * commands by clearing the ready bit.
+                */
+               clear_bit(STATUS_READY, &trans->shrd->status);
+               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+               wake_up(&priv->shrd->wait_command_queue);
+               IWL_ERR(trans, "RF is used by WiMAX\n");
+               return;
+       }
+
+       IWL_ERR(trans, "Loaded firmware version: %s\n",
+               priv->hw->wiphy->fw_version);
+
+       iwl_dump_nic_error_log(trans);
+       iwl_dump_csr(trans);
+       iwl_dump_fh(trans, NULL, false);
+       iwl_dump_nic_event_log(trans, false, NULL, false);
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS)
+               iwl_print_rx_config_cmd(priv(trans), IWL_RXON_CTX_BSS);
+#endif
+
+       iwlagn_fw_error(priv, false);
+}
+
+#define EVENT_START_OFFSET  (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
+                              u32 num_events, u32 mode,
+                              int pos, char **buf, size_t bufsz)
+{
+       u32 i;
+       u32 base;       /* SRAM byte address of event log header */
+       u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+       u32 ptr;        /* SRAM byte address of log data */
+       u32 ev, time, data; /* event log data */
+       unsigned long reg_flags;
+       struct iwl_priv *priv = priv(trans);
+
+       if (num_events == 0)
+               return pos;
+
+       base = priv->device_pointers.log_event_table;
+       if (priv->ucode_type == IWL_UCODE_INIT) {
+               if (!base)
+                       base = priv->init_evtlog_ptr;
+       } else {
+               if (!base)
+                       base = priv->inst_evtlog_ptr;
+       }
+
+       if (mode == 0)
+               event_size = 2 * sizeof(u32);
+       else
+               event_size = 3 * sizeof(u32);
+
+       ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+       /* Make sure device is powered up for SRAM reads */
+       spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags);
+       iwl_grab_nic_access(bus(trans));
+
+       /* Set starting address; reads will auto-increment */
+       iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr);
+       rmb();
+
+       /* "time" is actually "data" for mode 0 (no timestamp).
+       * place event id # at far right for easier visual parsing. */
+       for (i = 0; i < num_events; i++) {
+               ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+               time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+               if (mode == 0) {
+                       /* data, ev */
+                       if (bufsz) {
+                               pos += scnprintf(*buf + pos, bufsz - pos,
+                                               "EVT_LOG:0x%08x:%04u\n",
+                                               time, ev);
+                       } else {
+                               trace_iwlwifi_dev_ucode_event(priv, 0,
+                                       time, ev);
+                               IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
+                                       time, ev);
+                       }
+               } else {
+                       data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT);
+                       if (bufsz) {
+                               pos += scnprintf(*buf + pos, bufsz - pos,
+                                               "EVT_LOGT:%010u:0x%08x:%04u\n",
+                                                time, data, ev);
+                       } else {
+                               IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
+                                       time, data, ev);
+                               trace_iwlwifi_dev_ucode_event(priv, time,
+                                       data, ev);
+                       }
+               }
+       }
+
+       /* Allow device to power down */
+       iwl_release_nic_access(bus(trans));
+       spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags);
+       return pos;
+}
+
+/**
+ * iwl_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity,
+                                   u32 num_wraps, u32 next_entry,
+                                   u32 size, u32 mode,
+                                   int pos, char **buf, size_t bufsz)
+{
+       /*
+        * display the newest DEFAULT_LOG_ENTRIES entries
+        * i.e the entries just before the next ont that uCode would fill.
+        */
+       if (num_wraps) {
+               if (next_entry < size) {
+                       pos = iwl_print_event_log(trans,
+                                               capacity - (size - next_entry),
+                                               size - next_entry, mode,
+                                               pos, buf, bufsz);
+                       pos = iwl_print_event_log(trans, 0,
+                                                 next_entry, mode,
+                                                 pos, buf, bufsz);
+               } else
+                       pos = iwl_print_event_log(trans, next_entry - size,
+                                                 size, mode, pos, buf, bufsz);
+       } else {
+               if (next_entry < size) {
+                       pos = iwl_print_event_log(trans, 0, next_entry,
+                                                 mode, pos, buf, bufsz);
+               } else {
+                       pos = iwl_print_event_log(trans, next_entry - size,
+                                                 size, mode, pos, buf, bufsz);
+               }
+       }
+       return pos;
+}
+
+#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
+                           char **buf, bool display)
+{
+       u32 base;       /* SRAM byte address of event log header */
+       u32 capacity;   /* event log capacity in # entries */
+       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+       u32 num_wraps;  /* # times uCode wrapped to top of log */
+       u32 next_entry; /* index of next entry to be written by uCode */
+       u32 size;       /* # entries that we'll print */
+       u32 logsize;
+       int pos = 0;
+       size_t bufsz = 0;
+       struct iwl_priv *priv = priv(trans);
+
+       base = priv->device_pointers.log_event_table;
+       if (priv->ucode_type == IWL_UCODE_INIT) {
+               logsize = priv->init_evtlog_size;
+               if (!base)
+                       base = priv->init_evtlog_ptr;
+       } else {
+               logsize = priv->inst_evtlog_size;
+               if (!base)
+                       base = priv->inst_evtlog_ptr;
+       }
+
+       if (!iwlagn_hw_valid_rtc_data_addr(base)) {
+               IWL_ERR(trans,
+                       "Invalid event log pointer 0x%08X for %s uCode\n",
+                       base,
+                       (priv->ucode_type == IWL_UCODE_INIT)
+                                       ? "Init" : "RT");
+               return -EINVAL;
+       }
+
+       /* event log header */
+       capacity = iwl_read_targ_mem(bus(trans), base);
+       mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32)));
+       num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32)));
+       next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32)));
+
+       if (capacity > logsize) {
+               IWL_ERR(trans, "Log capacity %d is bogus, limit to %d "
+                       "entries\n", capacity, logsize);
+               capacity = logsize;
+       }
+
+       if (next_entry > logsize) {
+               IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n",
+                       next_entry, logsize);
+               next_entry = logsize;
+       }
+
+       size = num_wraps ? capacity : next_entry;
+
+       /* bail out if nothing in log */
+       if (size == 0) {
+               IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n");
+               return pos;
+       }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
+               size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+                       ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+       size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+               ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+       IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n",
+               size);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (display) {
+               if (full_log)
+                       bufsz = capacity * 48;
+               else
+                       bufsz = size * 48;
+               *buf = kmalloc(bufsz, GFP_KERNEL);
+               if (!*buf)
+                       return -ENOMEM;
+       }
+       if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
+               /*
+                * if uCode has wrapped back to top of log,
+                * start at the oldest entry,
+                * i.e the next one that uCode would fill.
+                */
+               if (num_wraps)
+                       pos = iwl_print_event_log(trans, next_entry,
+                                               capacity - next_entry, mode,
+                                               pos, buf, bufsz);
+               /* (then/else) start at top of log */
+               pos = iwl_print_event_log(trans, 0,
+                                         next_entry, mode, pos, buf, bufsz);
+       } else
+               pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
+                                               next_entry, size, mode,
+                                               pos, buf, bufsz);
+#else
+       pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
+                                       next_entry, size, mode,
+                                       pos, buf, bufsz);
+#endif
+       return pos;
+}
+
+/* tasklet for iwlagn interrupt */
+void iwl_irq_tasklet(struct iwl_trans *trans)
+{
+       u32 inta = 0;
+       u32 handled = 0;
+       unsigned long flags;
+       u32 i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       u32 inta_mask;
+#endif
+
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       /* Ack/clear/reset pending uCode interrupts.
+        * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+        */
+       /* There is a hardware bug in the interrupt mask function that some
+        * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
+        * they are disabled in the CSR_INT_MASK register. Furthermore the
+        * ICT interrupt handling mechanism has another bug that might cause
+        * these unmasked interrupts fail to be detected. We workaround the
+        * hardware bugs here by ACKing all the possible interrupts so that
+        * interrupt coalescing can still be achieved.
+        */
+       iwl_write32(bus(trans), CSR_INT,
+               trans_pcie->inta | ~trans_pcie->inta_mask);
+
+       inta = trans_pcie->inta;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
+               /* just for debug */
+               inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);
+               IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
+                               inta, inta_mask);
+       }
+#endif
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* saved interrupt in inta variable now we can reset trans_pcie->inta */
+       trans_pcie->inta = 0;
+
+       /* Now service all interrupt bits discovered above. */
+       if (inta & CSR_INT_BIT_HW_ERR) {
+               IWL_ERR(trans, "Hardware error detected.  Restarting.\n");
+
+               /* Tell the device to stop sending interrupts */
+               iwl_disable_interrupts(trans);
+
+               isr_stats->hw++;
+               iwl_irq_handle_error(trans);
+
+               handled |= CSR_INT_BIT_HW_ERR;
+
+               return;
+       }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+               /* NIC fires this, but we don't use it, redundant with WAKEUP */
+               if (inta & CSR_INT_BIT_SCD) {
+                       IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
+                                     "the frame/frames.\n");
+                       isr_stats->sch++;
+               }
+
+               /* Alive notification via Rx interrupt will do the real work */
+               if (inta & CSR_INT_BIT_ALIVE) {
+                       IWL_DEBUG_ISR(trans, "Alive interrupt\n");
+                       isr_stats->alive++;
+               }
+       }
+#endif
+       /* Safely ignore these bits for debug checks below */
+       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+       /* HW RF KILL switch toggled */
+       if (inta & CSR_INT_BIT_RF_KILL) {
+               int hw_rf_kill = 0;
+               if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
+                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+                       hw_rf_kill = 1;
+
+               IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
+                               hw_rf_kill ? "disable radio" : "enable radio");
+
+               isr_stats->rfkill++;
+
+               /* driver only loads ucode once setting the interface up.
+                * the driver allows loading the ucode even if the radio
+                * is killed. Hence update the killswitch state here. The
+                * rfkill handler will care about restarting if needed.
+                */
+               if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
+                       if (hw_rf_kill)
+                               set_bit(STATUS_RF_KILL_HW,
+                                       &trans->shrd->status);
+                       else
+                               clear_bit(STATUS_RF_KILL_HW,
+                                         &trans->shrd->status);
+                       iwl_set_hw_rfkill_state(priv(trans), hw_rf_kill);
+               }
+
+               handled |= CSR_INT_BIT_RF_KILL;
+       }
+
+       /* Chip got too hot and stopped itself */
+       if (inta & CSR_INT_BIT_CT_KILL) {
+               IWL_ERR(trans, "Microcode CT kill error detected.\n");
+               isr_stats->ctkill++;
+               handled |= CSR_INT_BIT_CT_KILL;
+       }
+
+       /* Error detected by uCode */
+       if (inta & CSR_INT_BIT_SW_ERR) {
+               IWL_ERR(trans, "Microcode SW error detected. "
+                       " Restarting 0x%X.\n", inta);
+               isr_stats->sw++;
+               iwl_irq_handle_error(trans);
+               handled |= CSR_INT_BIT_SW_ERR;
+       }
+
+       /* uCode wakes up after power-down sleep */
+       if (inta & CSR_INT_BIT_WAKEUP) {
+               IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
+               iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
+               for (i = 0; i < hw_params(trans).max_txq_num; i++)
+                       iwl_txq_update_write_ptr(trans,
+                                                &trans_pcie->txq[i]);
+
+               isr_stats->wakeup++;
+
+               handled |= CSR_INT_BIT_WAKEUP;
+       }
+
+       /* All uCode command responses, including Tx command responses,
+        * Rx "responses" (frame-received notification), and other
+        * notifications from uCode come through here*/
+       if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
+                       CSR_INT_BIT_RX_PERIODIC)) {
+               IWL_DEBUG_ISR(trans, "Rx interrupt\n");
+               if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+                       handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+                       iwl_write32(bus(trans), CSR_FH_INT_STATUS,
+                                       CSR_FH_INT_RX_MASK);
+               }
+               if (inta & CSR_INT_BIT_RX_PERIODIC) {
+                       handled |= CSR_INT_BIT_RX_PERIODIC;
+                       iwl_write32(bus(trans),
+                               CSR_INT, CSR_INT_BIT_RX_PERIODIC);
+               }
+               /* Sending RX interrupt require many steps to be done in the
+                * the device:
+                * 1- write interrupt to current index in ICT table.
+                * 2- dma RX frame.
+                * 3- update RX shared data to indicate last write index.
+                * 4- send interrupt.
+                * This could lead to RX race, driver could receive RX interrupt
+                * but the shared data changes does not reflect this;
+                * periodic interrupt will detect any dangling Rx activity.
+                */
+
+               /* Disable periodic interrupt; we use it as just a one-shot. */
+               iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
+                           CSR_INT_PERIODIC_DIS);
+               iwl_rx_handle(trans);
+
+               /*
+                * Enable periodic interrupt in 8 msec only if we received
+                * real RX interrupt (instead of just periodic int), to catch
+                * any dangling Rx interrupt.  If it was just the periodic
+                * interrupt, there was no dangling Rx activity, and no need
+                * to extend the periodic interrupt; one-shot is enough.
+                */
+               if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
+                       iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
+                                   CSR_INT_PERIODIC_ENA);
+
+               isr_stats->rx++;
+       }
+
+       /* This "Tx" DMA channel is used only for loading uCode */
+       if (inta & CSR_INT_BIT_FH_TX) {
+               iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
+               IWL_DEBUG_ISR(trans, "uCode load interrupt\n");
+               isr_stats->tx++;
+               handled |= CSR_INT_BIT_FH_TX;
+               /* Wake up uCode load routine, now that load is complete */
+               priv(trans)->ucode_write_complete = 1;
+               wake_up(&trans->shrd->wait_command_queue);
+       }
+
+       if (inta & ~handled) {
+               IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+               isr_stats->unhandled++;
+       }
+
+       if (inta & ~(trans_pcie->inta_mask)) {
+               IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n",
+                        inta & ~trans_pcie->inta_mask);
+       }
+
+       /* Re-enable all interrupts */
+       /* only Re-enable if disabled by irq */
+       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
+               iwl_enable_interrupts(trans);
+       /* Re-enable RF_KILL if it occurred */
+       else if (handled & CSR_INT_BIT_RF_KILL)
+               iwl_enable_rfkill_int(priv(trans));
+}
+
+/******************************************************************************
+ *
+ * ICT functions
+ *
+ ******************************************************************************/
+#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* Free dram table */
+void iwl_free_isr_ict(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (trans_pcie->ict_tbl_vir) {
+               dma_free_coherent(bus(trans)->dev,
+                                 (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+                                 trans_pcie->ict_tbl_vir,
+                                 trans_pcie->ict_tbl_dma);
+               trans_pcie->ict_tbl_vir = NULL;
+               memset(&trans_pcie->ict_tbl_dma, 0,
+                       sizeof(trans_pcie->ict_tbl_dma));
+               memset(&trans_pcie->aligned_ict_tbl_dma, 0,
+                       sizeof(trans_pcie->aligned_ict_tbl_dma));
+       }
+}
+
+
+/* allocate dram shared table it is a PAGE_SIZE aligned
+ * also reset all data related to ICT table interrupt.
+ */
+int iwl_alloc_isr_ict(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       /* allocate shrared data table */
+       trans_pcie->ict_tbl_vir =
+               dma_alloc_coherent(bus(trans)->dev,
+                                  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+                                  &trans_pcie->ict_tbl_dma, GFP_KERNEL);
+       if (!trans_pcie->ict_tbl_vir)
+               return -ENOMEM;
+
+       /* align table to PAGE_SIZE boundary */
+       trans_pcie->aligned_ict_tbl_dma =
+               ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
+
+       IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
+                          (unsigned long long)trans_pcie->ict_tbl_dma,
+                          (unsigned long long)trans_pcie->aligned_ict_tbl_dma,
+                          (int)(trans_pcie->aligned_ict_tbl_dma -
+                          trans_pcie->ict_tbl_dma));
+
+       trans_pcie->ict_tbl =  trans_pcie->ict_tbl_vir +
+                         (trans_pcie->aligned_ict_tbl_dma -
+                         trans_pcie->ict_tbl_dma);
+
+       IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
+                            trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
+                       (int)(trans_pcie->aligned_ict_tbl_dma -
+                           trans_pcie->ict_tbl_dma));
+
+       /* reset table and index to all 0 */
+       memset(trans_pcie->ict_tbl_vir, 0,
+               (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+       trans_pcie->ict_index = 0;
+
+       /* add periodic RX interrupt */
+       trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
+       return 0;
+}
+
+/* Device is going up inform it about using ICT interrupt table,
+ * also we need to tell the driver to start using ICT interrupt.
+ */
+int iwl_reset_ict(struct iwl_trans *trans)
+{
+       u32 val;
+       unsigned long flags;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (!trans_pcie->ict_tbl_vir)
+               return 0;
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwl_disable_interrupts(trans);
+
+       memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+
+       val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
+
+       val |= CSR_DRAM_INT_TBL_ENABLE;
+       val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
+
+       IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
+                       "aligned dma address %Lx\n",
+                       val,
+                       (unsigned long long)trans_pcie->aligned_ict_tbl_dma);
+
+       iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
+       trans_pcie->use_ict = true;
+       trans_pcie->ict_index = 0;
+       iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask);
+       iwl_enable_interrupts(trans);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       return 0;
+}
+
+/* Device is going down disable ict interrupt usage */
+void iwl_disable_ict(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       unsigned long flags;
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       trans_pcie->use_ict = false;
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
+
+static irqreturn_t iwl_isr(int irq, void *data)
+{
+       struct iwl_trans *trans = data;
+       struct iwl_trans_pcie *trans_pcie;
+       u32 inta, inta_mask;
+       unsigned long flags;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       u32 inta_fh;
+#endif
+       if (!trans)
+               return IRQ_NONE;
+
+       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       /* Disable (but don't clear!) interrupts here to avoid
+        *    back-to-back ISRs and sporadic interrupts from our NIC.
+        * If we have something to service, the tasklet will re-enable ints.
+        * If we *don't* have something, we'll re-enable before leaving here. */
+       inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);  /* just for debug */
+       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
+
+       /* Discover which interrupts are active/pending */
+       inta = iwl_read32(bus(trans), CSR_INT);
+
+       /* Ignore interrupt if there's nothing in NIC to service.
+        * This may be due to IRQ shared with another device,
+        * or due to sporadic interrupts thrown from our NIC. */
+       if (!inta) {
+               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+               goto none;
+       }
+
+       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+               /* Hardware disappeared. It might have already raised
+                * an interrupt */
+               IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+               goto unplugged;
+       }
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
+               inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS);
+               IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
+                             "fh 0x%08x\n", inta, inta_mask, inta_fh);
+       }
+#endif
+
+       trans_pcie->inta |= inta;
+       /* iwl_irq_tasklet() will service interrupts and re-enable them */
+       if (likely(inta))
+               tasklet_schedule(&trans_pcie->irq_tasklet);
+       else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+                       !trans_pcie->inta)
+               iwl_enable_interrupts(trans);
+
+ unplugged:
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+       return IRQ_HANDLED;
+
+ none:
+       /* re-enable interrupts here since we don't have anything to service. */
+       /* only Re-enable if disabled by irq  and no schedules tasklet. */
+       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+               !trans_pcie->inta)
+               iwl_enable_interrupts(trans);
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+       return IRQ_NONE;
+}
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+irqreturn_t iwl_isr_ict(int irq, void *data)
+{
+       struct iwl_trans *trans = data;
+       struct iwl_trans_pcie *trans_pcie;
+       u32 inta, inta_mask;
+       u32 val = 0;
+       unsigned long flags;
+
+       if (!trans)
+               return IRQ_NONE;
+
+       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       /* dram interrupt table not set yet,
+        * use legacy interrupt.
+        */
+       if (!trans_pcie->use_ict)
+               return iwl_isr(irq, data);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       /* Disable (but don't clear!) interrupts here to avoid
+        * back-to-back ISRs and sporadic interrupts from our NIC.
+        * If we have something to service, the tasklet will re-enable ints.
+        * If we *don't* have something, we'll re-enable before leaving here.
+        */
+       inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);  /* just for debug */
+       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
+
+
+       /* Ignore interrupt if there's nothing in NIC to service.
+        * This may be due to IRQ shared with another device,
+        * or due to sporadic interrupts thrown from our NIC. */
+       if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) {
+               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
+               goto none;
+       }
+
+       /* read all entries that not 0 start with ict_index */
+       while (trans_pcie->ict_tbl[trans_pcie->ict_index]) {
+
+               val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+               IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
+                               trans_pcie->ict_index,
+                               le32_to_cpu(
+                                 trans_pcie->ict_tbl[trans_pcie->ict_index]));
+               trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
+               trans_pcie->ict_index =
+                       iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+
+       }
+
+       /* We should not get this value, just ignore it. */
+       if (val == 0xffffffff)
+               val = 0;
+
+       /*
+        * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
+        * (bit 15 before shifting it to 31) to clear when using interrupt
+        * coalescing. fortunately, bits 18 and 19 stay set when this happens
+        * so we use them to decide on the real state of the Rx bit.
+        * In order words, bit 15 is set if bit 18 or bit 19 are set.
+        */
+       if (val & 0xC0000)
+               val |= 0x8000;
+
+       inta = (0xff & val) | ((0xff00 & val) << 16);
+       IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
+                       inta, inta_mask, val);
+
+       inta &= trans_pcie->inta_mask;
+       trans_pcie->inta |= inta;
+
+       /* iwl_irq_tasklet() will service interrupts and re-enable them */
+       if (likely(inta))
+               tasklet_schedule(&trans_pcie->irq_tasklet);
+       else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+                       !trans_pcie->inta) {
+               /* Allow interrupt if was disabled by this handler and
+                * no tasklet was schedules, We should not enable interrupt,
+                * tasklet will enable it.
+                */
+               iwl_enable_interrupts(trans);
+       }
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+       return IRQ_HANDLED;
+
+ none:
+       /* re-enable interrupts here since we don't have anything to service.
+        * only Re-enable if disabled by irq.
+        */
+       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
+               !trans_pcie->inta)
+               iwl_enable_interrupts(trans);
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+       return IRQ_NONE;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
new file mode 100644 (file)
index 0000000..ee7059d
--- /dev/null
@@ -0,0 +1,1128 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+/* TODO: remove include to iwl-dev.h */
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-io.h"
+#include "iwl-agn-hw.h"
+#include "iwl-helpers.h"
+#include "iwl-trans-pcie-int.h"
+
+#define IWL_TX_CRC_SIZE 4
+#define IWL_TX_DELIMITER_SIZE 4
+
+/**
+ * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
+                                          struct iwl_tx_queue *txq,
+                                          u16 byte_cnt)
+{
+       struct iwlagn_scd_bc_tbl *scd_bc_tbl;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       int write_ptr = txq->q.write_ptr;
+       int txq_id = txq->q.id;
+       u8 sec_ctl = 0;
+       u8 sta_id = 0;
+       u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+       __le16 bc_ent;
+       struct iwl_tx_cmd *tx_cmd =
+               (struct iwl_tx_cmd *) txq->cmd[txq->q.write_ptr]->payload;
+
+       scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
+
+       WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+
+       sta_id = tx_cmd->sta_id;
+       sec_ctl = tx_cmd->sec_ctl;
+
+       switch (sec_ctl & TX_CMD_SEC_MSK) {
+       case TX_CMD_SEC_CCM:
+               len += CCMP_MIC_LEN;
+               break;
+       case TX_CMD_SEC_TKIP:
+               len += TKIP_ICV_LEN;
+               break;
+       case TX_CMD_SEC_WEP:
+               len += WEP_IV_LEN + WEP_ICV_LEN;
+               break;
+       }
+
+       bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
+
+       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+       if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+               scd_bc_tbl[txq_id].
+                       tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
+}
+
+/**
+ * iwl_txq_update_write_ptr - Send new write index to hardware
+ */
+void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
+{
+       u32 reg = 0;
+       int txq_id = txq->q.id;
+
+       if (txq->need_update == 0)
+               return;
+
+       if (hw_params(trans).shadow_reg_enable) {
+               /* shadow register enabled */
+               iwl_write32(bus(trans), HBUS_TARG_WRPTR,
+                           txq->q.write_ptr | (txq_id << 8));
+       } else {
+               /* if we're trying to save power */
+               if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
+                       /* wake up nic if it's powered down ...
+                        * uCode will wake up, and interrupt us again, so next
+                        * time we'll skip this part. */
+                       reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
+
+                       if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+                               IWL_DEBUG_INFO(trans,
+                                       "Tx queue %d requesting wakeup,"
+                                       " GP1 = 0x%x\n", txq_id, reg);
+                               iwl_set_bit(bus(trans), CSR_GP_CNTRL,
+                                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+                               return;
+                       }
+
+                       iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
+                                    txq->q.write_ptr | (txq_id << 8));
+
+               /*
+                * else not in power-save mode,
+                * uCode will never sleep when we're
+                * trying to tx (during RFKILL, we're not trying to tx).
+                */
+               } else
+                       iwl_write32(bus(trans), HBUS_TARG_WRPTR,
+                                   txq->q.write_ptr | (txq_id << 8));
+       }
+       txq->need_update = 0;
+}
+
+static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+       dma_addr_t addr = get_unaligned_le32(&tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               addr |=
+               ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+       return addr;
+}
+
+static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+       return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+                                 dma_addr_t addr, u16 len)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+       u16 hi_n_len = len << 4;
+
+       put_unaligned_le32(addr, &tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+       tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+       tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+       return tfd->num_tbs & 0x1f;
+}
+
+static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
+                    struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
+{
+       int i;
+       int num_tbs;
+
+       /* Sanity check on number of chunks */
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
+               /* @todo issue fatal error, it is quite serious situation */
+               return;
+       }
+
+       /* Unmap tx_cmd */
+       if (num_tbs)
+               dma_unmap_single(bus(trans)->dev,
+                               dma_unmap_addr(meta, mapping),
+                               dma_unmap_len(meta, len),
+                               DMA_BIDIRECTIONAL);
+
+       /* Unmap chunks, if any. */
+       for (i = 1; i < num_tbs; i++)
+               dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i),
+                               iwl_tfd_tb_get_len(tfd, i), dma_dir);
+}
+
+/**
+ * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @trans - transport private data
+ * @txq - tx queue
+ * @index - the index of the TFD to be freed
+ *@dma_dir - the direction of the DMA mapping
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
+       int index, enum dma_data_direction dma_dir)
+{
+       struct iwl_tfd *tfd_tmp = txq->tfds;
+
+       iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
+
+       /* free SKB */
+       if (txq->skbs) {
+               struct sk_buff *skb;
+
+               skb = txq->skbs[index];
+
+               /* Can be called from irqs-disabled context
+                * If skb is not NULL, it means that the whole queue is being
+                * freed and that the queue is not empty - free the skb
+                */
+               if (skb) {
+                       iwl_free_skb(priv(trans), skb);
+                       txq->skbs[index] = NULL;
+               }
+       }
+}
+
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
+                                struct iwl_tx_queue *txq,
+                                dma_addr_t addr, u16 len,
+                                u8 reset)
+{
+       struct iwl_queue *q;
+       struct iwl_tfd *tfd, *tfd_tmp;
+       u32 num_tbs;
+
+       q = &txq->q;
+       tfd_tmp = txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
+
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       /* Each TFD can point to a maximum 20 Tx buffers */
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(trans, "Error can not send more than %d chunks\n",
+                         IWL_NUM_OF_TBS);
+               return -EINVAL;
+       }
+
+       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+               return -EINVAL;
+
+       if (unlikely(addr & ~IWL_TX_DMA_MASK))
+               IWL_ERR(trans, "Unaligned address = %llx\n",
+                         (unsigned long long)addr);
+
+       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+
+       return 0;
+}
+
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ ***************************************************/
+
+int iwl_queue_space(const struct iwl_queue *q)
+{
+       int s = q->read_ptr - q->write_ptr;
+
+       if (q->read_ptr > q->write_ptr)
+               s -= q->n_bd;
+
+       if (s <= 0)
+               s += q->n_window;
+       /* keep some reserve to not confuse empty and full situations */
+       s -= 2;
+       if (s < 0)
+               s = 0;
+       return s;
+}
+
+/**
+ * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
+{
+       q->n_bd = count;
+       q->n_window = slots_num;
+       q->id = id;
+
+       /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+        * and iwl_queue_dec_wrap are broken. */
+       if (WARN_ON(!is_power_of_2(count)))
+               return -EINVAL;
+
+       /* slots_num must be power-of-two size, otherwise
+        * get_cmd_index is broken. */
+       if (WARN_ON(!is_power_of_2(slots_num)))
+               return -EINVAL;
+
+       q->low_mark = q->n_window / 4;
+       if (q->low_mark < 4)
+               q->low_mark = 4;
+
+       q->high_mark = q->n_window / 8;
+       if (q->high_mark < 2)
+               q->high_mark = 2;
+
+       q->write_ptr = q->read_ptr = 0;
+
+       return 0;
+}
+
+static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
+                                         struct iwl_tx_queue *txq)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
+       int txq_id = txq->q.id;
+       int read_ptr = txq->q.read_ptr;
+       u8 sta_id = 0;
+       __le16 bc_ent;
+       struct iwl_tx_cmd *tx_cmd =
+               (struct iwl_tx_cmd *) txq->cmd[txq->q.read_ptr]->payload;
+
+       WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+
+       if (txq_id != trans->shrd->cmd_queue)
+               sta_id = tx_cmd->sta_id;
+
+       bc_ent = cpu_to_le16(1 | (sta_id << 12));
+       scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+
+       if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
+               scd_bc_tbl[txq_id].
+                       tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+}
+
+static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid,
+                                       u16 txq_id)
+{
+       u32 tbl_dw_addr;
+       u32 tbl_dw;
+       u16 scd_q2ratid;
+
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+       tbl_dw_addr = trans_pcie->scd_base_addr +
+                       SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
+
+       tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr);
+
+       if (txq_id & 0x1)
+               tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+       else
+               tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+       iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw);
+
+       return 0;
+}
+
+static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
+{
+       /* Simply stop the queue, but don't change any configuration;
+        * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+       iwl_write_prph(bus(trans),
+               SCD_QUEUE_STATUS_BITS(txq_id),
+               (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+               (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
+                               int txq_id, u32 index)
+{
+       iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
+                       (index & 0xff) | (txq_id << 8));
+       iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
+                                       struct iwl_tx_queue *txq,
+                                       int tx_fifo_id, int scd_retry)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int txq_id = txq->q.id;
+       int active =
+               test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0;
+
+       iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id),
+                       (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+                       (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
+                       (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
+                       SCD_QUEUE_STTS_REG_MSK);
+
+       txq->sched_retry = scd_retry;
+
+       IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n",
+                      active ? "Activate" : "Deactivate",
+                      scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
+}
+
+static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
+                                   u8 ctx, u16 tid)
+{
+       const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx];
+       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+               return ac_to_fifo[tid_to_ac[tid]];
+
+       /* no support for TIDs 8-15 yet */
+       return -EINVAL;
+}
+
+void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
+                                enum iwl_rxon_context_id ctx, int sta_id,
+                                int tid, int frame_limit)
+{
+       int tx_fifo, txq_id, ssn_idx;
+       u16 ra_tid;
+       unsigned long flags;
+       struct iwl_tid_data *tid_data;
+
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (WARN_ON(sta_id == IWL_INVALID_STATION))
+               return;
+       if (WARN_ON(tid >= IWL_MAX_TID_COUNT))
+               return;
+
+       tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid);
+       if (WARN_ON(tx_fifo < 0)) {
+               IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo);
+               return;
+       }
+
+       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+       tid_data = &trans->shrd->tid_data[sta_id][tid];
+       ssn_idx = SEQ_TO_SN(tid_data->seq_number);
+       txq_id = tid_data->agg.txq_id;
+       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+
+       ra_tid = BUILD_RAxTID(sta_id, tid);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       /* Stop this Tx queue before configuring it */
+       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
+
+       /* Map receiver-address / traffic-ID to this queue */
+       iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id);
+
+       /* Set this queue as a chain-building queue */
+       iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<<txq_id));
+
+       /* enable aggregations for the queue */
+       iwl_set_bits_prph(bus(trans), SCD_AGGR_SEL, (1<<txq_id));
+
+       /* Place first TFD at index corresponding to start sequence number.
+        * Assumes that ssn_idx is valid (!= 0xFFF) */
+       trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+       trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+       iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
+
+       /* Set up Tx window size and frame limit for this queue */
+       iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
+                       SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
+                       sizeof(u32),
+                       ((frame_limit <<
+                       SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+                       SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+                       ((frame_limit <<
+                       SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+                       SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+
+       iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
+
+       /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id],
+                                       tx_fifo, 1);
+
+       trans_pcie->txq[txq_id].sta_id = sta_id;
+       trans_pcie->txq[txq_id].tid = tid;
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+}
+
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
+ */
+static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int txq_id;
+
+       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+               if (!test_and_set_bit(txq_id,
+                                       &trans_pcie->txq_ctx_active_msk))
+                       return txq_id;
+       return -1;
+}
+
+int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
+                               enum iwl_rxon_context_id ctx, int sta_id,
+                               int tid, u16 *ssn)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tid_data *tid_data;
+       unsigned long flags;
+       int txq_id;
+
+       txq_id = iwlagn_txq_ctx_activate_free(trans);
+       if (txq_id == -1) {
+               IWL_ERR(trans, "No free aggregation queue available\n");
+               return -ENXIO;
+       }
+
+       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+       tid_data = &trans->shrd->tid_data[sta_id][tid];
+       *ssn = SEQ_TO_SN(tid_data->seq_number);
+       tid_data->agg.txq_id = txq_id;
+       iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
+
+       tid_data = &trans->shrd->tid_data[sta_id][tid];
+       if (tid_data->tfds_in_queue == 0) {
+               IWL_DEBUG_HT(trans, "HW queue is empty\n");
+               tid_data->agg.state = IWL_AGG_ON;
+               iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
+       } else {
+               IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW"
+                            "queue\n", tid_data->tfds_in_queue);
+               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+       }
+       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+
+       return 0;
+}
+
+void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
+
+       iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
+
+       trans_pcie->txq[txq_id].q.read_ptr = 0;
+       trans_pcie->txq[txq_id].q.write_ptr = 0;
+       /* supposes that ssn_idx is valid (!= 0xFFF) */
+       iwl_trans_set_wr_ptrs(trans, txq_id, 0);
+
+       iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
+       iwl_txq_ctx_deactivate(trans_pcie, txq_id);
+       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
+}
+
+int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
+                                 enum iwl_rxon_context_id ctx, int sta_id,
+                                 int tid)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       unsigned long flags;
+       int read_ptr, write_ptr;
+       struct iwl_tid_data *tid_data;
+       int txq_id;
+
+       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
+
+       tid_data = &trans->shrd->tid_data[sta_id][tid];
+       txq_id = tid_data->agg.txq_id;
+
+       if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IWLAGN_FIRST_AMPDU_QUEUE +
+               hw_params(trans).num_ampdu_queues <= txq_id)) {
+               IWL_ERR(trans,
+                       "queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
+                       IWLAGN_FIRST_AMPDU_QUEUE +
+                       hw_params(trans).num_ampdu_queues - 1);
+               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+               return -EINVAL;
+       }
+
+       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
+       case IWL_EMPTYING_HW_QUEUE_ADDBA:
+               /*
+               * This can happen if the peer stops aggregation
+               * again before we've had a chance to drain the
+               * queue we selected previously, i.e. before the
+               * session was really started completely.
+               */
+               IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
+               goto turn_off;
+       case IWL_AGG_ON:
+               break;
+       default:
+               IWL_WARN(trans, "Stopping AGG while state not ON"
+                               "or starting\n");
+       }
+
+       write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
+       read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
+
+       /* The queue is not empty */
+       if (write_ptr != read_ptr) {
+               IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n");
+               trans->shrd->tid_data[sta_id][tid].agg.state =
+                       IWL_EMPTYING_HW_QUEUE_DELBA;
+               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+               return 0;
+       }
+
+       IWL_DEBUG_HT(trans, "HW queue is empty\n");
+turn_off:
+       trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
+
+       /* do not restore/save irqs */
+       spin_unlock(&trans->shrd->sta_lock);
+       spin_lock(&trans->shrd->lock);
+
+       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
+
+       return 0;
+}
+
+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+
+/**
+ * iwl_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a point to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation is
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
+       struct iwl_queue *q = &txq->q;
+       struct iwl_device_cmd *out_cmd;
+       struct iwl_cmd_meta *out_meta;
+       dma_addr_t phys_addr;
+       unsigned long flags;
+       u32 idx;
+       u16 copy_size, cmd_size;
+       bool is_ct_kill = false;
+       bool had_nocopy = false;
+       int i;
+       u8 *cmd_dest;
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
+       int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
+       int trace_idx;
+#endif
+
+       if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
+               IWL_WARN(trans, "fw recovery, no hcmd send\n");
+               return -EIO;
+       }
+
+       if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
+           !(cmd->flags & CMD_ON_DEMAND)) {
+               IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
+               return -EIO;
+       }
+
+       copy_size = sizeof(out_cmd->hdr);
+       cmd_size = sizeof(out_cmd->hdr);
+
+       /* need one for the header if the first is NOCOPY */
+       BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
+
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
+                       had_nocopy = true;
+               } else {
+                       /* NOCOPY must not be followed by normal! */
+                       if (WARN_ON(had_nocopy))
+                               return -EINVAL;
+                       copy_size += cmd->len[i];
+               }
+               cmd_size += cmd->len[i];
+       }
+
+       /*
+        * If any of the command structures end up being larger than
+        * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
+        * allocated into separate TFDs, then we will need to
+        * increase the size of the buffers.
+        */
+       if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
+               return -EINVAL;
+
+       if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
+               IWL_WARN(trans, "Not sending command - %s KILL\n",
+                        iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
+               return -EIO;
+       }
+
+       spin_lock_irqsave(&trans->hcmd_lock, flags);
+
+       if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+               spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+
+               IWL_ERR(trans, "No space in command queue\n");
+               is_ct_kill = iwl_check_for_ct_kill(priv(trans));
+               if (!is_ct_kill) {
+                       IWL_ERR(trans, "Restarting adapter queue is full\n");
+                       iwlagn_fw_error(priv(trans), false);
+               }
+               return -ENOSPC;
+       }
+
+       idx = get_cmd_index(q, q->write_ptr);
+       out_cmd = txq->cmd[idx];
+       out_meta = &txq->meta[idx];
+
+       memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
+       if (cmd->flags & CMD_WANT_SKB)
+               out_meta->source = cmd;
+
+       /* set up the header */
+
+       out_cmd->hdr.cmd = cmd->id;
+       out_cmd->hdr.flags = 0;
+       out_cmd->hdr.sequence =
+               cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
+                                        INDEX_TO_SEQ(q->write_ptr));
+
+       /* and copy the data that needs to be copied */
+
+       cmd_dest = out_cmd->payload;
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
+                       break;
+               memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
+               cmd_dest += cmd->len[i];
+       }
+
+       IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, "
+                       "%d bytes at %d[%d]:%d\n",
+                       get_cmd_string(out_cmd->hdr.cmd),
+                       out_cmd->hdr.cmd,
+                       le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
+                       q->write_ptr, idx, trans->shrd->cmd_queue);
+
+       phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size,
+                               DMA_BIDIRECTIONAL);
+       if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
+               idx = -ENOMEM;
+               goto out;
+       }
+
+       dma_unmap_addr_set(out_meta, mapping, phys_addr);
+       dma_unmap_len_set(out_meta, len, copy_size);
+
+       iwlagn_txq_attach_buf_to_tfd(trans, txq,
+                                       phys_addr, copy_size, 1);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       trace_bufs[0] = &out_cmd->hdr;
+       trace_lens[0] = copy_size;
+       trace_idx = 1;
+#endif
+
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
+                       continue;
+               phys_addr = dma_map_single(bus(trans)->dev,
+                                          (void *)cmd->data[i],
+                                          cmd->len[i], DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(bus(trans)->dev, phys_addr)) {
+                       iwlagn_unmap_tfd(trans, out_meta,
+                                        &txq->tfds[q->write_ptr],
+                                        DMA_BIDIRECTIONAL);
+                       idx = -ENOMEM;
+                       goto out;
+               }
+
+               iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
+                                            cmd->len[i], 0);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+               trace_bufs[trace_idx] = cmd->data[i];
+               trace_lens[trace_idx] = cmd->len[i];
+               trace_idx++;
+#endif
+       }
+
+       out_meta->flags = cmd->flags;
+
+       txq->need_update = 1;
+
+       /* check that tracing gets all possible blocks */
+       BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
+                              trace_bufs[0], trace_lens[0],
+                              trace_bufs[1], trace_lens[1],
+                              trace_bufs[2], trace_lens[2]);
+#endif
+
+       /* Increment and update queue's write index */
+       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+       iwl_txq_update_write_ptr(trans, txq);
+
+ out:
+       spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+       return idx;
+}
+
+/**
+ * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
+                                  int idx)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
+       struct iwl_queue *q = &txq->q;
+       int nfreed = 0;
+
+       if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
+               IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
+                         "index %d is out of range [0-%d] %d %d.\n", __func__,
+                         txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
+               return;
+       }
+
+       for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+               if (nfreed++ > 0) {
+                       IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx,
+                                       q->write_ptr, q->read_ptr);
+                       iwlagn_fw_error(priv(trans), false);
+               }
+
+       }
+}
+
+/**
+ * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * @rxb: Rx buffer to reclaim
+ * @handler_status: return value of the handler of the command
+ *     (put in setup_rx_handlers)
+ *
+ * If an Rx buffer has an async callback associated with it the callback
+ * will be executed.  The attached skb (if present) will only be freed
+ * if the callback returns 1
+ */
+void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
+                        int handler_status)
+{
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+       int txq_id = SEQ_TO_QUEUE(sequence);
+       int index = SEQ_TO_INDEX(sequence);
+       int cmd_index;
+       struct iwl_device_cmd *cmd;
+       struct iwl_cmd_meta *meta;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
+       unsigned long flags;
+
+       /* If a Tx command is being handled and it isn't in the actual
+        * command queue then there a command routing bug has been introduced
+        * in the queue management code. */
+       if (WARN(txq_id != trans->shrd->cmd_queue,
+                "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+                 txq_id, trans->shrd->cmd_queue, sequence,
+                 trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
+                 trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
+               iwl_print_hex_error(trans, pkt, 32);
+               return;
+       }
+
+       cmd_index = get_cmd_index(&txq->q, index);
+       cmd = txq->cmd[cmd_index];
+       meta = &txq->meta[cmd_index];
+
+       txq->time_stamp = jiffies;
+
+       iwlagn_unmap_tfd(trans, meta, &txq->tfds[index],
+                        DMA_BIDIRECTIONAL);
+
+       /* Input error checking is done when commands are added to queue. */
+       if (meta->flags & CMD_WANT_SKB) {
+               meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+               meta->source->handler_status = handler_status;
+               rxb->page = NULL;
+       }
+
+       spin_lock_irqsave(&trans->hcmd_lock, flags);
+
+       iwl_hcmd_queue_reclaim(trans, txq_id, index);
+
+       if (!(meta->flags & CMD_ASYNC)) {
+               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+               IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
+                              get_cmd_string(cmd->hdr.cmd));
+               wake_up(&trans->shrd->wait_command_queue);
+       }
+
+       meta->flags = 0;
+
+       spin_unlock_irqrestore(&trans->hcmd_lock, flags);
+}
+
+#define HOST_COMPLETE_TIMEOUT (2 * HZ)
+
+static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+{
+       int ret;
+
+       /* An asynchronous command can not expect an SKB to be set. */
+       if (WARN_ON(cmd->flags & CMD_WANT_SKB))
+               return -EINVAL;
+
+
+       if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
+               return -EBUSY;
+
+       ret = iwl_enqueue_hcmd(trans, cmd);
+       if (ret < 0) {
+               IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
+                         get_cmd_string(cmd->id), ret);
+               return ret;
+       }
+       return 0;
+}
+
+static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int cmd_idx;
+       int ret;
+
+       lockdep_assert_held(&trans->shrd->mutex);
+
+       IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
+                       get_cmd_string(cmd->id));
+
+       set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+       IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
+                       get_cmd_string(cmd->id));
+
+       cmd_idx = iwl_enqueue_hcmd(trans, cmd);
+       if (cmd_idx < 0) {
+               ret = cmd_idx;
+               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+               IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
+                         get_cmd_string(cmd->id), ret);
+               return ret;
+       }
+
+       ret = wait_event_timeout(trans->shrd->wait_command_queue,
+                       !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
+                       HOST_COMPLETE_TIMEOUT);
+       if (!ret) {
+               if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
+                       IWL_ERR(trans,
+                               "Error sending %s: time out after %dms.\n",
+                               get_cmd_string(cmd->id),
+                               jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+
+                       clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
+                       IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command"
+                                "%s\n", get_cmd_string(cmd->id));
+                       ret = -ETIMEDOUT;
+                       goto cancel;
+               }
+       }
+
+       if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
+               IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
+                              get_cmd_string(cmd->id));
+               ret = -ECANCELED;
+               goto fail;
+       }
+       if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
+               IWL_ERR(trans, "Command %s failed: FW Error\n",
+                              get_cmd_string(cmd->id));
+               ret = -EIO;
+               goto fail;
+       }
+       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+               IWL_ERR(trans, "Error: Response NULL in '%s'\n",
+                         get_cmd_string(cmd->id));
+               ret = -EIO;
+               goto cancel;
+       }
+
+       return 0;
+
+cancel:
+       if (cmd->flags & CMD_WANT_SKB) {
+               /*
+                * Cancel the CMD_WANT_SKB flag for the cmd in the
+                * TX cmd queue. Otherwise in case the cmd comes
+                * in later, it will possibly set an invalid
+                * address (cmd->meta.source).
+                */
+               trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
+                                                       ~CMD_WANT_SKB;
+       }
+fail:
+       if (cmd->reply_page) {
+               iwl_free_pages(trans->shrd, cmd->reply_page);
+               cmd->reply_page = 0;
+       }
+
+       return ret;
+}
+
+int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
+{
+       if (cmd->flags & CMD_ASYNC)
+               return iwl_send_cmd_async(trans, cmd);
+
+       return iwl_send_cmd_sync(trans, cmd);
+}
+
+/* Frees buffers until index _not_ inclusive */
+int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
+                        struct sk_buff_head *skbs)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
+       struct iwl_queue *q = &txq->q;
+       int last_to_free;
+       int freed = 0;
+
+       /* This function is not meant to release cmd queue*/
+       if (WARN_ON(txq_id == trans->shrd->cmd_queue))
+               return 0;
+
+       /*Since we free until index _not_ inclusive, the one before index is
+        * the last we will free. This one must be used */
+       last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
+
+       if ((index >= q->n_bd) ||
+          (iwl_queue_used(q, last_to_free) == 0)) {
+               IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
+                         "last_to_free %d is out of range [0-%d] %d %d.\n",
+                         __func__, txq_id, last_to_free, q->n_bd,
+                         q->write_ptr, q->read_ptr);
+               return 0;
+       }
+
+       IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
+                          q->read_ptr, index);
+
+       if (WARN_ON(!skb_queue_empty(skbs)))
+               return 0;
+
+       for (;
+            q->read_ptr != index;
+            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+               if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL))
+                       continue;
+
+               __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]);
+
+               txq->skbs[txq->q.read_ptr] = NULL;
+
+               iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
+
+               iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE);
+               freed++;
+       }
+       return freed;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
new file mode 100644 (file)
index 0000000..b78ac65
--- /dev/null
@@ -0,0 +1,1986 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+#include <linux/bitops.h>
+#include <linux/gfp.h>
+
+#include "iwl-trans.h"
+#include "iwl-trans-pcie-int.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-shared.h"
+#include "iwl-eeprom.h"
+#include "iwl-agn-hw.h"
+
+static int iwl_trans_rx_alloc(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       struct device *dev = bus(trans)->dev;
+
+       memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
+
+       spin_lock_init(&rxq->lock);
+
+       if (WARN_ON(rxq->bd || rxq->rb_stts))
+               return -EINVAL;
+
+       /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
+       rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+                                    &rxq->bd_dma, GFP_KERNEL);
+       if (!rxq->bd)
+               goto err_bd;
+       memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
+
+       /*Allocate the driver's pointer to receive buffer status */
+       rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
+                                         &rxq->rb_stts_dma, GFP_KERNEL);
+       if (!rxq->rb_stts)
+               goto err_rb_stts;
+       memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
+
+       return 0;
+
+err_rb_stts:
+       dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
+                       rxq->bd, rxq->bd_dma);
+       memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+       rxq->bd = NULL;
+err_bd:
+       return -ENOMEM;
+}
+
+static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       int i;
+
+       /* Fill the rx_used queue with _all_ of the Rx buffers */
+       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+               /* In the reset function, these buffers may have been allocated
+                * to an SKB, so we need to unmap and free potential storage */
+               if (rxq->pool[i].page != NULL) {
+                       dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma,
+                               PAGE_SIZE << hw_params(trans).rx_page_order,
+                               DMA_FROM_DEVICE);
+                       __free_pages(rxq->pool[i].page,
+                                    hw_params(trans).rx_page_order);
+                       rxq->pool[i].page = NULL;
+               }
+               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+       }
+}
+
+static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
+                                struct iwl_rx_queue *rxq)
+{
+       u32 rb_size;
+       const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+       u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */
+
+       if (iwlagn_mod_params.amsdu_size_8K)
+               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+       else
+               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+       /* Stop Rx DMA */
+       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+       /* Reset driver's Rx queue write index */
+       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+       /* Tell device where to find RBD circular buffer in DRAM */
+       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+                          (u32)(rxq->bd_dma >> 8));
+
+       /* Tell device where in DRAM to update its Rx status */
+       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG,
+                          rxq->rb_stts_dma >> 4);
+
+       /* Enable Rx DMA
+        * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
+        *      the credit mechanism in 5000 HW RX FIFO
+        * Direct rx interrupts to hosts
+        * Rx buffer size 4 or 8k
+        * RB timeout 0x10
+        * 256 RBDs
+        */
+       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG,
+                          FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+                          FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
+                          FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+                          FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+                          rb_size|
+                          (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+                          (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+       /* Set interrupt coalescing timer to default (2048 usecs) */
+       iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+}
+
+static int iwl_rx_init(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+
+       int i, err;
+       unsigned long flags;
+
+       if (!rxq->bd) {
+               err = iwl_trans_rx_alloc(trans);
+               if (err)
+                       return err;
+       }
+
+       spin_lock_irqsave(&rxq->lock, flags);
+       INIT_LIST_HEAD(&rxq->rx_free);
+       INIT_LIST_HEAD(&rxq->rx_used);
+
+       iwl_trans_rxq_free_rx_bufs(trans);
+
+       for (i = 0; i < RX_QUEUE_SIZE; i++)
+               rxq->queue[i] = NULL;
+
+       /* Set us so that we have processed and used all buffers, but have
+        * not restocked the Rx queue with fresh buffers */
+       rxq->read = rxq->write = 0;
+       rxq->write_actual = 0;
+       rxq->free_count = 0;
+       spin_unlock_irqrestore(&rxq->lock, flags);
+
+       iwlagn_rx_replenish(trans);
+
+       iwl_trans_rx_hw_init(trans, rxq);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       rxq->need_update = 1;
+       iwl_rx_queue_update_write_ptr(trans, rxq);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       return 0;
+}
+
+static void iwl_trans_pcie_rx_free(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+
+       unsigned long flags;
+
+       /*if rxq->bd is NULL, it means that nothing has been allocated,
+        * exit now */
+       if (!rxq->bd) {
+               IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
+               return;
+       }
+
+       spin_lock_irqsave(&rxq->lock, flags);
+       iwl_trans_rxq_free_rx_bufs(trans);
+       spin_unlock_irqrestore(&rxq->lock, flags);
+
+       dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE,
+                         rxq->bd, rxq->bd_dma);
+       memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
+       rxq->bd = NULL;
+
+       if (rxq->rb_stts)
+               dma_free_coherent(bus(trans)->dev,
+                                 sizeof(struct iwl_rb_status),
+                                 rxq->rb_stts, rxq->rb_stts_dma);
+       else
+               IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
+       memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
+       rxq->rb_stts = NULL;
+}
+
+static int iwl_trans_rx_stop(struct iwl_trans *trans)
+{
+
+       /* stop Rx DMA */
+       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+       return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG,
+                           FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+}
+
+static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
+                                   struct iwl_dma_ptr *ptr, size_t size)
+{
+       if (WARN_ON(ptr->addr))
+               return -EINVAL;
+
+       ptr->addr = dma_alloc_coherent(bus(trans)->dev, size,
+                                      &ptr->dma, GFP_KERNEL);
+       if (!ptr->addr)
+               return -ENOMEM;
+       ptr->size = size;
+       return 0;
+}
+
+static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
+                                   struct iwl_dma_ptr *ptr)
+{
+       if (unlikely(!ptr->addr))
+               return;
+
+       dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma);
+       memset(ptr, 0, sizeof(*ptr));
+}
+
+static int iwl_trans_txq_alloc(struct iwl_trans *trans,
+                               struct iwl_tx_queue *txq, int slots_num,
+                               u32 txq_id)
+{
+       size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+       int i;
+
+       if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
+               return -EINVAL;
+
+       txq->q.n_window = slots_num;
+
+       txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, GFP_KERNEL);
+       txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, GFP_KERNEL);
+
+       if (!txq->meta || !txq->cmd)
+               goto error;
+
+       if (txq_id == trans->shrd->cmd_queue)
+               for (i = 0; i < slots_num; i++) {
+                       txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
+                                               GFP_KERNEL);
+                       if (!txq->cmd[i])
+                               goto error;
+               }
+
+       /* Alloc driver data array and TFD circular buffer */
+       /* Driver private data, only for Tx (not command) queues,
+        * not shared with device. */
+       if (txq_id != trans->shrd->cmd_queue) {
+               txq->skbs = kzalloc(sizeof(txq->skbs[0]) *
+                                  TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
+               if (!txq->skbs) {
+                       IWL_ERR(trans, "kmalloc for auxiliary BD "
+                                 "structures failed\n");
+                       goto error;
+               }
+       } else {
+               txq->skbs = NULL;
+       }
+
+       /* Circular buffer of transmit frame descriptors (TFDs),
+        * shared with device */
+       txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz,
+                                      &txq->q.dma_addr, GFP_KERNEL);
+       if (!txq->tfds) {
+               IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
+               goto error;
+       }
+       txq->q.id = txq_id;
+
+       return 0;
+error:
+       kfree(txq->skbs);
+       txq->skbs = NULL;
+       /* since txq->cmd has been zeroed,
+        * all non allocated cmd[i] will be NULL */
+       if (txq->cmd && txq_id == trans->shrd->cmd_queue)
+               for (i = 0; i < slots_num; i++)
+                       kfree(txq->cmd[i]);
+       kfree(txq->meta);
+       kfree(txq->cmd);
+       txq->meta = NULL;
+       txq->cmd = NULL;
+
+       return -ENOMEM;
+
+}
+
+static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
+                     int slots_num, u32 txq_id)
+{
+       int ret;
+
+       txq->need_update = 0;
+       memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
+
+       /*
+        * For the default queues 0-3, set up the swq_id
+        * already -- all others need to get one later
+        * (if they need one at all).
+        */
+       if (txq_id < 4)
+               iwl_set_swq_id(txq, txq_id, txq_id);
+
+       /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+        * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+       BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+       /* Initialize queue's high/low-water marks, and head/tail indexes */
+       ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
+                       txq_id);
+       if (ret)
+               return ret;
+
+       /*
+        * Tell nic where to find circular buffer of Tx Frame Descriptors for
+        * given Tx queue, and enable the DMA channel used for that queue.
+        * Circular buffer (TFD queue in DRAM) physical base address */
+       iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id),
+                            txq->q.dma_addr >> 8);
+
+       return 0;
+}
+
+/**
+ * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
+       struct iwl_queue *q = &txq->q;
+       enum dma_data_direction dma_dir;
+
+       if (!q->n_bd)
+               return;
+
+       /* In the command queue, all the TBs are mapped as BIDI
+        * so unmap them as such.
+        */
+       if (txq_id == trans->shrd->cmd_queue)
+               dma_dir = DMA_BIDIRECTIONAL;
+       else
+               dma_dir = DMA_TO_DEVICE;
+
+       while (q->write_ptr != q->read_ptr) {
+               /* The read_ptr needs to bound by q->n_window */
+               iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
+                                   dma_dir);
+               q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+       }
+}
+
+/**
+ * iwl_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
+       struct device *dev = bus(trans)->dev;
+       int i;
+       if (WARN_ON(!txq))
+               return;
+
+       iwl_tx_queue_unmap(trans, txq_id);
+
+       /* De-alloc array of command/tx buffers */
+
+       if (txq_id == trans->shrd->cmd_queue)
+               for (i = 0; i < txq->q.n_window; i++)
+                       kfree(txq->cmd[i]);
+
+       /* De-alloc circular buffer of TFDs */
+       if (txq->q.n_bd) {
+               dma_free_coherent(dev, sizeof(struct iwl_tfd) *
+                                 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+               memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
+       }
+
+       /* De-alloc array of per-TFD driver data */
+       kfree(txq->skbs);
+       txq->skbs = NULL;
+
+       /* deallocate arrays */
+       kfree(txq->cmd);
+       kfree(txq->meta);
+       txq->cmd = NULL;
+       txq->meta = NULL;
+
+       /* 0-fill queue descriptor structure */
+       memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
+{
+       int txq_id;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       /* Tx queues */
+       if (trans_pcie->txq) {
+               for (txq_id = 0;
+                    txq_id < hw_params(trans).max_txq_num; txq_id++)
+                       iwl_tx_queue_free(trans, txq_id);
+       }
+
+       kfree(trans_pcie->txq);
+       trans_pcie->txq = NULL;
+
+       iwlagn_free_dma_ptr(trans, &trans_pcie->kw);
+
+       iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
+}
+
+/**
+ * iwl_trans_tx_alloc - allocate TX context
+ * Allocate all Tx DMA structures and initialize them
+ *
+ * @param priv
+ * @return error code
+ */
+static int iwl_trans_tx_alloc(struct iwl_trans *trans)
+{
+       int ret;
+       int txq_id, slots_num;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       u16 scd_bc_tbls_size = hw_params(trans).max_txq_num *
+                       sizeof(struct iwlagn_scd_bc_tbl);
+
+       /*It is not allowed to alloc twice, so warn when this happens.
+        * We cannot rely on the previous allocation, so free and fail */
+       if (WARN_ON(trans_pcie->txq)) {
+               ret = -EINVAL;
+               goto error;
+       }
+
+       ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
+                                  scd_bc_tbls_size);
+       if (ret) {
+               IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
+               goto error;
+       }
+
+       /* Alloc keep-warm buffer */
+       ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
+       if (ret) {
+               IWL_ERR(trans, "Keep Warm allocation failed\n");
+               goto error;
+       }
+
+       trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) *
+                       hw_params(trans).max_txq_num, GFP_KERNEL);
+       if (!trans_pcie->txq) {
+               IWL_ERR(trans, "Not enough memory for txq\n");
+               ret = ENOMEM;
+               goto error;
+       }
+
+       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
+               slots_num = (txq_id == trans->shrd->cmd_queue) ?
+                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+               ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
+                                         slots_num, txq_id);
+               if (ret) {
+                       IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
+                       goto error;
+               }
+       }
+
+       return 0;
+
+error:
+       iwl_trans_pcie_tx_free(trans);
+
+       return ret;
+}
+static int iwl_tx_init(struct iwl_trans *trans)
+{
+       int ret;
+       int txq_id, slots_num;
+       unsigned long flags;
+       bool alloc = false;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       if (!trans_pcie->txq) {
+               ret = iwl_trans_tx_alloc(trans);
+               if (ret)
+                       goto error;
+               alloc = true;
+       }
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       /* Turn off all Tx DMA fifos */
+       iwl_write_prph(bus(trans), SCD_TXFACT, 0);
+
+       /* Tell NIC where to find the "keep warm" buffer */
+       iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG,
+                          trans_pcie->kw.dma >> 4);
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
+       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
+               slots_num = (txq_id == trans->shrd->cmd_queue) ?
+                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+               ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
+                                        slots_num, txq_id);
+               if (ret) {
+                       IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
+                       goto error;
+               }
+       }
+
+       return 0;
+error:
+       /*Upon error, free only if we allocated something */
+       if (alloc)
+               iwl_trans_pcie_tx_free(trans);
+       return ret;
+}
+
+static void iwl_set_pwr_vmain(struct iwl_trans *trans)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+               if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+                       iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
+                                              APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+                                              ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+       iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
+                              APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+                              ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+static int iwl_nic_init(struct iwl_trans *trans)
+{
+       unsigned long flags;
+
+       /* nic_init */
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwl_apm_init(priv(trans));
+
+       /* Set interrupt coalescing calibration timer to default (512 usecs) */
+       iwl_write8(bus(trans), CSR_INT_COALESCING,
+               IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       iwl_set_pwr_vmain(trans);
+
+       iwl_nic_config(priv(trans));
+
+       /* Allocate the RX queue, or reset if it is already allocated */
+       iwl_rx_init(trans);
+
+       /* Allocate or reset and init all Tx and Command queues */
+       if (iwl_tx_init(trans))
+               return -ENOMEM;
+
+       if (hw_params(trans).shadow_reg_enable) {
+               /* enable shadow regs in HW */
+               iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL,
+                       0x800FFFFF);
+       }
+
+       set_bit(STATUS_INIT, &trans->shrd->status);
+
+       return 0;
+}
+
+#define HW_READY_TIMEOUT (50)
+
+/* Note: returns poll_bit return value, which is >= 0 if success */
+static int iwl_set_hw_ready(struct iwl_trans *trans)
+{
+       int ret;
+
+       iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+       /* See if we got it */
+       ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+                               HW_READY_TIMEOUT);
+
+       IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
+       return ret;
+}
+
+/* Note: returns standard 0/-ERROR code */
+static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans)
+{
+       int ret;
+
+       IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
+
+       ret = iwl_set_hw_ready(trans);
+       if (ret >= 0)
+               return 0;
+
+       /* If HW is not ready, prepare the conditions to check again */
+       iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+                       CSR_HW_IF_CONFIG_REG_PREPARE);
+
+       ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
+                       ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+                       CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+       if (ret < 0)
+               return ret;
+
+       /* HW should be ready by now, check again. */
+       ret = iwl_set_hw_ready(trans);
+       if (ret >= 0)
+               return 0;
+       return ret;
+}
+
+#define IWL_AC_UNSET -1
+
+struct queue_to_fifo_ac {
+       s8 fifo, ac;
+};
+
+static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
+       { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+       { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+       { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+       { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+       { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
+};
+
+static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
+       { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
+       { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
+       { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
+       { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
+       { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
+       { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
+       { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
+       { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
+       { IWL_TX_FIFO_BE_IPAN, 2, },
+       { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
+       { IWL_TX_FIFO_AUX, IWL_AC_UNSET, },
+};
+
+static const u8 iwlagn_bss_ac_to_fifo[] = {
+       IWL_TX_FIFO_VO,
+       IWL_TX_FIFO_VI,
+       IWL_TX_FIFO_BE,
+       IWL_TX_FIFO_BK,
+};
+static const u8 iwlagn_bss_ac_to_queue[] = {
+       0, 1, 2, 3,
+};
+static const u8 iwlagn_pan_ac_to_fifo[] = {
+       IWL_TX_FIFO_VO_IPAN,
+       IWL_TX_FIFO_VI_IPAN,
+       IWL_TX_FIFO_BE_IPAN,
+       IWL_TX_FIFO_BK_IPAN,
+};
+static const u8 iwlagn_pan_ac_to_queue[] = {
+       7, 6, 5, 4,
+};
+
+static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
+{
+       int ret;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
+       trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
+       trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
+
+       trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo;
+       trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo;
+
+       trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
+       trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
+
+       if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
+            iwl_trans_pcie_prepare_card_hw(trans)) {
+               IWL_WARN(trans, "Exit HW not ready\n");
+               return -EIO;
+       }
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       if (iwl_read32(bus(trans), CSR_GP_CNTRL) &
+                       CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+               clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+       else
+               set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+
+       if (iwl_is_rfkill(trans->shrd)) {
+               iwl_set_hw_rfkill_state(priv(trans), true);
+               iwl_enable_interrupts(trans);
+               return -ERFKILL;
+       }
+
+       iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
+
+       ret = iwl_nic_init(trans);
+       if (ret) {
+               IWL_ERR(trans, "Unable to init nic\n");
+               return ret;
+       }
+
+       /* make sure rfkill handshake bits are cleared */
+       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR,
+                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+       /* clear (again), then enable host interrupts */
+       iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
+       iwl_enable_interrupts(trans);
+
+       /* really make sure rfkill handshake bits are cleared */
+       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+       return 0;
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->shrd->lock and mac access
+ */
+static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
+{
+       iwl_write_prph(bus(trans), SCD_TXFACT, mask);
+}
+
+static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
+{
+       const struct queue_to_fifo_ac *queue_to_fifo;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       u32 a;
+       unsigned long flags;
+       int i, chan;
+       u32 reg_val;
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       trans_pcie->scd_base_addr =
+               iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR);
+       a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
+       /* reset conext data memory */
+       for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
+               a += 4)
+               iwl_write_targ_mem(bus(trans), a, 0);
+       /* reset tx status memory */
+       for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
+               a += 4)
+               iwl_write_targ_mem(bus(trans), a, 0);
+       for (; a < trans_pcie->scd_base_addr +
+              SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
+              a += 4)
+               iwl_write_targ_mem(bus(trans), a, 0);
+
+       iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR,
+                      trans_pcie->scd_bc_tbls.dma >> 10);
+
+       /* Enable DMA channel */
+       for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
+               iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+       /* Update FH chicken bits */
+       reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG);
+       iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG,
+                          reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+       iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL,
+               SCD_QUEUECHAIN_SEL_ALL(trans));
+       iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0);
+
+       /* initiate the queues */
+       for (i = 0; i < hw_params(trans).max_txq_num; i++) {
+               iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0);
+               iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8));
+               iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
+                               SCD_CONTEXT_QUEUE_OFFSET(i), 0);
+               iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
+                               SCD_CONTEXT_QUEUE_OFFSET(i) +
+                               sizeof(u32),
+                               ((SCD_WIN_SIZE <<
+                               SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
+                               SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
+                               ((SCD_FRAME_LIMIT <<
+                               SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+                               SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
+       }
+
+       iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK,
+                       IWL_MASK(0, hw_params(trans).max_txq_num));
+
+       /* Activate all Tx DMA/FIFO channels */
+       iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
+
+       /* map queues to FIFOs */
+       if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+               queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
+       else
+               queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
+
+       iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
+
+       /* make sure all queue are not stopped */
+       memset(&trans_pcie->queue_stopped[0], 0,
+               sizeof(trans_pcie->queue_stopped));
+       for (i = 0; i < 4; i++)
+               atomic_set(&trans_pcie->queue_stop_count[i], 0);
+
+       /* reset to 0 to enable all the queue first */
+       trans_pcie->txq_ctx_active_msk = 0;
+
+       BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) <
+                                               IWLAGN_FIRST_AMPDU_QUEUE);
+       BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) <
+                                               IWLAGN_FIRST_AMPDU_QUEUE);
+
+       for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) {
+               int fifo = queue_to_fifo[i].fifo;
+               int ac = queue_to_fifo[i].ac;
+
+               iwl_txq_ctx_activate(trans_pcie, i);
+
+               if (fifo == IWL_TX_FIFO_UNUSED)
+                       continue;
+
+               if (ac != IWL_AC_UNSET)
+                       iwl_set_swq_id(&trans_pcie->txq[i], ac, i);
+               iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i],
+                                             fifo, 0);
+       }
+
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* Enable L1-Active */
+       iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG,
+                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+}
+
+/**
+ * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
+ */
+static int iwl_trans_tx_stop(struct iwl_trans *trans)
+{
+       int ch, txq_id;
+       unsigned long flags;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       /* Turn off all Tx DMA fifos */
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+
+       iwl_trans_txq_set_sched(trans, 0);
+
+       /* Stop each Tx DMA channel, and wait for it to be idle */
+       for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
+               iwl_write_direct32(bus(trans),
+                                  FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+               if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG,
+                                   FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+                                   1000))
+                       IWL_ERR(trans, "Failing on timeout while stopping"
+                           " DMA channel %d [0x%08x]", ch,
+                           iwl_read_direct32(bus(trans),
+                                             FH_TSSR_TX_STATUS_REG));
+       }
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       if (!trans_pcie->txq) {
+               IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
+               return 0;
+       }
+
+       /* Unmap DMA from host system and free skb's */
+       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
+               iwl_tx_queue_unmap(trans, txq_id);
+
+       return 0;
+}
+
+static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans)
+{
+       unsigned long flags;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwl_disable_interrupts(trans);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* wait to make sure we flush pending tasklet*/
+       synchronize_irq(bus(trans)->irq);
+       tasklet_kill(&trans_pcie->irq_tasklet);
+}
+
+static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
+{
+       /* stop and reset the on-board processor */
+       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+       /* tell the device to stop sending interrupts */
+       iwl_trans_pcie_disable_sync_irq(trans);
+
+       /* device going down, Stop using ICT table */
+       iwl_disable_ict(trans);
+
+       /*
+        * If a HW restart happens during firmware loading,
+        * then the firmware loading might call this function
+        * and later it might be called again due to the
+        * restart. So don't process again if the device is
+        * already dead.
+        */
+       if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
+               iwl_trans_tx_stop(trans);
+               iwl_trans_rx_stop(trans);
+
+               /* Power-down device's busmaster DMA clocks */
+               iwl_write_prph(bus(trans), APMG_CLK_DIS_REG,
+                              APMG_CLK_VAL_DMA_CLK_RQT);
+               udelay(5);
+       }
+
+       /* Make sure (redundant) we've released our request to stay awake */
+       iwl_clear_bit(bus(trans), CSR_GP_CNTRL,
+                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+       /* Stop the device, and put it in low power state */
+       iwl_apm_stop(priv(trans));
+}
+
+static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
+               struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+               u8 sta_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
+       struct iwl_cmd_meta *out_meta;
+       struct iwl_tx_queue *txq;
+       struct iwl_queue *q;
+
+       dma_addr_t phys_addr = 0;
+       dma_addr_t txcmd_phys;
+       dma_addr_t scratch_phys;
+       u16 len, firstlen, secondlen;
+       u16 seq_number = 0;
+       u8 wait_write_ptr = 0;
+       u8 txq_id;
+       u8 tid = 0;
+       bool is_agg = false;
+       __le16 fc = hdr->frame_control;
+       u8 hdr_len = ieee80211_hdrlen(fc);
+
+       /*
+        * Send this frame after DTIM -- there's a special queue
+        * reserved for this for contexts that support AP mode.
+        */
+       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+               txq_id = trans_pcie->mcast_queue[ctx];
+
+               /*
+                * The microcode will clear the more data
+                * bit in the last frame it transmits.
+                */
+               hdr->frame_control |=
+                       cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+       } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+               txq_id = IWL_AUX_QUEUE;
+       else
+               txq_id =
+                   trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
+
+       if (ieee80211_is_data_qos(fc)) {
+               u8 *qc = NULL;
+               struct iwl_tid_data *tid_data;
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               tid_data = &trans->shrd->tid_data[sta_id][tid];
+
+               if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
+                       return -1;
+
+               seq_number = tid_data->seq_number;
+               seq_number &= IEEE80211_SCTL_SEQ;
+               hdr->seq_ctrl = hdr->seq_ctrl &
+                               cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(seq_number);
+               seq_number += 0x10;
+               /* aggregation is on for this <sta,tid> */
+               if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+                       WARN_ON(tid_data->agg.state != IWL_AGG_ON);
+                       txq_id = tid_data->agg.txq_id;
+                       is_agg = true;
+               }
+       }
+
+       txq = &trans_pcie->txq[txq_id];
+       q = &txq->q;
+
+       /* Set up driver data for this TFD */
+       txq->skbs[q->write_ptr] = skb;
+       txq->cmd[q->write_ptr] = dev_cmd;
+
+       dev_cmd->hdr.cmd = REPLY_TX;
+       dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+                               INDEX_TO_SEQ(q->write_ptr)));
+
+       /* Set up first empty entry in queue's array of Tx/cmd buffers */
+       out_meta = &txq->meta[q->write_ptr];
+
+       /*
+        * Use the first empty entry in this queue's command buffer array
+        * to contain the Tx command and MAC header concatenated together
+        * (payload data will be in another buffer).
+        * Size of this varies, due to varying MAC header length.
+        * If end is not dword aligned, we'll have 2 extra bytes at the end
+        * of the MAC header (device reads on dword boundaries).
+        * We'll tell device about this padding later.
+        */
+       len = sizeof(struct iwl_tx_cmd) +
+               sizeof(struct iwl_cmd_header) + hdr_len;
+       firstlen = (len + 3) & ~3;
+
+       /* Tell NIC about any 2-byte padding after MAC header */
+       if (firstlen != len)
+               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+       /* Physical address of this Tx command's header (not MAC header!),
+        * within command buffer array. */
+       txcmd_phys = dma_map_single(bus(trans)->dev,
+                                   &dev_cmd->hdr, firstlen,
+                                   DMA_BIDIRECTIONAL);
+       if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys)))
+               return -1;
+       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+       dma_unmap_len_set(out_meta, len, firstlen);
+
+       if (!ieee80211_has_morefrags(fc)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
+
+       /* Set up TFD's 2nd entry to point directly to remainder of skb,
+        * if any (802.11 null frames have no payload). */
+       secondlen = skb->len - hdr_len;
+       if (secondlen > 0) {
+               phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len,
+                                          secondlen, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
+                       dma_unmap_single(bus(trans)->dev,
+                                        dma_unmap_addr(out_meta, mapping),
+                                        dma_unmap_len(out_meta, len),
+                                        DMA_BIDIRECTIONAL);
+                       return -1;
+               }
+       }
+
+       /* Attach buffers to TFD */
+       iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1);
+       if (secondlen > 0)
+               iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
+                                            secondlen, 0);
+
+       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+                               offsetof(struct iwl_tx_cmd, scratch);
+
+       /* take back ownership of DMA buffer to enable update */
+       dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
+       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
+
+       IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
+                    le16_to_cpu(dev_cmd->hdr.sequence));
+       IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+       iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+       iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+
+       /* Set up entry for this TFD in Tx byte-count array */
+       if (is_agg)
+               iwl_trans_txq_update_byte_cnt_tbl(trans, txq,
+                                              le16_to_cpu(tx_cmd->len));
+
+       dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
+
+       trace_iwlwifi_dev_tx(priv(trans),
+                            &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
+                            sizeof(struct iwl_tfd),
+                            &dev_cmd->hdr, firstlen,
+                            skb->data + hdr_len, secondlen);
+
+       /* Tell device the write index *just past* this latest filled TFD */
+       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+       iwl_txq_update_write_ptr(trans, txq);
+
+       if (ieee80211_is_data_qos(fc)) {
+               trans->shrd->tid_data[sta_id][tid].tfds_in_queue++;
+               if (!ieee80211_has_morefrags(fc))
+                       trans->shrd->tid_data[sta_id][tid].seq_number =
+                               seq_number;
+       }
+
+       /*
+        * At this point the frame is "transmitted" successfully
+        * and we will get a TX status notification eventually,
+        * regardless of the value of ret. "ret" only indicates
+        * whether or not we should update the write pointer.
+        */
+       if (iwl_queue_space(q) < q->high_mark) {
+               if (wait_write_ptr) {
+                       txq->need_update = 1;
+                       iwl_txq_update_write_ptr(trans, txq);
+               } else {
+                       iwl_stop_queue(trans, txq);
+               }
+       }
+       return 0;
+}
+
+static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans)
+{
+       /* Remove all resets to allow NIC to operate */
+       iwl_write32(bus(trans), CSR_RESET, 0);
+}
+
+static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       int err;
+
+       trans_pcie->inta_mask = CSR_INI_SET_MASK;
+
+       tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
+               iwl_irq_tasklet, (unsigned long)trans);
+
+       iwl_alloc_isr_ict(trans);
+
+       err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED,
+               DRV_NAME, trans);
+       if (err) {
+               IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq);
+               iwl_free_isr_ict(trans);
+               return err;
+       }
+
+       INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish);
+       return 0;
+}
+
+static int iwlagn_txq_check_empty(struct iwl_trans *trans,
+                          int sta_id, u8 tid, int txq_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_queue *q = &trans_pcie->txq[txq_id].q;
+       struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
+
+       lockdep_assert_held(&trans->shrd->sta_lock);
+
+       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
+       case IWL_EMPTYING_HW_QUEUE_DELBA:
+               /* We are reclaiming the last packet of the */
+               /* aggregated HW queue */
+               if ((txq_id  == tid_data->agg.txq_id) &&
+                   (q->read_ptr == q->write_ptr)) {
+                       IWL_DEBUG_HT(trans,
+                               "HW queue empty: continue DELBA flow\n");
+                       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
+                       tid_data->agg.state = IWL_AGG_OFF;
+                       iwl_stop_tx_ba_trans_ready(priv(trans),
+                                                  NUM_IWL_RXON_CTX,
+                                                  sta_id, tid);
+                       iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
+               }
+               break;
+       case IWL_EMPTYING_HW_QUEUE_ADDBA:
+               /* We are reclaiming the last packet of the queue */
+               if (tid_data->tfds_in_queue == 0) {
+                       IWL_DEBUG_HT(trans,
+                               "HW queue empty: continue ADDBA flow\n");
+                       tid_data->agg.state = IWL_AGG_ON;
+                       iwl_start_tx_ba_trans_ready(priv(trans),
+                                                   NUM_IWL_RXON_CTX,
+                                                   sta_id, tid);
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
+                           int sta_id, int tid, int freed)
+{
+       lockdep_assert_held(&trans->shrd->sta_lock);
+
+       if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
+               trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
+       else {
+               IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
+                       trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
+                       freed);
+               trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
+       }
+}
+
+static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
+                     int txq_id, int ssn, u32 status,
+                     struct sk_buff_head *skbs)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
+       enum iwl_agg_state agg_state;
+       /* n_bd is usually 256 => n_bd - 1 = 0xff */
+       int tfd_num = ssn & (txq->q.n_bd - 1);
+       int freed = 0;
+       bool cond;
+
+       txq->time_stamp = jiffies;
+
+       if (txq->sched_retry) {
+               agg_state =
+                       trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
+               cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
+       } else {
+               cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
+       }
+
+       if (txq->q.read_ptr != tfd_num) {
+               IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
+                               "scd_ssn=%d idx=%d txq=%d swq=%d\n",
+                               ssn , tfd_num, txq_id, txq->swq_id);
+               freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
+               if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
+                       iwl_wake_queue(trans, txq);
+       }
+
+       iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
+       iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
+}
+
+static void iwl_trans_pcie_free(struct iwl_trans *trans)
+{
+       iwl_trans_pcie_tx_free(trans);
+       iwl_trans_pcie_rx_free(trans);
+       free_irq(bus(trans)->irq, trans);
+       iwl_free_isr_ict(trans);
+       trans->shrd->trans = NULL;
+       kfree(trans);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
+{
+       /*
+        * This function is called when system goes into suspend state
+        * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
+        * first but since iwl_mac_stop() has no knowledge of who the caller is,
+        * it will not call apm_ops.stop() to stop the DMA operation.
+        * Calling apm_ops.stop here to make sure we stop the DMA.
+        *
+        * But of course ... if we have configured WoWLAN then we did other
+        * things already :-)
+        */
+       if (!trans->shrd->wowlan)
+               iwl_apm_stop(priv(trans));
+
+       return 0;
+}
+
+static int iwl_trans_pcie_resume(struct iwl_trans *trans)
+{
+       bool hw_rfkill = false;
+
+       iwl_enable_interrupts(trans);
+
+       if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
+                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+               hw_rfkill = true;
+
+       if (hw_rfkill)
+               set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+       else
+               clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
+
+       iwl_set_hw_rfkill_state(priv(trans), hw_rfkill);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
+                                         enum iwl_rxon_context_id ctx)
+{
+       u8 ac, txq_id;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       for (ac = 0; ac < AC_NUM; ac++) {
+               txq_id = trans_pcie->ac_to_queue[ctx][ac];
+               IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n",
+                       ac,
+                       (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
+                             ? "stopped" : "awake");
+               iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
+       }
+}
+
+const struct iwl_trans_ops trans_ops_pcie;
+
+static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd)
+{
+       struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) +
+                                             sizeof(struct iwl_trans_pcie),
+                                             GFP_KERNEL);
+       if (iwl_trans) {
+               struct iwl_trans_pcie *trans_pcie =
+                       IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
+               iwl_trans->ops = &trans_ops_pcie;
+               iwl_trans->shrd = shrd;
+               trans_pcie->trans = iwl_trans;
+               spin_lock_init(&iwl_trans->hcmd_lock);
+       }
+
+       return iwl_trans;
+}
+
+static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       iwl_stop_queue(trans, &trans_pcie->txq[txq_id]);
+}
+
+#define IWL_FLUSH_WAIT_MS      2000
+
+static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq;
+       struct iwl_queue *q;
+       int cnt;
+       unsigned long now = jiffies;
+       int ret = 0;
+
+       /* waiting for all the tx frames complete might take a while */
+       for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+               if (cnt == trans->shrd->cmd_queue)
+                       continue;
+               txq = &trans_pcie->txq[cnt];
+               q = &txq->q;
+               while (q->read_ptr != q->write_ptr && !time_after(jiffies,
+                      now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
+                       msleep(1);
+
+               if (q->read_ptr != q->write_ptr) {
+                       IWL_ERR(trans, "fail to flush all tx fifo queues\n");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+       }
+       return ret;
+}
+
+/*
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
+ */
+static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq = &trans_pcie->txq[cnt];
+       struct iwl_queue *q = &txq->q;
+       unsigned long timeout;
+
+       if (q->read_ptr == q->write_ptr) {
+               txq->time_stamp = jiffies;
+               return 0;
+       }
+
+       timeout = txq->time_stamp +
+                 msecs_to_jiffies(hw_params(trans).wd_timeout);
+
+       if (time_after(jiffies, timeout)) {
+               IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id,
+                       hw_params(trans).wd_timeout);
+               IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n",
+                       q->read_ptr, q->write_ptr);
+               return 1;
+       }
+
+       return 0;
+}
+
+static const char *get_fh_string(int cmd)
+{
+       switch (cmd) {
+       IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+       IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+       IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+       IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+       IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+       IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+       IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+       IWL_CMD(FH_TSSR_TX_STATUS_REG);
+       IWL_CMD(FH_TSSR_TX_ERROR_REG);
+       default:
+               return "UNKNOWN";
+       }
+}
+
+int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
+{
+       int i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+       int pos = 0;
+       size_t bufsz = 0;
+#endif
+       static const u32 fh_tbl[] = {
+               FH_RSCSR_CHNL0_STTS_WPTR_REG,
+               FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+               FH_RSCSR_CHNL0_WPTR,
+               FH_MEM_RCSR_CHNL0_CONFIG_REG,
+               FH_MEM_RSSR_SHARED_CTRL_REG,
+               FH_MEM_RSSR_RX_STATUS_REG,
+               FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+               FH_TSSR_TX_STATUS_REG,
+               FH_TSSR_TX_ERROR_REG
+       };
+#ifdef CONFIG_IWLWIFI_DEBUG
+       if (display) {
+               bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+               *buf = kmalloc(bufsz, GFP_KERNEL);
+               if (!*buf)
+                       return -ENOMEM;
+               pos += scnprintf(*buf + pos, bufsz - pos,
+                               "FH register values:\n");
+               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+                       pos += scnprintf(*buf + pos, bufsz - pos,
+                               "  %34s: 0X%08x\n",
+                               get_fh_string(fh_tbl[i]),
+                               iwl_read_direct32(bus(trans), fh_tbl[i]));
+               }
+               return pos;
+       }
+#endif
+       IWL_ERR(trans, "FH register values:\n");
+       for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
+               IWL_ERR(trans, "  %34s: 0X%08x\n",
+                       get_fh_string(fh_tbl[i]),
+                       iwl_read_direct32(bus(trans), fh_tbl[i]));
+       }
+       return 0;
+}
+
+static const char *get_csr_string(int cmd)
+{
+       switch (cmd) {
+       IWL_CMD(CSR_HW_IF_CONFIG_REG);
+       IWL_CMD(CSR_INT_COALESCING);
+       IWL_CMD(CSR_INT);
+       IWL_CMD(CSR_INT_MASK);
+       IWL_CMD(CSR_FH_INT_STATUS);
+       IWL_CMD(CSR_GPIO_IN);
+       IWL_CMD(CSR_RESET);
+       IWL_CMD(CSR_GP_CNTRL);
+       IWL_CMD(CSR_HW_REV);
+       IWL_CMD(CSR_EEPROM_REG);
+       IWL_CMD(CSR_EEPROM_GP);
+       IWL_CMD(CSR_OTP_GP_REG);
+       IWL_CMD(CSR_GIO_REG);
+       IWL_CMD(CSR_GP_UCODE_REG);
+       IWL_CMD(CSR_GP_DRIVER_REG);
+       IWL_CMD(CSR_UCODE_DRV_GP1);
+       IWL_CMD(CSR_UCODE_DRV_GP2);
+       IWL_CMD(CSR_LED_REG);
+       IWL_CMD(CSR_DRAM_INT_TBL_REG);
+       IWL_CMD(CSR_GIO_CHICKEN_BITS);
+       IWL_CMD(CSR_ANA_PLL_CFG);
+       IWL_CMD(CSR_HW_REV_WA_REG);
+       IWL_CMD(CSR_DBG_HPET_MEM_REG);
+       default:
+               return "UNKNOWN";
+       }
+}
+
+void iwl_dump_csr(struct iwl_trans *trans)
+{
+       int i;
+       static const u32 csr_tbl[] = {
+               CSR_HW_IF_CONFIG_REG,
+               CSR_INT_COALESCING,
+               CSR_INT,
+               CSR_INT_MASK,
+               CSR_FH_INT_STATUS,
+               CSR_GPIO_IN,
+               CSR_RESET,
+               CSR_GP_CNTRL,
+               CSR_HW_REV,
+               CSR_EEPROM_REG,
+               CSR_EEPROM_GP,
+               CSR_OTP_GP_REG,
+               CSR_GIO_REG,
+               CSR_GP_UCODE_REG,
+               CSR_GP_DRIVER_REG,
+               CSR_UCODE_DRV_GP1,
+               CSR_UCODE_DRV_GP2,
+               CSR_LED_REG,
+               CSR_DRAM_INT_TBL_REG,
+               CSR_GIO_CHICKEN_BITS,
+               CSR_ANA_PLL_CFG,
+               CSR_HW_REV_WA_REG,
+               CSR_DBG_HPET_MEM_REG
+       };
+       IWL_ERR(trans, "CSR values:\n");
+       IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is "
+               "CSR_INT_PERIODIC_REG)\n");
+       for (i = 0; i <  ARRAY_SIZE(csr_tbl); i++) {
+               IWL_ERR(trans, "  %25s: 0X%08x\n",
+                       get_csr_string(csr_tbl[i]),
+                       iwl_read32(bus(trans), csr_tbl[i]));
+       }
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/* create and remove of files */
+#define DEBUGFS_ADD_FILE(name, parent, mode) do {                      \
+       if (!debugfs_create_file(#name, mode, parent, trans,            \
+                                &iwl_dbgfs_##name##_ops))              \
+               return -ENOMEM;                                         \
+} while (0)
+
+/* file operation */
+#define DEBUGFS_READ_FUNC(name)                                         \
+static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
+                                       char __user *user_buf,          \
+                                       size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name)                                        \
+static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
+                                       const char __user *user_buf,    \
+                                       size_t count, loff_t *ppos);
+
+
+static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+#define DEBUGFS_READ_FILE_OPS(name)                                    \
+       DEBUGFS_READ_FUNC(name);                                        \
+static const struct file_operations iwl_dbgfs_##name##_ops = {         \
+       .read = iwl_dbgfs_##name##_read,                                \
+       .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
+};
+
+#define DEBUGFS_WRITE_FILE_OPS(name)                                    \
+       DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_dbgfs_##name##_ops = {          \
+       .write = iwl_dbgfs_##name##_write,                              \
+       .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
+};
+
+#define DEBUGFS_READ_WRITE_FILE_OPS(name)                              \
+       DEBUGFS_READ_FUNC(name);                                        \
+       DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_dbgfs_##name##_ops = {         \
+       .write = iwl_dbgfs_##name##_write,                              \
+       .read = iwl_dbgfs_##name##_read,                                \
+       .open = iwl_dbgfs_open_file_generic,                            \
+       .llseek = generic_file_llseek,                                  \
+};
+
+static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
+                                               char __user *user_buf,
+                                               size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_tx_queue *txq;
+       struct iwl_queue *q;
+       char *buf;
+       int pos = 0;
+       int cnt;
+       int ret;
+       const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
+
+       if (!trans_pcie->txq) {
+               IWL_ERR(trans, "txq not ready\n");
+               return -EAGAIN;
+       }
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
+               txq = &trans_pcie->txq[cnt];
+               q = &txq->q;
+               pos += scnprintf(buf + pos, bufsz - pos,
+                               "hwq %.2d: read=%u write=%u stop=%d"
+                               " swq_id=%#.2x (ac %d/hwq %d)\n",
+                               cnt, q->read_ptr, q->write_ptr,
+                               !!test_bit(cnt, trans_pcie->queue_stopped),
+                               txq->swq_id, txq->swq_id & 3,
+                               (txq->swq_id >> 2) & 0x1f);
+               if (cnt >= 4)
+                       continue;
+               /* for the ACs, display the stop count too */
+               pos += scnprintf(buf + pos, bufsz - pos,
+                       "        stop-count: %d\n",
+                       atomic_read(&trans_pcie->queue_stop_count[cnt]));
+       }
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
+                                               char __user *user_buf,
+                                               size_t count, loff_t *ppos) {
+       struct iwl_trans *trans = file->private_data;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
+       char buf[256];
+       int pos = 0;
+       const size_t bufsz = sizeof(buf);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+                                               rxq->read);
+       pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+                                               rxq->write);
+       pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+                                               rxq->free_count);
+       if (rxq->rb_stts) {
+               pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+                        le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
+       } else {
+               pos += scnprintf(buf + pos, bufsz - pos,
+                                       "closed_rb_num: Not Allocated\n");
+       }
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_log_event_read(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       char *buf;
+       int pos = 0;
+       ssize_t ret = -ENOMEM;
+
+       ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true);
+       if (buf) {
+               ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+               kfree(buf);
+       }
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_log_event_write(struct file *file,
+                                       const char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       u32 event_log_flag;
+       char buf[8];
+       int buf_size;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &event_log_flag) != 1)
+               return -EFAULT;
+       if (event_log_flag == 1)
+               iwl_dump_nic_event_log(trans, true, NULL, false);
+
+       return count;
+}
+
+static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos) {
+
+       struct iwl_trans *trans = file->private_data;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+       int pos = 0;
+       char *buf;
+       int bufsz = 24 * 64; /* 24 items * 64 char per item */
+       ssize_t ret;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IWL_ERR(trans, "Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "Interrupt Statistics Report:\n");
+
+       pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+               isr_stats->hw);
+       pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+               isr_stats->sw);
+       if (isr_stats->sw || isr_stats->hw) {
+               pos += scnprintf(buf + pos, bufsz - pos,
+                       "\tLast Restarting Code:  0x%X\n",
+                       isr_stats->err_code);
+       }
+#ifdef CONFIG_IWLWIFI_DEBUG
+       pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+               isr_stats->sch);
+       pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+               isr_stats->alive);
+#endif
+       pos += scnprintf(buf + pos, bufsz - pos,
+               "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+               isr_stats->ctkill);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+               isr_stats->wakeup);
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+               "Rx command responses:\t\t %u\n", isr_stats->rx);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+               isr_stats->tx);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+               isr_stats->unhandled);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       struct iwl_trans_pcie *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
+
+       char buf[8];
+       int buf_size;
+       u32 reset_flag;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%x", &reset_flag) != 1)
+               return -EFAULT;
+       if (reset_flag == 0)
+               memset(isr_stats, 0, sizeof(*isr_stats));
+
+       return count;
+}
+
+static ssize_t iwl_dbgfs_csr_write(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       char buf[8];
+       int buf_size;
+       int csr;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%d", &csr) != 1)
+               return -EFAULT;
+
+       iwl_dump_csr(trans);
+
+       return count;
+}
+
+static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_trans *trans = file->private_data;
+       char *buf;
+       int pos = 0;
+       ssize_t ret = -EFAULT;
+
+       ret = pos = iwl_dump_fh(trans, &buf, true);
+       if (buf) {
+               ret = simple_read_from_buffer(user_buf,
+                                             count, ppos, buf, pos);
+               kfree(buf);
+       }
+
+       return ret;
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(fh_reg);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_WRITE_FILE_OPS(csr);
+
+/*
+ * Create the debugfs files and directories
+ *
+ */
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+                                       struct dentry *dir)
+{
+       DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
+       DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
+       DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
+       DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
+       return 0;
+}
+#else
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+                                       struct dentry *dir)
+{ return 0; }
+
+#endif /*CONFIG_IWLWIFI_DEBUGFS */
+
+const struct iwl_trans_ops trans_ops_pcie = {
+       .alloc = iwl_trans_pcie_alloc,
+       .request_irq = iwl_trans_pcie_request_irq,
+       .start_device = iwl_trans_pcie_start_device,
+       .prepare_card_hw = iwl_trans_pcie_prepare_card_hw,
+       .stop_device = iwl_trans_pcie_stop_device,
+
+       .tx_start = iwl_trans_pcie_tx_start,
+       .wake_any_queue = iwl_trans_pcie_wake_any_queue,
+
+       .send_cmd = iwl_trans_pcie_send_cmd,
+
+       .tx = iwl_trans_pcie_tx,
+       .reclaim = iwl_trans_pcie_reclaim,
+
+       .tx_agg_disable = iwl_trans_pcie_tx_agg_disable,
+       .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc,
+       .tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
+
+       .kick_nic = iwl_trans_pcie_kick_nic,
+
+       .free = iwl_trans_pcie_free,
+       .stop_queue = iwl_trans_pcie_stop_queue,
+
+       .dbgfs_register = iwl_trans_pcie_dbgfs_register,
+
+       .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty,
+       .check_stuck_queue = iwl_trans_pcie_check_stuck_queue,
+
+#ifdef CONFIG_PM_SLEEP
+       .suspend = iwl_trans_pcie_suspend,
+       .resume = iwl_trans_pcie_resume,
+#endif
+};
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c
deleted file mode 100644 (file)
index 2d0ddb8..0000000
+++ /dev/null
@@ -1,1419 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <[email protected]>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/gfp.h>
-
-#include "iwl-dev.h"
-#include "iwl-agn.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
-
-/******************************************************************************
- *
- * RX path functions
- *
- ******************************************************************************/
-
-/*
- * Rx theory of operation
- *
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
- * each of which point to Receive Buffers to be filled by the NIC.  These get
- * used not only for Rx frames, but for any command response or notification
- * from the NIC.  The driver and NIC manage the Rx buffers by means
- * of indexes into the circular buffer.
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt.  The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->rxq is replenished and the READ INDEX is updated (updating the
- *   'processed' and 'read' driver indexes as well)
- * + A received packet is processed and handed to the kernel network stack,
- *   detached from the iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl_rx_queue_alloc()   Allocates rx_free
- * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
- *                            queue, updates firmware pointers, and updates
- *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
- *                            READ INDEX, detaching the SKB from the pool.
- *                            Moves the packet buffer from queue to rx_used.
- *                            Calls iwl_rx_queue_restock to refill any empty
- *                            slots.
- * ...
- *
- */
-
-/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
- */
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
-{
-       int s = q->read - q->write;
-       if (s <= 0)
-               s += RX_QUEUE_SIZE;
-       /* keep some buffer to not confuse full and empty queue */
-       s -= 2;
-       if (s < 0)
-               s = 0;
-       return s;
-}
-
-/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
-                       struct iwl_rx_queue *q)
-{
-       unsigned long flags;
-       u32 reg;
-
-       spin_lock_irqsave(&q->lock, flags);
-
-       if (q->need_update == 0)
-               goto exit_unlock;
-
-       if (hw_params(trans).shadow_reg_enable) {
-               /* shadow register enabled */
-               /* Device expects a multiple of 8 */
-               q->write_actual = (q->write & ~0x7);
-               iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual);
-       } else {
-               /* If power-saving is in use, make sure device is awake */
-               if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
-                       reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
-
-                       if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-                               IWL_DEBUG_INFO(trans,
-                                       "Rx queue requesting wakeup,"
-                                       " GP1 = 0x%x\n", reg);
-                               iwl_set_bit(bus(trans), CSR_GP_CNTRL,
-                                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                               goto exit_unlock;
-                       }
-
-                       q->write_actual = (q->write & ~0x7);
-                       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
-                                       q->write_actual);
-
-               /* Else device is assumed to be awake */
-               } else {
-                       /* Device expects a multiple of 8 */
-                       q->write_actual = (q->write & ~0x7);
-                       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR,
-                               q->write_actual);
-               }
-       }
-       q->need_update = 0;
-
- exit_unlock:
-       spin_unlock_irqrestore(&q->lock, flags);
-}
-
-/**
- * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr)
-{
-       return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-/**
- * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool
- *
- * If there are slots in the RX queue that need to be restocked,
- * and we have free pre-allocated buffers, fill the ranks as much
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rxq->lock, flags);
-       while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-               /* The overwritten rxb must be a used one */
-               rxb = rxq->queue[rxq->write];
-               BUG_ON(rxb && rxb->page);
-
-               /* Get next free Rx buffer, remove from free list */
-               element = rxq->rx_free.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-
-               /* Point to Rx buffer via next RBD in circular buffer */
-               rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma);
-               rxq->queue[rxq->write] = rxb;
-               rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-               rxq->free_count--;
-       }
-       spin_unlock_irqrestore(&rxq->lock, flags);
-       /* If the pre-allocated buffer pool is dropping low, schedule to
-        * refill it */
-       if (rxq->free_count <= RX_LOW_WATERMARK)
-               queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish);
-
-
-       /* If we've added more space for the firmware to place data, tell it.
-        * Increment device's write pointer in multiples of 8. */
-       if (rxq->write_actual != (rxq->write & ~0x7)) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               rxq->need_update = 1;
-               spin_unlock_irqrestore(&rxq->lock, flags);
-               iwl_rx_queue_update_write_ptr(trans, rxq);
-       }
-}
-
-/**
- * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * Also restock the Rx queue via iwl_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       struct list_head *element;
-       struct iwl_rx_mem_buffer *rxb;
-       struct page *page;
-       unsigned long flags;
-       gfp_t gfp_mask = priority;
-
-       while (1) {
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       return;
-               }
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               if (rxq->free_count > RX_LOW_WATERMARK)
-                       gfp_mask |= __GFP_NOWARN;
-
-               if (hw_params(trans).rx_page_order > 0)
-                       gfp_mask |= __GFP_COMP;
-
-               /* Alloc a new receive buffer */
-               page = alloc_pages(gfp_mask,
-                                 hw_params(trans).rx_page_order);
-               if (!page) {
-                       if (net_ratelimit())
-                               IWL_DEBUG_INFO(trans, "alloc_pages failed, "
-                                          "order: %d\n",
-                                          hw_params(trans).rx_page_order);
-
-                       if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-                           net_ratelimit())
-                               IWL_CRIT(trans, "Failed to alloc_pages with %s."
-                                        "Only %u free buffers remaining.\n",
-                                        priority == GFP_ATOMIC ?
-                                        "GFP_ATOMIC" : "GFP_KERNEL",
-                                        rxq->free_count);
-                       /* We don't reschedule replenish work here -- we will
-                        * call the restock method and if it still needs
-                        * more buffers it will schedule replenish */
-                       return;
-               }
-
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               if (list_empty(&rxq->rx_used)) {
-                       spin_unlock_irqrestore(&rxq->lock, flags);
-                       __free_pages(page, hw_params(trans).rx_page_order);
-                       return;
-               }
-               element = rxq->rx_used.next;
-               rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-               list_del(element);
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               BUG_ON(rxb->page);
-               rxb->page = page;
-               /* Get physical address of the RB */
-               rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0,
-                               PAGE_SIZE << hw_params(trans).rx_page_order,
-                               DMA_FROM_DEVICE);
-               /* dma address must be no more than 36 bits */
-               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
-               /* and also 256 byte aligned! */
-               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
-               spin_lock_irqsave(&rxq->lock, flags);
-
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-       }
-}
-
-void iwlagn_rx_replenish(struct iwl_trans *trans)
-{
-       unsigned long flags;
-
-       iwlagn_rx_allocate(trans, GFP_KERNEL);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       iwlagn_rx_queue_restock(trans);
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-}
-
-static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
-{
-       iwlagn_rx_allocate(trans, GFP_ATOMIC);
-
-       iwlagn_rx_queue_restock(trans);
-}
-
-void iwl_bg_rx_replenish(struct work_struct *data)
-{
-       struct iwl_trans_pcie *trans_pcie =
-           container_of(data, struct iwl_trans_pcie, rx_replenish);
-       struct iwl_trans *trans = trans_pcie->trans;
-
-       if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
-               return;
-
-       mutex_lock(&trans->shrd->mutex);
-       iwlagn_rx_replenish(trans);
-       mutex_unlock(&trans->shrd->mutex);
-}
-
-/**
- * iwl_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
-static void iwl_rx_handle(struct iwl_trans *trans)
-{
-       struct iwl_rx_mem_buffer *rxb;
-       struct iwl_rx_packet *pkt;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       u32 r, i;
-       int reclaim;
-       unsigned long flags;
-       u8 fill_rx = 0;
-       u32 count = 8;
-       int total_empty;
-
-       /* uCode's read index (stored in shared DRAM) indicates the last Rx
-        * buffer that the driver may process (last buffer filled by ucode). */
-       r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
-       i = rxq->read;
-
-       /* Rx interrupt, but nothing sent from uCode */
-       if (i == r)
-               IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i);
-
-       /* calculate total frames need to be restock after handling RX */
-       total_empty = r - rxq->write_actual;
-       if (total_empty < 0)
-               total_empty += RX_QUEUE_SIZE;
-
-       if (total_empty > (RX_QUEUE_SIZE / 2))
-               fill_rx = 1;
-
-       while (i != r) {
-               int len;
-
-               rxb = rxq->queue[i];
-
-               /* If an RXB doesn't have a Rx queue slot associated with it,
-                * then a bug has been introduced in the queue refilling
-                * routines -- catch it here */
-               if (WARN_ON(rxb == NULL)) {
-                       i = (i + 1) & RX_QUEUE_MASK;
-                       continue;
-               }
-
-               rxq->queue[i] = NULL;
-
-               dma_unmap_page(bus(trans)->dev, rxb->page_dma,
-                              PAGE_SIZE << hw_params(trans).rx_page_order,
-                              DMA_FROM_DEVICE);
-               pkt = rxb_addr(rxb);
-
-               IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
-                       i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-
-               len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-               len += sizeof(u32); /* account for status word */
-               trace_iwlwifi_dev_rx(priv(trans), pkt, len);
-
-               /* Reclaim a command buffer only if this packet is a response
-                *   to a (driver-originated) command.
-                * If the packet (e.g. Rx frame) originated from uCode,
-                *   there is no command buffer to reclaim.
-                * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-                *   but apparently a few don't get set; catch them here. */
-               reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-                       (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
-                       (pkt->hdr.cmd != REPLY_RX) &&
-                       (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
-                       (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
-                       (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-                       (pkt->hdr.cmd != REPLY_TX);
-
-               iwl_rx_dispatch(priv(trans), rxb);
-
-               /*
-                * XXX: After here, we should always check rxb->page
-                * against NULL before touching it or its virtual
-                * memory (pkt). Because some rx_handler might have
-                * already taken or freed the pages.
-                */
-
-               if (reclaim) {
-                       /* Invoke any callbacks, transfer the buffer to caller,
-                        * and fire off the (possibly) blocking
-                        * iwl_trans_send_cmd()
-                        * as we reclaim the driver command queue */
-                       if (rxb->page)
-                               iwl_tx_cmd_complete(priv(trans), rxb);
-                       else
-                               IWL_WARN(trans, "Claim null rxb?\n");
-               }
-
-               /* Reuse the page if possible. For notification packets and
-                * SKBs that fail to Rx correctly, add them back into the
-                * rx_free list for reuse later. */
-               spin_lock_irqsave(&rxq->lock, flags);
-               if (rxb->page != NULL) {
-                       rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page,
-                               0, PAGE_SIZE <<
-                                   hw_params(trans).rx_page_order,
-                               DMA_FROM_DEVICE);
-                       list_add_tail(&rxb->list, &rxq->rx_free);
-                       rxq->free_count++;
-               } else
-                       list_add_tail(&rxb->list, &rxq->rx_used);
-
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
-               i = (i + 1) & RX_QUEUE_MASK;
-               /* If there are a lot of unused frames,
-                * restock the Rx queue so ucode wont assert. */
-               if (fill_rx) {
-                       count++;
-                       if (count >= 8) {
-                               rxq->read = i;
-                               iwlagn_rx_replenish_now(trans);
-                               count = 0;
-                       }
-               }
-       }
-
-       /* Backtrack one entry */
-       rxq->read = i;
-       if (fill_rx)
-               iwlagn_rx_replenish_now(trans);
-       else
-               iwlagn_rx_queue_restock(trans);
-}
-
-static const char * const desc_lookup_text[] = {
-       "OK",
-       "FAIL",
-       "BAD_PARAM",
-       "BAD_CHECKSUM",
-       "NMI_INTERRUPT_WDG",
-       "SYSASSERT",
-       "FATAL_ERROR",
-       "BAD_COMMAND",
-       "HW_ERROR_TUNE_LOCK",
-       "HW_ERROR_TEMPERATURE",
-       "ILLEGAL_CHAN_FREQ",
-       "VCC_NOT_STABLE",
-       "FH_ERROR",
-       "NMI_INTERRUPT_HOST",
-       "NMI_INTERRUPT_ACTION_PT",
-       "NMI_INTERRUPT_UNKNOWN",
-       "UCODE_VERSION_MISMATCH",
-       "HW_ERROR_ABS_LOCK",
-       "HW_ERROR_CAL_LOCK_FAIL",
-       "NMI_INTERRUPT_INST_ACTION_PT",
-       "NMI_INTERRUPT_DATA_ACTION_PT",
-       "NMI_TRM_HW_ER",
-       "NMI_INTERRUPT_TRM",
-       "NMI_INTERRUPT_BREAK_POINT",
-       "DEBUG_0",
-       "DEBUG_1",
-       "DEBUG_2",
-       "DEBUG_3",
-};
-
-static struct { char *name; u8 num; } advanced_lookup[] = {
-       { "NMI_INTERRUPT_WDG", 0x34 },
-       { "SYSASSERT", 0x35 },
-       { "UCODE_VERSION_MISMATCH", 0x37 },
-       { "BAD_COMMAND", 0x38 },
-       { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
-       { "FATAL_ERROR", 0x3D },
-       { "NMI_TRM_HW_ERR", 0x46 },
-       { "NMI_INTERRUPT_TRM", 0x4C },
-       { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
-       { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
-       { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
-       { "NMI_INTERRUPT_HOST", 0x66 },
-       { "NMI_INTERRUPT_ACTION_PT", 0x7C },
-       { "NMI_INTERRUPT_UNKNOWN", 0x84 },
-       { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
-       { "ADVANCED_SYSASSERT", 0 },
-};
-
-static const char *desc_lookup(u32 num)
-{
-       int i;
-       int max = ARRAY_SIZE(desc_lookup_text);
-
-       if (num < max)
-               return desc_lookup_text[num];
-
-       max = ARRAY_SIZE(advanced_lookup) - 1;
-       for (i = 0; i < max; i++) {
-               if (advanced_lookup[i].num == num)
-                       break;
-       }
-       return advanced_lookup[i].name;
-}
-
-#define ERROR_START_OFFSET  (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
-
-static void iwl_dump_nic_error_log(struct iwl_trans *trans)
-{
-       u32 base;
-       struct iwl_error_event_table table;
-       struct iwl_priv *priv = priv(trans);
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       base = priv->device_pointers.error_event_table;
-       if (priv->ucode_type == IWL_UCODE_INIT) {
-               if (!base)
-                       base = priv->init_errlog_ptr;
-       } else {
-               if (!base)
-                       base = priv->inst_errlog_ptr;
-       }
-
-       if (!iwlagn_hw_valid_rtc_data_addr(base)) {
-               IWL_ERR(trans,
-                       "Not valid error log pointer 0x%08X for %s uCode\n",
-                       base,
-                       (priv->ucode_type == IWL_UCODE_INIT)
-                                       ? "Init" : "RT");
-               return;
-       }
-
-       iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table));
-
-       if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
-               IWL_ERR(trans, "Start IWL Error Log Dump:\n");
-               IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
-                       trans->shrd->status, table.valid);
-       }
-
-       trans_pcie->isr_stats.err_code = table.error_id;
-
-       trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
-                                     table.data1, table.data2, table.line,
-                                     table.blink1, table.blink2, table.ilink1,
-                                     table.ilink2, table.bcon_time, table.gp1,
-                                     table.gp2, table.gp3, table.ucode_ver,
-                                     table.hw_ver, table.brd_ver);
-       IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id,
-               desc_lookup(table.error_id));
-       IWL_ERR(trans, "0x%08X | uPc\n", table.pc);
-       IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1);
-       IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2);
-       IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1);
-       IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2);
-       IWL_ERR(trans, "0x%08X | data1\n", table.data1);
-       IWL_ERR(trans, "0x%08X | data2\n", table.data2);
-       IWL_ERR(trans, "0x%08X | line\n", table.line);
-       IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time);
-       IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low);
-       IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi);
-       IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1);
-       IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2);
-       IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3);
-       IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver);
-       IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver);
-       IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver);
-       IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd);
-}
-
-/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
- */
-static void iwl_irq_handle_error(struct iwl_trans *trans)
-{
-       struct iwl_priv *priv = priv(trans);
-       /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
-       if (priv->cfg->internal_wimax_coex &&
-           (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
-                       APMS_CLK_VAL_MRB_FUNC_MODE) ||
-            (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
-                       APMG_PS_CTRL_VAL_RESET_REQ))) {
-               /*
-                * Keep the restart process from trying to send host
-                * commands by clearing the ready bit.
-                */
-               clear_bit(STATUS_READY, &trans->shrd->status);
-               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-               wake_up_interruptible(&priv->wait_command_queue);
-               IWL_ERR(trans, "RF is used by WiMAX\n");
-               return;
-       }
-
-       IWL_ERR(trans, "Loaded firmware version: %s\n",
-               priv->hw->wiphy->fw_version);
-
-       iwl_dump_nic_error_log(trans);
-       iwl_dump_csr(trans);
-       iwl_dump_fh(trans, NULL, false);
-       iwl_dump_nic_event_log(trans, false, NULL, false);
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS)
-               iwl_print_rx_config_cmd(priv,
-                                       &priv->contexts[IWL_RXON_CTX_BSS]);
-#endif
-
-       iwlagn_fw_error(priv, false);
-}
-
-#define EVENT_START_OFFSET  (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
-                              u32 num_events, u32 mode,
-                              int pos, char **buf, size_t bufsz)
-{
-       u32 i;
-       u32 base;       /* SRAM byte address of event log header */
-       u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
-       u32 ptr;        /* SRAM byte address of log data */
-       u32 ev, time, data; /* event log data */
-       unsigned long reg_flags;
-       struct iwl_priv *priv = priv(trans);
-
-       if (num_events == 0)
-               return pos;
-
-       base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == IWL_UCODE_INIT) {
-               if (!base)
-                       base = priv->init_evtlog_ptr;
-       } else {
-               if (!base)
-                       base = priv->inst_evtlog_ptr;
-       }
-
-       if (mode == 0)
-               event_size = 2 * sizeof(u32);
-       else
-               event_size = 3 * sizeof(u32);
-
-       ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-       /* Make sure device is powered up for SRAM reads */
-       spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags);
-       iwl_grab_nic_access(bus(priv));
-
-       /* Set starting address; reads will auto-increment */
-       iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
-
-       /* "time" is actually "data" for mode 0 (no timestamp).
-       * place event id # at far right for easier visual parsing. */
-       for (i = 0; i < num_events; i++) {
-               ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
-               time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
-               if (mode == 0) {
-                       /* data, ev */
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "EVT_LOG:0x%08x:%04u\n",
-                                               time, ev);
-                       } else {
-                               trace_iwlwifi_dev_ucode_event(priv, 0,
-                                       time, ev);
-                               IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
-                                       time, ev);
-                       }
-               } else {
-                       data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "EVT_LOGT:%010u:0x%08x:%04u\n",
-                                                time, data, ev);
-                       } else {
-                               IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
-                                       time, data, ev);
-                               trace_iwlwifi_dev_ucode_event(priv, time,
-                                       data, ev);
-                       }
-               }
-       }
-
-       /* Allow device to power down */
-       iwl_release_nic_access(bus(priv));
-       spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags);
-       return pos;
-}
-
-/**
- * iwl_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity,
-                                   u32 num_wraps, u32 next_entry,
-                                   u32 size, u32 mode,
-                                   int pos, char **buf, size_t bufsz)
-{
-       /*
-        * display the newest DEFAULT_LOG_ENTRIES entries
-        * i.e the entries just before the next ont that uCode would fill.
-        */
-       if (num_wraps) {
-               if (next_entry < size) {
-                       pos = iwl_print_event_log(trans,
-                                               capacity - (size - next_entry),
-                                               size - next_entry, mode,
-                                               pos, buf, bufsz);
-                       pos = iwl_print_event_log(trans, 0,
-                                                 next_entry, mode,
-                                                 pos, buf, bufsz);
-               } else
-                       pos = iwl_print_event_log(trans, next_entry - size,
-                                                 size, mode, pos, buf, bufsz);
-       } else {
-               if (next_entry < size) {
-                       pos = iwl_print_event_log(trans, 0, next_entry,
-                                                 mode, pos, buf, bufsz);
-               } else {
-                       pos = iwl_print_event_log(trans, next_entry - size,
-                                                 size, mode, pos, buf, bufsz);
-               }
-       }
-       return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
-                           char **buf, bool display)
-{
-       u32 base;       /* SRAM byte address of event log header */
-       u32 capacity;   /* event log capacity in # entries */
-       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-       u32 num_wraps;  /* # times uCode wrapped to top of log */
-       u32 next_entry; /* index of next entry to be written by uCode */
-       u32 size;       /* # entries that we'll print */
-       u32 logsize;
-       int pos = 0;
-       size_t bufsz = 0;
-       struct iwl_priv *priv = priv(trans);
-
-       base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == IWL_UCODE_INIT) {
-               logsize = priv->init_evtlog_size;
-               if (!base)
-                       base = priv->init_evtlog_ptr;
-       } else {
-               logsize = priv->inst_evtlog_size;
-               if (!base)
-                       base = priv->inst_evtlog_ptr;
-       }
-
-       if (!iwlagn_hw_valid_rtc_data_addr(base)) {
-               IWL_ERR(trans,
-                       "Invalid event log pointer 0x%08X for %s uCode\n",
-                       base,
-                       (priv->ucode_type == IWL_UCODE_INIT)
-                                       ? "Init" : "RT");
-               return -EINVAL;
-       }
-
-       /* event log header */
-       capacity = iwl_read_targ_mem(bus(priv), base);
-       mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32)));
-       num_wraps = iwl_read_targ_mem(bus(priv), base + (2 * sizeof(u32)));
-       next_entry = iwl_read_targ_mem(bus(priv), base + (3 * sizeof(u32)));
-
-       if (capacity > logsize) {
-               IWL_ERR(trans, "Log capacity %d is bogus, limit to %d "
-                       "entries\n", capacity, logsize);
-               capacity = logsize;
-       }
-
-       if (next_entry > logsize) {
-               IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n",
-                       next_entry, logsize);
-               next_entry = logsize;
-       }
-
-       size = num_wraps ? capacity : next_entry;
-
-       /* bail out if nothing in log */
-       if (size == 0) {
-               IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n");
-               return pos;
-       }
-
-       /* enable/disable bt channel inhibition */
-       priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
-               size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-                       ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-       size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-               ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-       IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n",
-               size);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (display) {
-               if (full_log)
-                       bufsz = capacity * 48;
-               else
-                       bufsz = size * 48;
-               *buf = kmalloc(bufsz, GFP_KERNEL);
-               if (!*buf)
-                       return -ENOMEM;
-       }
-       if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
-               /*
-                * if uCode has wrapped back to top of log,
-                * start at the oldest entry,
-                * i.e the next one that uCode would fill.
-                */
-               if (num_wraps)
-                       pos = iwl_print_event_log(trans, next_entry,
-                                               capacity - next_entry, mode,
-                                               pos, buf, bufsz);
-               /* (then/else) start at top of log */
-               pos = iwl_print_event_log(trans, 0,
-                                         next_entry, mode, pos, buf, bufsz);
-       } else
-               pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
-                                               next_entry, size, mode,
-                                               pos, buf, bufsz);
-#else
-       pos = iwl_print_last_event_logs(trans, capacity, num_wraps,
-                                       next_entry, size, mode,
-                                       pos, buf, bufsz);
-#endif
-       return pos;
-}
-
-/* tasklet for iwlagn interrupt */
-void iwl_irq_tasklet(struct iwl_trans *trans)
-{
-       u32 inta = 0;
-       u32 handled = 0;
-       unsigned long flags;
-       u32 i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       u32 inta_mask;
-#endif
-
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
-
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       /* Ack/clear/reset pending uCode interrupts.
-        * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
-        */
-       /* There is a hardware bug in the interrupt mask function that some
-        * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
-        * they are disabled in the CSR_INT_MASK register. Furthermore the
-        * ICT interrupt handling mechanism has another bug that might cause
-        * these unmasked interrupts fail to be detected. We workaround the
-        * hardware bugs here by ACKing all the possible interrupts so that
-        * interrupt coalescing can still be achieved.
-        */
-       iwl_write32(bus(trans), CSR_INT,
-               trans_pcie->inta | ~trans_pcie->inta_mask);
-
-       inta = trans_pcie->inta;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
-               /* just for debug */
-               inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);
-               IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
-                               inta, inta_mask);
-       }
-#endif
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       /* saved interrupt in inta variable now we can reset trans_pcie->inta */
-       trans_pcie->inta = 0;
-
-       /* Now service all interrupt bits discovered above. */
-       if (inta & CSR_INT_BIT_HW_ERR) {
-               IWL_ERR(trans, "Hardware error detected.  Restarting.\n");
-
-               /* Tell the device to stop sending interrupts */
-               iwl_disable_interrupts(trans);
-
-               isr_stats->hw++;
-               iwl_irq_handle_error(trans);
-
-               handled |= CSR_INT_BIT_HW_ERR;
-
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
-               /* NIC fires this, but we don't use it, redundant with WAKEUP */
-               if (inta & CSR_INT_BIT_SCD) {
-                       IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
-                                     "the frame/frames.\n");
-                       isr_stats->sch++;
-               }
-
-               /* Alive notification via Rx interrupt will do the real work */
-               if (inta & CSR_INT_BIT_ALIVE) {
-                       IWL_DEBUG_ISR(trans, "Alive interrupt\n");
-                       isr_stats->alive++;
-               }
-       }
-#endif
-       /* Safely ignore these bits for debug checks below */
-       inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-       /* HW RF KILL switch toggled */
-       if (inta & CSR_INT_BIT_RF_KILL) {
-               int hw_rf_kill = 0;
-               if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-                       hw_rf_kill = 1;
-
-               IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
-                               hw_rf_kill ? "disable radio" : "enable radio");
-
-               isr_stats->rfkill++;
-
-               /* driver only loads ucode once setting the interface up.
-                * the driver allows loading the ucode even if the radio
-                * is killed. Hence update the killswitch state here. The
-                * rfkill handler will care about restarting if needed.
-                */
-               if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
-                       if (hw_rf_kill)
-                               set_bit(STATUS_RF_KILL_HW,
-                                       &trans->shrd->status);
-                       else
-                               clear_bit(STATUS_RF_KILL_HW,
-                                         &trans->shrd->status);
-                       wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy,
-                                                 hw_rf_kill);
-               }
-
-               handled |= CSR_INT_BIT_RF_KILL;
-       }
-
-       /* Chip got too hot and stopped itself */
-       if (inta & CSR_INT_BIT_CT_KILL) {
-               IWL_ERR(trans, "Microcode CT kill error detected.\n");
-               isr_stats->ctkill++;
-               handled |= CSR_INT_BIT_CT_KILL;
-       }
-
-       /* Error detected by uCode */
-       if (inta & CSR_INT_BIT_SW_ERR) {
-               IWL_ERR(trans, "Microcode SW error detected. "
-                       " Restarting 0x%X.\n", inta);
-               isr_stats->sw++;
-               iwl_irq_handle_error(trans);
-               handled |= CSR_INT_BIT_SW_ERR;
-       }
-
-       /* uCode wakes up after power-down sleep */
-       if (inta & CSR_INT_BIT_WAKEUP) {
-               IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
-               iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
-               for (i = 0; i < hw_params(trans).max_txq_num; i++)
-                       iwl_txq_update_write_ptr(trans,
-                                                &trans_pcie->txq[i]);
-
-               isr_stats->wakeup++;
-
-               handled |= CSR_INT_BIT_WAKEUP;
-       }
-
-       /* All uCode command responses, including Tx command responses,
-        * Rx "responses" (frame-received notification), and other
-        * notifications from uCode come through here*/
-       if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
-                       CSR_INT_BIT_RX_PERIODIC)) {
-               IWL_DEBUG_ISR(trans, "Rx interrupt\n");
-               if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
-                       handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-                       iwl_write32(bus(trans), CSR_FH_INT_STATUS,
-                                       CSR_FH_INT_RX_MASK);
-               }
-               if (inta & CSR_INT_BIT_RX_PERIODIC) {
-                       handled |= CSR_INT_BIT_RX_PERIODIC;
-                       iwl_write32(bus(trans),
-                               CSR_INT, CSR_INT_BIT_RX_PERIODIC);
-               }
-               /* Sending RX interrupt require many steps to be done in the
-                * the device:
-                * 1- write interrupt to current index in ICT table.
-                * 2- dma RX frame.
-                * 3- update RX shared data to indicate last write index.
-                * 4- send interrupt.
-                * This could lead to RX race, driver could receive RX interrupt
-                * but the shared data changes does not reflect this;
-                * periodic interrupt will detect any dangling Rx activity.
-                */
-
-               /* Disable periodic interrupt; we use it as just a one-shot. */
-               iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
-                           CSR_INT_PERIODIC_DIS);
-               iwl_rx_handle(trans);
-
-               /*
-                * Enable periodic interrupt in 8 msec only if we received
-                * real RX interrupt (instead of just periodic int), to catch
-                * any dangling Rx interrupt.  If it was just the periodic
-                * interrupt, there was no dangling Rx activity, and no need
-                * to extend the periodic interrupt; one-shot is enough.
-                */
-               if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
-                       iwl_write8(bus(trans), CSR_INT_PERIODIC_REG,
-                                   CSR_INT_PERIODIC_ENA);
-
-               isr_stats->rx++;
-       }
-
-       /* This "Tx" DMA channel is used only for loading uCode */
-       if (inta & CSR_INT_BIT_FH_TX) {
-               iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
-               IWL_DEBUG_ISR(trans, "uCode load interrupt\n");
-               isr_stats->tx++;
-               handled |= CSR_INT_BIT_FH_TX;
-               /* Wake up uCode load routine, now that load is complete */
-               priv(trans)->ucode_write_complete = 1;
-               wake_up_interruptible(&priv(trans)->wait_command_queue);
-       }
-
-       if (inta & ~handled) {
-               IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-               isr_stats->unhandled++;
-       }
-
-       if (inta & ~(trans_pcie->inta_mask)) {
-               IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n",
-                        inta & ~trans_pcie->inta_mask);
-       }
-
-       /* Re-enable all interrupts */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
-               iwl_enable_interrupts(trans);
-       /* Re-enable RF_KILL if it occurred */
-       else if (handled & CSR_INT_BIT_RF_KILL)
-               iwl_enable_rfkill_int(priv(trans));
-}
-
-/******************************************************************************
- *
- * ICT functions
- *
- ******************************************************************************/
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
-
-/* Free dram table */
-void iwl_free_isr_ict(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (trans_pcie->ict_tbl_vir) {
-               dma_free_coherent(bus(trans)->dev,
-                                 (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-                                 trans_pcie->ict_tbl_vir,
-                                 trans_pcie->ict_tbl_dma);
-               trans_pcie->ict_tbl_vir = NULL;
-               memset(&trans_pcie->ict_tbl_dma, 0,
-                       sizeof(trans_pcie->ict_tbl_dma));
-               memset(&trans_pcie->aligned_ict_tbl_dma, 0,
-                       sizeof(trans_pcie->aligned_ict_tbl_dma));
-       }
-}
-
-
-/* allocate dram shared table it is a PAGE_SIZE aligned
- * also reset all data related to ICT table interrupt.
- */
-int iwl_alloc_isr_ict(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       /* allocate shrared data table */
-       trans_pcie->ict_tbl_vir =
-               dma_alloc_coherent(bus(trans)->dev,
-                                  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-                                  &trans_pcie->ict_tbl_dma, GFP_KERNEL);
-       if (!trans_pcie->ict_tbl_vir)
-               return -ENOMEM;
-
-       /* align table to PAGE_SIZE boundary */
-       trans_pcie->aligned_ict_tbl_dma =
-               ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
-
-       IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
-                          (unsigned long long)trans_pcie->ict_tbl_dma,
-                          (unsigned long long)trans_pcie->aligned_ict_tbl_dma,
-                          (int)(trans_pcie->aligned_ict_tbl_dma -
-                          trans_pcie->ict_tbl_dma));
-
-       trans_pcie->ict_tbl =  trans_pcie->ict_tbl_vir +
-                         (trans_pcie->aligned_ict_tbl_dma -
-                         trans_pcie->ict_tbl_dma);
-
-       IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
-                            trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
-                       (int)(trans_pcie->aligned_ict_tbl_dma -
-                           trans_pcie->ict_tbl_dma));
-
-       /* reset table and index to all 0 */
-       memset(trans_pcie->ict_tbl_vir, 0,
-               (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
-       trans_pcie->ict_index = 0;
-
-       /* add periodic RX interrupt */
-       trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
-       return 0;
-}
-
-/* Device is going up inform it about using ICT interrupt table,
- * also we need to tell the driver to start using ICT interrupt.
- */
-int iwl_reset_ict(struct iwl_trans *trans)
-{
-       u32 val;
-       unsigned long flags;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (!trans_pcie->ict_tbl_vir)
-               return 0;
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       iwl_disable_interrupts(trans);
-
-       memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
-
-       val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
-
-       val |= CSR_DRAM_INT_TBL_ENABLE;
-       val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
-
-       IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
-                       "aligned dma address %Lx\n",
-                       val,
-                       (unsigned long long)trans_pcie->aligned_ict_tbl_dma);
-
-       iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
-       trans_pcie->use_ict = true;
-       trans_pcie->ict_index = 0;
-       iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask);
-       iwl_enable_interrupts(trans);
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       return 0;
-}
-
-/* Device is going down disable ict interrupt usage */
-void iwl_disable_ict(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       unsigned long flags;
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       trans_pcie->use_ict = false;
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-}
-
-static irqreturn_t iwl_isr(int irq, void *data)
-{
-       struct iwl_trans *trans = data;
-       struct iwl_trans_pcie *trans_pcie;
-       u32 inta, inta_mask;
-       unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       u32 inta_fh;
-#endif
-       if (!trans)
-               return IRQ_NONE;
-
-       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       /* Disable (but don't clear!) interrupts here to avoid
-        *    back-to-back ISRs and sporadic interrupts from our NIC.
-        * If we have something to service, the tasklet will re-enable ints.
-        * If we *don't* have something, we'll re-enable before leaving here. */
-       inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);  /* just for debug */
-       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
-
-       /* Discover which interrupts are active/pending */
-       inta = iwl_read32(bus(trans), CSR_INT);
-
-       /* Ignore interrupt if there's nothing in NIC to service.
-        * This may be due to IRQ shared with another device,
-        * or due to sporadic interrupts thrown from our NIC. */
-       if (!inta) {
-               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-               goto none;
-       }
-
-       if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-               /* Hardware disappeared. It might have already raised
-                * an interrupt */
-               IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-               goto unplugged;
-       }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
-               inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS);
-               IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
-                             "fh 0x%08x\n", inta, inta_mask, inta_fh);
-       }
-#endif
-
-       trans_pcie->inta |= inta;
-       /* iwl_irq_tasklet() will service interrupts and re-enable them */
-       if (likely(inta))
-               tasklet_schedule(&trans_pcie->irq_tasklet);
-       else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-                       !trans_pcie->inta)
-               iwl_enable_interrupts(trans);
-
- unplugged:
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-       return IRQ_HANDLED;
-
- none:
-       /* re-enable interrupts here since we don't have anything to service. */
-       /* only Re-enable if disabled by irq  and no schedules tasklet. */
-       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-               !trans_pcie->inta)
-               iwl_enable_interrupts(trans);
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-       return IRQ_NONE;
-}
-
-/* interrupt handler using ict table, with this interrupt driver will
- * stop using INTA register to get device's interrupt, reading this register
- * is expensive, device will write interrupts in ICT dram table, increment
- * index then will fire interrupt to driver, driver will OR all ICT table
- * entries from current index up to table entry with 0 value. the result is
- * the interrupt we need to service, driver will set the entries back to 0 and
- * set index.
- */
-irqreturn_t iwl_isr_ict(int irq, void *data)
-{
-       struct iwl_trans *trans = data;
-       struct iwl_trans_pcie *trans_pcie;
-       u32 inta, inta_mask;
-       u32 val = 0;
-       unsigned long flags;
-
-       if (!trans)
-               return IRQ_NONE;
-
-       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       /* dram interrupt table not set yet,
-        * use legacy interrupt.
-        */
-       if (!trans_pcie->use_ict)
-               return iwl_isr(irq, data);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       /* Disable (but don't clear!) interrupts here to avoid
-        * back-to-back ISRs and sporadic interrupts from our NIC.
-        * If we have something to service, the tasklet will re-enable ints.
-        * If we *don't* have something, we'll re-enable before leaving here.
-        */
-       inta_mask = iwl_read32(bus(trans), CSR_INT_MASK);  /* just for debug */
-       iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000);
-
-
-       /* Ignore interrupt if there's nothing in NIC to service.
-        * This may be due to IRQ shared with another device,
-        * or due to sporadic interrupts thrown from our NIC. */
-       if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) {
-               IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-               goto none;
-       }
-
-       /* read all entries that not 0 start with ict_index */
-       while (trans_pcie->ict_tbl[trans_pcie->ict_index]) {
-
-               val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
-               IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
-                               trans_pcie->ict_index,
-                               le32_to_cpu(
-                                 trans_pcie->ict_tbl[trans_pcie->ict_index]));
-               trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
-               trans_pcie->ict_index =
-                       iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
-
-       }
-
-       /* We should not get this value, just ignore it. */
-       if (val == 0xffffffff)
-               val = 0;
-
-       /*
-        * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit
-        * (bit 15 before shifting it to 31) to clear when using interrupt
-        * coalescing. fortunately, bits 18 and 19 stay set when this happens
-        * so we use them to decide on the real state of the Rx bit.
-        * In order words, bit 15 is set if bit 18 or bit 19 are set.
-        */
-       if (val & 0xC0000)
-               val |= 0x8000;
-
-       inta = (0xff & val) | ((0xff00 & val) << 16);
-       IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
-                       inta, inta_mask, val);
-
-       inta &= trans_pcie->inta_mask;
-       trans_pcie->inta |= inta;
-
-       /* iwl_irq_tasklet() will service interrupts and re-enable them */
-       if (likely(inta))
-               tasklet_schedule(&trans_pcie->irq_tasklet);
-       else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-                       !trans_pcie->inta) {
-               /* Allow interrupt if was disabled by this handler and
-                * no tasklet was schedules, We should not enable interrupt,
-                * tasklet will enable it.
-                */
-               iwl_enable_interrupts(trans);
-       }
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-       return IRQ_HANDLED;
-
- none:
-       /* re-enable interrupts here since we don't have anything to service.
-        * only Re-enable if disabled by irq.
-        */
-       if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-               !trans_pcie->inta)
-               iwl_enable_interrupts(trans);
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-       return IRQ_NONE;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
deleted file mode 100644 (file)
index 5dd6a6d..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <[email protected]>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-#include "iwl-agn.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
-
-/**
- * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
-                                          struct iwl_tx_queue *txq,
-                                          u16 byte_cnt)
-{
-       struct iwlagn_scd_bc_tbl *scd_bc_tbl;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       int write_ptr = txq->q.write_ptr;
-       int txq_id = txq->q.id;
-       u8 sec_ctl = 0;
-       u8 sta_id = 0;
-       u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-       __le16 bc_ent;
-
-       scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
-
-       WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
-
-       sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
-       sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
-
-       switch (sec_ctl & TX_CMD_SEC_MSK) {
-       case TX_CMD_SEC_CCM:
-               len += CCMP_MIC_LEN;
-               break;
-       case TX_CMD_SEC_TKIP:
-               len += TKIP_ICV_LEN;
-               break;
-       case TX_CMD_SEC_WEP:
-               len += WEP_IV_LEN + WEP_ICV_LEN;
-               break;
-       }
-
-       bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
-
-       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
-       if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               scd_bc_tbl[txq_id].
-                       tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-/**
- * iwl_txq_update_write_ptr - Send new write index to hardware
- */
-void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
-{
-       u32 reg = 0;
-       int txq_id = txq->q.id;
-
-       if (txq->need_update == 0)
-               return;
-
-       if (hw_params(trans).shadow_reg_enable) {
-               /* shadow register enabled */
-               iwl_write32(bus(trans), HBUS_TARG_WRPTR,
-                           txq->q.write_ptr | (txq_id << 8));
-       } else {
-               /* if we're trying to save power */
-               if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) {
-                       /* wake up nic if it's powered down ...
-                        * uCode will wake up, and interrupt us again, so next
-                        * time we'll skip this part. */
-                       reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1);
-
-                       if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-                               IWL_DEBUG_INFO(trans,
-                                       "Tx queue %d requesting wakeup,"
-                                       " GP1 = 0x%x\n", txq_id, reg);
-                               iwl_set_bit(bus(trans), CSR_GP_CNTRL,
-                                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-                               return;
-                       }
-
-                       iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
-                                    txq->q.write_ptr | (txq_id << 8));
-
-               /*
-                * else not in power-save mode,
-                * uCode will never sleep when we're
-                * trying to tx (during RFKILL, we're not trying to tx).
-                */
-               } else
-                       iwl_write32(bus(trans), HBUS_TARG_WRPTR,
-                                   txq->q.write_ptr | (txq_id << 8));
-       }
-       txq->need_update = 0;
-}
-
-static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-       dma_addr_t addr = get_unaligned_le32(&tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               addr |=
-               ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
-
-       return addr;
-}
-
-static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-       return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
-static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
-                                 dma_addr_t addr, u16 len)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-       u16 hi_n_len = len << 4;
-
-       put_unaligned_le32(addr, &tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
-
-       tb->hi_n_len = cpu_to_le16(hi_n_len);
-
-       tfd->num_tbs = idx + 1;
-}
-
-static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
-{
-       return tfd->num_tbs & 0x1f;
-}
-
-static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
-                    struct iwl_tfd *tfd, enum dma_data_direction dma_dir)
-{
-       int i;
-       int num_tbs;
-
-       /* Sanity check on number of chunks */
-       num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
-               /* @todo issue fatal error, it is quite serious situation */
-               return;
-       }
-
-       /* Unmap tx_cmd */
-       if (num_tbs)
-               dma_unmap_single(bus(trans)->dev,
-                               dma_unmap_addr(meta, mapping),
-                               dma_unmap_len(meta, len),
-                               DMA_BIDIRECTIONAL);
-
-       /* Unmap chunks, if any. */
-       for (i = 1; i < num_tbs; i++)
-               dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i),
-                               iwl_tfd_tb_get_len(tfd, i), dma_dir);
-}
-
-/**
- * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- * @trans - transport private data
- * @txq - tx queue
- * @index - the index of the TFD to be freed
- *
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
-void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-       int index)
-{
-       struct iwl_tfd *tfd_tmp = txq->tfds;
-
-       iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index],
-                        DMA_TO_DEVICE);
-
-       /* free SKB */
-       if (txq->skbs) {
-               struct sk_buff *skb;
-
-               skb = txq->skbs[index];
-
-               /* can be called from irqs-disabled context */
-               if (skb) {
-                       dev_kfree_skb_any(skb);
-                       txq->skbs[index] = NULL;
-               }
-       }
-}
-
-int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
-                                struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len,
-                                u8 reset)
-{
-       struct iwl_queue *q;
-       struct iwl_tfd *tfd, *tfd_tmp;
-       u32 num_tbs;
-
-       q = &txq->q;
-       tfd_tmp = txq->tfds;
-       tfd = &tfd_tmp[q->write_ptr];
-
-       if (reset)
-               memset(tfd, 0, sizeof(*tfd));
-
-       num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-       /* Each TFD can point to a maximum 20 Tx buffers */
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(trans, "Error can not send more than %d chunks\n",
-                         IWL_NUM_OF_TBS);
-               return -EINVAL;
-       }
-
-       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
-               return -EINVAL;
-
-       if (unlikely(addr & ~IWL_TX_DMA_MASK))
-               IWL_ERR(trans, "Unaligned address = %llx\n",
-                         (unsigned long long)addr);
-
-       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
-
-       return 0;
-}
-
-/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
- * DMA services
- *
- * Theory of operation
- *
- * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
- * of buffer descriptors, each of which points to one or more data buffers for
- * the device to read from or fill.  Driver and device exchange status of each
- * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
- * entries in each circular buffer, to protect against confusing empty and full
- * queue states.
- *
- * The device reads or writes the data in the queues via the device's several
- * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
- *
- * For Tx queue, there are low mark and high mark limits. If, after queuing
- * the packet for Tx, free space become < low mark, Tx queue stopped. When
- * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
- * Tx queue resumed.
- *
- ***************************************************/
-
-int iwl_queue_space(const struct iwl_queue *q)
-{
-       int s = q->read_ptr - q->write_ptr;
-
-       if (q->read_ptr > q->write_ptr)
-               s -= q->n_bd;
-
-       if (s <= 0)
-               s += q->n_window;
-       /* keep some reserve to not confuse empty and full situations */
-       s -= 2;
-       if (s < 0)
-               s = 0;
-       return s;
-}
-
-/**
- * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
-{
-       q->n_bd = count;
-       q->n_window = slots_num;
-       q->id = id;
-
-       /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-        * and iwl_queue_dec_wrap are broken. */
-       if (WARN_ON(!is_power_of_2(count)))
-               return -EINVAL;
-
-       /* slots_num must be power-of-two size, otherwise
-        * get_cmd_index is broken. */
-       if (WARN_ON(!is_power_of_2(slots_num)))
-               return -EINVAL;
-
-       q->low_mark = q->n_window / 4;
-       if (q->low_mark < 4)
-               q->low_mark = 4;
-
-       q->high_mark = q->n_window / 8;
-       if (q->high_mark < 2)
-               q->high_mark = 2;
-
-       q->write_ptr = q->read_ptr = 0;
-
-       return 0;
-}
-
-static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
-                                         struct iwl_tx_queue *txq)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
-       int txq_id = txq->q.id;
-       int read_ptr = txq->q.read_ptr;
-       u8 sta_id = 0;
-       __le16 bc_ent;
-
-       WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
-
-       if (txq_id != trans->shrd->cmd_queue)
-               sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
-
-       bc_ent = cpu_to_le16(1 | (sta_id << 12));
-       scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
-
-       if (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               scd_bc_tbl[txq_id].
-                       tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
-}
-
-static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid,
-                                       u16 txq_id)
-{
-       u32 tbl_dw_addr;
-       u32 tbl_dw;
-       u16 scd_q2ratid;
-
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
-       tbl_dw_addr = trans_pcie->scd_base_addr +
-                       SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
-
-       tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr);
-
-       if (txq_id & 0x1)
-               tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
-       else
-               tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-       iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw);
-
-       return 0;
-}
-
-static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
-{
-       /* Simply stop the queue, but don't change any configuration;
-        * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-       iwl_write_prph(bus(trans),
-               SCD_QUEUE_STATUS_BITS(txq_id),
-               (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-               (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
-                               int txq_id, u32 index)
-{
-       iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
-                       (index & 0xff) | (txq_id << 8));
-       iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
-                                       struct iwl_tx_queue *txq,
-                                       int tx_fifo_id, int scd_retry)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int txq_id = txq->q.id;
-       int active =
-               test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0;
-
-       iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id),
-                       (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
-                       (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
-                       (1 << SCD_QUEUE_STTS_REG_POS_WSL) |
-                       SCD_QUEUE_STTS_REG_MSK);
-
-       txq->sched_retry = scd_retry;
-
-       IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n",
-                      active ? "Activate" : "Deactivate",
-                      scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
-}
-
-static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
-                                   u8 ctx, u16 tid)
-{
-       const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx];
-       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-               return ac_to_fifo[tid_to_ac[tid]];
-
-       /* no support for TIDs 8-15 yet */
-       return -EINVAL;
-}
-
-void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
-                                enum iwl_rxon_context_id ctx, int sta_id,
-                                int tid, int frame_limit)
-{
-       int tx_fifo, txq_id, ssn_idx;
-       u16 ra_tid;
-       unsigned long flags;
-       struct iwl_tid_data *tid_data;
-
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (WARN_ON(sta_id == IWL_INVALID_STATION))
-               return;
-       if (WARN_ON(tid >= IWL_MAX_TID_COUNT))
-               return;
-
-       tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid);
-       if (WARN_ON(tx_fifo < 0)) {
-               IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo);
-               return;
-       }
-
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       ssn_idx = SEQ_TO_SN(tid_data->seq_number);
-       txq_id = tid_data->agg.txq_id;
-       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-
-       ra_tid = BUILD_RAxTID(sta_id, tid);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       /* Stop this Tx queue before configuring it */
-       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
-
-       /* Map receiver-address / traffic-ID to this queue */
-       iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id);
-
-       /* Set this queue as a chain-building queue */
-       iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<<txq_id));
-
-       /* enable aggregations for the queue */
-       iwl_set_bits_prph(bus(trans), SCD_AGGR_SEL, (1<<txq_id));
-
-       /* Place first TFD at index corresponding to start sequence number.
-        * Assumes that ssn_idx is valid (!= 0xFFF) */
-       trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-       trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-       iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
-
-       /* Set up Tx window size and frame limit for this queue */
-       iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
-                       SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
-                       sizeof(u32),
-                       ((frame_limit <<
-                       SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
-                       SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
-                       ((frame_limit <<
-                       SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-                       SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-
-       iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
-
-       /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
-       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id],
-                                       tx_fifo, 1);
-
-       trans_pcie->txq[txq_id].sta_id = sta_id;
-       trans_pcie->txq[txq_id].tid = tid;
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-}
-
-/*
- * Find first available (lowest unused) Tx Queue, mark it "active".
- * Called only when finding queue for aggregation.
- * Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
- */
-static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int txq_id;
-
-       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
-               if (!test_and_set_bit(txq_id,
-                                       &trans_pcie->txq_ctx_active_msk))
-                       return txq_id;
-       return -1;
-}
-
-int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
-                               enum iwl_rxon_context_id ctx, int sta_id,
-                               int tid, u16 *ssn)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tid_data *tid_data;
-       unsigned long flags;
-       u16 txq_id;
-       struct iwl_priv *priv = priv(trans);
-
-       txq_id = iwlagn_txq_ctx_activate_free(trans);
-       if (txq_id == -1) {
-               IWL_ERR(trans, "No free aggregation queue available\n");
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
-       tid_data->agg.txq_id = txq_id;
-       iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
-
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       if (tid_data->tfds_in_queue == 0) {
-               IWL_DEBUG_HT(trans, "HW queue is empty\n");
-               tid_data->agg.state = IWL_AGG_ON;
-               iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
-       } else {
-               IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW"
-                            "queue\n", tid_data->tfds_in_queue);
-               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-       }
-       spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
-       return 0;
-}
-
-void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
-
-       iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
-
-       trans_pcie->txq[txq_id].q.read_ptr = 0;
-       trans_pcie->txq[txq_id].q.write_ptr = 0;
-       /* supposes that ssn_idx is valid (!= 0xFFF) */
-       iwl_trans_set_wr_ptrs(trans, txq_id, 0);
-
-       iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
-       iwl_txq_ctx_deactivate(trans_pcie, txq_id);
-       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
-}
-
-int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
-                                 enum iwl_rxon_context_id ctx, int sta_id,
-                                 int tid)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
-       int read_ptr, write_ptr;
-       struct iwl_tid_data *tid_data;
-       int txq_id;
-
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       txq_id = tid_data->agg.txq_id;
-
-       if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-           (IWLAGN_FIRST_AMPDU_QUEUE +
-               hw_params(trans).num_ampdu_queues <= txq_id)) {
-               IWL_ERR(trans,
-                       "queue number out of range: %d, must be %d to %d\n",
-                       txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
-                       IWLAGN_FIRST_AMPDU_QUEUE +
-                       hw_params(trans).num_ampdu_queues - 1);
-               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-               return -EINVAL;
-       }
-
-       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /*
-               * This can happen if the peer stops aggregation
-               * again before we've had a chance to drain the
-               * queue we selected previously, i.e. before the
-               * session was really started completely.
-               */
-               IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
-               goto turn_off;
-       case IWL_AGG_ON:
-               break;
-       default:
-               IWL_WARN(trans, "Stopping AGG while state not ON"
-                               "or starting\n");
-       }
-
-       write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
-       read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
-
-       /* The queue is not empty */
-       if (write_ptr != read_ptr) {
-               IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n");
-               trans->shrd->tid_data[sta_id][tid].agg.state =
-                       IWL_EMPTYING_HW_QUEUE_DELBA;
-               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-               return 0;
-       }
-
-       IWL_DEBUG_HT(trans, "HW queue is empty\n");
-turn_off:
-       trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
-
-       /* do not restore/save irqs */
-       spin_unlock(&trans->shrd->sta_lock);
-       spin_lock(&trans->shrd->lock);
-
-       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
-
-       return 0;
-}
-
-/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
-
-/**
- * iwl_enqueue_hcmd - enqueue a uCode command
- * @priv: device private data point
- * @cmd: a point to the ucode command structure
- *
- * The function returns < 0 values to indicate the operation is
- * failed. On success, it turns the index (> 0) of command in the
- * command queue.
- */
-static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
-       struct iwl_queue *q = &txq->q;
-       struct iwl_device_cmd *out_cmd;
-       struct iwl_cmd_meta *out_meta;
-       dma_addr_t phys_addr;
-       unsigned long flags;
-       u32 idx;
-       u16 copy_size, cmd_size;
-       bool is_ct_kill = false;
-       bool had_nocopy = false;
-       int i;
-       u8 *cmd_dest;
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-       const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
-       int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
-       int trace_idx;
-#endif
-
-       if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
-               IWL_WARN(trans, "fw recovery, no hcmd send\n");
-               return -EIO;
-       }
-
-       if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
-           !(cmd->flags & CMD_ON_DEMAND)) {
-               IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
-               return -EIO;
-       }
-
-       copy_size = sizeof(out_cmd->hdr);
-       cmd_size = sizeof(out_cmd->hdr);
-
-       /* need one for the header if the first is NOCOPY */
-       BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
-
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-               if (!cmd->len[i])
-                       continue;
-               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
-                       had_nocopy = true;
-               } else {
-                       /* NOCOPY must not be followed by normal! */
-                       if (WARN_ON(had_nocopy))
-                               return -EINVAL;
-                       copy_size += cmd->len[i];
-               }
-               cmd_size += cmd->len[i];
-       }
-
-       /*
-        * If any of the command structures end up being larger than
-        * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
-        * allocated into separate TFDs, then we will need to
-        * increase the size of the buffers.
-        */
-       if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
-               return -EINVAL;
-
-       if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
-               IWL_WARN(trans, "Not sending command - %s KILL\n",
-                        iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
-               return -EIO;
-       }
-
-       spin_lock_irqsave(&trans->hcmd_lock, flags);
-
-       if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-               spin_unlock_irqrestore(&trans->hcmd_lock, flags);
-
-               IWL_ERR(trans, "No space in command queue\n");
-               is_ct_kill = iwl_check_for_ct_kill(priv(trans));
-               if (!is_ct_kill) {
-                       IWL_ERR(trans, "Restarting adapter queue is full\n");
-                       iwlagn_fw_error(priv(trans), false);
-               }
-               return -ENOSPC;
-       }
-
-       idx = get_cmd_index(q, q->write_ptr);
-       out_cmd = txq->cmd[idx];
-       out_meta = &txq->meta[idx];
-
-       memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
-       if (cmd->flags & CMD_WANT_SKB)
-               out_meta->source = cmd;
-       if (cmd->flags & CMD_ASYNC)
-               out_meta->callback = cmd->callback;
-
-       /* set up the header */
-
-       out_cmd->hdr.cmd = cmd->id;
-       out_cmd->hdr.flags = 0;
-       out_cmd->hdr.sequence =
-               cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
-                                        INDEX_TO_SEQ(q->write_ptr));
-
-       /* and copy the data that needs to be copied */
-
-       cmd_dest = &out_cmd->cmd.payload[0];
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-               if (!cmd->len[i])
-                       continue;
-               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
-                       break;
-               memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
-               cmd_dest += cmd->len[i];
-       }
-
-       IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, "
-                       "%d bytes at %d[%d]:%d\n",
-                       get_cmd_string(out_cmd->hdr.cmd),
-                       out_cmd->hdr.cmd,
-                       le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
-                       q->write_ptr, idx, trans->shrd->cmd_queue);
-
-       phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size,
-                               DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
-               idx = -ENOMEM;
-               goto out;
-       }
-
-       dma_unmap_addr_set(out_meta, mapping, phys_addr);
-       dma_unmap_len_set(out_meta, len, copy_size);
-
-       iwlagn_txq_attach_buf_to_tfd(trans, txq,
-                                       phys_addr, copy_size, 1);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-       trace_bufs[0] = &out_cmd->hdr;
-       trace_lens[0] = copy_size;
-       trace_idx = 1;
-#endif
-
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
-               if (!cmd->len[i])
-                       continue;
-               if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
-                       continue;
-               phys_addr = dma_map_single(bus(trans)->dev,
-                                          (void *)cmd->data[i],
-                                          cmd->len[i], DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(bus(trans)->dev, phys_addr)) {
-                       iwlagn_unmap_tfd(trans, out_meta,
-                                        &txq->tfds[q->write_ptr],
-                                        DMA_BIDIRECTIONAL);
-                       idx = -ENOMEM;
-                       goto out;
-               }
-
-               iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
-                                            cmd->len[i], 0);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-               trace_bufs[trace_idx] = cmd->data[i];
-               trace_lens[trace_idx] = cmd->len[i];
-               trace_idx++;
-#endif
-       }
-
-       out_meta->flags = cmd->flags;
-
-       txq->need_update = 1;
-
-       /* check that tracing gets all possible blocks */
-       BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
-#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
-       trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
-                              trace_bufs[0], trace_lens[0],
-                              trace_bufs[1], trace_lens[1],
-                              trace_bufs[2], trace_lens[2]);
-#endif
-
-       /* Increment and update queue's write index */
-       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_txq_update_write_ptr(trans, txq);
-
- out:
-       spin_unlock_irqrestore(&trans->hcmd_lock, flags);
-       return idx;
-}
-
-/**
- * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms.  If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans(priv));
-       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-       int nfreed = 0;
-
-       if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
-               IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
-                         "index %d is out of range [0-%d] %d %d.\n", __func__,
-                         txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);
-               return;
-       }
-
-       for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
-            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-               if (nfreed++ > 0) {
-                       IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
-                                       q->write_ptr, q->read_ptr);
-                       iwlagn_fw_error(priv, false);
-               }
-
-       }
-}
-
-/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
- * @rxb: Rx buffer to reclaim
- *
- * If an Rx buffer has an async callback associated with it the callback
- * will be executed.  The attached skb (if present) will only be freed
- * if the callback returns 1
- */
-void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-       int txq_id = SEQ_TO_QUEUE(sequence);
-       int index = SEQ_TO_INDEX(sequence);
-       int cmd_index;
-       struct iwl_device_cmd *cmd;
-       struct iwl_cmd_meta *meta;
-       struct iwl_trans *trans = trans(priv);
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
-       unsigned long flags;
-
-       /* If a Tx command is being handled and it isn't in the actual
-        * command queue then there a command routing bug has been introduced
-        * in the queue management code. */
-       if (WARN(txq_id != trans->shrd->cmd_queue,
-                "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
-                 txq_id, trans->shrd->cmd_queue, sequence,
-                 trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
-                 trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
-               iwl_print_hex_error(priv, pkt, 32);
-               return;
-       }
-
-       cmd_index = get_cmd_index(&txq->q, index);
-       cmd = txq->cmd[cmd_index];
-       meta = &txq->meta[cmd_index];
-
-       iwlagn_unmap_tfd(trans, meta, &txq->tfds[index],
-                        DMA_BIDIRECTIONAL);
-
-       /* Input error checking is done when commands are added to queue. */
-       if (meta->flags & CMD_WANT_SKB) {
-               meta->source->reply_page = (unsigned long)rxb_addr(rxb);
-               rxb->page = NULL;
-       } else if (meta->callback)
-               meta->callback(priv, cmd, pkt);
-
-       spin_lock_irqsave(&trans->hcmd_lock, flags);
-
-       iwl_hcmd_queue_reclaim(priv, txq_id, index);
-
-       if (!(meta->flags & CMD_ASYNC)) {
-               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-               IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
-                              get_cmd_string(cmd->hdr.cmd));
-               wake_up_interruptible(&priv->wait_command_queue);
-       }
-
-       meta->flags = 0;
-
-       spin_unlock_irqrestore(&trans->hcmd_lock, flags);
-}
-
-const char *get_cmd_string(u8 cmd)
-{
-       switch (cmd) {
-               IWL_CMD(REPLY_ALIVE);
-               IWL_CMD(REPLY_ERROR);
-               IWL_CMD(REPLY_RXON);
-               IWL_CMD(REPLY_RXON_ASSOC);
-               IWL_CMD(REPLY_QOS_PARAM);
-               IWL_CMD(REPLY_RXON_TIMING);
-               IWL_CMD(REPLY_ADD_STA);
-               IWL_CMD(REPLY_REMOVE_STA);
-               IWL_CMD(REPLY_REMOVE_ALL_STA);
-               IWL_CMD(REPLY_TXFIFO_FLUSH);
-               IWL_CMD(REPLY_WEPKEY);
-               IWL_CMD(REPLY_TX);
-               IWL_CMD(REPLY_LEDS_CMD);
-               IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-               IWL_CMD(COEX_PRIORITY_TABLE_CMD);
-               IWL_CMD(COEX_MEDIUM_NOTIFICATION);
-               IWL_CMD(COEX_EVENT_CMD);
-               IWL_CMD(REPLY_QUIET_CMD);
-               IWL_CMD(REPLY_CHANNEL_SWITCH);
-               IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-               IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-               IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-               IWL_CMD(POWER_TABLE_CMD);
-               IWL_CMD(PM_SLEEP_NOTIFICATION);
-               IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-               IWL_CMD(REPLY_SCAN_CMD);
-               IWL_CMD(REPLY_SCAN_ABORT_CMD);
-               IWL_CMD(SCAN_START_NOTIFICATION);
-               IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-               IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-               IWL_CMD(BEACON_NOTIFICATION);
-               IWL_CMD(REPLY_TX_BEACON);
-               IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-               IWL_CMD(QUIET_NOTIFICATION);
-               IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-               IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-               IWL_CMD(REPLY_BT_CONFIG);
-               IWL_CMD(REPLY_STATISTICS_CMD);
-               IWL_CMD(STATISTICS_NOTIFICATION);
-               IWL_CMD(REPLY_CARD_STATE_CMD);
-               IWL_CMD(CARD_STATE_NOTIFICATION);
-               IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-               IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
-               IWL_CMD(SENSITIVITY_CMD);
-               IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
-               IWL_CMD(REPLY_RX_PHY_CMD);
-               IWL_CMD(REPLY_RX_MPDU_CMD);
-               IWL_CMD(REPLY_RX);
-               IWL_CMD(REPLY_COMPRESSED_BA);
-               IWL_CMD(CALIBRATION_CFG_CMD);
-               IWL_CMD(CALIBRATION_RES_NOTIFICATION);
-               IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
-               IWL_CMD(REPLY_TX_POWER_DBM_CMD);
-               IWL_CMD(TEMPERATURE_NOTIFICATION);
-               IWL_CMD(TX_ANT_CONFIGURATION_CMD);
-               IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
-               IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
-               IWL_CMD(REPLY_BT_COEX_PROT_ENV);
-               IWL_CMD(REPLY_WIPAN_PARAMS);
-               IWL_CMD(REPLY_WIPAN_RXON);
-               IWL_CMD(REPLY_WIPAN_RXON_TIMING);
-               IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
-               IWL_CMD(REPLY_WIPAN_QOS_PARAM);
-               IWL_CMD(REPLY_WIPAN_WEPKEY);
-               IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
-               IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
-               IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
-               IWL_CMD(REPLY_WOWLAN_PATTERNS);
-               IWL_CMD(REPLY_WOWLAN_WAKEUP_FILTER);
-               IWL_CMD(REPLY_WOWLAN_TSC_RSC_PARAMS);
-               IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS);
-               IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL);
-               IWL_CMD(REPLY_WOWLAN_GET_STATUS);
-       default:
-               return "UNKNOWN";
-
-       }
-}
-
-#define HOST_COMPLETE_TIMEOUT (2 * HZ)
-
-static void iwl_generic_cmd_callback(struct iwl_priv *priv,
-                                    struct iwl_device_cmd *cmd,
-                                    struct iwl_rx_packet *pkt)
-{
-       if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-               IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
-                       get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-               return;
-       }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       switch (cmd->hdr.cmd) {
-       case REPLY_TX_LINK_QUALITY_CMD:
-       case SENSITIVITY_CMD:
-               IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
-                               get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-               break;
-       default:
-               IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
-                               get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-       }
-#endif
-}
-
-static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
-{
-       int ret;
-
-       /* An asynchronous command can not expect an SKB to be set. */
-       if (WARN_ON(cmd->flags & CMD_WANT_SKB))
-               return -EINVAL;
-
-       /* Assign a generic callback if one is not provided */
-       if (!cmd->callback)
-               cmd->callback = iwl_generic_cmd_callback;
-
-       if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
-               return -EBUSY;
-
-       ret = iwl_enqueue_hcmd(trans, cmd);
-       if (ret < 0) {
-               IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
-                         get_cmd_string(cmd->id), ret);
-               return ret;
-       }
-       return 0;
-}
-
-static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int cmd_idx;
-       int ret;
-
-       lockdep_assert_held(&trans->shrd->mutex);
-
-        /* A synchronous command can not have a callback set. */
-       if (WARN_ON(cmd->callback))
-               return -EINVAL;
-
-       IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
-                       get_cmd_string(cmd->id));
-
-       set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-       IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
-                       get_cmd_string(cmd->id));
-
-       cmd_idx = iwl_enqueue_hcmd(trans, cmd);
-       if (cmd_idx < 0) {
-               ret = cmd_idx;
-               clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-               IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n",
-                         get_cmd_string(cmd->id), ret);
-               return ret;
-       }
-
-       ret = wait_event_interruptible_timeout(priv(trans)->wait_command_queue,
-                       !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
-                       HOST_COMPLETE_TIMEOUT);
-       if (!ret) {
-               if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
-                       IWL_ERR(trans,
-                               "Error sending %s: time out after %dms.\n",
-                               get_cmd_string(cmd->id),
-                               jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
-
-                       clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-                       IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command"
-                                "%s\n", get_cmd_string(cmd->id));
-                       ret = -ETIMEDOUT;
-                       goto cancel;
-               }
-       }
-
-       if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
-               IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
-                              get_cmd_string(cmd->id));
-               ret = -ECANCELED;
-               goto fail;
-       }
-       if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
-               IWL_ERR(trans, "Command %s failed: FW Error\n",
-                              get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto fail;
-       }
-       if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
-               IWL_ERR(trans, "Error: Response NULL in '%s'\n",
-                         get_cmd_string(cmd->id));
-               ret = -EIO;
-               goto cancel;
-       }
-
-       return 0;
-
-cancel:
-       if (cmd->flags & CMD_WANT_SKB) {
-               /*
-                * Cancel the CMD_WANT_SKB flag for the cmd in the
-                * TX cmd queue. Otherwise in case the cmd comes
-                * in later, it will possibly set an invalid
-                * address (cmd->meta.source).
-                */
-               trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
-                                                       ~CMD_WANT_SKB;
-       }
-fail:
-       if (cmd->reply_page) {
-               iwl_free_pages(trans->shrd, cmd->reply_page);
-               cmd->reply_page = 0;
-       }
-
-       return ret;
-}
-
-int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
-{
-       if (cmd->flags & CMD_ASYNC)
-               return iwl_send_cmd_async(trans, cmd);
-
-       return iwl_send_cmd_sync(trans, cmd);
-}
-
-int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
-               u16 len, const void *data)
-{
-       struct iwl_host_cmd cmd = {
-               .id = id,
-               .len = { len, },
-               .data = { data, },
-               .flags = flags,
-       };
-
-       return iwl_trans_pcie_send_cmd(trans, &cmd);
-}
-
-/* Frees buffers until index _not_ inclusive */
-int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
-                        struct sk_buff_head *skbs)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-       int last_to_free;
-       int freed = 0;
-
-       /*Since we free until index _not_ inclusive, the one before index is
-        * the last we will free. This one must be used */
-       last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
-
-       if ((index >= q->n_bd) ||
-          (iwl_queue_used(q, last_to_free) == 0)) {
-               IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
-                         "last_to_free %d is out of range [0-%d] %d %d.\n",
-                         __func__, txq_id, last_to_free, q->n_bd,
-                         q->write_ptr, q->read_ptr);
-               return 0;
-       }
-
-       IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
-                          q->read_ptr, index);
-
-       if (WARN_ON(!skb_queue_empty(skbs)))
-               return 0;
-
-       for (;
-            q->read_ptr != index;
-            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-               if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL))
-                       continue;
-
-               __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]);
-
-               txq->skbs[txq->q.read_ptr] = NULL;
-
-               iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
-
-               iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr);
-               freed++;
-       }
-       return freed;
-}
index cec13adb018e548a3e55ee2f719ab0ba85e2d85e..1b20c4fb791b07bac2473978d79f24c37a4b5703 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *****************************************************************************/
-#include <linux/interrupt.h>
-#include <linux/debugfs.h>
-#include <linux/bitops.h>
-#include <linux/gfp.h>
 
-#include "iwl-dev.h"
 #include "iwl-trans.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-trans-int-pcie.h"
-/*TODO remove uneeded includes when the transport layer tx_free will be here */
-#include "iwl-agn.h"
-#include "iwl-shared.h"
 
-static int iwl_trans_rx_alloc(struct iwl_trans *trans)
+int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
+                          u32 flags, u16 len, const void *data)
 {
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       struct device *dev = bus(trans)->dev;
-
-       memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
-
-       spin_lock_init(&rxq->lock);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-
-       if (WARN_ON(rxq->bd || rxq->rb_stts))
-               return -EINVAL;
-
-       /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */
-       rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
-                                    &rxq->bd_dma, GFP_KERNEL);
-       if (!rxq->bd)
-               goto err_bd;
-       memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE);
-
-       /*Allocate the driver's pointer to receive buffer status */
-       rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts),
-                                         &rxq->rb_stts_dma, GFP_KERNEL);
-       if (!rxq->rb_stts)
-               goto err_rb_stts;
-       memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
-
-       return 0;
-
-err_rb_stts:
-       dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
-                       rxq->bd, rxq->bd_dma);
-       memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
-       rxq->bd = NULL;
-err_bd:
-       return -ENOMEM;
-}
-
-static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       int i;
-
-       /* Fill the rx_used queue with _all_ of the Rx buffers */
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-               /* In the reset function, these buffers may have been allocated
-                * to an SKB, so we need to unmap and free potential storage */
-               if (rxq->pool[i].page != NULL) {
-                       dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma,
-                               PAGE_SIZE << hw_params(trans).rx_page_order,
-                               DMA_FROM_DEVICE);
-                       __free_pages(rxq->pool[i].page,
-                                    hw_params(trans).rx_page_order);
-                       rxq->pool[i].page = NULL;
-               }
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-       }
-}
-
-static void iwl_trans_rx_hw_init(struct iwl_trans *trans,
-                                struct iwl_rx_queue *rxq)
-{
-       u32 rb_size;
-       const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-       u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
-
-       rb_timeout = RX_RB_TIMEOUT;
-
-       if (iwlagn_mod_params.amsdu_size_8K)
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
-       else
-               rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
-       /* Stop Rx DMA */
-       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
-       /* Reset driver's Rx queue write index */
-       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
-       /* Tell device where to find RBD circular buffer in DRAM */
-       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-                          (u32)(rxq->bd_dma >> 8));
-
-       /* Tell device where in DRAM to update its Rx status */
-       iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG,
-                          rxq->rb_stts_dma >> 4);
-
-       /* Enable Rx DMA
-        * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
-        *      the credit mechanism in 5000 HW RX FIFO
-        * Direct rx interrupts to hosts
-        * Rx buffer size 4 or 8k
-        * RB timeout 0x10
-        * 256 RBDs
-        */
-       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG,
-                          FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
-                          FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
-                          FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
-                          FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
-                          rb_size|
-                          (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
-                          (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
-
-       /* Set interrupt coalescing timer to default (2048 usecs) */
-       iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
-}
-
-static int iwl_rx_init(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-
-       int i, err;
-       unsigned long flags;
-
-       if (!rxq->bd) {
-               err = iwl_trans_rx_alloc(trans);
-               if (err)
-                       return err;
-       }
-
-       spin_lock_irqsave(&rxq->lock, flags);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-
-       iwl_trans_rxq_free_rx_bufs(trans);
-
-       for (i = 0; i < RX_QUEUE_SIZE; i++)
-               rxq->queue[i] = NULL;
-
-       /* Set us so that we have processed and used all buffers, but have
-        * not restocked the Rx queue with fresh buffers */
-       rxq->read = rxq->write = 0;
-       rxq->write_actual = 0;
-       rxq->free_count = 0;
-       spin_unlock_irqrestore(&rxq->lock, flags);
-
-       iwlagn_rx_replenish(trans);
-
-       iwl_trans_rx_hw_init(trans, rxq);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       rxq->need_update = 1;
-       iwl_rx_queue_update_write_ptr(trans, rxq);
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       return 0;
-}
-
-static void iwl_trans_pcie_rx_free(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-
-       unsigned long flags;
-
-       /*if rxq->bd is NULL, it means that nothing has been allocated,
-        * exit now */
-       if (!rxq->bd) {
-               IWL_DEBUG_INFO(trans, "Free NULL rx context\n");
-               return;
-       }
-
-       spin_lock_irqsave(&rxq->lock, flags);
-       iwl_trans_rxq_free_rx_bufs(trans);
-       spin_unlock_irqrestore(&rxq->lock, flags);
-
-       dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE,
-                         rxq->bd, rxq->bd_dma);
-       memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
-       rxq->bd = NULL;
-
-       if (rxq->rb_stts)
-               dma_free_coherent(bus(trans)->dev,
-                                 sizeof(struct iwl_rb_status),
-                                 rxq->rb_stts, rxq->rb_stts_dma);
-       else
-               IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
-       memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
-       rxq->rb_stts = NULL;
-}
-
-static int iwl_trans_rx_stop(struct iwl_trans *trans)
-{
-
-       /* stop Rx DMA */
-       iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-       return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG,
-                           FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-}
-
-static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans,
-                                   struct iwl_dma_ptr *ptr, size_t size)
-{
-       if (WARN_ON(ptr->addr))
-               return -EINVAL;
-
-       ptr->addr = dma_alloc_coherent(bus(trans)->dev, size,
-                                      &ptr->dma, GFP_KERNEL);
-       if (!ptr->addr)
-               return -ENOMEM;
-       ptr->size = size;
-       return 0;
-}
-
-static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans,
-                                   struct iwl_dma_ptr *ptr)
-{
-       if (unlikely(!ptr->addr))
-               return;
-
-       dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma);
-       memset(ptr, 0, sizeof(*ptr));
-}
-
-static int iwl_trans_txq_alloc(struct iwl_trans *trans,
-                               struct iwl_tx_queue *txq, int slots_num,
-                               u32 txq_id)
-{
-       size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
-       int i;
-
-       if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
-               return -EINVAL;
-
-       txq->q.n_window = slots_num;
-
-       txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
-                           GFP_KERNEL);
-       txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
-                          GFP_KERNEL);
-
-       if (!txq->meta || !txq->cmd)
-               goto error;
-
-       if (txq_id == trans->shrd->cmd_queue)
-               for (i = 0; i < slots_num; i++) {
-                       txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
-                                               GFP_KERNEL);
-                       if (!txq->cmd[i])
-                               goto error;
-               }
-
-       /* Alloc driver data array and TFD circular buffer */
-       /* Driver private data, only for Tx (not command) queues,
-        * not shared with device. */
-       if (txq_id != trans->shrd->cmd_queue) {
-               txq->skbs = kzalloc(sizeof(txq->skbs[0]) *
-                                  TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
-               if (!txq->skbs) {
-                       IWL_ERR(trans, "kmalloc for auxiliary BD "
-                                 "structures failed\n");
-                       goto error;
-               }
-       } else {
-               txq->skbs = NULL;
-       }
-
-       /* Circular buffer of transmit frame descriptors (TFDs),
-        * shared with device */
-       txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz,
-                                      &txq->q.dma_addr, GFP_KERNEL);
-       if (!txq->tfds) {
-               IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
-               goto error;
-       }
-       txq->q.id = txq_id;
-
-       return 0;
-error:
-       kfree(txq->skbs);
-       txq->skbs = NULL;
-       /* since txq->cmd has been zeroed,
-        * all non allocated cmd[i] will be NULL */
-       if (txq->cmd && txq_id == trans->shrd->cmd_queue)
-               for (i = 0; i < slots_num; i++)
-                       kfree(txq->cmd[i]);
-       kfree(txq->meta);
-       kfree(txq->cmd);
-       txq->meta = NULL;
-       txq->cmd = NULL;
-
-       return -ENOMEM;
-
-}
-
-static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
-                     int slots_num, u32 txq_id)
-{
-       int ret;
-
-       txq->need_update = 0;
-       memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num);
-
-       /*
-        * For the default queues 0-3, set up the swq_id
-        * already -- all others need to get one later
-        * (if they need one at all).
-        */
-       if (txq_id < 4)
-               iwl_set_swq_id(txq, txq_id, txq_id);
-
-       /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-        * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
-       BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
-       /* Initialize queue's high/low-water marks, and head/tail indexes */
-       ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
-                       txq_id);
-       if (ret)
-               return ret;
-
-       /*
-        * Tell nic where to find circular buffer of Tx Frame Descriptors for
-        * given Tx queue, and enable the DMA channel used for that queue.
-        * Circular buffer (TFD queue in DRAM) physical base address */
-       iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id),
-                            txq->q.dma_addr >> 8);
-
-       return 0;
-}
-
-/**
- * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
- */
-static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-
-       if (!q->n_bd)
-               return;
-
-       while (q->write_ptr != q->read_ptr) {
-               /* The read_ptr needs to bound by q->n_window */
-               iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr));
-               q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
-       }
-}
-
-/**
- * iwl_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       struct device *dev = bus(trans)->dev;
-       int i;
-       if (WARN_ON(!txq))
-               return;
-
-       iwl_tx_queue_unmap(trans, txq_id);
-
-       /* De-alloc array of command/tx buffers */
-
-       if (txq_id == trans->shrd->cmd_queue)
-               for (i = 0; i < txq->q.n_window; i++)
-                       kfree(txq->cmd[i]);
-
-       /* De-alloc circular buffer of TFDs */
-       if (txq->q.n_bd) {
-               dma_free_coherent(dev, sizeof(struct iwl_tfd) *
-                                 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
-               memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
-       }
-
-       /* De-alloc array of per-TFD driver data */
-       kfree(txq->skbs);
-       txq->skbs = NULL;
-
-       /* deallocate arrays */
-       kfree(txq->cmd);
-       kfree(txq->meta);
-       txq->cmd = NULL;
-       txq->meta = NULL;
-
-       /* 0-fill queue descriptor structure */
-       memset(txq, 0, sizeof(*txq));
-}
-
-/**
- * iwl_trans_tx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
-{
-       int txq_id;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       /* Tx queues */
-       if (trans_pcie->txq) {
-               for (txq_id = 0;
-                    txq_id < hw_params(trans).max_txq_num; txq_id++)
-                       iwl_tx_queue_free(trans, txq_id);
-       }
-
-       kfree(trans_pcie->txq);
-       trans_pcie->txq = NULL;
-
-       iwlagn_free_dma_ptr(trans, &trans_pcie->kw);
-
-       iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls);
-}
-
-/**
- * iwl_trans_tx_alloc - allocate TX context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-static int iwl_trans_tx_alloc(struct iwl_trans *trans)
-{
-       int ret;
-       int txq_id, slots_num;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       u16 scd_bc_tbls_size = hw_params(trans).max_txq_num *
-                       sizeof(struct iwlagn_scd_bc_tbl);
-
-       /*It is not allowed to alloc twice, so warn when this happens.
-        * We cannot rely on the previous allocation, so free and fail */
-       if (WARN_ON(trans_pcie->txq)) {
-               ret = -EINVAL;
-               goto error;
-       }
-
-       ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls,
-                                  scd_bc_tbls_size);
-       if (ret) {
-               IWL_ERR(trans, "Scheduler BC Table allocation failed\n");
-               goto error;
-       }
-
-       /* Alloc keep-warm buffer */
-       ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE);
-       if (ret) {
-               IWL_ERR(trans, "Keep Warm allocation failed\n");
-               goto error;
-       }
-
-       trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) *
-                       hw_params(trans).max_txq_num, GFP_KERNEL);
-       if (!trans_pcie->txq) {
-               IWL_ERR(trans, "Not enough memory for txq\n");
-               ret = ENOMEM;
-               goto error;
-       }
-
-       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
-       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
-               slots_num = (txq_id == trans->shrd->cmd_queue) ?
-                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
-                                         slots_num, txq_id);
-               if (ret) {
-                       IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
-                       goto error;
-               }
-       }
-
-       return 0;
-
-error:
-       iwl_trans_pcie_tx_free(trans);
-
-       return ret;
-}
-static int iwl_tx_init(struct iwl_trans *trans)
-{
-       int ret;
-       int txq_id, slots_num;
-       unsigned long flags;
-       bool alloc = false;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       if (!trans_pcie->txq) {
-               ret = iwl_trans_tx_alloc(trans);
-               if (ret)
-                       goto error;
-               alloc = true;
-       }
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       /* Turn off all Tx DMA fifos */
-       iwl_write_prph(bus(trans), SCD_TXFACT, 0);
-
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG,
-                          trans_pcie->kw.dma >> 4);
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
-       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
-               slots_num = (txq_id == trans->shrd->cmd_queue) ?
-                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
-                                        slots_num, txq_id);
-               if (ret) {
-                       IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
-                       goto error;
-               }
-       }
-
-       return 0;
-error:
-       /*Upon error, free only if we allocated something */
-       if (alloc)
-               iwl_trans_pcie_tx_free(trans);
-       return ret;
-}
-
-static void iwl_set_pwr_vmain(struct iwl_priv *priv)
-{
-       struct iwl_trans *trans = trans(priv);
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do:
-
-               if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
-                       iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
-                                              APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-                                              ~APMG_PS_CTRL_MSK_PWR_SRC);
- */
-
-       iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG,
-                              APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-                              ~APMG_PS_CTRL_MSK_PWR_SRC);
-}
-
-static int iwl_nic_init(struct iwl_trans *trans)
-{
-       unsigned long flags;
-       struct iwl_priv *priv = priv(trans);
-
-       /* nic_init */
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       iwl_apm_init(priv);
-
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(bus(trans), CSR_INT_COALESCING,
-               IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       iwl_set_pwr_vmain(priv);
-
-       priv->cfg->lib->nic_config(priv);
-
-       /* Allocate the RX queue, or reset if it is already allocated */
-       iwl_rx_init(trans);
-
-       /* Allocate or reset and init all Tx and Command queues */
-       if (iwl_tx_init(trans))
-               return -ENOMEM;
-
-       if (hw_params(trans).shadow_reg_enable) {
-               /* enable shadow regs in HW */
-               iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL,
-                       0x800FFFFF);
-       }
-
-       set_bit(STATUS_INIT, &trans->shrd->status);
-
-       return 0;
-}
-
-#define HW_READY_TIMEOUT (50)
-
-/* Note: returns poll_bit return value, which is >= 0 if success */
-static int iwl_set_hw_ready(struct iwl_trans *trans)
-{
-       int ret;
-
-       iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
-               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
-
-       /* See if we got it */
-       ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
-                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-                               CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
-                               HW_READY_TIMEOUT);
-
-       IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
-       return ret;
-}
-
-/* Note: returns standard 0/-ERROR code */
-static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans)
-{
-       int ret;
-
-       IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
-
-       ret = iwl_set_hw_ready(trans);
-       if (ret >= 0)
-               return 0;
-
-       /* If HW is not ready, prepare the conditions to check again */
-       iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
-                       CSR_HW_IF_CONFIG_REG_PREPARE);
-
-       ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG,
-                       ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
-                       CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
-
-       if (ret < 0)
-               return ret;
-
-       /* HW should be ready by now, check again. */
-       ret = iwl_set_hw_ready(trans);
-       if (ret >= 0)
-               return 0;
-       return ret;
-}
-
-#define IWL_AC_UNSET -1
-
-struct queue_to_fifo_ac {
-       s8 fifo, ac;
-};
-
-static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
-       { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
-       { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
-       { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
-       { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
-       { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
-};
-
-static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
-       { IWL_TX_FIFO_VO, IEEE80211_AC_VO, },
-       { IWL_TX_FIFO_VI, IEEE80211_AC_VI, },
-       { IWL_TX_FIFO_BE, IEEE80211_AC_BE, },
-       { IWL_TX_FIFO_BK, IEEE80211_AC_BK, },
-       { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, },
-       { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, },
-       { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, },
-       { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
-       { IWL_TX_FIFO_BE_IPAN, 2, },
-       { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
-       { IWL_TX_FIFO_AUX, IWL_AC_UNSET, },
-};
-
-static const u8 iwlagn_bss_ac_to_fifo[] = {
-       IWL_TX_FIFO_VO,
-       IWL_TX_FIFO_VI,
-       IWL_TX_FIFO_BE,
-       IWL_TX_FIFO_BK,
-};
-static const u8 iwlagn_bss_ac_to_queue[] = {
-       0, 1, 2, 3,
-};
-static const u8 iwlagn_pan_ac_to_fifo[] = {
-       IWL_TX_FIFO_VO_IPAN,
-       IWL_TX_FIFO_VI_IPAN,
-       IWL_TX_FIFO_BE_IPAN,
-       IWL_TX_FIFO_BK_IPAN,
-};
-static const u8 iwlagn_pan_ac_to_queue[] = {
-       7, 6, 5, 4,
-};
-
-static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
-{
-       int ret;
-       struct iwl_priv *priv = priv(trans);
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
-       trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
-       trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
-
-       trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo;
-       trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo;
-
-       trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
-       trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
-
-       if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
-            iwl_trans_pcie_prepare_card_hw(trans)) {
-               IWL_WARN(trans, "Exit HW not ready\n");
-               return -EIO;
-       }
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       if (iwl_read32(bus(trans), CSR_GP_CNTRL) &
-                       CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-
-       if (iwl_is_rfkill(trans->shrd)) {
-               wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
-               iwl_enable_interrupts(trans);
-               return -ERFKILL;
-       }
-
-       iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
-
-       ret = iwl_nic_init(trans);
-       if (ret) {
-               IWL_ERR(trans, "Unable to init nic\n");
-               return ret;
-       }
-
-       /* make sure rfkill handshake bits are cleared */
-       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR,
-                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-       /* clear (again), then enable host interrupts */
-       iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF);
-       iwl_enable_interrupts(trans);
-
-       /* really make sure rfkill handshake bits are cleared */
-       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-       return 0;
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->shrd->lock and mac access
- */
-static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
-{
-       iwl_write_prph(bus(trans), SCD_TXFACT, mask);
-}
-
-static void iwl_trans_pcie_tx_start(struct iwl_trans *trans)
-{
-       const struct queue_to_fifo_ac *queue_to_fifo;
-       struct iwl_rxon_context *ctx;
-       struct iwl_priv *priv = priv(trans);
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       u32 a;
-       unsigned long flags;
-       int i, chan;
-       u32 reg_val;
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       trans_pcie->scd_base_addr =
-               iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR);
-       a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
-       /* reset conext data memory */
-       for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
-               a += 4)
-               iwl_write_targ_mem(bus(trans), a, 0);
-       /* reset tx status memory */
-       for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
-               a += 4)
-               iwl_write_targ_mem(bus(trans), a, 0);
-       for (; a < trans_pcie->scd_base_addr +
-              SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
-              a += 4)
-               iwl_write_targ_mem(bus(trans), a, 0);
-
-       iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR,
-                      trans_pcie->scd_bc_tbls.dma >> 10);
-
-       /* Enable DMA channel */
-       for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)
-               iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-                               FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-       /* Update FH chicken bits */
-       reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG);
-       iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG,
-                          reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-       iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL,
-               SCD_QUEUECHAIN_SEL_ALL(trans));
-       iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0);
-
-       /* initiate the queues */
-       for (i = 0; i < hw_params(trans).max_txq_num; i++) {
-               iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0);
-               iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8));
-               iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
-                               SCD_CONTEXT_QUEUE_OFFSET(i), 0);
-               iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
-                               SCD_CONTEXT_QUEUE_OFFSET(i) +
-                               sizeof(u32),
-                               ((SCD_WIN_SIZE <<
-                               SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
-                               SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
-                               ((SCD_FRAME_LIMIT <<
-                               SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-                               SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
-       }
-
-       iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK,
-                       IWL_MASK(0, hw_params(trans).max_txq_num));
-
-       /* Activate all Tx DMA/FIFO channels */
-       iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
-
-       /* map queues to FIFOs */
-       if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
-               queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo;
-       else
-               queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
-
-       iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
-
-       /* make sure all queue are not stopped */
-       memset(&trans_pcie->queue_stopped[0], 0,
-               sizeof(trans_pcie->queue_stopped));
-       for (i = 0; i < 4; i++)
-               atomic_set(&trans_pcie->queue_stop_count[i], 0);
-       for_each_context(priv, ctx)
-               ctx->last_tx_rejected = false;
-
-       /* reset to 0 to enable all the queue first */
-       trans_pcie->txq_ctx_active_msk = 0;
-
-       BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) <
-                                               IWLAGN_FIRST_AMPDU_QUEUE);
-       BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) <
-                                               IWLAGN_FIRST_AMPDU_QUEUE);
-
-       for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) {
-               int fifo = queue_to_fifo[i].fifo;
-               int ac = queue_to_fifo[i].ac;
-
-               iwl_txq_ctx_activate(trans_pcie, i);
-
-               if (fifo == IWL_TX_FIFO_UNUSED)
-                       continue;
-
-               if (ac != IWL_AC_UNSET)
-                       iwl_set_swq_id(&trans_pcie->txq[i], ac, i);
-               iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i],
-                                             fifo, 0);
-       }
-
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       /* Enable L1-Active */
-       iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG,
-                         APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-static int iwl_trans_tx_stop(struct iwl_trans *trans)
-{
-       int ch, txq_id;
-       unsigned long flags;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-
-       iwl_trans_txq_set_sched(trans, 0);
-
-       /* Stop each Tx DMA channel, and wait for it to be idle */
-       for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
-               iwl_write_direct32(bus(trans),
-                                  FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-               if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG,
-                                   FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-                                   1000))
-                       IWL_ERR(trans, "Failing on timeout while stopping"
-                           " DMA channel %d [0x%08x]", ch,
-                           iwl_read_direct32(bus(trans),
-                                             FH_TSSR_TX_STATUS_REG));
-       }
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       if (!trans_pcie->txq) {
-               IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
-               return 0;
-       }
-
-       /* Unmap DMA from host system and free skb's */
-       for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
-               iwl_tx_queue_unmap(trans, txq_id);
-
-       return 0;
-}
-
-static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans)
-{
-       unsigned long flags;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       spin_lock_irqsave(&trans->shrd->lock, flags);
-       iwl_disable_interrupts(trans);
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(bus(trans)->irq);
-       tasklet_kill(&trans_pcie->irq_tasklet);
-}
-
-static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
-{
-       /* stop and reset the on-board processor */
-       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       /* tell the device to stop sending interrupts */
-       iwl_trans_pcie_disable_sync_irq(trans);
-
-       /* device going down, Stop using ICT table */
-       iwl_disable_ict(trans);
-
-       /*
-        * If a HW restart happens during firmware loading,
-        * then the firmware loading might call this function
-        * and later it might be called again due to the
-        * restart. So don't process again if the device is
-        * already dead.
-        */
-       if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
-               iwl_trans_tx_stop(trans);
-               iwl_trans_rx_stop(trans);
-
-               /* Power-down device's busmaster DMA clocks */
-               iwl_write_prph(bus(trans), APMG_CLK_DIS_REG,
-                              APMG_CLK_VAL_DMA_CLK_RQT);
-               udelay(5);
-       }
-
-       /* Make sure (redundant) we've released our request to stay awake */
-       iwl_clear_bit(bus(trans), CSR_GP_CNTRL,
-                       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       /* Stop the device, and put it in low power state */
-       iwl_apm_stop(priv(trans));
-}
-
-static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
-               struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx;
-       struct iwl_cmd_meta *out_meta;
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-
-       dma_addr_t phys_addr = 0;
-       dma_addr_t txcmd_phys;
-       dma_addr_t scratch_phys;
-       u16 len, firstlen, secondlen;
-       u16 seq_number = 0;
-       u8 wait_write_ptr = 0;
-       u8 txq_id;
-       u8 tid = 0;
-       bool is_agg = false;
-       __le16 fc = hdr->frame_control;
-       u8 hdr_len = ieee80211_hdrlen(fc);
-
-       /*
-        * Send this frame after DTIM -- there's a special queue
-        * reserved for this for contexts that support AP mode.
-        */
-       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
-               txq_id = trans_pcie->mcast_queue[ctx];
-
-               /*
-                * The microcode will clear the more data
-                * bit in the last frame it transmits.
-                */
-               hdr->frame_control |=
-                       cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-       } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
-               txq_id = IWL_AUX_QUEUE;
-       else
-               txq_id =
-                   trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
-
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = NULL;
-               struct iwl_tid_data *tid_data;
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               tid_data = &trans->shrd->tid_data[sta_id][tid];
-
-               if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
-                       return -1;
-
-               seq_number = tid_data->seq_number;
-               seq_number &= IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(seq_number);
-               seq_number += 0x10;
-               /* aggregation is on for this <sta,tid> */
-               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
-                   tid_data->agg.state == IWL_AGG_ON) {
-                       txq_id = tid_data->agg.txq_id;
-                       is_agg = true;
-               }
-       }
-
-       txq = &trans_pcie->txq[txq_id];
-       q = &txq->q;
-
-       /* Set up driver data for this TFD */
-       txq->skbs[q->write_ptr] = skb;
-       txq->cmd[q->write_ptr] = dev_cmd;
-
-       dev_cmd->hdr.cmd = REPLY_TX;
-       dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-                               INDEX_TO_SEQ(q->write_ptr)));
-
-       /* Set up first empty entry in queue's array of Tx/cmd buffers */
-       out_meta = &txq->meta[q->write_ptr];
-
-       /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
-        */
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       firstlen = (len + 3) & ~3;
-
-       /* Tell NIC about any 2-byte padding after MAC header */
-       if (firstlen != len)
-               tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
-
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = dma_map_single(bus(trans)->dev,
-                                   &dev_cmd->hdr, firstlen,
-                                   DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys)))
-               return -1;
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, firstlen);
-
-       if (!ieee80211_has_morefrags(fc)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
-
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames have no payload). */
-       secondlen = skb->len - hdr_len;
-       if (secondlen > 0) {
-               phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len,
-                                          secondlen, DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) {
-                       dma_unmap_single(bus(trans)->dev,
-                                        dma_unmap_addr(out_meta, mapping),
-                                        dma_unmap_len(out_meta, len),
-                                        DMA_BIDIRECTIONAL);
-                       return -1;
-               }
-       }
-
-       /* Attach buffers to TFD */
-       iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1);
-       if (secondlen > 0)
-               iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr,
-                                            secondlen, 0);
-
-       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-                               offsetof(struct iwl_tx_cmd, scratch);
-
-       /* take back ownership of DMA buffer to enable update */
-       dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen,
-                       DMA_BIDIRECTIONAL);
-       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
-       IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
-                    le16_to_cpu(dev_cmd->hdr.sequence));
-       IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-       iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
-       iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
-
-       /* Set up entry for this TFD in Tx byte-count array */
-       if (is_agg)
-               iwl_trans_txq_update_byte_cnt_tbl(trans, txq,
-                                              le16_to_cpu(tx_cmd->len));
-
-       dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen,
-                       DMA_BIDIRECTIONAL);
-
-       trace_iwlwifi_dev_tx(priv(trans),
-                            &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
-                            sizeof(struct iwl_tfd),
-                            &dev_cmd->hdr, firstlen,
-                            skb->data + hdr_len, secondlen);
-
-       /* Tell device the write index *just past* this latest filled TFD */
-       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-       iwl_txq_update_write_ptr(trans, txq);
-
-       if (ieee80211_is_data_qos(fc)) {
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue++;
-               if (!ieee80211_has_morefrags(fc))
-                       trans->shrd->tid_data[sta_id][tid].seq_number =
-                               seq_number;
-       }
-
-       /*
-        * At this point the frame is "transmitted" successfully
-        * and we will get a TX status notification eventually,
-        * regardless of the value of ret. "ret" only indicates
-        * whether or not we should update the write pointer.
-        */
-       if (iwl_queue_space(q) < q->high_mark) {
-               if (wait_write_ptr) {
-                       txq->need_update = 1;
-                       iwl_txq_update_write_ptr(trans, txq);
-               } else {
-                       iwl_stop_queue(trans, txq);
-               }
-       }
-       return 0;
-}
-
-static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans)
-{
-       /* Remove all resets to allow NIC to operate */
-       iwl_write32(bus(trans), CSR_RESET, 0);
-}
-
-static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       int err;
-
-       trans_pcie->inta_mask = CSR_INI_SET_MASK;
-
-       tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
-               iwl_irq_tasklet, (unsigned long)trans);
-
-       iwl_alloc_isr_ict(trans);
-
-       err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED,
-               DRV_NAME, trans);
-       if (err) {
-               IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq);
-               iwl_free_isr_ict(trans);
-               return err;
-       }
-
-       INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish);
-       return 0;
-}
-
-static int iwlagn_txq_check_empty(struct iwl_trans *trans,
-                          int sta_id, u8 tid, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_queue *q = &trans_pcie->txq[txq_id].q;
-       struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
-
-       lockdep_assert_held(&trans->shrd->sta_lock);
-
-       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_DELBA:
-               /* We are reclaiming the last packet of the */
-               /* aggregated HW queue */
-               if ((txq_id  == tid_data->agg.txq_id) &&
-                   (q->read_ptr == q->write_ptr)) {
-                       IWL_DEBUG_HT(trans,
-                               "HW queue empty: continue DELBA flow\n");
-                       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
-                       tid_data->agg.state = IWL_AGG_OFF;
-                       iwl_stop_tx_ba_trans_ready(priv(trans),
-                                                  NUM_IWL_RXON_CTX,
-                                                  sta_id, tid);
-                       iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
-               }
-               break;
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /* We are reclaiming the last packet of the queue */
-               if (tid_data->tfds_in_queue == 0) {
-                       IWL_DEBUG_HT(trans,
-                               "HW queue empty: continue ADDBA flow\n");
-                       tid_data->agg.state = IWL_AGG_ON;
-                       iwl_start_tx_ba_trans_ready(priv(trans),
-                                                   NUM_IWL_RXON_CTX,
-                                                   sta_id, tid);
-               }
-               break;
-       }
-
-       return 0;
-}
-
-static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
-                           int sta_id, int tid, int freed)
-{
-       lockdep_assert_held(&trans->shrd->sta_lock);
-
-       if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
-       else {
-               IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
-                       trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
-                       freed);
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
-       }
-}
-
-static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
-                     int txq_id, int ssn, u32 status,
-                     struct sk_buff_head *skbs)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       /* n_bd is usually 256 => n_bd - 1 = 0xff */
-       int tfd_num = ssn & (txq->q.n_bd - 1);
-       int freed = 0;
-       u8 agg_state;
-       bool cond;
-
-       txq->time_stamp = jiffies;
-
-       if (txq->sched_retry) {
-               agg_state =
-                       trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
-               cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
-       } else {
-               cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
-       }
-
-       if (txq->q.read_ptr != tfd_num) {
-               IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
-                               "scd_ssn=%d idx=%d txq=%d swq=%d\n",
-                               ssn , tfd_num, txq_id, txq->swq_id);
-               freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
-               if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
-                       iwl_wake_queue(trans, txq);
-       }
-
-       iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
-       iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
-}
-
-static void iwl_trans_pcie_free(struct iwl_trans *trans)
-{
-       iwl_trans_pcie_tx_free(trans);
-       iwl_trans_pcie_rx_free(trans);
-       free_irq(bus(trans)->irq, trans);
-       iwl_free_isr_ict(trans);
-       trans->shrd->trans = NULL;
-       kfree(trans);
-}
-
-#ifdef CONFIG_PM
-
-static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
-{
-       /*
-        * This function is called when system goes into suspend state
-        * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
-        * first but since iwl_mac_stop() has no knowledge of who the caller is,
-        * it will not call apm_ops.stop() to stop the DMA operation.
-        * Calling apm_ops.stop here to make sure we stop the DMA.
-        *
-        * But of course ... if we have configured WoWLAN then we did other
-        * things already :-)
-        */
-       if (!trans->shrd->wowlan)
-               iwl_apm_stop(priv(trans));
-
-       return 0;
-}
-
-static int iwl_trans_pcie_resume(struct iwl_trans *trans)
-{
-       bool hw_rfkill = false;
-
-       iwl_enable_interrupts(trans);
-
-       if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) &
-                               CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
-               hw_rfkill = true;
-
-       if (hw_rfkill)
-               set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-       else
-               clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
-
-       wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, hw_rfkill);
-
-       return 0;
-}
-#else /* CONFIG_PM */
-static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
-{ return 0; }
-
-static int iwl_trans_pcie_resume(struct iwl_trans *trans)
-{ return 0; }
-
-#endif /* CONFIG_PM */
-
-static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
-                                         u8 ctx)
-{
-       u8 ac, txq_id;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       for (ac = 0; ac < AC_NUM; ac++) {
-               txq_id = trans_pcie->ac_to_queue[ctx][ac];
-               IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n",
-                       ac,
-                       (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
-                             ? "stopped" : "awake");
-               iwl_wake_queue(trans, &trans_pcie->txq[txq_id]);
-       }
-}
-
-const struct iwl_trans_ops trans_ops_pcie;
-
-static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd)
-{
-       struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) +
-                                             sizeof(struct iwl_trans_pcie),
-                                             GFP_KERNEL);
-       if (iwl_trans) {
-               struct iwl_trans_pcie *trans_pcie =
-                       IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
-               iwl_trans->ops = &trans_ops_pcie;
-               iwl_trans->shrd = shrd;
-               trans_pcie->trans = iwl_trans;
-               spin_lock_init(&iwl_trans->hcmd_lock);
-       }
-
-       return iwl_trans;
-}
-
-static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       iwl_stop_queue(trans, &trans_pcie->txq[txq_id]);
-}
-
-#define IWL_FLUSH_WAIT_MS      2000
-
-static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       int cnt;
-       unsigned long now = jiffies;
-       int ret = 0;
-
-       /* waiting for all the tx frames complete might take a while */
-       for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
-               if (cnt == trans->shrd->cmd_queue)
-                       continue;
-               txq = &trans_pcie->txq[cnt];
-               q = &txq->q;
-               while (q->read_ptr != q->write_ptr && !time_after(jiffies,
-                      now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
-                       msleep(1);
-
-               if (q->read_ptr != q->write_ptr) {
-                       IWL_ERR(trans, "fail to flush all tx fifo queues\n");
-                       ret = -ETIMEDOUT;
-                       break;
-               }
-       }
-       return ret;
-}
-
-/*
- * On every watchdog tick we check (latest) time stamp. If it does not
- * change during timeout period and queue is not empty we reset firmware.
- */
-static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq = &trans_pcie->txq[cnt];
-       struct iwl_queue *q = &txq->q;
-       unsigned long timeout;
-
-       if (q->read_ptr == q->write_ptr) {
-               txq->time_stamp = jiffies;
-               return 0;
-       }
-
-       timeout = txq->time_stamp +
-                 msecs_to_jiffies(hw_params(trans).wd_timeout);
-
-       if (time_after(jiffies, timeout)) {
-               IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id,
-                       hw_params(trans).wd_timeout);
-               return 1;
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/* create and remove of files */
-#define DEBUGFS_ADD_FILE(name, parent, mode) do {                      \
-       if (!debugfs_create_file(#name, mode, parent, trans,            \
-                                &iwl_dbgfs_##name##_ops))              \
-               return -ENOMEM;                                         \
-} while (0)
-
-/* file operation */
-#define DEBUGFS_READ_FUNC(name)                                         \
-static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
-                                       char __user *user_buf,          \
-                                       size_t count, loff_t *ppos);
-
-#define DEBUGFS_WRITE_FUNC(name)                                        \
-static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
-                                       const char __user *user_buf,    \
-                                       size_t count, loff_t *ppos);
-
-
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-#define DEBUGFS_READ_FILE_OPS(name)                                    \
-       DEBUGFS_READ_FUNC(name);                                        \
-static const struct file_operations iwl_dbgfs_##name##_ops = {         \
-       .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
-       .llseek = generic_file_llseek,                                  \
-};
-
-#define DEBUGFS_WRITE_FILE_OPS(name)                                    \
-       DEBUGFS_WRITE_FUNC(name);                                       \
-static const struct file_operations iwl_dbgfs_##name##_ops = {          \
-       .write = iwl_dbgfs_##name##_write,                              \
-       .open = iwl_dbgfs_open_file_generic,                            \
-       .llseek = generic_file_llseek,                                  \
-};
-
-#define DEBUGFS_READ_WRITE_FILE_OPS(name)                              \
-       DEBUGFS_READ_FUNC(name);                                        \
-       DEBUGFS_WRITE_FUNC(name);                                       \
-static const struct file_operations iwl_dbgfs_##name##_ops = {         \
-       .write = iwl_dbgfs_##name##_write,                              \
-       .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
-       .llseek = generic_file_llseek,                                  \
-};
-
-static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       struct iwl_priv *priv = priv(trans);
-       int pos = 0, ofs = 0;
-       int cnt = 0, entry;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       char *buf;
-       int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
-               (hw_params(trans).max_txq_num * 32 * 8) + 400;
-       const u8 *ptr;
-       ssize_t ret;
-
-       if (!trans_pcie->txq) {
-               IWL_ERR(trans, "txq not ready\n");
-               return -EAGAIN;
-       }
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(trans, "Can not allocate buffer\n");
-               return -ENOMEM;
-       }
-       pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
-       for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
-               txq = &trans_pcie->txq[cnt];
-               q = &txq->q;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "q[%d]: read_ptr: %u, write_ptr: %u\n",
-                               cnt, q->read_ptr, q->write_ptr);
-       }
-       if (priv->tx_traffic &&
-               (iwl_get_debug_level(trans->shrd) & IWL_DL_TX)) {
-               ptr = priv->tx_traffic;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
-               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
-                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
-                            entry++,  ofs += 16) {
-                               pos += scnprintf(buf + pos, bufsz - pos,
-                                               "0x%.4x ", ofs);
-                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
-                                                  buf + pos, bufsz - pos, 0);
-                               pos += strlen(buf + pos);
-                               if (bufsz - pos > 0)
-                                       buf[pos++] = '\n';
-                       }
-               }
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "read: %u, write: %u\n",
-                        rxq->read, rxq->write);
-
-       if (priv->rx_traffic &&
-               (iwl_get_debug_level(trans->shrd) & IWL_DL_RX)) {
-               ptr = priv->rx_traffic;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
-               for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
-                       for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
-                            entry++,  ofs += 16) {
-                               pos += scnprintf(buf + pos, bufsz - pos,
-                                               "0x%.4x ", ofs);
-                               hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
-                                                  buf + pos, bufsz - pos, 0);
-                               pos += strlen(buf + pos);
-                               if (bufsz - pos > 0)
-                                       buf[pos++] = '\n';
-                       }
-               }
-       }
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       char buf[8];
-       int buf_size;
-       int traffic_log;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &traffic_log) != 1)
-               return -EFAULT;
-       if (traffic_log == 0)
-               iwl_reset_traffic_log(priv(trans));
-
-       return count;
-}
-
-static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_priv *priv = priv(trans);
-       struct iwl_tx_queue *txq;
-       struct iwl_queue *q;
-       char *buf;
-       int pos = 0;
-       int cnt;
-       int ret;
-       const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
-
-       if (!trans_pcie->txq) {
-               IWL_ERR(priv, "txq not ready\n");
-               return -EAGAIN;
-       }
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
-               txq = &trans_pcie->txq[cnt];
-               q = &txq->q;
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "hwq %.2d: read=%u write=%u stop=%d"
-                               " swq_id=%#.2x (ac %d/hwq %d)\n",
-                               cnt, q->read_ptr, q->write_ptr,
-                               !!test_bit(cnt, trans_pcie->queue_stopped),
-                               txq->swq_id, txq->swq_id & 3,
-                               (txq->swq_id >> 2) & 0x1f);
-               if (cnt >= 4)
-                       continue;
-               /* for the ACs, display the stop count too */
-               pos += scnprintf(buf + pos, bufsz - pos,
-                       "        stop-count: %d\n",
-                       atomic_read(&trans_pcie->queue_stop_count[cnt]));
-       }
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
-                                               char __user *user_buf,
-                                               size_t count, loff_t *ppos) {
-       struct iwl_trans *trans = file->private_data;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_rx_queue *rxq = &trans_pcie->rxq;
-       char buf[256];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
-                                               rxq->read);
-       pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
-                                               rxq->write);
-       pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
-                                               rxq->free_count);
-       if (rxq->rb_stts) {
-               pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
-                        le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
-       } else {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                                       "closed_rb_num: Not Allocated\n");
-       }
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_log_event_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       char *buf;
-       int pos = 0;
-       ssize_t ret = -ENOMEM;
-
-       ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true);
-       if (buf) {
-               ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-               kfree(buf);
-       }
-       return ret;
-}
-
-static ssize_t iwl_dbgfs_log_event_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       u32 event_log_flag;
-       char buf[8];
-       int buf_size;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &event_log_flag) != 1)
-               return -EFAULT;
-       if (event_log_flag == 1)
-               iwl_dump_nic_event_log(trans, true, NULL, false);
-
-       return count;
-}
-
-static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_trans *trans = file->private_data;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
-
-       int pos = 0;
-       char *buf;
-       int bufsz = 24 * 64; /* 24 items * 64 char per item */
-       ssize_t ret;
-
-       buf = kzalloc(bufsz, GFP_KERNEL);
-       if (!buf) {
-               IWL_ERR(trans, "Can not allocate Buffer\n");
-               return -ENOMEM;
-       }
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "Interrupt Statistics Report:\n");
-
-       pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
-               isr_stats->hw);
-       pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
-               isr_stats->sw);
-       if (isr_stats->sw || isr_stats->hw) {
-               pos += scnprintf(buf + pos, bufsz - pos,
-                       "\tLast Restarting Code:  0x%X\n",
-                       isr_stats->err_code);
-       }
-#ifdef CONFIG_IWLWIFI_DEBUG
-       pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
-               isr_stats->sch);
-       pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
-               isr_stats->alive);
-#endif
-       pos += scnprintf(buf + pos, bufsz - pos,
-               "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
-               isr_stats->ctkill);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
-               isr_stats->wakeup);
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-               "Rx command responses:\t\t %u\n", isr_stats->rx);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
-               isr_stats->tx);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
-               isr_stats->unhandled);
-
-       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
-
-       char buf[8];
-       int buf_size;
-       u32 reset_flag;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%x", &reset_flag) != 1)
-               return -EFAULT;
-       if (reset_flag == 0)
-               memset(isr_stats, 0, sizeof(*isr_stats));
-
-       return count;
-}
-
-static const char *get_csr_string(int cmd)
-{
-       switch (cmd) {
-       IWL_CMD(CSR_HW_IF_CONFIG_REG);
-       IWL_CMD(CSR_INT_COALESCING);
-       IWL_CMD(CSR_INT);
-       IWL_CMD(CSR_INT_MASK);
-       IWL_CMD(CSR_FH_INT_STATUS);
-       IWL_CMD(CSR_GPIO_IN);
-       IWL_CMD(CSR_RESET);
-       IWL_CMD(CSR_GP_CNTRL);
-       IWL_CMD(CSR_HW_REV);
-       IWL_CMD(CSR_EEPROM_REG);
-       IWL_CMD(CSR_EEPROM_GP);
-       IWL_CMD(CSR_OTP_GP_REG);
-       IWL_CMD(CSR_GIO_REG);
-       IWL_CMD(CSR_GP_UCODE_REG);
-       IWL_CMD(CSR_GP_DRIVER_REG);
-       IWL_CMD(CSR_UCODE_DRV_GP1);
-       IWL_CMD(CSR_UCODE_DRV_GP2);
-       IWL_CMD(CSR_LED_REG);
-       IWL_CMD(CSR_DRAM_INT_TBL_REG);
-       IWL_CMD(CSR_GIO_CHICKEN_BITS);
-       IWL_CMD(CSR_ANA_PLL_CFG);
-       IWL_CMD(CSR_HW_REV_WA_REG);
-       IWL_CMD(CSR_DBG_HPET_MEM_REG);
-       default:
-               return "UNKNOWN";
-       }
-}
-
-void iwl_dump_csr(struct iwl_trans *trans)
-{
-       int i;
-       static const u32 csr_tbl[] = {
-               CSR_HW_IF_CONFIG_REG,
-               CSR_INT_COALESCING,
-               CSR_INT,
-               CSR_INT_MASK,
-               CSR_FH_INT_STATUS,
-               CSR_GPIO_IN,
-               CSR_RESET,
-               CSR_GP_CNTRL,
-               CSR_HW_REV,
-               CSR_EEPROM_REG,
-               CSR_EEPROM_GP,
-               CSR_OTP_GP_REG,
-               CSR_GIO_REG,
-               CSR_GP_UCODE_REG,
-               CSR_GP_DRIVER_REG,
-               CSR_UCODE_DRV_GP1,
-               CSR_UCODE_DRV_GP2,
-               CSR_LED_REG,
-               CSR_DRAM_INT_TBL_REG,
-               CSR_GIO_CHICKEN_BITS,
-               CSR_ANA_PLL_CFG,
-               CSR_HW_REV_WA_REG,
-               CSR_DBG_HPET_MEM_REG
+       struct iwl_host_cmd cmd = {
+               .id = id,
+               .len = { len, },
+               .data = { data, },
+               .flags = flags,
        };
-       IWL_ERR(trans, "CSR values:\n");
-       IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is "
-               "CSR_INT_PERIODIC_REG)\n");
-       for (i = 0; i <  ARRAY_SIZE(csr_tbl); i++) {
-               IWL_ERR(trans, "  %25s: 0X%08x\n",
-                       get_csr_string(csr_tbl[i]),
-                       iwl_read32(bus(trans), csr_tbl[i]));
-       }
-}
 
-static ssize_t iwl_dbgfs_csr_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       char buf[8];
-       int buf_size;
-       int csr;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &csr) != 1)
-               return -EFAULT;
-
-       iwl_dump_csr(trans);
-
-       return count;
-}
-
-static const char *get_fh_string(int cmd)
-{
-       switch (cmd) {
-       IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
-       IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
-       IWL_CMD(FH_RSCSR_CHNL0_WPTR);
-       IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
-       IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
-       IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
-       IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
-       IWL_CMD(FH_TSSR_TX_STATUS_REG);
-       IWL_CMD(FH_TSSR_TX_ERROR_REG);
-       default:
-               return "UNKNOWN";
-       }
+       return iwl_trans_send_cmd(trans, &cmd);
 }
-
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
-{
-       int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       int pos = 0;
-       size_t bufsz = 0;
-#endif
-       static const u32 fh_tbl[] = {
-               FH_RSCSR_CHNL0_STTS_WPTR_REG,
-               FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-               FH_RSCSR_CHNL0_WPTR,
-               FH_MEM_RCSR_CHNL0_CONFIG_REG,
-               FH_MEM_RSSR_SHARED_CTRL_REG,
-               FH_MEM_RSSR_RX_STATUS_REG,
-               FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
-               FH_TSSR_TX_STATUS_REG,
-               FH_TSSR_TX_ERROR_REG
-       };
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (display) {
-               bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
-               *buf = kmalloc(bufsz, GFP_KERNEL);
-               if (!*buf)
-                       return -ENOMEM;
-               pos += scnprintf(*buf + pos, bufsz - pos,
-                               "FH register values:\n");
-               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
-                       pos += scnprintf(*buf + pos, bufsz - pos,
-                               "  %34s: 0X%08x\n",
-                               get_fh_string(fh_tbl[i]),
-                               iwl_read_direct32(bus(trans), fh_tbl[i]));
-               }
-               return pos;
-       }
-#endif
-       IWL_ERR(trans, "FH register values:\n");
-       for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
-               IWL_ERR(trans, "  %34s: 0X%08x\n",
-                       get_fh_string(fh_tbl[i]),
-                       iwl_read_direct32(bus(trans), fh_tbl[i]));
-       }
-       return 0;
-}
-
-static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_trans *trans = file->private_data;
-       char *buf;
-       int pos = 0;
-       ssize_t ret = -EFAULT;
-
-       ret = pos = iwl_dump_fh(trans, &buf, true);
-       if (buf) {
-               ret = simple_read_from_buffer(user_buf,
-                                             count, ppos, buf, pos);
-               kfree(buf);
-       }
-
-       return ret;
-}
-
-DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
-DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
-DEBUGFS_READ_FILE_OPS(fh_reg);
-DEBUGFS_READ_FILE_OPS(rx_queue);
-DEBUGFS_READ_FILE_OPS(tx_queue);
-DEBUGFS_WRITE_FILE_OPS(csr);
-
-/*
- * Create the debugfs files and directories
- *
- */
-static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
-                                       struct dentry *dir)
-{
-       DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
-       DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
-       DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
-       DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
-       return 0;
-}
-#else
-static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
-                                       struct dentry *dir)
-{ return 0; }
-
-#endif /*CONFIG_IWLWIFI_DEBUGFS */
-
-const struct iwl_trans_ops trans_ops_pcie = {
-       .alloc = iwl_trans_pcie_alloc,
-       .request_irq = iwl_trans_pcie_request_irq,
-       .start_device = iwl_trans_pcie_start_device,
-       .prepare_card_hw = iwl_trans_pcie_prepare_card_hw,
-       .stop_device = iwl_trans_pcie_stop_device,
-
-       .tx_start = iwl_trans_pcie_tx_start,
-       .wake_any_queue = iwl_trans_pcie_wake_any_queue,
-
-       .send_cmd = iwl_trans_pcie_send_cmd,
-       .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu,
-
-       .tx = iwl_trans_pcie_tx,
-       .reclaim = iwl_trans_pcie_reclaim,
-
-       .tx_agg_disable = iwl_trans_pcie_tx_agg_disable,
-       .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc,
-       .tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
-
-       .kick_nic = iwl_trans_pcie_kick_nic,
-
-       .free = iwl_trans_pcie_free,
-       .stop_queue = iwl_trans_pcie_stop_queue,
-
-       .dbgfs_register = iwl_trans_pcie_dbgfs_register,
-
-       .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty,
-       .check_stuck_queue = iwl_trans_pcie_check_stuck_queue,
-
-       .suspend = iwl_trans_pcie_suspend,
-       .resume = iwl_trans_pcie_resume,
-};
-
index 7a2daa886dfd155a0647ec757e186997eb923a5a..c5923125c3f96bb8fe7625e2b59e0ba1cde4b8d7 100644 (file)
  * layer */
 
 struct iwl_priv;
-struct iwl_rxon_context;
-struct iwl_host_cmd;
 struct iwl_shared;
-struct iwl_device_cmd;
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+       CMD_SYNC = 0,
+       CMD_ASYNC = BIT(0),
+       CMD_WANT_SKB = BIT(1),
+       CMD_ON_DEMAND = BIT(2),
+};
+
+#define DEF_CMD_PAYLOAD_SIZE 320
+
+/**
+ * struct iwl_device_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for commands that
+ * aren't fully copied and use other TFD space.
+ */
+struct iwl_device_cmd {
+       struct iwl_cmd_header hdr;      /* uCode API */
+       u8 payload[DEF_CMD_PAYLOAD_SIZE];
+} __packed;
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
+#define IWL_MAX_CMD_TFDS       2
+
+enum iwl_hcmd_dataflag {
+       IWL_HCMD_DFL_NOCOPY     = BIT(0),
+};
+
+/**
+ * struct iwl_host_cmd - Host command to the uCode
+ * @data: array of chunks that composes the data of the host command
+ * @reply_page: pointer to the page that holds the response to the host command
+ * @handler_status: return value of the handler of the command
+ *     (put in setup_rx_handlers) - valid for SYNC mode only
+ * @callback:
+ * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
+ * @len: array of the lenths of the chunks in data
+ * @dataflags:
+ * @id: id of the host command
+ */
+struct iwl_host_cmd {
+       const void *data[IWL_MAX_CMD_TFDS];
+       unsigned long reply_page;
+       int handler_status;
+
+       u32 flags;
+       u16 len[IWL_MAX_CMD_TFDS];
+       u8 dataflags[IWL_MAX_CMD_TFDS];
+       u8 id;
+};
 
 /**
  * struct iwl_trans_ops - transport specific operations
@@ -91,7 +144,6 @@ struct iwl_device_cmd;
  * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
  * @stop_device:stops the whole device (embedded CPU put to reset)
  * @send_cmd:send a host command
- * @send_cmd_pdu:send a host command: flags can be CMD_*
  * @tx: send an skb
  * @reclaim: free packet until ssn. Returns a list of freed packets.
  * @tx_agg_alloc: allocate resources for a TX BA session
@@ -118,14 +170,14 @@ struct iwl_trans_ops {
        void (*stop_device)(struct iwl_trans *trans);
        void (*tx_start)(struct iwl_trans *trans);
 
-       void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx);
+       void (*wake_any_queue)(struct iwl_trans *trans,
+                              enum iwl_rxon_context_id ctx);
 
        int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 
-       int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len,
-                    const void *data);
        int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
-               struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id);
+               struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+               u8 sta_id);
        void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
                        int txq_id, int ssn, u32 status,
                        struct sk_buff_head *skbs);
@@ -149,9 +201,10 @@ struct iwl_trans_ops {
        int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
        int (*check_stuck_queue)(struct iwl_trans *trans, int q);
        int (*wait_tx_queue_empty)(struct iwl_trans *trans);
-
+#ifdef CONFIG_PM_SLEEP
        int (*suspend)(struct iwl_trans *trans);
        int (*resume)(struct iwl_trans *trans);
+#endif
 };
 
 /**
@@ -195,7 +248,8 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans)
        trans->ops->tx_start(trans);
 }
 
-static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx)
+static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
+                                           enum iwl_rxon_context_id ctx)
 {
        trans->ops->wake_any_queue(trans, ctx);
 }
@@ -207,14 +261,12 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
        return trans->ops->send_cmd(trans, cmd);
 }
 
-static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
-                                       u32 flags, u16 len, const void *data)
-{
-       return trans->ops->send_cmd_pdu(trans, id, flags, len, data);
-}
+int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
+                          u32 flags, u16 len, const void *data);
 
 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
-               struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id)
+               struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
+               u8 sta_id)
 {
        return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
 }
@@ -279,6 +331,7 @@ static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
        return trans->ops->dbgfs_register(trans, dir);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static inline int iwl_trans_suspend(struct iwl_trans *trans)
 {
        return trans->ops->suspend(trans);
@@ -288,6 +341,7 @@ static inline int iwl_trans_resume(struct iwl_trans *trans)
 {
        return trans->ops->resume(trans);
 }
+#endif
 
 /*****************************************************
 * Transport layers implementations
index 0c846f5a646ab9859bb2451c7a1d4c9970c0aecd..8147f1e2a0b0d4a15521f66a82369450bb58af05 100644 (file)
@@ -973,6 +973,23 @@ static const struct {
        { MODEL_8682, "libertas/usb8682.bin" }
 };
 
+#ifdef CONFIG_OLPC
+
+static int try_olpc_fw(struct if_usb_card *cardp)
+{
+       int retval = -ENOENT;
+
+       /* try the OLPC firmware first; fall back to fw_table list */
+       if (machine_is_olpc() && cardp->model == MODEL_8388)
+               retval = request_firmware(&cardp->fw,
+                               "libertas/usb8388_olpc.bin", &cardp->udev->dev);
+       return retval;
+}
+
+#else
+static int try_olpc_fw(struct if_usb_card *cardp) { return -ENOENT; }
+#endif /* !CONFIG_OLPC */
+
 static int get_fw(struct if_usb_card *cardp, const char *fwname)
 {
        int i;
@@ -981,6 +998,10 @@ static int get_fw(struct if_usb_card *cardp, const char *fwname)
        if (fwname)
                return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
 
+       /* Handle OLPC firmware */
+       if (try_olpc_fw(cardp) == 0)
+               return 0;
+
        /* Otherwise search for firmware to use */
        for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
                if (fw_table[i].model != cardp->model)
index 5cdad92277fab0252d55d1bf873d4e30d3b1e4b3..62b4c2938608d67873d66afb8be9e288247820b9 100644 (file)
@@ -147,13 +147,12 @@ static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1,
        u8 *ptr = rate1, *tmp;
        u32 i, j;
 
-       tmp = kmalloc(rate1_size, GFP_KERNEL);
+       tmp = kmemdup(rate1, rate1_size, GFP_KERNEL);
        if (!tmp) {
                dev_err(priv->adapter->dev, "failed to alloc tmp buf\n");
                return -ENOMEM;
        }
 
-       memcpy(tmp, rate1, rate1_size);
        memset(rate1, 0, rate1_size);
 
        for (i = 0; rate2[i] && i < rate2_size; i++) {
index 37ca2f90ad63360486b8e2e7cd441e13931bed12..8d8588db1cd960d71fc34c4e564768ecf40bd30b 100644 (file)
@@ -1479,12 +1479,12 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
                dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
                return -ENOMEM;
        }
-       beacon_ie = kzalloc(ie_len, GFP_KERNEL);
+
+       beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
        if (!beacon_ie) {
                dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
                return -ENOMEM;
        }
-       memcpy(beacon_ie, ie_buf, ie_len);
 
        ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
                                        ie_len, beacon_period,
@@ -1986,7 +1986,7 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
                priv->curr_bcn_size = curr_bss->beacon_buf_size;
 
                kfree(priv->curr_bcn_buf);
-               priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size,
+               priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
                                                GFP_KERNEL);
                if (!priv->curr_bcn_buf) {
                        dev_err(priv->adapter->dev,
index 3fca219bcfb6deea19dcef14e324c2f5e9d8b1ea..1df5ef6b4953bc51b25c59c0e94183077daf5cd5 100644 (file)
@@ -199,13 +199,15 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                        dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
                        return -ENOMEM;
                }
-               beacon_ie = kzalloc(bss->len_beacon_ies, GFP_KERNEL);
+
+               beacon_ie = kmemdup(bss->information_elements,
+                                       bss->len_beacon_ies, GFP_KERNEL);
                if (!beacon_ie) {
-                       dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
+                       kfree(bss_desc);
+                       dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
                        return -ENOMEM;
                }
-               memcpy(beacon_ie, bss->information_elements,
-                      bss->len_beacon_ies);
+
                ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
                                                beacon_ie, bss->len_beacon_ies,
                                                bss->beacon_interval,
@@ -866,10 +868,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
        ret = mwifiex_rate_ioctl_cfg(priv, rate);
 
        if (!ret) {
-               if (rate && rate->is_rate_auto)
+               if (rate->is_rate_auto)
                        rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
                                                        priv->tx_htinfo);
-               else if (rate)
+               else
                        rate->rate = priv->data_rate;
        } else {
                ret = -1;
index 771280a47ea7c66da2f1d74fa2fb92e4c4a9fe46..ea1395aafa39104e9f2791242d4fbb8baaefd439 100644 (file)
@@ -5501,6 +5501,14 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
 
        /* Set rssi values to dBm */
        hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
+
+       /*
+        * Ask mac80211 to not to trigger PS mode
+        * based on PM bit of incoming frames.
+        */
+       if (priv->ap_fw)
+               hw->flags |= IEEE80211_HW_AP_LINK_PS;
+
        hw->vif_data_size = sizeof(struct mwl8k_vif);
        hw->sta_data_size = sizeof(struct mwl8k_sta);
 
index c69a7d71f4cad3cf2b6f1a90b19d1512f6d849e7..4778620347c491003fc3ff3fd02550e61d597c19 100644 (file)
 
 /*
  * LED_CFG: LED control
+ * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
+ * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
+ * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
  * color LED's:
  *   0: off
  *   1: blinking upon TX2
index ef67f6786a84785bc00c629789d25011ca6148ce..31c98509f7e6c639565fb7d2c72492fb47d7ba7c 100644 (file)
@@ -493,7 +493,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
        rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
                           test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
-                          txdesc->key_idx : 0xff);
+                          txdesc->key_idx : txdesc->u.ht.wcid);
        rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
                           txdesc->length);
        rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
@@ -601,7 +601,7 @@ void rt2800_process_rxwi(struct queue_entry *entry,
 }
 EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
 
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -609,13 +609,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
        u32 word;
        u16 mcs, real_mcs;
        int aggr, ampdu;
-       __le32 *txwi;
 
        /*
         * Obtain the status about this packet.
         */
        txdesc.flags = 0;
-       txwi = rt2800_drv_get_txwi(entry);
        rt2x00_desc_read(txwi, 0, &word);
 
        mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
@@ -899,28 +897,12 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
        }
 }
 
-static int rt2800_blink_set(struct led_classdev *led_cdev,
-                           unsigned long *delay_on, unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u32 reg;
-
-       rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
-       rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
-       rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
-       rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
-
-       return 0;
-}
-
 static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
                     struct rt2x00_led *led, enum led_type type)
 {
        led->rt2x00dev = rt2x00dev;
        led->type = type;
        led->led_dev.brightness_set = rt2800_brightness_set;
-       led->led_dev.blink_set = rt2800_blink_set;
        led->flags = LED_INITIALIZED;
 }
 #endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -928,11 +910,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
 /*
  * Configuration handlers.
  */
-static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_crypto *crypto,
-                                   struct ieee80211_key_conf *key)
+static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
+                              const u8 *address,
+                              int wcid)
 {
        struct mac_wcid_entry wcid_entry;
+       u32 offset;
+
+       offset = MAC_WCID_ENTRY(wcid);
+
+       memset(&wcid_entry, 0xff, sizeof(wcid_entry));
+       if (address)
+               memcpy(wcid_entry.mac, address, ETH_ALEN);
+
+       rt2800_register_multiwrite(rt2x00dev, offset,
+                                     &wcid_entry, sizeof(wcid_entry));
+}
+
+static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+       u32 offset;
+       offset = MAC_WCID_ATTR_ENTRY(wcid);
+       rt2800_register_write(rt2x00dev, offset, 0);
+}
+
+static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
+                                          int wcid, u32 bssidx)
+{
+       u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
+       u32 reg;
+
+       /*
+        * The BSS Idx numbers is split in a main value of 3 bits,
+        * and a extended field for adding one additional bit to the value.
+        */
+       rt2800_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
+       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
+                          (bssidx & 0x8) >> 3);
+       rt2800_register_write(rt2x00dev, offset, reg);
+}
+
+static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
+                                          struct rt2x00lib_crypto *crypto,
+                                          struct ieee80211_key_conf *key)
+{
        struct mac_iveiv_entry iveiv_entry;
        u32 offset;
        u32 reg;
@@ -952,14 +974,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
                                   (crypto->cipher & 0x7));
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
                                   (crypto->cipher & 0x8) >> 3);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
-                                  (crypto->bssidx & 0x7));
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
-                                  (crypto->bssidx & 0x8) >> 3);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
                rt2800_register_write(rt2x00dev, offset, reg);
        } else {
-               rt2800_register_write(rt2x00dev, offset, 0);
+               /* Delete the cipher without touching the bssidx */
+               rt2800_register_read(rt2x00dev, offset, &reg);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
+               rt2800_register_write(rt2x00dev, offset, reg);
        }
 
        offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
@@ -972,14 +996,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
        iveiv_entry.iv[3] |= key->keyidx << 6;
        rt2800_register_multiwrite(rt2x00dev, offset,
                                      &iveiv_entry, sizeof(iveiv_entry));
-
-       offset = MAC_WCID_ENTRY(key->hw_key_idx);
-
-       memset(&wcid_entry, 0, sizeof(wcid_entry));
-       if (crypto->cmd == SET_KEY)
-               memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
-       rt2800_register_multiwrite(rt2x00dev, offset,
-                                     &wcid_entry, sizeof(wcid_entry));
 }
 
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1026,20 +1042,24 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
        /*
         * Update WCID information
         */
-       rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+       rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
+       rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
+                                      crypto->bssidx);
+       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
 
-static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
+static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
 {
+       struct mac_wcid_entry wcid_entry;
        int idx;
-       u32 offset, reg;
+       u32 offset;
 
        /*
-        * Search for the first free pairwise key entry and return the
-        * corresponding index.
+        * Search for the first free WCID entry and return the corresponding
+        * index.
         *
         * Make sure the WCID starts _after_ the last possible shared key
         * entry (>32).
@@ -1049,11 +1069,17 @@ static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
         * first 222 entries.
         */
        for (idx = 33; idx <= 222; idx++) {
-               offset = MAC_WCID_ATTR_ENTRY(idx);
-               rt2800_register_read(rt2x00dev, offset, &reg);
-               if (!reg)
+               offset = MAC_WCID_ENTRY(idx);
+               rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
+                                         sizeof(wcid_entry));
+               if (is_broadcast_ether_addr(wcid_entry.mac))
                        return idx;
        }
+
+       /*
+        * Use -1 to indicate that we don't have any more space in the WCID
+        * table.
+        */
        return -1;
 }
 
@@ -1063,13 +1089,15 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 {
        struct hw_key_entry key_entry;
        u32 offset;
-       int idx;
 
        if (crypto->cmd == SET_KEY) {
-               idx = rt2800_find_pairwise_keyslot(rt2x00dev);
-               if (idx < 0)
+               /*
+                * Allow key configuration only for STAs that are
+                * known by the hw.
+                */
+               if (crypto->wcid < 0)
                        return -ENOSPC;
-               key->hw_key_idx = idx;
+               key->hw_key_idx = crypto->wcid;
 
                memcpy(key_entry.key, crypto->key,
                       sizeof(key_entry.key));
@@ -1086,12 +1114,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        /*
         * Update WCID information
         */
-       rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
 
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta)
+{
+       int wcid;
+       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+       /*
+        * Find next free WCID.
+        */
+       wcid = rt2800_find_wcid(rt2x00dev);
+
+       /*
+        * Store selected wcid even if it is invalid so that we can
+        * later decide if the STA is uploaded into the hw.
+        */
+       sta_priv->wcid = wcid;
+
+       /*
+        * No space left in the device, however, we can still communicate
+        * with the STA -> No error.
+        */
+       if (wcid < 0)
+               return 0;
+
+       /*
+        * Clean up WCID attributes and write STA address to the device.
+        */
+       rt2800_delete_wcid_attr(rt2x00dev, wcid);
+       rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
+       rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
+                                      rt2x00lib_get_bssidx(rt2x00dev, vif));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_add);
+
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+       /*
+        * Remove WCID entry, no need to clean the attributes as they will
+        * get renewed when the WCID is reused.
+        */
+       rt2800_config_wcid(rt2x00dev, NULL, wcid);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_remove);
+
 void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
                          const unsigned int filter_flags)
 {
@@ -2771,11 +2846,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                                         SHARED_KEY_MODE_ENTRY(i), 0);
 
        for (i = 0; i < 256; i++) {
-               static const u32 wcid[2] = { 0xffffffff, 0x00ffffff };
-               rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
-                                             wcid, sizeof(wcid));
-
-               rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
+               rt2800_config_wcid(rt2x00dev, NULL, i);
+               rt2800_delete_wcid_attr(rt2x00dev, i);
                rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
        }
 
@@ -3697,14 +3769,15 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
        rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
 
        /* Apparently the data is read from end to start */
-       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3,
-                                       (u32 *)&rt2x00dev->eeprom[i]);
-       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2,
-                                       (u32 *)&rt2x00dev->eeprom[i + 2]);
-       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1,
-                                       (u32 *)&rt2x00dev->eeprom[i + 4]);
-       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0,
-                                       (u32 *)&rt2x00dev->eeprom[i + 6]);
+       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
+       /* The returned value is in CPU order, but eeprom is le */
+       rt2x00dev->eeprom[i] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
 
        mutex_unlock(&rt2x00dev->csr_mutex);
 }
@@ -3870,19 +3943,23 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
                return -ENODEV;
        }
 
-       if (!rt2x00_rf(rt2x00dev, RF2820) &&
-           !rt2x00_rf(rt2x00dev, RF2850) &&
-           !rt2x00_rf(rt2x00dev, RF2720) &&
-           !rt2x00_rf(rt2x00dev, RF2750) &&
-           !rt2x00_rf(rt2x00dev, RF3020) &&
-           !rt2x00_rf(rt2x00dev, RF2020) &&
-           !rt2x00_rf(rt2x00dev, RF3021) &&
-           !rt2x00_rf(rt2x00dev, RF3022) &&
-           !rt2x00_rf(rt2x00dev, RF3052) &&
-           !rt2x00_rf(rt2x00dev, RF3320) &&
-           !rt2x00_rf(rt2x00dev, RF5370) &&
-           !rt2x00_rf(rt2x00dev, RF5390)) {
-               ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+       switch (rt2x00dev->chip.rf) {
+       case RF2820:
+       case RF2850:
+       case RF2720:
+       case RF2750:
+       case RF3020:
+       case RF2020:
+       case RF3021:
+       case RF3022:
+       case RF3052:
+       case RF3320:
+       case RF5370:
+       case RF5390:
+               break;
+       default:
+               ERROR(rt2x00dev, "Invalid RF chipset 0x%x detected.\n",
+                     rt2x00dev->chip.rf);
                return -ENODEV;
        }
 
@@ -4409,8 +4486,19 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn,
                        u8 buf_size)
 {
+       struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
        int ret = 0;
 
+       /*
+        * Don't allow aggregation for stations the hardware isn't aware
+        * of because tx status reports for frames to an unknown station
+        * always contain wcid=255 and thus we can't distinguish between
+        * multiple stations which leads to unwanted situations when the
+        * hw reorders frames due to aggregation.
+        */
+       if (sta_priv->wcid < 0)
+               return 1;
+
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
        case IEEE80211_AMPDU_RX_STOP:
index 69deb3148ae77348fed373464868aefeee6327fc..7a2511f6785c53d7423abd495c3c10b19c84fe97 100644 (file)
@@ -152,7 +152,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
                          struct txentry_desc *txdesc);
 void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
 
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
 
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
 void rt2800_clear_beacon(struct queue_entry *entry);
@@ -166,6 +166,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                               struct rt2x00lib_crypto *crypto,
                               struct ieee80211_key_conf *key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta);
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
 void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
                          const unsigned int filter_flags);
 void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
index cabf249aa55b7e4b957a206d8d14faee816c1fa2..da48c8ac27bd53c3a3ef92d135c66c71d902573d 100644 (file)
@@ -619,11 +619,11 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
        /*
         * Initialize TX descriptor
         */
-       rt2x00_desc_read(txd, 0, &word);
+       word = 0;
        rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
        rt2x00_desc_write(txd, 0, word);
 
-       rt2x00_desc_read(txd, 1, &word);
+       word = 0;
        rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
        rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
                           !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
@@ -634,12 +634,12 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
        rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
        rt2x00_desc_write(txd, 1, word);
 
-       rt2x00_desc_read(txd, 2, &word);
+       word = 0;
        rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
                           skbdesc->skb_dma + TXWI_DESC_SIZE);
        rt2x00_desc_write(txd, 2, word);
 
-       rt2x00_desc_read(txd, 3, &word);
+       word = 0;
        rt2x00_set_field32(&word, TXD_W3_WIV,
                           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
@@ -760,7 +760,7 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
                }
 
                entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               rt2800_txdone_entry(entry, status);
+               rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
 
                if (--max_tx_done == 0)
                        break;
@@ -1015,6 +1015,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
        .get_stats              = rt2x00mac_get_stats,
        .get_tkip_seq           = rt2800_get_tkip_seq,
        .set_rts_threshold      = rt2800_set_rts_threshold,
+       .sta_add                = rt2x00mac_sta_add,
+       .sta_remove             = rt2x00mac_sta_remove,
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt2800_conf_tx,
        .get_tsf                = rt2800_get_tsf,
@@ -1076,6 +1078,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
        .config_erp             = rt2800_config_erp,
        .config_ant             = rt2800_config_ant,
        .config                 = rt2800_config,
+       .sta_add                = rt2800_sta_add,
+       .sta_remove             = rt2800_sta_remove,
 };
 
 static const struct data_queue_desc rt2800pci_queue_rx = {
@@ -1153,6 +1157,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
 #endif
 #ifdef CONFIG_RT2800PCI_RT53XX
        { PCI_DEVICE(0x1814, 0x5390) },
+       { PCI_DEVICE(0x1814, 0x539a) },
        { PCI_DEVICE(0x1814, 0x539f) },
 #endif
        { 0, }
index 507559361d87f7cd657586cd96c095c1484a3d49..f1565792f2701c6285b202456c831341f6f5e181 100644 (file)
@@ -464,6 +464,15 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
        int wcid, ack, pid;
        int tx_wcid, tx_ack, tx_pid;
 
+       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
+               WARNING(entry->queue->rt2x00dev,
+                       "Data pending for entry %u in queue %u\n",
+                       entry->entry_idx, entry->queue->qid);
+               cond_resched();
+               return false;
+       }
+
        wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
        ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
        pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
@@ -529,12 +538,12 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
                        if (rt2800usb_txdone_entry_check(entry, reg))
                                break;
+                       entry = NULL;
                }
 
-               if (!entry || rt2x00queue_empty(queue))
-                       break;
-
-               rt2800_txdone_entry(entry, reg);
+               if (entry)
+                       rt2800_txdone_entry(entry, reg,
+                                           rt2800usb_get_txwi(entry));
        }
 }
 
@@ -558,8 +567,10 @@ static void rt2800usb_work_txdone(struct work_struct *work)
                while (!rt2x00queue_empty(queue)) {
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                                break;
+
                        if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
                                rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
                        else if (rt2x00queue_status_timeout(entry))
@@ -749,6 +760,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
        .get_stats              = rt2x00mac_get_stats,
        .get_tkip_seq           = rt2800_get_tkip_seq,
        .set_rts_threshold      = rt2800_set_rts_threshold,
+       .sta_add                = rt2x00mac_sta_add,
+       .sta_remove             = rt2x00mac_sta_remove,
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt2800_conf_tx,
        .get_tsf                = rt2800_get_tsf,
@@ -806,6 +819,8 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
        .config_erp             = rt2800_config_erp,
        .config_ant             = rt2800_config_ant,
        .config                 = rt2800_config,
+       .sta_add                = rt2800_sta_add,
+       .sta_remove             = rt2800_sta_remove,
 };
 
 static const struct data_queue_desc rt2800usb_queue_rx = {
@@ -921,6 +936,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x07d1, 0x3c16) },
        /* Draytek */
        { USB_DEVICE(0x07fa, 0x7712) },
+       /* DVICO */
+       { USB_DEVICE(0x0fe9, 0xb307) },
        /* Edimax */
        { USB_DEVICE(0x7392, 0x7711) },
        { USB_DEVICE(0x7392, 0x7717) },
index f82bfeb79ebb67dc73c8d85cb434ab0b0cdacb7e..cbf8eb334e96126fa0ec591a7ab8f0a95a33bcdb 100644 (file)
@@ -478,6 +478,8 @@ struct rt2x00lib_crypto {
        u8 key[16];
        u8 tx_mic[8];
        u8 rx_mic[8];
+
+       int wcid;
 };
 
 /*
@@ -511,6 +513,19 @@ struct rt2x00intf_conf {
        __le32 bssid[2];
 };
 
+/*
+ * Private structure for storing STA details
+ * wcid: Wireless Client ID
+ */
+struct rt2x00_sta {
+       int wcid;
+};
+
+static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
+{
+       return (struct rt2x00_sta *)sta->drv_priv;
+}
+
 /*
  * rt2x00lib callback functions.
  */
@@ -620,6 +635,11 @@ struct rt2x00lib_ops {
        void (*config) (struct rt2x00_dev *rt2x00dev,
                        struct rt2x00lib_conf *libconf,
                        const unsigned int changed_flags);
+       int (*sta_add) (struct rt2x00_dev *rt2x00dev,
+                       struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta);
+       int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
+                          int wcid);
 };
 
 /*
@@ -1225,6 +1245,12 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
 }
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
+/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+                        struct ieee80211_vif *vif);
+
 /*
  * Interrupt context handlers.
  */
@@ -1261,6 +1287,10 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 #else
 #define rt2x00mac_set_key      NULL
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta);
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta);
 void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
 void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
 int rt2x00mac_get_stats(struct ieee80211_hw *hw,
index 92ff6a72a2bb422771c85788cda715ed797068c2..e1fb2a8569be292d0f26f5347b0bfa828737bd39 100644 (file)
 #include "rt2x00.h"
 #include "rt2x00lib.h"
 
+/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+                        struct ieee80211_vif *vif)
+{
+       /*
+        * When in STA mode, bssidx is always 0 otherwise local_address[5]
+        * contains the bss number, see BSS_ID_MASK comments for details.
+        */
+       if (rt2x00dev->intf_sta_count)
+               return 0;
+       return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
+
 /*
  * Radio control handlers.
  */
@@ -914,6 +930,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
        else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
                rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
 
+       /*
+        * Tell mac80211 about the size of our private STA structure.
+        */
+       rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
+
        /*
         * Allocate tx status FIFO for driver use.
         */
index 4ccf238059730cf20e589d9f567e35a3af3f189d..cef1c878c37ede1775f00278cc0cc58b0bb68bdc 100644 (file)
@@ -494,6 +494,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        struct rt2x00lib_crypto crypto;
        static const u8 bcast_addr[ETH_ALEN] =
                { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
+       struct rt2x00_sta *sta_priv = NULL;
 
        if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
                return 0;
@@ -504,24 +505,18 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        memset(&crypto, 0, sizeof(crypto));
 
-       /*
-        * When in STA mode, bssidx is always 0 otherwise local_address[5]
-        * contains the bss number, see BSS_ID_MASK comments for details.
-        */
-       if (rt2x00dev->intf_sta_count)
-               crypto.bssidx = 0;
-       else
-               crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
-
+       crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
        crypto.cipher = rt2x00crypto_key_to_cipher(key);
        if (crypto.cipher == CIPHER_NONE)
                return -EOPNOTSUPP;
 
        crypto.cmd = cmd;
 
-       if (sta)
+       if (sta) {
                crypto.address = sta->addr;
-       else
+               sta_priv = sta_to_rt2x00_sta(sta);
+               crypto.wcid = sta_priv->wcid;
+       } else
                crypto.address = bcast_addr;
 
        if (crypto.cipher == CIPHER_TKIP)
@@ -560,6 +555,39 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+       /*
+        * If there's no space left in the device table store
+        * -1 as wcid but tell mac80211 everything went ok.
+        */
+       if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
+               sta_priv->wcid = -1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
+
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+       /*
+        * If we never sent the STA to the device no need to clean it up.
+        */
+       if (sta_priv->wcid < 0)
+               return 0;
+
+       return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
+
 void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
index 29edb9fbe6f172298285f6269db5b51d1c541576..5adfb3eab9cda4c07465fa4ec3ad404e2baba212 100644 (file)
@@ -310,11 +310,16 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct rt2x00_sta *sta_priv = NULL;
 
-       if (tx_info->control.sta)
+       if (tx_info->control.sta) {
                txdesc->u.ht.mpdu_density =
                    tx_info->control.sta->ht_cap.ampdu_density;
 
+               sta_priv = sta_to_rt2x00_sta(tx_info->control.sta);
+               txdesc->u.ht.wcid = sta_priv->wcid;
+       }
+
        txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
 
        /*
index f2100f4ddcffd1c0fa35259a407237cc9eb38a7d..349008d1fb286adefe2d6ccb0a815d8fd1003a3e 100644 (file)
@@ -288,8 +288,8 @@ enum txentry_desc_flags {
  * @signal: PLCP signal.
  * @service: PLCP service.
  * @msc: MCS.
- * @stbc: STBC.
- * @ba_size: BA size.
+ * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
+ * @ba_size: Size of the recepients RX reorder buffer - 1.
  * @rate_mode: Rate mode (See @enum rate_modulation).
  * @mpdu_density: MDPU density.
  * @retry_limit: Max number of retries.
@@ -321,6 +321,7 @@ struct txentry_desc {
                        u8 ba_size;
                        u8 mpdu_density;
                        enum txop txop;
+                       int wcid;
                } ht;
        } u;
 
index b6b4542c2460e6539de067048270385fba345d85..1e31050dafc9e9b2ea2a59073137de053e48074b 100644 (file)
@@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
        struct queue_entry *entry = (struct queue_entry *)urb->context;
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 
-       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
-
-       if (rt2x00dev->ops->lib->tx_dma_done)
-               rt2x00dev->ops->lib->tx_dma_done(entry);
-
-       /*
-        * Report the frame as DMA done
-        */
-       rt2x00lib_dmadone(entry);
-
        /*
         * Check if the frame was correctly uploaded
         */
        if (urb->status)
                set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
 
+       if (rt2x00dev->ops->lib->tx_dma_done)
+               rt2x00dev->ops->lib->tx_dma_done(entry);
        /*
         * Schedule the delayed work for reading the TX status
         * from the device.
@@ -874,18 +871,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
 {
        struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       int retval;
-
-       retval = rt2x00lib_suspend(rt2x00dev, state);
-       if (retval)
-               return retval;
 
-       /*
-        * Decrease usbdev refcount.
-        */
-       usb_put_dev(interface_to_usbdev(usb_intf));
-
-       return 0;
+       return rt2x00lib_suspend(rt2x00dev, state);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_suspend);
 
@@ -894,8 +881,6 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)
        struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
        struct rt2x00_dev *rt2x00dev = hw->priv;
 
-       usb_get_dev(interface_to_usbdev(usb_intf));
-
        return rt2x00lib_resume(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_resume);
index 6a93939f44e887984d3f9877a8753485b3d82980..0baeb894f093e11e81f13f3d55c4c1624f546536 100644 (file)
@@ -2420,6 +2420,7 @@ static struct usb_device_id rt73usb_device_table[] = {
        /* Buffalo */
        { USB_DEVICE(0x0411, 0x00d8) },
        { USB_DEVICE(0x0411, 0x00d9) },
+       { USB_DEVICE(0x0411, 0x00e6) },
        { USB_DEVICE(0x0411, 0x00f4) },
        { USB_DEVICE(0x0411, 0x0116) },
        { USB_DEVICE(0x0411, 0x0119) },
index 1bdc1aa305c0ea1c48e371da14a31cd9b95a86ed..04c4e9eb6ee6ed726357fb6bb3ac8da26c4aa7be 100644 (file)
@@ -610,6 +610,11 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 
                        mac->link_state = MAC80211_NOLINK;
                        memset(mac->bssid, 0, 6);
+
+                       /* reset sec info */
+                       rtl_cam_reset_sec_info(hw);
+
+                       rtl_cam_reset_all_entry(hw);
                        mac->vendor = PEER_UNKNOWN;
 
                        RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
@@ -1063,6 +1068,9 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                 *or clear all entry here.
                 */
                rtl_cam_delete_one_entry(hw, mac_addr, key_idx);
+
+               rtl_cam_reset_sec_info(hw);
+
                break;
        default:
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
index 4c34c4c1ae56b96f0a1c248cafe20e13027f0030..b7ecb9e44aa93de421dc4ba6e839c3c909a6908b 100644 (file)
@@ -133,6 +133,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
        rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
        rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+       if (!rtlpriv->psc.inactiveps)
+               pr_info("rtl8192ce: Power Save off (module option)\n");
+       if (!rtlpriv->psc.fwctrl_lps)
+               pr_info("rtl8192ce: FW Power Save off (module option)\n");
        rtlpriv->psc.reg_fwctrl_lps = 3;
        rtlpriv->psc.reg_max_lps_awakeintvl = 5;
        /* for ASPM, you can close aspm through
@@ -356,10 +360,10 @@ module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444);
 module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444);
 module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444);
 module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(fwlps, "using linked fw control power save "
-                "(default 1 is open)\n");
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
 
 static struct pci_driver rtl92ce_driver = {
        .name = KBUILD_MODNAME,
index 81ae64234f80a102a317b78cb3e3a79a263d49a7..c8977a50ca36de7b2d52f3abe8f55d4abd004e07 100644 (file)
@@ -537,12 +537,6 @@ do {                                                       \
                memset(__pdesc, 0, _size);      \
 } while (0);
 
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
-       (_pdesc->rxmcs == DESC92_RATE1M ||              \
-        _pdesc->rxmcs == DESC92_RATE2M ||              \
-        _pdesc->rxmcs == DESC92_RATE5_5M ||            \
-        _pdesc->rxmcs == DESC92_RATE11M)
-
 struct rx_fwinfo_92c {
        u8 gain_trsw[4];
        u8 pwdb_all;
index 35529f701fc04b1f469cd911ccfd1aa4f5b8cb61..626d88e88e26b70c598d902c01747d8341a18965 100644 (file)
@@ -87,12 +87,6 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
 
 u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
 
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
-       (GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\
-        GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\
-        GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
-        GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)
-
 struct rx_fwinfo_92c {
        u8 gain_trsw[4];
        u8 pwdb_all;
index 195666a0c854007c34744b24ae92da047337fdff..424b8a0323e21c602b117b3a12b24fc217e55503 100644 (file)
@@ -281,6 +281,8 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)},
        /* 8188CE-VAU USB minCard (b/g mode only) */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
+       /* 8188RU in Alfa AWUS036NHR */
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
        /* 8188 Combo for BC4 */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
 
@@ -303,20 +305,23 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
        /* HP - Lite-On ,8188CUS Slim Combo */
        {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */
        {RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
        {RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
        {RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
        {RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
        {RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
-       {RTL_USB_DEVICE(0x3358, 0x13d3, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
+       {RTL_USB_DEVICE(0x13d3, 0x3358, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
        /* Russian customer -Azwave (8188CE-VAU  b/g mode only) */
-       {RTL_USB_DEVICE(0x3359, 0x13d3, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x13d3, 0x3359, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(0x4855, 0x0090, rtl92cu_hal_cfg)}, /* Feixun */
+       {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */
+       {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */
 
        /****** 8192CU ********/
        {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
        {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
        {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
-       {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Abocom -Abocom*/
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
index c4161148e0d87ab20136e57ce2dfadd993a8fd16..bc33b147f44f70f502d3dfe83994f0f3ed4e57c7 100644 (file)
@@ -548,15 +548,16 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
                               (tcb_desc->rts_use_shortpreamble ? 1 : 0)
                               : (tcb_desc->rts_use_shortgi ? 1 : 0)));
        if (mac->bw_40) {
-               if (tcb_desc->packet_bw) {
+               if (rate_flag & IEEE80211_TX_RC_DUP_DATA) {
                        SET_TX_DESC_DATA_BW(txdesc, 1);
                        SET_TX_DESC_DATA_SC(txdesc, 3);
+               } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){
+                       SET_TX_DESC_DATA_BW(txdesc, 1);
+                       SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc);
                } else {
                        SET_TX_DESC_DATA_BW(txdesc, 0);
-                               if (rate_flag & IEEE80211_TX_RC_DUP_DATA)
-                                       SET_TX_DESC_DATA_SC(txdesc,
-                                                         mac->cur_40_prime_sc);
-                       }
+                       SET_TX_DESC_DATA_SC(txdesc, 0);
+               }
        } else {
                SET_TX_DESC_DATA_BW(txdesc, 0);
                SET_TX_DESC_DATA_SC(txdesc, 0);
index f6419b7ed2f47908cd4dadaca7d35eeb236f2a5d..c681597c7f205084e52f1f2e307d935033542087 100644 (file)
@@ -150,6 +150,10 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
        rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
        rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+       if (!rtlpriv->psc.inactiveps)
+               pr_info("rtl8192ce: Power Save off (module option)\n");
+       if (!rtlpriv->psc.fwctrl_lps)
+               pr_info("rtl8192ce: FW Power Save off (module option)\n");
        rtlpriv->psc.reg_fwctrl_lps = 3;
        rtlpriv->psc.reg_max_lps_awakeintvl = 5;
        /* for ASPM, you can close aspm through
@@ -376,10 +380,10 @@ module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444);
 module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444);
 module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
 module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1"
-                " is open)\n");
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
 
 static struct pci_driver rtl92de_driver = {
        .name = KBUILD_MODNAME,
index 6c2236868c9aea260fd4099d007eeec48edf1731..4d55d0b6816dca21b1b4322b46be14f1e87cf7b7 100644 (file)
@@ -537,12 +537,6 @@ do {                                                       \
                memset((void *)__pdesc, 0, _size);      \
 } while (0);
 
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
-       (_pdesc->rxmcs == DESC92_RATE1M ||              \
-        _pdesc->rxmcs == DESC92_RATE2M ||              \
-        _pdesc->rxmcs == DESC92_RATE5_5M ||            \
-        _pdesc->rxmcs == DESC92_RATE11M)
-
 /* For 92D early mode */
 #define SET_EARLYMODE_PKTNUM(__paddr, __value)         \
        SET_BITS_OFFSET_LE(__paddr, 0, 3, __value)
index 68204ea175ddf594898cf1a8f60cd327025caa40..c6c044816d39e585a4cf9e0625675aaf1a1d7574 100644 (file)
@@ -459,7 +459,7 @@ do {                                                                \
 #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val)  \
        SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
 
-#define RX_HAL_IS_CCK_RATE(_pdesc)\
+#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
        (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||  \
         GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||  \
         GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
index 0055a1c845a2f8c213e8c8c4f945836e737cf5ad..24bd331a54842bfbcaacdd501ccf8bd14547e044 100644 (file)
@@ -164,6 +164,10 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
        rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
        rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+       if (!rtlpriv->psc.inactiveps)
+               pr_info("rtl8192ce: Power Save off (module option)\n");
+       if (!rtlpriv->psc.fwctrl_lps)
+               pr_info("rtl8192ce: FW Power Save off (module option)\n");
        rtlpriv->psc.reg_fwctrl_lps = 3;
        rtlpriv->psc.reg_max_lps_awakeintvl = 5;
        /* for ASPM, you can close aspm through
@@ -378,6 +382,7 @@ MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids);
 
 MODULE_AUTHOR("lizhaoming      <[email protected]>");
 MODULE_AUTHOR("Realtek WlanFAE <[email protected]>");
+MODULE_AUTHOR("Larry Finger    <[email protected]>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless");
 MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin");
@@ -386,11 +391,10 @@ module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444);
 module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444);
 module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
 module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
-MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
-MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
-MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is "
-                "open)\n");
-
+MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
+MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
 
 static struct pci_driver rtl92se_driver = {
        .name = KBUILD_MODNAME,
index d9aeae7f8bdbed1e4ec68f7ab8138a2969c22802..ba137da082b5a223e86e073f93e8cc1cff319243 100644 (file)
@@ -126,7 +126,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
        bool in_powersavemode = false;
        bool is_cck_rate;
 
-       is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+       is_cck_rate = SE_RX_HAL_IS_CCK_RATE(pdesc);
        pstats->packet_matchbssid = packet_match_bssid;
        pstats->packet_toself = packet_toself;
        pstats->is_cck = is_cck_rate;
index 8a9091968f316f449a5c7380e9ea7a738db3c76f..615f6b4463e6977b50e345f43778b4737c8a0bfe 100644 (file)
@@ -165,6 +165,12 @@ enum hardware_type {
 #define IS_HARDWARE_TYPE_8723U(rtlhal)                 \
        (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
 
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+       (_pdesc->rxmcs == DESC92_RATE1M ||              \
+        _pdesc->rxmcs == DESC92_RATE2M ||              \
+        _pdesc->rxmcs == DESC92_RATE5_5M ||            \
+        _pdesc->rxmcs == DESC92_RATE11M)
+
 enum scan_operation_backup_opt {
        SCAN_OPT_BACKUP = 0,
        SCAN_OPT_RESTORE,
index ef8370edace709f8c1fb3437403fe4447f7d7d12..ad87a1ac6462aab40befe12db72eef99fcc52f5b 100644 (file)
@@ -140,8 +140,6 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
        auth->sleep_auth = sleep_auth;
 
        ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
-       if (ret < 0)
-               return ret;
 
 out:
        kfree(auth);
@@ -681,10 +679,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl)
 
        ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD,
                                   detection, sizeof(*detection));
-       if (ret < 0) {
+       if (ret < 0)
                wl1251_warning("failed to set cca threshold: %d", ret);
-               return ret;
-       }
 
 out:
        kfree(detection);
index 81f164bc4888f2389d86764c4c66a64295e9f18d..d14d69d733a07fc9bd9e77c4e2192e42ea8f83c9 100644 (file)
@@ -241,7 +241,7 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
        if (ret < 0) {
                wl1251_error("tx %s cmd for channel %d failed",
                             enable ? "start" : "stop", channel);
-               return ret;
+               goto out;
        }
 
        wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
index 07bcb1548d8b2e51ec758372d7ec0a5b52fcbc2d..3fe388b87c2e339204833eff359eb22b6a0ccba7 100644 (file)
@@ -19,16 +19,6 @@ config WL12XX
          If you choose to build a module, it will be called wl12xx. Say N if
          unsure.
 
-config WL12XX_HT
-        bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)"
-        depends on WL12XX && EXPERIMENTAL
-        default n
-        ---help---
-          This will enable 802.11 HT support in the wl12xx module.
-
-         That configuration is temporary due to the code incomplete and
-         still in testing process.
-
 config WL12XX_SPI
        tristate "TI wl12xx SPI support"
        depends on WL12XX && SPI_MASTER
index e047594794aa16408f85c73566ff25d4d65e0288..399849eeb247cd3014d3827654b14e28dbeaa184 100644 (file)
@@ -78,8 +78,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
        auth->sleep_auth = sleep_auth;
 
        ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
-       if (ret < 0)
-               return ret;
 
 out:
        kfree(auth);
@@ -576,10 +574,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
 
        ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
                                   detection, sizeof(*detection));
-       if (ret < 0) {
+       if (ret < 0)
                wl1271_warning("failed to set cca threshold: %d", ret);
-               return ret;
-       }
 
 out:
        kfree(detection);
@@ -1691,3 +1687,43 @@ out:
        kfree(acx);
        return ret;
 }
+
+int wl12xx_acx_config_hangover(struct wl1271 *wl)
+{
+       struct wl12xx_acx_config_hangover *acx;
+       struct conf_hangover_settings *conf = &wl->conf.hangover;
+       int ret;
+
+       wl1271_debug(DEBUG_ACX, "acx config hangover");
+
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       acx->recover_time = cpu_to_le32(conf->recover_time);
+       acx->hangover_period = conf->hangover_period;
+       acx->dynamic_mode = conf->dynamic_mode;
+       acx->early_termination_mode = conf->early_termination_mode;
+       acx->max_period = conf->max_period;
+       acx->min_period = conf->min_period;
+       acx->increase_delta = conf->increase_delta;
+       acx->decrease_delta = conf->decrease_delta;
+       acx->quiet_time = conf->quiet_time;
+       acx->increase_time = conf->increase_time;
+       acx->window_size = acx->window_size;
+
+       ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx,
+                                  sizeof(*acx));
+
+       if (ret < 0) {
+               wl1271_warning("acx config hangover failed: %d", ret);
+               goto out;
+       }
+
+out:
+       kfree(acx);
+       return ret;
+
+}
index 758c596f62f6042477397b18468151983e3b2a83..556ee4e282d566317a1d9c9244469844d4bd11fe 100644 (file)
@@ -1144,6 +1144,23 @@ struct wl12xx_acx_set_rate_mgmt_params {
        u8 padding2[2];
 } __packed;
 
+struct wl12xx_acx_config_hangover {
+       struct acx_header header;
+
+       __le32 recover_time;
+       u8 hangover_period;
+       u8 dynamic_mode;
+       u8 early_termination_mode;
+       u8 max_period;
+       u8 min_period;
+       u8 increase_delta;
+       u8 decrease_delta;
+       u8 quiet_time;
+       u8 increase_time;
+       u8 window_size;
+       u8 padding[2];
+} __packed;
+
 enum {
        ACX_WAKE_UP_CONDITIONS      = 0x0002,
        ACX_MEM_CFG                 = 0x0003,
@@ -1281,5 +1298,6 @@ int wl1271_acx_config_ps(struct wl1271 *wl);
 int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
+int wl12xx_acx_config_hangover(struct wl1271 *wl);
 
 #endif /* __WL1271_ACX_H__ */
index cc70422c0575a2f89056ae08c22c2c32c0f6db3b..6d5664bfc37dcffa9deaf904a092b8d59e50cbb0 100644 (file)
@@ -294,9 +294,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
                 */
                if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
                    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
-                       /* for now 11a is unsupported in AP mode */
-                       if (wl->bss_type != BSS_TYPE_AP_BSS &&
-                           nvs->general_params.dual_mode_select)
+                       if (nvs->general_params.dual_mode_select)
                                wl->enable_11a = true;
                }
 
index 817bc183bc8372f0a7fb22a286e977229862f2d6..084262f169b2e3469b3150f21657a08ce0f8a758 100644 (file)
@@ -895,7 +895,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
        struct acx_header *acx = buf;
        int ret;
 
-       wl1271_debug(DEBUG_CMD, "cmd configure");
+       wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
 
        acx->id = cpu_to_le16(id);
 
@@ -1413,7 +1413,7 @@ out:
 int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 {
        struct wl12xx_cmd_add_peer *cmd;
-       int ret;
+       int i, ret;
        u32 sta_rates;
 
        wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
@@ -1424,15 +1424,19 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
                goto out;
        }
 
-       /* currently we don't support UAPSD */
-       cmd->sp_len = 0;
-
        memcpy(cmd->addr, sta->addr, ETH_ALEN);
        cmd->bss_index = WL1271_AP_BSS_INDEX;
        cmd->aid = sta->aid;
        cmd->hlid = hlid;
+       cmd->sp_len = sta->max_sp;
        cmd->wmm = sta->wme ? 1 : 0;
 
+       for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)
+               if (sta->wme && (sta->uapsd_queues & BIT(i)))
+                       cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER;
+               else
+                       cmd->psd_type[i] = WL1271_PSD_LEGACY;
+
        sta_rates = sta->supp_rates[wl->band];
        if (sta->ht_cap.ht_supported)
                sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
@@ -1440,7 +1444,8 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
        cmd->supported_rates =
                cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates));
 
-       wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates);
+       wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
+                    cmd->supported_rates, sta->uapsd_queues);
 
        ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
        if (ret < 0) {
index 22c2f373dd04b51d9593df45f0769767c05a4277..8e4d11ec0c55fd7cda5b90a1751a48031d7abb41 100644 (file)
@@ -591,6 +591,13 @@ enum wl12xx_ssid_type {
        WL12XX_SSID_TYPE_ANY = 2,
 };
 
+enum wl1271_psd_type {
+       WL1271_PSD_LEGACY = 0,
+       WL1271_PSD_UPSD_TRIGGER = 1,
+       WL1271_PSD_LEGACY_PSPOLL = 2,
+       WL1271_PSD_SAPSD = 3
+};
+
 struct wl12xx_cmd_add_peer {
        struct wl1271_cmd_header header;
 
index 82f205c4334266e1eb83743c80570f18381796e9..45428a21f9e2af980c843726acfeab407c284d55 100644 (file)
@@ -915,14 +915,6 @@ struct conf_conn_settings {
         */
        u8 psm_entry_nullfunc_retries;
 
-       /*
-        * Specifies the time to linger in active mode after successfully
-        * transmitting the PSM entry null-func frame.
-        *
-        * Range 0 - 255 TU's
-        */
-       u8 psm_entry_hangover_period;
-
        /*
         *
         * Specifies the interval of the connection keep-alive null-func
@@ -1236,6 +1228,20 @@ struct conf_rate_policy_settings {
        u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
 };
 
+struct conf_hangover_settings {
+       u32 recover_time;
+       u8 hangover_period;
+       u8 dynamic_mode;
+       u8 early_termination_mode;
+       u8 max_period;
+       u8 min_period;
+       u8 increase_delta;
+       u8 decrease_delta;
+       u8 quiet_time;
+       u8 increase_time;
+       u8 window_size;
+};
+
 struct conf_drv_settings {
        struct conf_sg_settings sg;
        struct conf_rx_settings rx;
@@ -1254,6 +1260,7 @@ struct conf_drv_settings {
        struct conf_rx_streaming_settings rx_streaming;
        struct conf_fwlog fwlog;
        struct conf_rate_policy_settings rate;
+       struct conf_hangover_settings hangover;
        u8 hci_io_ds;
 };
 
index d59354f537021f7b6ebbfeb5c4a77bf25c762a5e..3999fd528302cfbadd26a7f9fe8862caaf175656 100644 (file)
@@ -265,18 +265,10 @@ static ssize_t gpio_power_write(struct file *file,
                           size_t count, loff_t *ppos)
 {
        struct wl1271 *wl = file->private_data;
-       char buf[10];
-       size_t len;
        unsigned long value;
        int ret;
 
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len)) {
-               return -EFAULT;
-       }
-       buf[len] = '\0';
-
-       ret = kstrtoul(buf, 0, &value);
+       ret = kstrtoul_from_user(user_buf, count, 10, &value);
        if (ret < 0) {
                wl1271_warning("illegal value in gpio_power");
                return -EINVAL;
@@ -427,17 +419,10 @@ static ssize_t dtim_interval_write(struct file *file,
                                   size_t count, loff_t *ppos)
 {
        struct wl1271 *wl = file->private_data;
-       char buf[10];
-       size_t len;
        unsigned long value;
        int ret;
 
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-       buf[len] = '\0';
-
-       ret = kstrtoul(buf, 0, &value);
+       ret = kstrtoul_from_user(user_buf, count, 10, &value);
        if (ret < 0) {
                wl1271_warning("illegal value for dtim_interval");
                return -EINVAL;
@@ -492,17 +477,10 @@ static ssize_t beacon_interval_write(struct file *file,
                                     size_t count, loff_t *ppos)
 {
        struct wl1271 *wl = file->private_data;
-       char buf[10];
-       size_t len;
        unsigned long value;
        int ret;
 
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-       buf[len] = '\0';
-
-       ret = kstrtoul(buf, 0, &value);
+       ret = kstrtoul_from_user(user_buf, count, 10, &value);
        if (ret < 0) {
                wl1271_warning("illegal value for beacon_interval");
                return -EINVAL;
@@ -542,17 +520,10 @@ static ssize_t rx_streaming_interval_write(struct file *file,
                           size_t count, loff_t *ppos)
 {
        struct wl1271 *wl = file->private_data;
-       char buf[10];
-       size_t len;
        unsigned long value;
        int ret;
 
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-       buf[len] = '\0';
-
-       ret = kstrtoul(buf, 0, &value);
+       ret = kstrtoul_from_user(user_buf, count, 10, &value);
        if (ret < 0) {
                wl1271_warning("illegal value in rx_streaming_interval!");
                return -EINVAL;
@@ -601,17 +572,10 @@ static ssize_t rx_streaming_always_write(struct file *file,
                           size_t count, loff_t *ppos)
 {
        struct wl1271 *wl = file->private_data;
-       char buf[10];
-       size_t len;
        unsigned long value;
        int ret;
 
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-       buf[len] = '\0';
-
-       ret = kstrtoul(buf, 0, &value);
+       ret = kstrtoul_from_user(user_buf, count, 10, &value);
        if (ret < 0) {
                wl1271_warning("illegal value in rx_streaming_write!");
                return -EINVAL;
@@ -655,6 +619,47 @@ static const struct file_operations rx_streaming_always_ops = {
        .llseek = default_llseek,
 };
 
+static ssize_t beacon_filtering_write(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct wl1271 *wl = file->private_data;
+       char buf[10];
+       size_t len;
+       unsigned long value;
+       int ret;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+
+       ret = kstrtoul(buf, 0, &value);
+       if (ret < 0) {
+               wl1271_warning("illegal value for beacon_filtering!");
+               return -EINVAL;
+       }
+
+       mutex_lock(&wl->mutex);
+
+       ret = wl1271_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
+       ret = wl1271_acx_beacon_filter_opt(wl, !!value);
+
+       wl1271_ps_elp_sleep(wl);
+out:
+       mutex_unlock(&wl->mutex);
+       return count;
+}
+
+static const struct file_operations beacon_filtering_ops = {
+       .write = beacon_filtering_write,
+       .open = wl1271_open_file_generic,
+       .llseek = default_llseek,
+};
+
 static int wl1271_debugfs_add_files(struct wl1271 *wl,
                                     struct dentry *rootdir)
 {
@@ -767,6 +772,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
        DEBUGFS_ADD(driver_state, rootdir);
        DEBUGFS_ADD(dtim_interval, rootdir);
        DEBUGFS_ADD(beacon_interval, rootdir);
+       DEBUGFS_ADD(beacon_filtering, rootdir);
 
        streaming = debugfs_create_dir("rx_streaming", rootdir);
        if (!streaming || IS_ERR(streaming))
index 0bd7b020a42025f44e306d39de7819153a21fb41..c73fe4c6b6167652a220ede10dccb31e662613a9 100644 (file)
@@ -171,19 +171,26 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,
        wl->last_rssi_event = event;
 }
 
-static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
+static void wl1271_stop_ba_event(struct wl1271 *wl)
 {
-       /* Convert the value to bool */
-       wl->ba_allowed = !!ba_allowed;
-
-       /*
-        * Return in case:
-        * there are not BA open or the event indication is to allowed BA
-        */
-       if ((!wl->ba_rx_bitmap) || (wl->ba_allowed))
-               return;
+       if (wl->bss_type != BSS_TYPE_AP_BSS) {
+               if (!wl->ba_rx_bitmap)
+                       return;
+               ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap,
+                                            wl->bssid);
+       } else {
+               int i;
+               struct wl1271_link *lnk;
+               for (i = WL1271_AP_STA_HLID_START; i < WL12XX_MAX_LINKS; i++) {
+                       lnk = &wl->links[i];
+                       if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
+                               continue;
 
-       ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
+                       ieee80211_stop_rx_ba_session(wl->vif,
+                                                    lnk->ba_bitmap,
+                                                    lnk->addr);
+               }
+       }
 }
 
 static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
@@ -283,12 +290,14 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
                        wl1271_event_rssi_trigger(wl, mbox);
        }
 
-       if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
+       if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
                wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
                             "ba_allowed = 0x%x", mbox->rx_ba_allowed);
 
-               if (wl->vif)
-                       wl1271_stop_ba_event(wl, mbox->rx_ba_allowed);
+               wl->ba_allowed = !!mbox->rx_ba_allowed;
+
+               if (wl->vif && !wl->ba_allowed)
+                       wl1271_stop_ba_event(wl);
        }
 
        if ((vector & DUMMY_PACKET_EVENT_ID)) {
index b13bebea95e00c0cbe9070ad19847b92ca94a995..09515f5e5e1dffc30647d19142ab160db5e9d335 100644 (file)
@@ -707,6 +707,11 @@ int wl1271_hw_init(struct wl1271 *wl)
        if (ret < 0)
                goto out_free_memmap;
 
+       /* configure hangover */
+       ret = wl12xx_acx_config_hangover(wl);
+       if (ret < 0)
+               goto out_free_memmap;
+
        return 0;
 
  out_free_memmap:
index 82f4408e89ad278c575928d9266a5bb32305a044..680f5582618efad8385ca03b9793566970fd4d67 100644 (file)
@@ -236,10 +236,9 @@ static struct conf_drv_settings default_conf = {
                .ps_poll_recovery_period     = 700,
                .bet_enable                  = CONF_BET_MODE_ENABLE,
                .bet_max_consecutive         = 50,
-               .psm_entry_retries           = 5,
+               .psm_entry_retries           = 8,
                .psm_exit_retries            = 16,
                .psm_entry_nullfunc_retries  = 3,
-               .psm_entry_hangover_period   = 1,
                .keep_alive_interval         = 55000,
                .max_listen_interval         = 20,
        },
@@ -267,8 +266,8 @@ static struct conf_drv_settings default_conf = {
        },
        .sched_scan = {
                /* sched_scan requires dwell times in TU instead of TU/1000 */
-               .min_dwell_time_active = 8,
-               .max_dwell_time_active = 30,
+               .min_dwell_time_active = 30,
+               .max_dwell_time_active = 60,
                .dwell_time_passive    = 100,
                .dwell_time_dfs        = 150,
                .num_probe_reqs        = 2,
@@ -359,9 +358,23 @@ static struct conf_drv_settings default_conf = {
                        0x00, 0x00, 0x00,
                },
        },
+       .hangover = {
+               .recover_time               = 0,
+               .hangover_period            = 20,
+               .dynamic_mode               = 1,
+               .early_termination_mode     = 1,
+               .max_period                 = 20,
+               .min_period                 = 1,
+               .increase_delta             = 1,
+               .decrease_delta             = 2,
+               .quiet_time                 = 4,
+               .increase_time              = 1,
+               .window_size                = 16,
+       },
 };
 
 static char *fwlog_param;
+static bool bug_on_recovery;
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
                                         bool reset_tx_queues);
@@ -757,13 +770,14 @@ static int wl1271_plt_init(struct wl1271 *wl)
 
 static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
 {
-       bool fw_ps;
+       bool fw_ps, single_sta;
 
        /* only regulate station links */
        if (hlid < WL1271_AP_STA_HLID_START)
                return;
 
        fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+       single_sta = (wl->active_sta_count == 1);
 
        /*
         * Wake up from high level PS if the STA is asleep with too little
@@ -772,8 +786,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
        if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_end(wl, hlid);
 
-       /* Start high-level PS if the STA is asleep with enough blocks in FW */
-       else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
+       /*
+        * Start high-level PS if the STA is asleep with enough blocks in FW.
+        * Make an exception if this is the only connected station. In this
+        * case FW-memory congestion is not a problem.
+        */
+       else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_start(wl, hlid, true);
 }
 
@@ -1213,6 +1231,8 @@ static void wl1271_recovery_work(struct work_struct *work)
        wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
                    wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
 
+       BUG_ON(bug_on_recovery);
+
        /*
         * Advance security sequence number to overcome potential progress
         * in the firmware during recovery. This doens't hurt if the network is
@@ -1222,9 +1242,6 @@ static void wl1271_recovery_work(struct work_struct *work)
            test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
                wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING;
 
-       if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-               ieee80211_connection_loss(wl->vif);
-
        /* Prevent spurious TX during FW restart */
        ieee80211_stop_queues(wl->hw);
 
@@ -1528,7 +1545,13 @@ out:
 int wl1271_tx_dummy_packet(struct wl1271 *wl)
 {
        unsigned long flags;
-       int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
+       int q;
+
+       /* no need to queue a new dummy packet if one is already pending */
+       if (test_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags))
+               return 0;
+
+       q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));
 
        spin_lock_irqsave(&wl->wl_lock, flags);
        set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
@@ -1802,10 +1825,16 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl)
 {
        switch (wl->bss_type) {
        case BSS_TYPE_AP_BSS:
-               return WL1271_ROLE_AP;
+               if (wl->p2p)
+                       return WL1271_ROLE_P2P_GO;
+               else
+                       return WL1271_ROLE_AP;
 
        case BSS_TYPE_STA_BSS:
-               return WL1271_ROLE_STA;
+               if (wl->p2p)
+                       return WL1271_ROLE_P2P_CL;
+               else
+                       return WL1271_ROLE_STA;
 
        case BSS_TYPE_IBSS:
                return WL1271_ROLE_IBSS;
@@ -1827,7 +1856,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
        bool booted = false;
 
        wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
-                    vif->type, vif->addr);
+                    ieee80211_vif_type_p2p(vif), vif->addr);
 
        mutex_lock(&wl->mutex);
        if (wl->vif) {
@@ -1847,7 +1876,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       switch (vif->type) {
+       switch (ieee80211_vif_type_p2p(vif)) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+               wl->p2p = 1;
+               /* fall-through */
        case NL80211_IFTYPE_STATION:
                wl->bss_type = BSS_TYPE_STA_BSS;
                wl->set_bss_type = BSS_TYPE_STA_BSS;
@@ -1856,6 +1888,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
                wl->bss_type = BSS_TYPE_IBSS;
                wl->set_bss_type = BSS_TYPE_STA_BSS;
                break;
+       case NL80211_IFTYPE_P2P_GO:
+               wl->p2p = 1;
+               /* fall-through */
        case NL80211_IFTYPE_AP:
                wl->bss_type = BSS_TYPE_AP_BSS;
                break;
@@ -2051,6 +2086,7 @@ deinit:
        wl->ssid_len = 0;
        wl->bss_type = MAX_BSS_TYPE;
        wl->set_bss_type = MAX_BSS_TYPE;
+       wl->p2p = 0;
        wl->band = IEEE80211_BAND_2GHZ;
 
        wl->rx_counter = 0;
@@ -2064,6 +2100,7 @@ deinit:
        wl->session_counter = 0;
        wl->rate_set = CONF_TX_RATE_MASK_BASIC;
        wl->vif = NULL;
+       wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
        wl1271_free_ap_keys(wl);
        memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
        wl->ap_fw_ps_map = 0;
@@ -2074,6 +2111,7 @@ deinit:
        memset(wl->roles_map, 0, sizeof(wl->roles_map));
        memset(wl->links_map, 0, sizeof(wl->links_map));
        memset(wl->roc_map, 0, sizeof(wl->roc_map));
+       wl->active_sta_count = 0;
 
        /* The system link is always allocated */
        __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
@@ -2199,10 +2237,14 @@ out:
 
 static void wl1271_set_band_rate(struct wl1271 *wl)
 {
-       if (wl->band == IEEE80211_BAND_2GHZ)
+       if (wl->band == IEEE80211_BAND_2GHZ) {
                wl->basic_rate_set = wl->conf.tx.basic_rate;
-       else
+               wl->rate_set = wl->conf.tx.basic_rate;
+       } else {
                wl->basic_rate_set = wl->conf.tx.basic_rate_5;
+               wl->rate_set = wl->conf.tx.basic_rate_5;
+       }
+
 }
 
 static bool wl12xx_is_roc(struct wl1271 *wl)
@@ -2653,6 +2695,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff
                };
 
+               /*
+                * A STA set to GEM cipher requires 2 tx spare blocks.
+                * Return to default value when GEM cipher key is removed
+                */
+               if (key_type == KEY_GEM) {
+                       if (action == KEY_ADD_OR_REPLACE)
+                               wl->tx_spare_blocks = 2;
+                       else if (action == KEY_REMOVE)
+                               wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+               }
+
                addr = sta ? sta->addr : bcast_addr;
 
                if (is_zero_ether_addr(addr)) {
@@ -3345,19 +3398,6 @@ sta_not_found:
                        ret = wl1271_acx_conn_monit_params(wl, true);
                        if (ret < 0)
                                goto out;
-
-                       /* If we want to go in PSM but we're not there yet */
-                       if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
-                           !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-                               enum wl1271_cmd_ps_mode mode;
-
-                               mode = STATION_POWER_SAVE_MODE;
-                               ret = wl1271_ps_set_mode(wl, mode,
-                                                        wl->basic_rate,
-                                                        true);
-                               if (ret < 0)
-                                       goto out;
-                       }
                } else {
                        /* use defaults when not associated */
                        bool was_assoc =
@@ -3501,6 +3541,19 @@ sta_not_found:
                        if (ret < 0)
                                goto out;
                }
+
+               /* If we want to go in PSM but we're not there yet */
+               if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
+                   !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+                       enum wl1271_cmd_ps_mode mode;
+
+                       mode = STATION_POWER_SAVE_MODE;
+                       ret = wl1271_ps_set_mode(wl, mode,
+                                                wl->basic_rate,
+                                                true);
+                       if (ret < 0)
+                               goto out;
+               }
        }
 
        /* Handle new association with HT. Do this after join. */
@@ -3713,14 +3766,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
        wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
        *hlid = wl_sta->hlid;
        memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
+       wl->active_sta_count++;
        return 0;
 }
 
-static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
 {
        int id = hlid - WL1271_AP_STA_HLID_START;
 
-       if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+       if (hlid < WL1271_AP_STA_HLID_START)
+               return;
+
+       if (!test_bit(id, wl->ap_hlid_map))
                return;
 
        clear_bit(id, wl->ap_hlid_map);
@@ -3729,6 +3786,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
        wl1271_tx_reset_link_queues(wl, hlid);
        __clear_bit(hlid, &wl->ap_ps_map);
        __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+       wl->active_sta_count--;
 }
 
 static int wl1271_op_sta_add(struct ieee80211_hw *hw,
@@ -4050,7 +4108,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
 /* 11n STA capabilities */
 #define HW_RX_HIGHEST_RATE     72
 
-#ifdef CONFIG_WL12XX_HT
 #define WL12XX_HT_CAP { \
        .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
               (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
@@ -4063,11 +4120,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = {
                .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
                }, \
 }
-#else
-#define WL12XX_HT_CAP { \
-       .ht_supported = false, \
-}
-#endif
 
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_supported_band wl1271_band_2ghz = {
@@ -4467,14 +4519,19 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
                IEEE80211_HW_SUPPORTS_CQM_RSSI |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                IEEE80211_HW_SPECTRUM_MGMT |
-               IEEE80211_HW_AP_LINK_PS;
+               IEEE80211_HW_AP_LINK_PS |
+               IEEE80211_HW_AMPDU_AGGREGATION |
+               IEEE80211_HW_TX_AMPDU_SETUP_IN_HW;
 
        wl->hw->wiphy->cipher_suites = cipher_suites;
        wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
        wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+               BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
        wl->hw->wiphy->max_scan_ssids = 1;
+       wl->hw->wiphy->max_sched_scan_ssids = 16;
+       wl->hw->wiphy->max_match_sets = 16;
        /*
         * Maximum length of elements in scanning probe request templates
         * should be the maximum length possible for a template, without
@@ -4483,6 +4540,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
        wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
                        sizeof(struct ieee80211_header);
 
+       wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+
        /* make sure all our channels fit in the scanned_ch bitmask */
        BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
                     ARRAY_SIZE(wl1271_channels_5ghz) >
@@ -4599,6 +4658,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->sched_scanning = false;
        wl->tx_security_seq = 0;
        wl->tx_security_last_seq_lsb = 0;
+       wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
        wl->role_id = WL12XX_INVALID_ROLE_ID;
        wl->system_hlid = WL12XX_SYSTEM_HLID;
        wl->sta_hlid = WL12XX_INVALID_LINK_ID;
@@ -4607,6 +4667,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->session_counter = 0;
        wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
        wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
+       wl->active_sta_count = 0;
        setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
                    (unsigned long) wl);
        wl->fwlog_size = 0;
@@ -4758,6 +4819,9 @@ module_param_named(fwlog, fwlog_param, charp, 0);
 MODULE_PARM_DESC(keymap,
                 "FW logger options: continuous, ondemand, dbgpins or disable");
 
+module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <[email protected]>");
 MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
index 4b720b1b9f65666de26aa9a91f56df1e101116e3..c15ebf2efd40a6e71fc710da1de8206c98c5294d 100644 (file)
@@ -199,15 +199,19 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
        unsigned long flags;
        int filtered[NUM_TX_QUEUES];
 
-       /* filter all frames currently the low level queus for this hlid */
+       /* filter all frames currently in the low level queues for this hlid */
        for (i = 0; i < NUM_TX_QUEUES; i++) {
                filtered[i] = 0;
                while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+                       filtered[i]++;
+
+                       if (WARN_ON(wl12xx_is_dummy_packet(wl, skb)))
+                               continue;
+
                        info = IEEE80211_SKB_CB(skb);
                        info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
                        info->status.rates[0].idx = -1;
                        ieee80211_tx_status_ni(wl->hw, skb);
-                       filtered[i]++;
                }
        }
 
index 78d8410da1f4586c947912c8ec9086b7a0fd81dc..dee4cfe9ccc1ed87a9979418e12bfc1f46ace708 100644 (file)
@@ -66,11 +66,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
 
        status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
 
-#ifdef CONFIG_WL12XX_HT
        /* 11n support */
        if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
                status->flag |= RX_FLAG_HT;
-#endif
 
        status->signal = desc->rssi;
 
@@ -107,6 +105,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        u8 beacon = 0;
        u8 is_data = 0;
        u8 reserved = unaligned ? NET_IP_ALIGN : 0;
+       u16 seq_num;
 
        /*
         * In PLT mode we seem to get frames and mac80211 warns about them,
@@ -169,9 +168,11 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
 
        wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
 
-       wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb,
+       seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+       wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
                     skb->len - desc->pad_len,
-                    beacon ? "beacon" : "");
+                    beacon ? "beacon" : "",
+                    seq_num);
 
        skb_trim(skb, skb->len - desc->pad_len);
 
index 7229eaa8901807576ddb5e2ecdd820b61763a4f0..eeccc9f095bb28cb5e4ff408b1ea6453e210265d 100644 (file)
@@ -65,8 +65,9 @@ void wl1271_scan_complete_work(struct work_struct *work)
        /* return to ROC if needed */
        is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
        is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
-       if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
-           (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) {
+       if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
+            (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) &&
+           !test_bit(wl->dev_role_id, wl->roc_map)) {
                /* restore remain on channel */
                wl12xx_cmd_role_start_dev(wl);
                wl12xx_roc(wl, wl->dev_role_id);
@@ -164,9 +165,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
                goto out;
        }
 
-       /* We always use high priority scans */
-       scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
-
        /* No SSIDs means that we have a forced passive scan */
        if (passive || wl->scan.req->n_ssids == 0)
                scan_options |= WL1271_SCAN_OPT_PASSIVE;
@@ -473,6 +471,105 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
                cfg->passive[2] || cfg->active[2];
 }
 
+/* Returns the scan type to be used or a negative value on error */
+static int
+wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
+                                struct cfg80211_sched_scan_request *req)
+{
+       struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
+       struct cfg80211_match_set *sets = req->match_sets;
+       struct cfg80211_ssid *ssids = req->ssids;
+       int ret = 0, type, i, j, n_match_ssids = 0;
+
+       wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+
+       /* count the match sets that contain SSIDs */
+       for (i = 0; i < req->n_match_sets; i++)
+               if (sets[i].ssid.ssid_len > 0)
+                       n_match_ssids++;
+
+       /* No filter, no ssids or only bcast ssid */
+       if (!n_match_ssids &&
+           (!req->n_ssids ||
+            (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
+               type = SCAN_SSID_FILTER_ANY;
+               goto out;
+       }
+
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (!n_match_ssids) {
+               /* No filter, with ssids */
+               type = SCAN_SSID_FILTER_DISABLED;
+
+               for (i = 0; i < req->n_ssids; i++) {
+                       cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
+                               SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
+                       cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
+                       memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
+                              ssids[i].ssid_len);
+                       cmd->n_ssids++;
+               }
+       } else {
+               type = SCAN_SSID_FILTER_LIST;
+
+               /* Add all SSIDs from the filters */
+               for (i = 0; i < req->n_match_sets; i++) {
+                       /* ignore sets without SSIDs */
+                       if (!sets[i].ssid.ssid_len)
+                               continue;
+
+                       cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
+                       cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
+                       memcpy(cmd->ssids[cmd->n_ssids].ssid,
+                              sets[i].ssid.ssid, sets[i].ssid.ssid_len);
+                       cmd->n_ssids++;
+               }
+               if ((req->n_ssids > 1) ||
+                   (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
+                       /*
+                        * Mark all the SSIDs passed in the SSID list as HIDDEN,
+                        * so they're used in probe requests.
+                        */
+                       for (i = 0; i < req->n_ssids; i++) {
+                               for (j = 0; j < cmd->n_ssids; j++)
+                                       if (!memcmp(req->ssids[i].ssid,
+                                                  cmd->ssids[j].ssid,
+                                                  req->ssids[i].ssid_len)) {
+                                               cmd->ssids[j].type =
+                                                       SCAN_SSID_TYPE_HIDDEN;
+                                               break;
+                                       }
+                               /* Fail if SSID isn't present in the filters */
+                               if (j == req->n_ssids) {
+                                       ret = -EINVAL;
+                                       goto out_free;
+                               }
+                       }
+               }
+       }
+
+       wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
+
+       ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
+                             sizeof(*cmd), 0);
+       if (ret < 0) {
+               wl1271_error("cmd sched scan ssid list failed");
+               goto out_free;
+       }
+
+out_free:
+       kfree(cmd);
+out:
+       if (ret < 0)
+               return ret;
+       return type;
+}
+
 int wl1271_scan_sched_scan_config(struct wl1271 *wl,
                                  struct cfg80211_sched_scan_request *req,
                                  struct ieee80211_sched_scan_ies *ies)
@@ -504,15 +601,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
        for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
                cfg->intervals[i] = cpu_to_le32(req->interval);
 
-       if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
-               cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
-               cfg->ssid_len = req->ssids[0].ssid_len;
-               memcpy(cfg->ssid, req->ssids[0].ssid,
-                      req->ssids[0].ssid_len);
-       } else {
-               cfg->filter_type = SCAN_SSID_FILTER_ANY;
-               cfg->ssid_len = 0;
-       }
+       cfg->ssid_len = 0;
+       ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
+       if (ret < 0)
+               goto out;
+
+       cfg->filter_type = ret;
+
+       wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
 
        if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
                wl1271_error("scan channel list is empty");
index ac2e5661397c89816ad12eac1224a99d776fb785..516a8980723c3c5ec90773db35ab24d2163ccb3f 100644 (file)
@@ -164,7 +164,7 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
        /* If enabled, tell runtime PM not to power off the card */
        if (pm_runtime_enabled(&func->dev)) {
                ret = pm_runtime_get_sync(&func->dev);
-               if (ret)
+               if (ret < 0)
                        goto out;
        } else {
                /* Runtime PM is disabled: power up the card manually */
index 5d5e1ef87206a4e1722510084ba4cab2783cf0bd..4ae8effaee22828acf9565d47d9ad599f4ac9c00 100644 (file)
@@ -36,7 +36,6 @@ enum wl1271_tm_commands {
        WL1271_TM_CMD_TEST,
        WL1271_TM_CMD_INTERROGATE,
        WL1271_TM_CMD_CONFIGURE,
-       WL1271_TM_CMD_NVS_PUSH,
        WL1271_TM_CMD_SET_PLT_MODE,
        WL1271_TM_CMD_RECOVER,
 
@@ -139,12 +138,15 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
 
        if (ret < 0) {
                wl1271_warning("testmode cmd interrogate failed: %d", ret);
+               kfree(cmd);
                return ret;
        }
 
        skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
-       if (!skb)
+       if (!skb) {
+               kfree(cmd);
                return -ENOMEM;
+       }
 
        NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
 
@@ -187,48 +189,6 @@ static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
        return 0;
 }
 
-static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
-{
-       int ret = 0;
-       size_t len;
-       void *buf;
-
-       wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
-
-       if (!tb[WL1271_TM_ATTR_DATA])
-               return -EINVAL;
-
-       buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
-       len = nla_len(tb[WL1271_TM_ATTR_DATA]);
-
-       mutex_lock(&wl->mutex);
-
-       kfree(wl->nvs);
-
-       if ((wl->chip.id == CHIP_ID_1283_PG20) &&
-           (len != sizeof(struct wl128x_nvs_file)))
-               return -EINVAL;
-       else if (len != sizeof(struct wl1271_nvs_file))
-               return -EINVAL;
-
-       wl->nvs = kzalloc(len, GFP_KERNEL);
-       if (!wl->nvs) {
-               wl1271_error("could not allocate memory for the nvs file");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memcpy(wl->nvs, buf, len);
-       wl->nvs_len = len;
-
-       wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
-
-out:
-       mutex_unlock(&wl->mutex);
-
-       return ret;
-}
-
 static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
 {
        u32 val;
@@ -285,8 +245,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
                return wl1271_tm_cmd_interrogate(wl, tb);
        case WL1271_TM_CMD_CONFIGURE:
                return wl1271_tm_cmd_configure(wl, tb);
-       case WL1271_TM_CMD_NVS_PUSH:
-               return wl1271_tm_cmd_nvs_push(wl, tb);
        case WL1271_TM_CMD_SET_PLT_MODE:
                return wl1271_tm_cmd_set_plt_mode(wl, tb);
        case WL1271_TM_CMD_RECOVER:
index 0f1578577b1a7be0148c1ef5cff5d4bb8016a752..9d4157ce0950ea0dd964bbb21a8f9c5027f03497 100644 (file)
@@ -30,6 +30,7 @@
 #include "reg.h"
 #include "ps.h"
 #include "tx.h"
+#include "event.h"
 
 static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
 {
@@ -125,25 +126,31 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 
 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 {
-       bool fw_ps;
+       bool fw_ps, single_sta;
        u8 tx_pkts;
 
        /* only regulate station links */
        if (hlid < WL1271_AP_STA_HLID_START)
                return;
 
+       if (WARN_ON(!wl1271_is_active_sta(wl, hlid)))
+           return;
+
        fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
        tx_pkts = wl->links[hlid].allocated_pkts;
+       single_sta = (wl->active_sta_count == 1);
 
        /*
         * if in FW PS and there is enough data in FW we can put the link
         * into high-level PS and clean out its TX queues.
+        * Make an exception if this is the only connected station. In this
+        * case FW-memory congestion is not a problem.
         */
-       if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
+       if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_start(wl, hlid, true);
 }
 
-static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
 {
        return wl->dummy_packet == skb;
 }
@@ -204,9 +211,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
        u32 len;
        u32 total_blocks;
        int id, ret = -EBUSY, ac;
-
-       /* we use 1 spare block */
-       u32 spare_blocks = 1;
+       u32 spare_blocks = wl->tx_spare_blocks;
 
        if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
                return -EAGAIN;
@@ -220,6 +225,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
           in the firmware */
        len = wl12xx_calc_packet_alignment(wl, total_len);
 
+       /* in case of a dummy packet, use default amount of spare mem blocks */
+       if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
+               spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+
        total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
                spare_blocks;
 
@@ -451,7 +460,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
                rate_set >>= 1;
        }
 
-#ifdef CONFIG_WL12XX_HT
        /* MCS rates indication are on bits 16 - 23 */
        rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;
 
@@ -460,7 +468,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
                        enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
                rate_set >>= 1;
        }
-#endif
 
        return enabled_rates;
 }
@@ -884,6 +891,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
        /* TX failure */
        if (wl->bss_type == BSS_TYPE_AP_BSS) {
                for (i = 0; i < AP_MAX_LINKS; i++) {
+                       wl1271_free_sta(wl, i);
                        wl1271_tx_reset_link_queues(wl, i);
                        wl->links[i].allocated_pkts = 0;
                        wl->links[i].prev_freed_pkts = 0;
@@ -903,10 +911,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
                                        ieee80211_tx_status_ni(wl->hw, skb);
                                }
                        }
-                       wl->tx_queue_count[i] = 0;
                }
+
+               wl->ba_rx_bitmap = 0;
        }
 
+       for (i = 0; i < NUM_TX_QUEUES; i++)
+               wl->tx_queue_count[i] = 0;
+
        wl->stopped_queues_map = 0;
 
        /*
index 7da35c0e411bfeefe22635733c9c1eff2684fba3..d6fdbf904a09304e6fcdf7c5ace5fad6645c1c8c 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef __TX_H__
 #define __TX_H__
 
+#define TX_HW_BLOCK_SPARE_DEFAULT        1
 #define TX_HW_BLOCK_SIZE                 252
 
 #define TX_HW_MGMT_PKT_LIFETIME_TU       2000
@@ -213,5 +214,9 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
 u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
 void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
 void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
+bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
+
+/* from main.c */
+void wl1271_free_sta(struct wl1271 *wl, u8 hlid);
 
 #endif
index 61a7c2163ea2e463e0357e887de582f569dc374d..3ceb20c170bc60f159ede7db9c9d3c3bcb6b48d4 100644 (file)
@@ -234,14 +234,14 @@ struct wl1271_stats {
 #define NUM_TX_QUEUES              4
 #define NUM_RX_PKT_DESC            8
 
-#define AP_MAX_STATIONS            5
+#define AP_MAX_STATIONS            8
 
 /* Broadcast and Global links + system link + links to stations */
 /*
  * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
  * the places that use this.
  */
-#define AP_MAX_LINKS               (AP_MAX_STATIONS + 3)
+#define AP_MAX_LINKS               (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
 
 /* FW status registers */
 struct wl12xx_fw_status {
@@ -402,6 +402,7 @@ struct wl1271 {
        u8 mac_addr[ETH_ALEN];
        u8 bss_type;
        u8 set_bss_type;
+       u8 p2p; /* we are using p2p role */
        u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
        u8 ssid_len;
        int channel;
@@ -425,6 +426,9 @@ struct wl1271 {
        u32 tx_allocated_blocks;
        u32 tx_results_count;
 
+       /* amount of spare TX blocks to use */
+       u32 tx_spare_blocks;
+
        /* Accounting for allocated / available Tx packets in HW */
        u32 tx_pkts_freed[NUM_TX_QUEUES];
        u32 tx_allocated_pkts[NUM_TX_QUEUES];
@@ -623,6 +627,9 @@ struct wl1271 {
 
        /* number of currently active RX BA sessions */
        int ba_rx_session_count;
+
+       /* AP-mode - number of currently connected stations */
+       int active_sta_count;
 };
 
 struct wl1271_station {
index 2acff4307ca401c70b40909826e9d5e1cccb6c3f..5af959274d4ef0c6ba4b355a49575604101db0d1 100644 (file)
@@ -27,4 +27,15 @@ config NFC_PN533
          Say Y here to compile support for PN533 devices into the
          kernel or say M to compile it as module (pn533).
 
+config NFC_WILINK
+       tristate "Texas Instruments NFC WiLink driver"
+       depends on TI_ST && NFC_NCI
+       help
+         This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC
+         combo devices. This makes use of shared transport line discipline
+         core driver to communicate with the NFC core of the combo chip.
+
+         Say Y here to compile support for Texas Instrument's NFC WiLink driver
+         into the kernel or say M to compile it as module.
+
 endmenu
index 8ef446d2c1bd9f57206c8c48cba7a0487eb6d98a..ab99e8572f02a8f1cdb5ef389559e1a1ccb5dd37 100644 (file)
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_PN544_NFC)                += pn544.o
 obj-$(CONFIG_NFC_PN533)                += pn533.o
+obj-$(CONFIG_NFC_WILINK)       += nfcwilink.o
 
 ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
new file mode 100644 (file)
index 0000000..5b0f1ff
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ *  Texas Instrument's NFC Driver For Shared Transport.
+ *
+ *  NFC Driver acts as interface between NCI core and
+ *  TI Shared Transport Layer.
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on btwilink.c, which was written
+ *  by Raja Mani and Pavan Savoy.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/ti_wilink_st.h>
+
+#define NFCWILINK_CHNL                 12
+#define NFCWILINK_OPCODE               7
+#define NFCWILINK_MAX_FRAME_SIZE       300
+#define NFCWILINK_HDR_LEN              4
+#define NFCWILINK_OFFSET_LEN_IN_HDR    1
+#define NFCWILINK_LEN_SIZE             2
+#define NFCWILINK_REGISTER_TIMEOUT     8000    /* 8 sec */
+
+struct nfcwilink_hdr {
+       u8 chnl;
+       u8 opcode;
+       u16 len;
+} __packed;
+
+struct nfcwilink {
+       struct platform_device          *pdev;
+       struct nci_dev                  *ndev;
+       unsigned long                   flags;
+
+       char                            st_register_cb_status;
+       long                            (*st_write) (struct sk_buff *);
+       struct completion               st_register_completed;
+};
+
+/* NFCWILINK driver flags */
+enum {
+       NFCWILINK_RUNNING,
+};
+
+/* Called by ST when registration is complete */
+static void nfcwilink_register_complete(void *priv_data, char data)
+{
+       struct nfcwilink *drv = priv_data;
+
+       nfc_dev_dbg(&drv->pdev->dev, "register_complete entry");
+
+       /* store ST registration status */
+       drv->st_register_cb_status = data;
+
+       /* complete the wait in nfc_st_open() */
+       complete(&drv->st_register_completed);
+}
+
+/* Called by ST when receive data is available */
+static long nfcwilink_receive(void *priv_data, struct sk_buff *skb)
+{
+       struct nfcwilink *drv = priv_data;
+       int rc;
+
+       nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len);
+
+       if (!skb)
+               return -EFAULT;
+
+       if (!drv) {
+               kfree_skb(skb);
+               return -EFAULT;
+       }
+
+       /* strip the ST header
+       (apart for the chnl byte, which is not received in the hdr) */
+       skb_pull(skb, (NFCWILINK_HDR_LEN-1));
+
+       skb->dev = (void *) drv->ndev;
+
+       /* Forward skb to NCI core layer */
+       rc = nci_recv_frame(skb);
+       if (rc < 0) {
+               nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+/* protocol structure registered with ST */
+static struct st_proto_s nfcwilink_proto = {
+       .chnl_id = NFCWILINK_CHNL,
+       .max_frame_size = NFCWILINK_MAX_FRAME_SIZE,
+       .hdr_len = (NFCWILINK_HDR_LEN-1),       /* not including chnl byte */
+       .offset_len_in_hdr = NFCWILINK_OFFSET_LEN_IN_HDR,
+       .len_size = NFCWILINK_LEN_SIZE,
+       .reserve = 0,
+       .recv = nfcwilink_receive,
+       .reg_complete_cb = nfcwilink_register_complete,
+       .write = NULL,
+};
+
+static int nfcwilink_open(struct nci_dev *ndev)
+{
+       struct nfcwilink *drv = nci_get_drvdata(ndev);
+       unsigned long comp_ret;
+       int rc;
+
+       nfc_dev_dbg(&drv->pdev->dev, "open entry");
+
+       if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) {
+               rc = -EBUSY;
+               goto exit;
+       }
+
+       nfcwilink_proto.priv_data = drv;
+
+       init_completion(&drv->st_register_completed);
+       drv->st_register_cb_status = -EINPROGRESS;
+
+       rc = st_register(&nfcwilink_proto);
+       if (rc < 0) {
+               if (rc == -EINPROGRESS) {
+                       comp_ret = wait_for_completion_timeout(
+                       &drv->st_register_completed,
+                       msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT));
+
+                       nfc_dev_dbg(&drv->pdev->dev,
+                       "wait_for_completion_timeout returned %ld",
+                       comp_ret);
+
+                       if (comp_ret == 0) {
+                               /* timeout */
+                               rc = -ETIMEDOUT;
+                               goto clear_exit;
+                       } else if (drv->st_register_cb_status != 0) {
+                               rc = drv->st_register_cb_status;
+                               nfc_dev_err(&drv->pdev->dev,
+                               "st_register_cb failed %d", rc);
+                               goto clear_exit;
+                       }
+               } else {
+                       nfc_dev_err(&drv->pdev->dev,
+                               "st_register failed %d", rc);
+                       goto clear_exit;
+               }
+       }
+
+       /* st_register MUST fill the write callback */
+       BUG_ON(nfcwilink_proto.write == NULL);
+       drv->st_write = nfcwilink_proto.write;
+
+       goto exit;
+
+clear_exit:
+       clear_bit(NFCWILINK_RUNNING, &drv->flags);
+
+exit:
+       return rc;
+}
+
+static int nfcwilink_close(struct nci_dev *ndev)
+{
+       struct nfcwilink *drv = nci_get_drvdata(ndev);
+       int rc;
+
+       nfc_dev_dbg(&drv->pdev->dev, "close entry");
+
+       if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags))
+               return 0;
+
+       rc = st_unregister(&nfcwilink_proto);
+       if (rc)
+               nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc);
+
+       drv->st_write = NULL;
+
+       return rc;
+}
+
+static int nfcwilink_send(struct sk_buff *skb)
+{
+       struct nci_dev *ndev = (struct nci_dev *)skb->dev;
+       struct nfcwilink *drv = nci_get_drvdata(ndev);
+       struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000};
+       long len;
+
+       nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len);
+
+       if (!test_bit(NFCWILINK_RUNNING, &drv->flags))
+               return -EBUSY;
+
+       /* add the ST hdr to the start of the buffer */
+       hdr.len = skb->len;
+       memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN);
+
+       /* Insert skb to shared transport layer's transmit queue.
+        * Freeing skb memory is taken care in shared transport layer,
+        * so don't free skb memory here.
+        */
+       len = drv->st_write(skb);
+       if (len < 0) {
+               kfree_skb(skb);
+               nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static struct nci_ops nfcwilink_ops = {
+       .open = nfcwilink_open,
+       .close = nfcwilink_close,
+       .send = nfcwilink_send,
+};
+
+static int nfcwilink_probe(struct platform_device *pdev)
+{
+       static struct nfcwilink *drv;
+       int rc;
+       u32 protocols;
+
+       nfc_dev_dbg(&pdev->dev, "probe entry");
+
+       drv = kzalloc(sizeof(struct nfcwilink), GFP_KERNEL);
+       if (!drv) {
+               rc = -ENOMEM;
+               goto exit;
+       }
+
+       drv->pdev = pdev;
+
+       protocols = NFC_PROTO_JEWEL_MASK
+                       | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
+                       | NFC_PROTO_ISO14443_MASK
+                       | NFC_PROTO_NFC_DEP_MASK;
+
+       drv->ndev = nci_allocate_device(&nfcwilink_ops,
+                                       protocols,
+                                       NFCWILINK_HDR_LEN,
+                                       0);
+       if (!drv->ndev) {
+               nfc_dev_err(&pdev->dev, "nci_allocate_device failed");
+               rc = -ENOMEM;
+               goto free_exit;
+       }
+
+       nci_set_parent_dev(drv->ndev, &pdev->dev);
+       nci_set_drvdata(drv->ndev, drv);
+
+       rc = nci_register_device(drv->ndev);
+       if (rc < 0) {
+               nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc);
+               goto free_dev_exit;
+       }
+
+       dev_set_drvdata(&pdev->dev, drv);
+
+       goto exit;
+
+free_dev_exit:
+       nci_free_device(drv->ndev);
+
+free_exit:
+       kfree(drv);
+
+exit:
+       return rc;
+}
+
+static int nfcwilink_remove(struct platform_device *pdev)
+{
+       struct nfcwilink *drv = dev_get_drvdata(&pdev->dev);
+       struct nci_dev *ndev;
+
+       nfc_dev_dbg(&pdev->dev, "remove entry");
+
+       if (!drv)
+               return -EFAULT;
+
+       ndev = drv->ndev;
+
+       nci_unregister_device(ndev);
+       nci_free_device(ndev);
+
+       kfree(drv);
+
+       dev_set_drvdata(&pdev->dev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver nfcwilink_driver = {
+       .probe = nfcwilink_probe,
+       .remove = nfcwilink_remove,
+       .driver = {
+               .name = "nfcwilink",
+               .owner = THIS_MODULE,
+       },
+};
+
+/* ------- Module Init/Exit interfaces ------ */
+static int __init nfcwilink_init(void)
+{
+       printk(KERN_INFO "NFC Driver for TI WiLink");
+
+       return platform_driver_register(&nfcwilink_driver);
+}
+
+static void __exit nfcwilink_exit(void)
+{
+       platform_driver_unregister(&nfcwilink_driver);
+}
+
+module_init(nfcwilink_init);
+module_exit(nfcwilink_exit);
+
+/* ------ Module Info ------ */
+
+MODULE_AUTHOR("Ilan Elias <[email protected]>");
+MODULE_DESCRIPTION("NFC Driver for TI Shared Transport");
+MODULE_LICENSE("GPL");
index f81a93e5b59dfa865e413454a82ab01539c6457f..7bcb1febef0dd06246642f58878cace232706500 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/usb.h>
 #include <linux/nfc.h>
 #include <linux/netdevice.h>
-#include <net/nfc.h>
+#include <net/nfc/nfc.h>
 
 #define VERSION "0.1"
 
@@ -1432,6 +1432,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
 }
 
 struct nfc_ops pn533_nfc_ops = {
+       .dev_up = NULL,
+       .dev_down = NULL,
        .start_poll = pn533_start_poll,
        .stop_poll = pn533_stop_poll,
        .activate_target = pn533_activate_target,
index a7ae33d06f246006f56a39b2a84adc40a0114c59..1526d965ed064d864fb9c38db5d4067b8dd7bbe0 100644 (file)
@@ -378,4 +378,13 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value);
 /* PMU support */
 extern void bcma_pmu_init(struct bcma_drv_cc *cc);
 
+extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset,
+                                 u32 value);
+extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset,
+                                   u32 mask, u32 set);
+extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
+                                       u32 offset, u32 mask, u32 set);
+extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
+                                      u32 offset, u32 mask, u32 set);
+
 #endif /* LINUX_BCMA_DRIVER_CC_H_ */
index 37f95f2e10f9606164b441fd0e4622bd01879183..b5e0a5c344fd69677507f8e24ed4890d143e6136 100644 (file)
 #define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK  0x0060
 /* A-MSDU 802.11n */
 #define IEEE80211_QOS_CTL_A_MSDU_PRESENT       0x0080
+/* Mesh Control 802.11s */
+#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT  0x0100
 
 /* U-APSD queue for WMM IEs sent by AP */
 #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD      (1<<7)
@@ -775,6 +777,13 @@ struct ieee80211_mmie {
        u8 mic[8];
 } __attribute__ ((packed));
 
+struct ieee80211_vendor_ie {
+       u8 element_id;
+       u8 len;
+       u8 oui[3];
+       u8 oui_type;
+} __packed;
+
 /* Control frames */
 struct ieee80211_rts {
        __le16 frame_control;
@@ -1468,6 +1477,9 @@ enum ieee80211_sa_query_action {
 
 #define WLAN_PMKID_LEN                 16
 
+#define WLAN_OUI_WFA                   0x506f9a
+#define WLAN_OUI_TYPE_WFA_P2P          9
+
 /*
  * WMM/802.11e Tspec Element
  */
index c525e0b5876b9286d110a5f4dc14de7e4b93f010..36cb955b05cc517fc09ffcb0126571f7ccb5bcc0 100644 (file)
  *
  * @NFC_CMD_GET_DEVICE: request information about a device (requires
  *     %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices
+ * @NFC_CMD_DEV_UP: turn on the nfc device
+ *     (requires %NFC_ATTR_DEVICE_INDEX)
+ * @NFC_CMD_DEV_DOWN: turn off the nfc device
+ *     (requires %NFC_ATTR_DEVICE_INDEX)
  * @NFC_CMD_START_POLL: start polling for targets using the given protocols
  *     (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS)
  * @NFC_CMD_STOP_POLL: stop polling for targets (requires
@@ -56,6 +60,8 @@
 enum nfc_commands {
        NFC_CMD_UNSPEC,
        NFC_CMD_GET_DEVICE,
+       NFC_CMD_DEV_UP,
+       NFC_CMD_DEV_DOWN,
        NFC_CMD_START_POLL,
        NFC_CMD_STOP_POLL,
        NFC_CMD_GET_TARGET,
index 0343504082a81847de1184d911d9f3b2b2d189b1..460b12a8ef6654f7f45902a28399dbe85126baab 100644 (file)
  *     this command may also be sent by the driver as an MLME event to
  *     inform userspace of the new replay counter.
  *
+ * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
+ *     of PMKSA caching dandidates.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -623,6 +626,8 @@ enum nl80211_commands {
 
        NL80211_CMD_SET_REKEY_OFFLOAD,
 
+       NL80211_CMD_PMKSA_CANDIDATE,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -769,6 +774,8 @@ enum nl80211_commands {
  *     that can be added to a scan request
  * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information
  *     elements that can be added to a scheduled scan request
+ * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be
+ *     used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute.
  *
  * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
  * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
@@ -1011,6 +1018,24 @@ enum nl80211_commands {
 
  * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
  *     cycles, in msecs.
+
+ * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more
+ *     sets of attributes to match during scheduled scans.  Only BSSs
+ *     that match any of the sets will be reported.  These are
+ *     pass-thru filter rules.
+ *     For a match to succeed, the BSS must match all attributes of a
+ *     set.  Since not every hardware supports matching all types of
+ *     attributes, there is no guarantee that the reported BSSs are
+ *     fully complying with the match sets and userspace needs to be
+ *     able to ignore them by itself.
+ *     Thus, the implementation is somewhat hardware-dependent, but
+ *     this is only an optimization and the userspace application
+ *     needs to handle all the non-filtered results anyway.
+ *     If the match attributes don't make sense when combined with
+ *     the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID
+ *     is included in the probe request, but the match attributes
+ *     will never let it go through), -EINVAL may be returned.
+ *     If ommited, no filtering is done.
  *
  * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
  *     interface combinations. In each nested item, it contains attributes
@@ -1044,6 +1069,14 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
  *     of the station, see &enum nl80211_sta_wme_attr.
+ * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
+ *     as AP.
+ *
+ * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
+ *     roaming to another AP in the same ESS if the signal lever is low.
+ *
+ * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
+ *     candidate information, see &enum nl80211_pmksa_candidate_attr.
  *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1256,6 +1289,14 @@ enum nl80211_attrs {
        NL80211_ATTR_IE_ASSOC_RESP,
 
        NL80211_ATTR_STA_WME,
+       NL80211_ATTR_SUPPORT_AP_UAPSD,
+
+       NL80211_ATTR_ROAM_SUPPORT,
+
+       NL80211_ATTR_SCHED_SCAN_MATCH,
+       NL80211_ATTR_MAX_MATCH_SETS,
+
+       NL80211_ATTR_PMKSA_CANDIDATE,
 
        /* add attributes here, update the policy in nl80211.c */
 
@@ -1715,6 +1756,26 @@ enum nl80211_reg_rule_attr {
        NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
 };
 
+/**
+ * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
+ * only report BSS with matching SSID.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+ *     attribute number currently defined
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_sched_scan_match_attr {
+       __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID,
+
+       NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+
+       /* keep last */
+       __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
+       NL80211_SCHED_SCAN_MATCH_ATTR_MAX =
+               __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
+};
+
 /**
  * enum nl80211_reg_rule_flags - regulatory rule flags
  *
@@ -2490,8 +2551,10 @@ enum nl80211_hidden_ssid {
 /**
  * enum nl80211_sta_wme_attr - station WME attributes
  * @__NL80211_STA_WME_INVALID: invalid number for nested attribute
- * @NL80211_STA_WME_QUEUES: bitmap of uapsd queues.
- * @NL80211_STA_WME_MAX_SP: max service period.
+ * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format
+ *     is the same as the AC bitmap in the QoS info field.
+ * @NL80211_STA_WME_MAX_SP: max service period. the format is the same
+ *     as the MAX_SP field in the QoS info field (but already shifted down).
  * @__NL80211_STA_WME_AFTER_LAST: internal
  * @NL80211_STA_WME_MAX: highest station WME attribute
  */
@@ -2505,4 +2568,27 @@ enum nl80211_sta_wme_attr {
        NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1
 };
 
+/**
+ * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates
+ * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes
+ * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher
+ *     priority)
+ * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets)
+ * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag)
+ * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes
+ *     (internal)
+ * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute
+ *     (internal)
+ */
+enum nl80211_pmksa_candidate_attr {
+       __NL80211_PMKSA_CANDIDATE_INVALID,
+       NL80211_PMKSA_CANDIDATE_INDEX,
+       NL80211_PMKSA_CANDIDATE_BSSID,
+       NL80211_PMKSA_CANDIDATE_PREAUTH,
+
+       /* keep last */
+       NUM_NL80211_PMKSA_CANDIDATE,
+       MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
+};
+
 #endif /* __LINUX_NL80211_H */
index 8623217f84d07501de8ac3c70f00306addbd5db4..f10ed7b4a714b99abac271bbd09a2ec483cf6246 100644 (file)
@@ -25,7 +25,7 @@ struct ssb_sprom {
        u8 et1phyaddr;          /* MII address for enet1 */
        u8 et0mdcport;          /* MDIO for enet0 */
        u8 et1mdcport;          /* MDIO for enet1 */
-       u8 board_rev;           /* Board revision number from SPROM. */
+       u16 board_rev;          /* Board revision number from SPROM. */
        u8 country_code;        /* Country Code */
        u16 leddc_on_time;      /* LED Powersave Duty Cycle On Count */
        u16 leddc_off_time;     /* LED Powersave Duty Cycle Off Count */
index eb2659aefd97a07b10eba00b79fe7b73350e8827..ccfdf3f63ce503fb654c17ca93c2037b9805cc27 100644 (file)
@@ -441,6 +441,10 @@ enum plink_actions {
  * @plink_action: plink action to take
  * @plink_state: set the peer link state for a station
  * @ht_capa: HT capabilities of station
+ * @uapsd_queues: bitmap of queues configured for uapsd. same format
+ *     as the AC bitmap in the QoS info field
+ * @max_sp: max Service Period. same format as the MAX_SP in the
+ *     QoS info field (but already shifted down)
  */
 struct station_parameters {
        u8 *supported_rates;
@@ -875,6 +879,15 @@ struct cfg80211_scan_request {
        struct ieee80211_channel *channels[0];
 };
 
+/**
+ * struct cfg80211_match_set - sets of attributes to match
+ *
+ * @ssid: SSID to be matched
+ */
+struct cfg80211_match_set {
+       struct cfg80211_ssid ssid;
+};
+
 /**
  * struct cfg80211_sched_scan_request - scheduled scan request description
  *
@@ -884,6 +897,11 @@ struct cfg80211_scan_request {
  * @interval: interval between each scheduled scan cycle
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
+ * @match_sets: sets of parameters to be matched for a scan result
+ *     entry to be considered valid and to be passed to the host
+ *     (others are filtered out).
+ *     If ommited, all results are passed.
+ * @n_match_sets: number of match sets
  * @wiphy: the wiphy this was for
  * @dev: the interface
  * @channels: channels to scan
@@ -895,6 +913,8 @@ struct cfg80211_sched_scan_request {
        u32 interval;
        const u8 *ie;
        size_t ie_len;
+       struct cfg80211_match_set *match_sets;
+       int n_match_sets;
 
        /* internal */
        struct wiphy *wiphy;
@@ -1619,6 +1639,9 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
  *     auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
  * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
+ *     firmware.
+ * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
  */
 enum wiphy_flags {
        WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
@@ -1633,6 +1656,8 @@ enum wiphy_flags {
        WIPHY_FLAG_MESH_AUTH                    = BIT(10),
        WIPHY_FLAG_SUPPORTS_SCHED_SCAN          = BIT(11),
        WIPHY_FLAG_ENFORCE_COMBINATIONS         = BIT(12),
+       WIPHY_FLAG_SUPPORTS_FW_ROAM             = BIT(13),
+       WIPHY_FLAG_AP_UAPSD                     = BIT(14),
 };
 
 /**
@@ -1789,6 +1814,8 @@ struct wiphy_wowlan_support {
  *     by default for perm_addr. In this case, the mask should be set to
  *     all-zeroes. In this case it is assumed that the device can handle
  *     the same number of arbitrary MAC addresses.
+ * @registered: protects ->resume and ->suspend sysfs callbacks against
+ *     unregister hardware
  * @debugfsdir: debugfs directory used for this wiphy, will be renamed
  *     automatically on wiphy renames
  * @dev: (virtual) struct device for this wiphy
@@ -1809,6 +1836,9 @@ struct wiphy_wowlan_support {
  *     any given scan
  * @max_sched_scan_ssids: maximum number of SSIDs the device can scan
  *     for in any given scheduled scan
+ * @max_match_sets: maximum number of match sets the device can handle
+ *     when performing a scheduled scan, 0 if filtering is not
+ *     supported.
  * @max_scan_ie_len: maximum length of user-controlled IEs device can
  *     add to probe request frames transmitted during a scan, must not
  *     include fixed IEs like supported rates
@@ -1866,6 +1896,7 @@ struct wiphy {
        int bss_priv_size;
        u8 max_scan_ssids;
        u8 max_sched_scan_ssids;
+       u8 max_match_sets;
        u16 max_scan_ie_len;
        u16 max_sched_scan_ie_len;
 
@@ -1911,6 +1942,9 @@ struct wiphy {
         * you need use set_wiphy_dev() (see below) */
        struct device dev;
 
+       /* protects ->resume, ->suspend sysfs callbacks against unregister hw */
+       bool registered;
+
        /* dir in debugfs: ieee80211/<wiphyname> */
        struct dentry *debugfsdir;
 
@@ -2427,6 +2461,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
  */
 const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
 
+/**
+ * cfg80211_find_vendor_ie - find vendor specific information element in data
+ *
+ * @oui: vendor OUI
+ * @oui_type: vendor-specific OUI type
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * This function will return %NULL if the vendor specific element ID
+ * could not be found or if the element is invalid (claims to be
+ * longer than the given data), or a pointer to the first byte
+ * of the requested element, that is the byte containing the
+ * element ID. There are no checks on the element length
+ * other than having to fit into the given data.
+ */
+const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
+                                 const u8 *ies, int len);
+
 /**
  * DOC: Regulatory enforcement infrastructure
  *
@@ -3087,6 +3139,17 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
 void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
                               const u8 *replay_ctr, gfp_t gfp);
 
+/**
+ * cfg80211_pmksa_candidate_notify - notify about PMKSA caching candidate
+ * @dev: network device
+ * @index: candidate index (the smaller the index, the higher the priority)
+ * @bssid: BSSID of AP
+ * @preauth: Whether AP advertises support for RSN pre-authentication
+ * @gfp: allocation flags
+ */
+void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
+                                    const u8 *bssid, bool preauth, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
index 2e752df575109dc1526d22d1dbe40aa5a3ed5f77..c0f63fd0c52b092bb92bbbc020733f275f7688ad 100644 (file)
@@ -164,13 +164,14 @@ struct ieee80211_low_level_stats {
  * @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
  *     that it is only ever disabled for station mode.
  * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
+ * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
  */
 enum ieee80211_bss_change {
        BSS_CHANGED_ASSOC               = 1<<0,
        BSS_CHANGED_ERP_CTS_PROT        = 1<<1,
        BSS_CHANGED_ERP_PREAMBLE        = 1<<2,
        BSS_CHANGED_ERP_SLOT            = 1<<3,
-       BSS_CHANGED_HT                  = 1<<4,
+       BSS_CHANGED_HT                  = 1<<4,
        BSS_CHANGED_BASIC_RATES         = 1<<5,
        BSS_CHANGED_BEACON_INT          = 1<<6,
        BSS_CHANGED_BSSID               = 1<<7,
@@ -181,6 +182,7 @@ enum ieee80211_bss_change {
        BSS_CHANGED_ARP_FILTER          = 1<<12,
        BSS_CHANGED_QOS                 = 1<<13,
        BSS_CHANGED_IDLE                = 1<<14,
+       BSS_CHANGED_SSID                = 1<<15,
 
        /* when adding here, make sure to change ieee80211_reconfig */
 };
@@ -254,6 +256,9 @@ enum ieee80211_rssi_event {
  * @idle: This interface is idle. There's also a global idle flag in the
  *     hardware config which may be more appropriate depending on what
  *     your driver/device needs to do.
+ * @ssid: The SSID of the current vif. Only valid in AP-mode.
+ * @ssid_len: Length of SSID given in @ssid.
+ * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
  */
 struct ieee80211_bss_conf {
        const u8 *bssid;
@@ -280,6 +285,9 @@ struct ieee80211_bss_conf {
        bool arp_filter_enabled;
        bool qos;
        bool idle;
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       size_t ssid_len;
+       bool hidden_ssid;
 };
 
 /**
@@ -947,6 +955,9 @@ enum set_key_cmd {
  * @wme: indicates whether the STA supports WME. Only valid during AP-mode.
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *), size is determined in hw information.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
+ *     if wme is supported.
+ * @max_sp: max Service Period. Only valid if wme is supported.
  */
 struct ieee80211_sta {
        u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1096,6 +1107,10 @@ enum sta_notify_cmd {
  *     stations based on the PM bit of incoming frames.
  *     Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
  *     the PS mode of connected stations.
+ *
+ * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session
+ *     setup strictly in HW. mac80211 should not attempt to do this in
+ *     software.
  */
 enum ieee80211_hw_flags {
        IEEE80211_HW_HAS_RATE_CONTROL                   = 1<<0,
@@ -1121,6 +1136,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_SUPPORTS_CQM_RSSI                  = 1<<20,
        IEEE80211_HW_SUPPORTS_PER_STA_GTK               = 1<<21,
        IEEE80211_HW_AP_LINK_PS                         = 1<<22,
+       IEEE80211_HW_TX_AMPDU_SETUP_IN_HW               = 1<<23,
 };
 
 /**
@@ -3220,6 +3236,19 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
 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 */
 
 /**
diff --git a/include/net/nfc.h b/include/net/nfc.h
deleted file mode 100644 (file)
index 87b51fe..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2011 Instituto Nokia de Tecnologia
- *
- * Authors:
- *    Lauro Ramos Venancio <[email protected]>
- *    Aloisio Almeida Jr <[email protected]>
- *
- * 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; if not, write to the
- * Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __NET_NFC_H
-#define __NET_NFC_H
-
-#include <linux/device.h>
-#include <linux/skbuff.h>
-
-#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg)
-#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg)
-#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg)
-
-struct nfc_dev;
-
-/**
- * data_exchange_cb_t - Definition of nfc_data_exchange callback
- *
- * @context: nfc_data_exchange cb_context parameter
- * @skb: response data
- * @err: If an error has occurred during data exchange, it is the
- *     error number. Zero means no error.
- *
- * When a rx or tx package is lost or corrupted or the target gets out
- * of the operating field, err is -EIO.
- */
-typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
-                                                               int err);
-
-struct nfc_ops {
-       int (*start_poll)(struct nfc_dev *dev, u32 protocols);
-       void (*stop_poll)(struct nfc_dev *dev);
-       int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
-                                                       u32 protocol);
-       void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
-       int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
-                               struct sk_buff *skb, data_exchange_cb_t cb,
-                                                       void *cb_context);
-};
-
-struct nfc_target {
-       u32 idx;
-       u32 supported_protocols;
-       u16 sens_res;
-       u8 sel_res;
-};
-
-struct nfc_genl_data {
-       u32 poll_req_pid;
-       struct mutex genl_data_mutex;
-};
-
-struct nfc_dev {
-       unsigned idx;
-       unsigned target_idx;
-       struct nfc_target *targets;
-       int n_targets;
-       int targets_generation;
-       spinlock_t targets_lock;
-       struct device dev;
-       bool polling;
-       struct nfc_genl_data genl_data;
-       u32 supported_protocols;
-
-       int tx_headroom;
-       int tx_tailroom;
-
-       struct nfc_ops *ops;
-};
-#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
-
-extern struct class nfc_class;
-
-struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
-                                       u32 supported_protocols,
-                                       int tx_headroom,
-                                       int tx_tailroom);
-
-/**
- * nfc_free_device - free nfc device
- *
- * @dev: The nfc device to free
- */
-static inline void nfc_free_device(struct nfc_dev *dev)
-{
-       put_device(&dev->dev);
-}
-
-int nfc_register_device(struct nfc_dev *dev);
-
-void nfc_unregister_device(struct nfc_dev *dev);
-
-/**
- * nfc_set_parent_dev - set the parent device
- *
- * @nfc_dev: The nfc device whose parent is being set
- * @dev: The parent device
- */
-static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
-                                       struct device *dev)
-{
-       nfc_dev->dev.parent = dev;
-}
-
-/**
- * nfc_set_drvdata - set driver specifc data
- *
- * @dev: The nfc device
- * @data: Pointer to driver specifc data
- */
-static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)
-{
-       dev_set_drvdata(&dev->dev, data);
-}
-
-/**
- * nfc_get_drvdata - get driver specifc data
- *
- * @dev: The nfc device
- */
-static inline void *nfc_get_drvdata(struct nfc_dev *dev)
-{
-       return dev_get_drvdata(&dev->dev);
-}
-
-/**
- * nfc_device_name - get the nfc device name
- *
- * @dev: The nfc device whose name to return
- */
-static inline const char *nfc_device_name(struct nfc_dev *dev)
-{
-       return dev_name(&dev->dev);
-}
-
-struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);
-
-int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
-                                                       int ntargets);
-
-#endif /* __NET_NFC_H */
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
new file mode 100644 (file)
index 0000000..39b85bc
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on hci.h, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __NCI_H
+#define __NCI_H
+
+/* NCI constants */
+#define NCI_MAX_NUM_MAPPING_CONFIGS                            10
+#define NCI_MAX_NUM_RF_CONFIGS                                 10
+#define NCI_MAX_NUM_CONN                                       10
+
+/* NCI Status Codes */
+#define        NCI_STATUS_OK                                           0x00
+#define        NCI_STATUS_REJECTED                                     0x01
+#define        NCI_STATUS_MESSAGE_CORRUPTED                            0x02
+#define        NCI_STATUS_BUFFER_FULL                                  0x03
+#define        NCI_STATUS_FAILED                                       0x04
+#define        NCI_STATUS_NOT_INITIALIZED                              0x05
+#define        NCI_STATUS_SYNTAX_ERROR                                 0x06
+#define        NCI_STATUS_SEMANTIC_ERROR                               0x07
+#define        NCI_STATUS_UNKNOWN_GID                                  0x08
+#define        NCI_STATUS_UNKNOWN_OID                                  0x09
+#define        NCI_STATUS_INVALID_PARAM                                0x0a
+#define        NCI_STATUS_MESSAGE_SIZE_EXCEEDED                        0x0b
+/* Discovery Specific Status Codes */
+#define        NCI_STATUS_DISCOVERY_ALREADY_STARTED                    0xa0
+#define        NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED           0xa1
+/* RF Interface Specific Status Codes */
+#define        NCI_STATUS_RF_TRANSMISSION_ERROR                        0xb0
+#define        NCI_STATUS_RF_PROTOCOL_ERROR                            0xb1
+#define        NCI_STATUS_RF_TIMEOUT_ERROR                             0xb2
+#define        NCI_STATUS_RF_LINK_LOSS_ERROR                           0xb3
+/* NFCEE Interface Specific Status Codes */
+#define        NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED          0xc0
+#define        NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED            0xc1
+#define        NCI_STATUS_NFCEE_TRANSMISSION_ERROR                     0xc2
+#define        NCI_STATUS_NFCEE_PROTOCOL_ERROR                         0xc3
+#define NCI_STATUS_NFCEE_TIMEOUT_ERROR                         0xc4
+
+/* NCI RF Technology and Mode */
+#define NCI_NFC_A_PASSIVE_POLL_MODE                            0x00
+#define NCI_NFC_B_PASSIVE_POLL_MODE                            0x01
+#define NCI_NFC_F_PASSIVE_POLL_MODE                            0x02
+#define NCI_NFC_A_ACTIVE_POLL_MODE                             0x03
+#define NCI_NFC_F_ACTIVE_POLL_MODE                             0x05
+#define NCI_NFC_A_PASSIVE_LISTEN_MODE                          0x80
+#define NCI_NFC_B_PASSIVE_LISTEN_MODE                          0x81
+#define NCI_NFC_F_PASSIVE_LISTEN_MODE                          0x82
+#define NCI_NFC_A_ACTIVE_LISTEN_MODE                           0x83
+#define NCI_NFC_F_ACTIVE_LISTEN_MODE                           0x85
+
+/* NCI RF Protocols */
+#define NCI_RF_PROTOCOL_UNKNOWN                                        0x00
+#define NCI_RF_PROTOCOL_T1T                                    0x01
+#define NCI_RF_PROTOCOL_T2T                                    0x02
+#define NCI_RF_PROTOCOL_T3T                                    0x03
+#define NCI_RF_PROTOCOL_ISO_DEP                                        0x04
+#define NCI_RF_PROTOCOL_NFC_DEP                                        0x05
+
+/* NCI RF Interfaces */
+#define NCI_RF_INTERFACE_RFU                                   0x00
+#define        NCI_RF_INTERFACE_FRAME                                  0x01
+#define        NCI_RF_INTERFACE_ISO_DEP                                0x02
+#define        NCI_RF_INTERFACE_NFC_DEP                                0x03
+
+/* NCI RF_DISCOVER_MAP_CMD modes */
+#define NCI_DISC_MAP_MODE_POLL                                 0x01
+#define NCI_DISC_MAP_MODE_LISTEN                               0x02
+#define NCI_DISC_MAP_MODE_BOTH                                 0x03
+
+/* NCI Discovery Types */
+#define NCI_DISCOVERY_TYPE_POLL_A_PASSIVE                      0x00
+#define        NCI_DISCOVERY_TYPE_POLL_B_PASSIVE                       0x01
+#define        NCI_DISCOVERY_TYPE_POLL_F_PASSIVE                       0x02
+#define        NCI_DISCOVERY_TYPE_POLL_A_ACTIVE                        0x03
+#define        NCI_DISCOVERY_TYPE_POLL_F_ACTIVE                        0x05
+#define        NCI_DISCOVERY_TYPE_WAKEUP_A_PASSIVE                     0x06
+#define        NCI_DISCOVERY_TYPE_WAKEUP_B_PASSIVE                     0x07
+#define        NCI_DISCOVERY_TYPE_WAKEUP_A_ACTIVE                      0x09
+#define        NCI_DISCOVERY_TYPE_LISTEN_A_PASSIVE                     0x80
+#define        NCI_DISCOVERY_TYPE_LISTEN_B_PASSIVE                     0x81
+#define        NCI_DISCOVERY_TYPE_LISTEN_F_PASSIVE                     0x82
+#define        NCI_DISCOVERY_TYPE_LISTEN_A_ACTIVE                      0x83
+#define        NCI_DISCOVERY_TYPE_LISTEN_F_ACTIVE                      0x85
+
+/* NCI Deactivation Type */
+#define        NCI_DEACTIVATE_TYPE_IDLE_MODE                           0x00
+#define        NCI_DEACTIVATE_TYPE_SLEEP_MODE                          0x01
+#define        NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE                       0x02
+#define        NCI_DEACTIVATE_TYPE_RF_LINK_LOSS                        0x03
+#define        NCI_DEACTIVATE_TYPE_DISCOVERY_ERROR                     0x04
+
+/* Message Type (MT) */
+#define NCI_MT_DATA_PKT                                                0x00
+#define NCI_MT_CMD_PKT                                         0x01
+#define NCI_MT_RSP_PKT                                         0x02
+#define NCI_MT_NTF_PKT                                         0x03
+
+#define nci_mt(hdr)                    (((hdr)[0]>>5)&0x07)
+#define nci_mt_set(hdr, mt)            ((hdr)[0] |= (__u8)(((mt)&0x07)<<5))
+
+/* Packet Boundary Flag (PBF) */
+#define NCI_PBF_LAST                                           0x00
+#define NCI_PBF_CONT                                           0x01
+
+#define nci_pbf(hdr)                   (__u8)(((hdr)[0]>>4)&0x01)
+#define nci_pbf_set(hdr, pbf)          ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4))
+
+/* Control Opcode manipulation */
+#define nci_opcode_pack(gid, oid)      (__u16)((((__u16)((gid)&0x0f))<<8)|\
+                                       ((__u16)((oid)&0x3f)))
+#define nci_opcode(hdr)                        nci_opcode_pack(hdr[0], hdr[1])
+#define nci_opcode_gid(op)             (__u8)(((op)&0x0f00)>>8)
+#define nci_opcode_oid(op)             (__u8)((op)&0x003f)
+
+/* Payload Length */
+#define nci_plen(hdr)                  (__u8)((hdr)[2])
+
+/* Connection ID */
+#define nci_conn_id(hdr)               (__u8)(((hdr)[0])&0x0f)
+
+/* GID values */
+#define        NCI_GID_CORE                                            0x0
+#define        NCI_GID_RF_MGMT                                         0x1
+#define        NCI_GID_NFCEE_MGMT                                      0x2
+#define        NCI_GID_PROPRIETARY                                     0xf
+
+/* ---- NCI Packet structures ---- */
+#define NCI_CTRL_HDR_SIZE                                      3
+#define NCI_DATA_HDR_SIZE                                      3
+
+struct nci_ctrl_hdr {
+       __u8    gid;            /* MT & PBF & GID */
+       __u8    oid;
+       __u8    plen;
+} __packed;
+
+struct nci_data_hdr {
+       __u8    conn_id;        /* MT & PBF & ConnID */
+       __u8    rfu;
+       __u8    plen;
+} __packed;
+
+/* ------------------------ */
+/* -----  NCI Commands ---- */
+/* ------------------------ */
+#define NCI_OP_CORE_RESET_CMD          nci_opcode_pack(NCI_GID_CORE, 0x00)
+
+#define NCI_OP_CORE_INIT_CMD           nci_opcode_pack(NCI_GID_CORE, 0x01)
+
+#define NCI_OP_CORE_SET_CONFIG_CMD     nci_opcode_pack(NCI_GID_CORE, 0x02)
+
+#define NCI_OP_CORE_CONN_CREATE_CMD    nci_opcode_pack(NCI_GID_CORE, 0x04)
+struct nci_core_conn_create_cmd {
+       __u8    target_handle;
+       __u8    num_target_specific_params;
+} __packed;
+
+#define NCI_OP_CORE_CONN_CLOSE_CMD     nci_opcode_pack(NCI_GID_CORE, 0x06)
+
+#define NCI_OP_RF_DISCOVER_MAP_CMD     nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+struct disc_map_config {
+       __u8    rf_protocol;
+       __u8    mode;
+       __u8    rf_interface_type;
+} __packed;
+
+struct nci_rf_disc_map_cmd {
+       __u8                            num_mapping_configs;
+       struct disc_map_config          mapping_configs
+                                       [NCI_MAX_NUM_MAPPING_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_CMD         nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct disc_config {
+       __u8    type;
+       __u8    frequency;
+} __packed;
+
+struct nci_rf_disc_cmd {
+       __u8                            num_disc_configs;
+       struct disc_config              disc_configs[NCI_MAX_NUM_RF_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_CMD       nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_cmd {
+       __u8    type;
+} __packed;
+
+/* ----------------------- */
+/* ---- NCI Responses ---- */
+/* ----------------------- */
+#define NCI_OP_CORE_RESET_RSP          nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_rsp {
+       __u8    status;
+       __u8    nci_ver;
+} __packed;
+
+#define NCI_OP_CORE_INIT_RSP           nci_opcode_pack(NCI_GID_CORE, 0x01)
+struct nci_core_init_rsp_1 {
+       __u8    status;
+       __le32  nfcc_features;
+       __u8    num_supported_rf_interfaces;
+       __u8    supported_rf_interfaces[0];     /* variable size array */
+       /* continuted in nci_core_init_rsp_2 */
+} __packed;
+
+struct nci_core_init_rsp_2 {
+       __u8    max_logical_connections;
+       __le16  max_routing_table_size;
+       __u8    max_control_packet_payload_length;
+       __le16  rf_sending_buffer_size;
+       __le16  rf_receiving_buffer_size;
+       __le16  manufacturer_id;
+} __packed;
+
+#define NCI_OP_CORE_SET_CONFIG_RSP     nci_opcode_pack(NCI_GID_CORE, 0x02)
+
+#define NCI_OP_CORE_CONN_CREATE_RSP    nci_opcode_pack(NCI_GID_CORE, 0x04)
+struct nci_core_conn_create_rsp {
+       __u8    status;
+       __u8    max_pkt_payload_size;
+       __u8    initial_num_credits;
+       __u8    conn_id;
+} __packed;
+
+#define NCI_OP_CORE_CONN_CLOSE_RSP     nci_opcode_pack(NCI_GID_CORE, 0x06)
+
+#define NCI_OP_RF_DISCOVER_MAP_RSP     nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+
+#define NCI_OP_RF_DISCOVER_RSP         nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+
+#define NCI_OP_RF_DEACTIVATE_RSP       nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+
+/* --------------------------- */
+/* ---- NCI Notifications ---- */
+/* --------------------------- */
+#define NCI_OP_CORE_CONN_CREDITS_NTF   nci_opcode_pack(NCI_GID_CORE, 0x07)
+struct conn_credit_entry {
+       __u8    conn_id;
+       __u8    credits;
+} __packed;
+
+struct nci_core_conn_credit_ntf {
+       __u8                            num_entries;
+       struct conn_credit_entry        conn_entries[NCI_MAX_NUM_CONN];
+} __packed;
+
+#define NCI_OP_RF_FIELD_INFO_NTF       nci_opcode_pack(NCI_GID_CORE, 0x08)
+struct nci_rf_field_info_ntf {
+       __u8    rf_field_status;
+} __packed;
+
+#define NCI_OP_RF_ACTIVATE_NTF         nci_opcode_pack(NCI_GID_RF_MGMT, 0x05)
+struct rf_tech_specific_params_nfca_poll {
+       __u16   sens_res;
+       __u8    nfcid1_len;     /* 0, 4, 7, or 10 Bytes */
+       __u8    nfcid1[10];
+       __u8    sel_res_len;    /* 0 or 1 Bytes */
+       __u8    sel_res;
+} __packed;
+
+struct activation_params_nfca_poll_iso_dep {
+       __u8    rats_res_len;
+       __u8    rats_res[20];
+};
+
+struct nci_rf_activate_ntf {
+       __u8    target_handle;
+       __u8    rf_protocol;
+       __u8    rf_tech_and_mode;
+       __u8    rf_tech_specific_params_len;
+
+       union {
+               struct rf_tech_specific_params_nfca_poll nfca_poll;
+       } rf_tech_specific_params;
+
+       __u8    rf_interface_type;
+       __u8    activation_params_len;
+
+       union {
+               struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
+       } activation_params;
+
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_NTF       nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+
+#endif /* __NCI_H */
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
new file mode 100644 (file)
index 0000000..2563f3a
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on hci_core.h, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __NCI_CORE_H
+#define __NCI_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+
+#include <net/nfc/nfc.h>
+#include <net/nfc/nci.h>
+
+/* NCI device state */
+enum {
+       NCI_INIT,
+       NCI_UP,
+       NCI_DISCOVERY,
+       NCI_POLL_ACTIVE,
+};
+
+/* NCI timeouts */
+#define NCI_RESET_TIMEOUT                      5000
+#define NCI_INIT_TIMEOUT                       5000
+#define NCI_RF_DISC_TIMEOUT                    5000
+#define NCI_RF_DEACTIVATE_TIMEOUT              5000
+#define NCI_CMD_TIMEOUT                                5000
+
+struct nci_dev;
+
+struct nci_ops {
+       int (*open)(struct nci_dev *ndev);
+       int (*close)(struct nci_dev *ndev);
+       int (*send)(struct sk_buff *skb);
+};
+
+#define NCI_MAX_SUPPORTED_RF_INTERFACES                4
+
+/* NCI Core structures */
+struct nci_dev {
+       struct nfc_dev          *nfc_dev;
+       struct nci_ops          *ops;
+
+       int                     tx_headroom;
+       int                     tx_tailroom;
+
+       unsigned long           flags;
+
+       atomic_t                cmd_cnt;
+       atomic_t                credits_cnt;
+
+       struct timer_list       cmd_timer;
+
+       struct workqueue_struct *cmd_wq;
+       struct work_struct      cmd_work;
+
+       struct workqueue_struct *rx_wq;
+       struct work_struct      rx_work;
+
+       struct workqueue_struct *tx_wq;
+       struct work_struct      tx_work;
+
+       struct sk_buff_head     cmd_q;
+       struct sk_buff_head     rx_q;
+       struct sk_buff_head     tx_q;
+
+       struct mutex            req_lock;
+       struct completion       req_completion;
+       __u32                   req_status;
+       __u32                   req_result;
+
+       void                    *driver_data;
+
+       __u32                   poll_prots;
+       __u32                   target_available_prots;
+       __u32                   target_active_prot;
+
+       /* received during NCI_OP_CORE_RESET_RSP */
+       __u8                    nci_ver;
+
+       /* received during NCI_OP_CORE_INIT_RSP */
+       __u32                   nfcc_features;
+       __u8                    num_supported_rf_interfaces;
+       __u8                    supported_rf_interfaces
+                               [NCI_MAX_SUPPORTED_RF_INTERFACES];
+       __u8                    max_logical_connections;
+       __u16                   max_routing_table_size;
+       __u8                    max_control_packet_payload_length;
+       __u16                   rf_sending_buffer_size;
+       __u16                   rf_receiving_buffer_size;
+       __u16                   manufacturer_id;
+
+       /* received during NCI_OP_CORE_CONN_CREATE_RSP for static conn 0 */
+       __u8                    max_pkt_payload_size;
+       __u8                    initial_num_credits;
+       __u8                    conn_id;
+
+       /* stored during nci_data_exchange */
+       data_exchange_cb_t      data_exchange_cb;
+       void                    *data_exchange_cb_context;
+       struct sk_buff          *rx_data_reassembly;
+};
+
+/* ----- NCI Devices ----- */
+struct nci_dev *nci_allocate_device(struct nci_ops *ops,
+                               __u32 supported_protocols,
+                               int tx_headroom,
+                               int tx_tailroom);
+void nci_free_device(struct nci_dev *ndev);
+int nci_register_device(struct nci_dev *ndev);
+void nci_unregister_device(struct nci_dev *ndev);
+int nci_recv_frame(struct sk_buff *skb);
+
+static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
+                                               unsigned int len,
+                                               gfp_t how)
+{
+       struct sk_buff *skb;
+
+       skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
+       if (skb)
+               skb_reserve(skb, ndev->tx_headroom);
+
+       return skb;
+}
+
+static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
+{
+       nfc_set_parent_dev(ndev->nfc_dev, dev);
+}
+
+static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
+{
+       ndev->driver_data = data;
+}
+
+static inline void *nci_get_drvdata(struct nci_dev *ndev)
+{
+       return ndev->driver_data;
+}
+
+void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
+int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
+                               int err);
+
+/* ----- NCI requests ----- */
+#define NCI_REQ_DONE           0
+#define NCI_REQ_PEND           1
+#define NCI_REQ_CANCELED       2
+
+void nci_req_complete(struct nci_dev *ndev, int result);
+
+/* ----- NCI status code ----- */
+int nci_to_errno(__u8 code);
+
+#endif /* __NCI_CORE_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
new file mode 100644 (file)
index 0000000..6a7f602
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 Instituto Nokia de Tecnologia
+ *
+ * Authors:
+ *    Lauro Ramos Venancio <[email protected]>
+ *    Aloisio Almeida Jr <[email protected]>
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __NET_NFC_H
+#define __NET_NFC_H
+
+#include <linux/device.h>
+#include <linux/skbuff.h>
+
+#define nfc_dev_info(dev, fmt, arg...) dev_info((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_err(dev, fmt, arg...) dev_err((dev), "NFC: " fmt "\n", ## arg)
+#define nfc_dev_dbg(dev, fmt, arg...) dev_dbg((dev), fmt "\n", ## arg)
+
+struct nfc_dev;
+
+/**
+ * data_exchange_cb_t - Definition of nfc_data_exchange callback
+ *
+ * @context: nfc_data_exchange cb_context parameter
+ * @skb: response data
+ * @err: If an error has occurred during data exchange, it is the
+ *     error number. Zero means no error.
+ *
+ * When a rx or tx package is lost or corrupted or the target gets out
+ * of the operating field, err is -EIO.
+ */
+typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
+                                                               int err);
+
+struct nfc_ops {
+       int (*dev_up)(struct nfc_dev *dev);
+       int (*dev_down)(struct nfc_dev *dev);
+       int (*start_poll)(struct nfc_dev *dev, u32 protocols);
+       void (*stop_poll)(struct nfc_dev *dev);
+       int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
+                                                       u32 protocol);
+       void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
+       int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
+                               struct sk_buff *skb, data_exchange_cb_t cb,
+                                                       void *cb_context);
+};
+
+struct nfc_target {
+       u32 idx;
+       u32 supported_protocols;
+       u16 sens_res;
+       u8 sel_res;
+};
+
+struct nfc_genl_data {
+       u32 poll_req_pid;
+       struct mutex genl_data_mutex;
+};
+
+struct nfc_dev {
+       unsigned idx;
+       unsigned target_idx;
+       struct nfc_target *targets;
+       int n_targets;
+       int targets_generation;
+       spinlock_t targets_lock;
+       struct device dev;
+       bool dev_up;
+       bool polling;
+       bool remote_activated;
+       struct nfc_genl_data genl_data;
+       u32 supported_protocols;
+
+       int tx_headroom;
+       int tx_tailroom;
+
+       struct nfc_ops *ops;
+};
+#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
+
+extern struct class nfc_class;
+
+struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
+                                       u32 supported_protocols,
+                                       int tx_headroom,
+                                       int tx_tailroom);
+
+/**
+ * nfc_free_device - free nfc device
+ *
+ * @dev: The nfc device to free
+ */
+static inline void nfc_free_device(struct nfc_dev *dev)
+{
+       put_device(&dev->dev);
+}
+
+int nfc_register_device(struct nfc_dev *dev);
+
+void nfc_unregister_device(struct nfc_dev *dev);
+
+/**
+ * nfc_set_parent_dev - set the parent device
+ *
+ * @nfc_dev: The nfc device whose parent is being set
+ * @dev: The parent device
+ */
+static inline void nfc_set_parent_dev(struct nfc_dev *nfc_dev,
+                                       struct device *dev)
+{
+       nfc_dev->dev.parent = dev;
+}
+
+/**
+ * nfc_set_drvdata - set driver specifc data
+ *
+ * @dev: The nfc device
+ * @data: Pointer to driver specifc data
+ */
+static inline void nfc_set_drvdata(struct nfc_dev *dev, void *data)
+{
+       dev_set_drvdata(&dev->dev, data);
+}
+
+/**
+ * nfc_get_drvdata - get driver specifc data
+ *
+ * @dev: The nfc device
+ */
+static inline void *nfc_get_drvdata(struct nfc_dev *dev)
+{
+       return dev_get_drvdata(&dev->dev);
+}
+
+/**
+ * nfc_device_name - get the nfc device name
+ *
+ * @dev: The nfc device whose name to return
+ */
+static inline const char *nfc_device_name(struct nfc_dev *dev)
+{
+       return dev_name(&dev->dev);
+}
+
+struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);
+
+int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
+                                                       int ntargets);
+
+#endif /* __NET_NFC_H */
index 8add9b4999129bcbdf62122221bd4bfec0c686ac..117e0d161780b4a94d6350d0618a87d5937ffc6a 100644 (file)
@@ -494,9 +494,8 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
        BT_DBG("sk %p", sk);
 
        add_wait_queue(sk_sleep(sk), &wait);
+       set_current_state(TASK_INTERRUPTIBLE);
        while (sk->sk_state != state) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
                if (!timeo) {
                        err = -EINPROGRESS;
                        break;
@@ -510,12 +509,13 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
                release_sock(sk);
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
+               set_current_state(TASK_INTERRUPTIBLE);
 
                err = sock_error(sk);
                if (err)
                        break;
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
        return err;
 }
index 8e6c06158f8ebf02268362d4286b4763813b4e0c..e7ee5314f39a1e6a611dd3f0bd59c10c012ae699 100644 (file)
@@ -155,6 +155,7 @@ struct bnep_session {
        unsigned int  role;
        unsigned long state;
        unsigned long flags;
+       atomic_t      terminate;
        struct task_struct *task;
 
        struct ethhdr eh;
index ca39fcf010ce3353e73312f4172f32c9ce12cb1f..d9edfe8bf9d677268cfc1f1e10b85f04d9f00f73 100644 (file)
@@ -484,9 +484,11 @@ static int bnep_session(void *arg)
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk_sleep(sk), &wait);
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
 
+               if (atomic_read(&s->terminate))
+                       break;
                /* RX */
                while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
                        skb_orphan(skb);
@@ -504,7 +506,7 @@ static int bnep_session(void *arg)
 
                schedule();
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        /* Cleanup session */
@@ -640,9 +642,10 @@ int bnep_del_connection(struct bnep_conndel_req *req)
        down_read(&bnep_session_sem);
 
        s = __bnep_get_session(req->dst);
-       if (s)
-               kthread_stop(s->task);
-       else
+       if (s) {
+               atomic_inc(&s->terminate);
+               wake_up_process(s->task);
+       } else
                err = -ENOENT;
 
        up_read(&bnep_session_sem);
index 040f67b12978c17713e4040937127b0cc814de8e..50f0d135eb8f201daf8156c433f08a973bfa338f 100644 (file)
@@ -386,7 +386,8 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl)
 
        capi_ctr_down(ctrl);
 
-       kthread_stop(session->task);
+       atomic_inc(&session->terminate);
+       wake_up_process(session->task);
 }
 
 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
index db43b54ac9afb91cfc78f911f8a15c05104fe7ed..c32638dddbf9409d685c3436eb1b1541d04d5a9e 100644 (file)
@@ -81,6 +81,7 @@ struct cmtp_session {
 
        char name[BTNAMSIZ];
 
+       atomic_t terminate;
        struct task_struct *task;
 
        wait_queue_head_t wait;
index c5b11af908be4fc3ab6c7a0cebb9639900feb162..521baa4fe835eb775f24e59dda205ae76d1f87ce 100644 (file)
@@ -292,9 +292,11 @@ static int cmtp_session(void *arg)
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk_sleep(sk), &wait);
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
 
+               if (atomic_read(&session->terminate))
+                       break;
                if (sk->sk_state != BT_CONNECTED)
                        break;
 
@@ -307,7 +309,7 @@ static int cmtp_session(void *arg)
 
                schedule();
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        down_write(&cmtp_session_sem);
@@ -380,16 +382,17 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
 
        if (!(session->flags & (1 << CMTP_LOOPBACK))) {
                err = cmtp_attach_device(session);
-               if (err < 0)
-                       goto detach;
+               if (err < 0) {
+                       atomic_inc(&session->terminate);
+                       wake_up_process(session->task);
+                       up_write(&cmtp_session_sem);
+                       return err;
+               }
        }
 
        up_write(&cmtp_session_sem);
        return 0;
 
-detach:
-       cmtp_detach_device(session);
-
 unlink:
        __cmtp_unlink_session(session);
 
@@ -414,7 +417,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
                skb_queue_purge(&session->transmit);
 
                /* Stop session thread */
-               kthread_stop(session->task);
+               atomic_inc(&session->terminate);
+               wake_up_process(session->task);
        } else
                err = -ENOENT;
 
index ec0bc3f60f2eea4216471746fdbea09c51b3fbcb..56943add45cc44707167f4877e27fe5630b00c95 100644 (file)
@@ -1209,7 +1209,6 @@ static void hci_cmd_timer(unsigned long arg)
 
        BT_ERR("%s command tx timeout", hdev->name);
        atomic_set(&hdev->cmd_cnt, 1);
-       clear_bit(HCI_RESET, &hdev->flags);
        tasklet_schedule(&hdev->cmd_task);
 }
 
@@ -1327,7 +1326,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
 
        entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
        if (!entry) {
-               return -ENOMEM;
+               err = -ENOMEM;
                goto err;
        }
 
@@ -2408,7 +2407,10 @@ static void hci_cmd_task(unsigned long arg)
                if (hdev->sent_cmd) {
                        atomic_dec(&hdev->cmd_cnt);
                        hci_send_frame(skb);
-                       mod_timer(&hdev->cmd_timer,
+                       if (test_bit(HCI_RESET, &hdev->flags))
+                               del_timer(&hdev->cmd_timer);
+                       else
+                               mod_timer(&hdev->cmd_timer,
                                  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
                } else {
                        skb_queue_head(&hdev->cmd_q, skb);
index a40170e022e84e5e88f4ccbe4eb8724d5411c49d..7ef4eb4435fb4444585e9e8c6b54ef1effd486a9 100644 (file)
@@ -58,8 +58,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
        if (status)
                return;
 
-       if (test_bit(HCI_MGMT, &hdev->flags) &&
-                               test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+       if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
+                       test_bit(HCI_MGMT, &hdev->flags))
                mgmt_discovering(hdev->id, 0);
 
        hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status);
@@ -76,8 +76,8 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
        if (status)
                return;
 
-       if (test_bit(HCI_MGMT, &hdev->flags) &&
-                               test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+       if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
+                               test_bit(HCI_MGMT, &hdev->flags))
                mgmt_discovering(hdev->id, 0);
 
        hci_conn_check_pending(hdev);
@@ -959,9 +959,8 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
                return;
        }
 
-       if (test_bit(HCI_MGMT, &hdev->flags) &&
-                                       !test_and_set_bit(HCI_INQUIRY,
-                                                       &hdev->flags))
+       if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) &&
+                               test_bit(HCI_MGMT, &hdev->flags))
                mgmt_discovering(hdev->id, 1);
 }
 
@@ -1340,8 +1339,8 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
 
        BT_DBG("%s status %d", hdev->name, status);
 
-       if (test_bit(HCI_MGMT, &hdev->flags) &&
-                               test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+       if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) &&
+                               test_bit(HCI_MGMT, &hdev->flags))
                mgmt_discovering(hdev->id, 0);
 
        hci_req_complete(hdev, HCI_OP_INQUIRY, status);
index 43b4c2deb7cc05bdc875e3f7b23a999468f5c1a4..fb68f344c34a68e5a4334b751196680ac33ffdfe 100644 (file)
@@ -764,6 +764,7 @@ static int hidp_session(void *arg)
 
        up_write(&hidp_session_sem);
 
+       kfree(session->rd_data);
        kfree(session);
        return 0;
 }
@@ -841,7 +842,8 @@ static int hidp_setup_input(struct hidp_session *session,
 
        err = input_register_device(input);
        if (err < 0) {
-               hci_conn_put_device(session->conn);
+               input_free_device(input);
+               session->input = NULL;
                return err;
        }
 
@@ -1044,8 +1046,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        }
 
        err = hid_add_device(session->hid);
-       if (err < 0)
-               goto err_add_device;
+       if (err < 0) {
+               atomic_inc(&session->terminate);
+               wake_up_process(session->task);
+               up_write(&hidp_session_sem);
+               return err;
+       }
 
        if (session->input) {
                hidp_send_ctrl_message(session,
@@ -1059,12 +1065,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        up_write(&hidp_session_sem);
        return 0;
 
-err_add_device:
-       hid_destroy_device(session->hid);
-       session->hid = NULL;
-       atomic_inc(&session->terminate);
-       wake_up_process(session->task);
-
 unlink:
        hidp_del_timer(session);
 
@@ -1090,7 +1090,6 @@ purge:
 failed:
        up_write(&hidp_session_sem);
 
-       input_free_device(session->input);
        kfree(session);
        return err;
 }
index 3204ba8a701ca0d7c99eebfc629d22e51a007021..b3bdb482bbe6f5fdf2d197fc1035082f495c448b 100644 (file)
@@ -1159,9 +1159,8 @@ int __l2cap_wait_ack(struct sock *sk)
        int timeo = HZ/5;
 
        add_wait_queue(sk_sleep(sk), &wait);
-       while ((chan->unacked_frames > 0 && chan->conn)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (chan->unacked_frames > 0 && chan->conn) {
                if (!timeo)
                        timeo = HZ/5;
 
@@ -1173,6 +1172,7 @@ int __l2cap_wait_ack(struct sock *sk)
                release_sock(sk);
                timeo = schedule_timeout(timeo);
                lock_sock(sk);
+               set_current_state(TASK_INTERRUPTIBLE);
 
                err = sock_error(sk);
                if (err)
index 5c36b3e8739cb706f9aa47e74a0ed9c5f72b8e24..61f1f623091dbcd89992a64a635fc8de62963795 100644 (file)
@@ -235,30 +235,26 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
 
        lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
        BT_DBG("sk %p timeo %ld", sk, timeo);
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+               nsk = bt_accept_dequeue(sk, newsock);
+               if (nsk)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -266,8 +262,12 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
@@ -993,7 +993,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
        INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
 
        sk->sk_destruct = l2cap_sock_destruct;
-       sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
+       sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
 
        sock_reset_flag(sk, SOCK_ZAPPED);
 
index 5759bb7054f7f4aca8822271b7de4da8997af915..5ba3f6df665cda5748044aaf21133f620979ca55 100644 (file)
@@ -62,7 +62,6 @@ static DEFINE_MUTEX(rfcomm_mutex);
 #define rfcomm_lock()  mutex_lock(&rfcomm_mutex)
 #define rfcomm_unlock()        mutex_unlock(&rfcomm_mutex)
 
-static unsigned long rfcomm_event;
 
 static LIST_HEAD(session_list);
 
@@ -120,7 +119,6 @@ static inline void rfcomm_schedule(void)
 {
        if (!rfcomm_thread)
                return;
-       set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
        wake_up_process(rfcomm_thread);
 }
 
@@ -2038,19 +2036,18 @@ static int rfcomm_run(void *unused)
 
        rfcomm_add_listener(BDADDR_ANY);
 
-       while (!kthread_should_stop()) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
-                       /* No pending events. Let's sleep.
-                        * Incoming connections and data will wake us up. */
-                       schedule();
-               }
-               set_current_state(TASK_RUNNING);
+
+               if (kthread_should_stop())
+                       break;
 
                /* Process stuff */
-               clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
                rfcomm_process_sessions();
+
+               schedule();
        }
+       __set_current_state(TASK_RUNNING);
 
        rfcomm_kill_listener();
 
index 8f01e6b11a7037d487c5a32072d460d56760a64a..482722bbc7a052c67053a95ad357463a5bc641bf 100644 (file)
@@ -485,11 +485,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
 
        lock_sock(sk);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        if (sk->sk_type != SOCK_STREAM) {
                err = -EINVAL;
                goto done;
@@ -501,19 +496,20 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               nsk = bt_accept_dequeue(sk, newsock);
+               if (nsk)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -521,8 +517,12 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock(sk);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
index 4c3621b5e0aa2344196767bdeb6be407918732b4..8270f05e3f1f27b0883020eede325df8d17154d0 100644 (file)
@@ -564,30 +564,26 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
 
        lock_sock(sk);
 
-       if (sk->sk_state != BT_LISTEN) {
-               err = -EBADFD;
-               goto done;
-       }
-
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
        BT_DBG("sk %p timeo %ld", sk, timeo);
 
        /* Wait for an incoming connection. (wake-one). */
        add_wait_queue_exclusive(sk_sleep(sk), &wait);
-       while (!(ch = bt_accept_dequeue(sk, newsock))) {
+       while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
-               if (!timeo) {
-                       err = -EAGAIN;
+
+               if (sk->sk_state != BT_LISTEN) {
+                       err = -EBADFD;
                        break;
                }
 
-               release_sock(sk);
-               timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               ch = bt_accept_dequeue(sk, newsock);
+               if (ch)
+                       break;
 
-               if (sk->sk_state != BT_LISTEN) {
-                       err = -EBADFD;
+               if (!timeo) {
+                       err = -EAGAIN;
                        break;
                }
 
@@ -595,8 +591,12 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag
                        err = sock_intr_errno(timeo);
                        break;
                }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock(sk);
        }
-       set_current_state(TASK_RUNNING);
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
 
        if (err)
index fd1aaf2a4a6c47eae03cd40c469055d86be12a14..e6cab51dceb078e43e8a0657f424b03364c82926 100644 (file)
@@ -167,12 +167,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
        u16 capab;
 
        skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
-
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer "
-                      "for addba resp frame\n", sdata->name);
+       if (!skb)
                return;
-       }
 
        skb_reserve(skb, local->hw.extra_tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
@@ -279,14 +275,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 
        /* prepare A-MPDU MLME for Rx aggregation */
        tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
-       if (!tid_agg_rx) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
-                                       tid);
-#endif
+       if (!tid_agg_rx)
                goto end;
-       }
 
        spin_lock_init(&tid_agg_rx->reorder_lock);
 
@@ -306,11 +296,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
        tid_agg_rx->reorder_time =
                kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
        if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_ERR "can not allocate reordering buffer "
-                              "to tid %d\n", tid);
-#endif
                kfree(tid_agg_rx->reorder_buf);
                kfree(tid_agg_rx->reorder_time);
                kfree(tid_agg_rx);
index 018108d1a2fd5079d16a04edb030520aca0d7d8b..3cef5a7281cb2d5c2db9c3c82a9b5037dbf550b8 100644 (file)
@@ -68,11 +68,9 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
 
        skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
 
-       if (!skb) {
-               printk(KERN_ERR "%s: failed to allocate buffer "
-                               "for addba request frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
        memset(mgmt, 0, 24);
@@ -106,19 +104,18 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
        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;
        u16 bar_control = 0;
 
        skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
-       if (!skb) {
-               printk(KERN_ERR "%s: failed to allocate buffer for "
-                       "bar frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
        bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
        memset(bar, 0, sizeof(*bar));
@@ -135,6 +132,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
        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)
@@ -364,7 +362,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
                return -EINVAL;
 
        if ((tid >= STA_TID_NUM) ||
-           !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION))
+           !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) ||
+           (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW))
                return -EINVAL;
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -413,11 +412,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
        /* prepare A-MPDU MLME for Tx aggregation */
        tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
        if (!tid_tx) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
-                                       tid);
-#endif
                ret = -ENOMEM;
                goto err_unlock_sta;
        }
@@ -574,14 +568,9 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
        struct ieee80211_ra_tid *ra_tid;
        struct sk_buff *skb = dev_alloc_skb(0);
 
-       if (unlikely(!skb)) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_WARNING "%s: Not enough memory, "
-                              "dropping start BA session", sdata->name);
-#endif
+       if (unlikely(!skb))
                return;
-       }
+
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
        memcpy(&ra_tid->ra, ra, ETH_ALEN);
        ra_tid->tid = tid;
@@ -727,14 +716,9 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
        struct ieee80211_ra_tid *ra_tid;
        struct sk_buff *skb = dev_alloc_skb(0);
 
-       if (unlikely(!skb)) {
-#ifdef CONFIG_MAC80211_HT_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_WARNING "%s: Not enough memory, "
-                              "dropping stop BA session", sdata->name);
-#endif
+       if (unlikely(!skb))
                return;
-       }
+
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
        memcpy(&ra_tid->ra, ra, ETH_ALEN);
        ra_tid->tid = tid;
index 0baaaecf4558858e531a2643c1bf7401abb0b8b8..b57ddf941e598a121ea1197fcd857a6e05bb50b0 100644 (file)
@@ -455,6 +455,20 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        return ret;
 }
 
+static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata,
+                                    struct beacon_parameters *params)
+{
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+
+       bss_conf->ssid_len = params->ssid_len;
+
+       if (params->ssid_len)
+               memcpy(bss_conf->ssid, params->ssid, params->ssid_len);
+
+       bss_conf->hidden_ssid =
+               (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
+}
+
 /*
  * This handles both adding a beacon and setting new beacon info
  */
@@ -548,8 +562,11 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
        kfree(old);
 
+       ieee80211_config_ap_ssid(sdata, params);
+
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
-                                               BSS_CHANGED_BEACON);
+                                               BSS_CHANGED_BEACON |
+                                               BSS_CHANGED_SSID);
        return 0;
 }
 
@@ -921,7 +938,7 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
        if (dst)
                return mesh_path_del(dst, sdata);
 
-       mesh_path_flush(sdata);
+       mesh_path_flush_by_iface(sdata);
        return 0;
 }
 
index 267ed45ef6a2aa05fa49c3078ca4a9cc32c86382..c9141168fd4343bc562168be5457ba80069fc549 100644 (file)
@@ -297,6 +297,9 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
        char *buf = kzalloc(mxln, GFP_KERNEL);
        int sf = 0; /* how many written so far */
 
+       if (!buf)
+               return 0;
+
        sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags);
        if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
                sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n");
@@ -347,6 +350,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
                sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n");
        if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
                sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n");
+       if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)
+               sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n");
 
        rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
        kfree(buf);
index 6e8eab7919e2e2a95db3ee761419b066d5c7655a..dd046291751852118783b087f81b6dee6a8da253 100644 (file)
@@ -340,6 +340,8 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
 IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
 IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
 IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
+IEEE80211_IF_FILE(dropped_frames_congestion,
+               u.mesh.mshstats.dropped_frames_congestion, DEC);
 IEEE80211_IF_FILE(dropped_frames_no_route,
                u.mesh.mshstats.dropped_frames_no_route, DEC);
 IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
@@ -463,6 +465,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
        MESHSTATS_ADD(fwded_frames);
        MESHSTATS_ADD(dropped_frames_ttl);
        MESHSTATS_ADD(dropped_frames_no_route);
+       MESHSTATS_ADD(dropped_frames_congestion);
        MESHSTATS_ADD(estab_plinks);
 #undef MESHSTATS_ADD
 }
index 7cfc286946c07db43e5b41b0705f827f9551f59b..2b9b52c69569b29c53756f7eb33fa7cbfb4f8b85 100644 (file)
@@ -186,12 +186,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
        u16 params;
 
        skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
-
-       if (!skb) {
-               printk(KERN_ERR "%s: failed to allocate buffer "
-                                       "for delba frame\n", sdata->name);
+       if (!skb)
                return;
-       }
 
        skb_reserve(skb, local->hw.extra_tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
index 56c24cabf26d3cb6552f157320e1e782acff16cf..836b2752ecd6f694523263c0cc5ae0475c26af87 100644 (file)
@@ -417,7 +417,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
  * must be callable in atomic context.
  */
 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-                                       u8 *bssid,u8 *addr, u32 supp_rates,
+                                       u8 *bssid, u8 *addr, u32 supp_rates,
                                        gfp_t gfp)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
index c204cee1189c4a858ca64c633ff0e8a26fcec453..21186e280ceb11e50f47446f83e203e387ba4dd5 100644 (file)
@@ -261,6 +261,7 @@ struct mesh_stats {
        __u32 fwded_frames;             /* Mesh total forwarded frames */
        __u32 dropped_frames_ttl;       /* Not transmitted since mesh_ttl == 0*/
        __u32 dropped_frames_no_route;  /* Not transmitted, no route found */
+       __u32 dropped_frames_congestion;/* Not forwarded due to congestion */
        atomic_t estab_plinks;
 };
 
@@ -670,6 +671,7 @@ enum queue_stop_reason {
        IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
        IEEE80211_QUEUE_STOP_REASON_SUSPEND,
        IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+       IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE,
 };
 
 #ifdef CONFIG_MAC80211_LEDS
@@ -1186,7 +1188,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);
index 556e7e6ddf0a6b26dda29a33c00ee6c4d0ffed5b..4116a7542b6b51af584dad4c6a22e264caa6fa18 100644 (file)
@@ -460,17 +460,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                synchronize_rcu();
                kfree(old_beacon);
 
-               /* free all potentially still buffered bcast frames */
-               while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-                       local->total_ps_buffered--;
-                       dev_kfree_skb(skb);
-               }
-
                /* down all dependent devices, that is VLANs */
                list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
                                         u.vlan.list)
                        dev_close(vlan->dev);
                WARN_ON(!list_empty(&sdata->u.ap.vlans));
+
+               /* free all potentially still buffered bcast frames */
+               local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
+               skb_queue_purge(&sdata->u.ap.ps_bc_buf);
        }
 
        if (going_down)
@@ -1214,6 +1212,9 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
        list_del_rcu(&sdata->list);
        mutex_unlock(&sdata->local->iflist_mtx);
 
+       if (ieee80211_vif_is_mesh(&sdata->vif))
+               mesh_path_flush_by_iface(sdata);
+
        synchronize_rcu();
        unregister_netdevice(sdata->dev);
 }
@@ -1233,6 +1234,9 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
        list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
                list_del(&sdata->list);
 
+               if (ieee80211_vif_is_mesh(&sdata->vif))
+                       mesh_path_flush_by_iface(sdata);
+
                unregister_netdevice_queue(sdata->dev, &unreg_list);
        }
        mutex_unlock(&local->iflist_mtx);
index 104fdd9862bdfe41cfefdf038dfe732be30616d4..a5809a1a623988791a1d4d831dff35d16e44d532 100644 (file)
@@ -1013,7 +1013,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
        cancel_work_sync(&local->reconfig_filter);
 
        ieee80211_clear_tx_pending(local);
-       sta_info_stop(local);
        rate_control_deinitialize(local);
 
        if (skb_queue_len(&local->skb_queue) ||
@@ -1025,6 +1024,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        destroy_workqueue(local->workqueue);
        wiphy_unregister(local->hw.wiphy);
+       sta_info_stop(local);
        ieee80211_wep_free(local);
        ieee80211_led_exit(local);
        kfree(local->int_scan_req);
index 28ab510e621a58a040d9f14a5c9384f09296ebb5..a4225ae69681dbac88d9e664f747526f55c5fb70 100644 (file)
@@ -200,10 +200,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
        }
 
        p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
-       if (!p) {
-               printk(KERN_DEBUG "o11s: could not allocate RMC entry\n");
+       if (!p)
                return 0;
-       }
+
        p->seqnum = seqnum;
        p->exp_time = jiffies + RMC_TIMEOUT;
        memcpy(p->sa, sa, ETH_ALEN);
@@ -464,8 +463,7 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
                memcpy(hdr->addr3, meshsa, ETH_ALEN);
                return 24;
        } else {
-               *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
-                               IEEE80211_FCTL_TODS);
+               *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
                /* RA TA DA SA */
                memset(hdr->addr1, 0, ETH_ALEN);   /* RA is resolved later */
                memcpy(hdr->addr2, meshsa, ETH_ALEN);
index 20272072171f8c0bf2548fd4d80ede98fa59db5a..7118e8e8855ce5bbff0b0b98e3a573b3bf3bb3aa 100644 (file)
@@ -80,7 +80,9 @@ enum mesh_deferred_task_flags {
  *     retry
  * @discovery_retries: number of discovery retries
  * @flags: mesh path flags, as specified on &enum mesh_path_flags
- * @state_lock: mesh path state lock
+ * @state_lock: mesh path state lock used to protect changes to the
+ * mpath itself.  No need to take this lock when adding or removing
+ * an mpath to a hash bucket on a path table.
  * @is_gate: the destination station of this path is a mesh gate
  *
  *
@@ -238,7 +240,6 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx,
                struct ieee80211_sub_if_data *sdata);
 void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
-void mesh_path_flush(struct ieee80211_sub_if_data *sdata);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_mgmt *mgmt, size_t len);
 int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
@@ -275,6 +276,7 @@ void mesh_pathtbl_unregister(void);
 int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata);
 void mesh_path_timer(unsigned long data);
 void mesh_path_flush_by_nexthop(struct sta_info *sta);
+void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
 void mesh_path_discard_frame(struct sk_buff *skb,
                struct ieee80211_sub_if_data *sdata);
 void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
index fd4f76a3e139ef3fb88211e058a58b044792a369..6df7913d7ca4baeadc784695aae2ebd311426809 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/slab.h>
+#include "wme.h"
 #include "mesh.h"
 
 #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
@@ -202,6 +203,26 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
        return 0;
 }
 
+
+/*  Headroom is not adjusted.  Caller should ensure that skb has sufficient
+ *  headroom in case the frame is encrypted. */
+static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
+               struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       skb_set_mac_header(skb, 0);
+       skb_set_network_header(skb, 0);
+       skb_set_transport_header(skb, 0);
+
+       /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
+       skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+       skb->priority = 7;
+
+       info->control.vif = &sdata->vif;
+       ieee80211_set_qos_hdr(sdata, skb);
+}
+
 /**
  * mesh_send_path error - Sends a PERR mesh management frame
  *
@@ -209,6 +230,10 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
  * @target_sn: SN of the broken destination
  * @target_rcode: reason code for this PERR
  * @ra: node this frame is addressed to
+ *
+ * Note: This function may be called with driver locks taken that the driver
+ * also acquires in the TX path.  To avoid a deadlock we don't transmit the
+ * frame directly but add it to the pending queue instead.
  */
 int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
                       __le16 target_rcode, const u8 *ra,
@@ -222,7 +247,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 
        if (!skb)
                return -1;
-       skb_reserve(skb, local->hw.extra_tx_headroom);
+       skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
        /* 25 is the size of the common mgmt part (24) plus the size of the
         * common action part (1)
         */
@@ -263,7 +288,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
        pos += 4;
        memcpy(pos, &target_rcode, 2);
 
-       ieee80211_tx_skb(sdata, skb);
+       /* see note in function header */
+       prepare_frame_for_deferred_tx(sdata, skb);
+       ieee80211_add_pending_skb(local, skb);
        return 0;
 }
 
index ede4f5242e0b7e1be9fc36cbda954a8ed9d7e5c0..332b5ff1e885e2f3cac6568a35b87782a727335b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <net/mac80211.h>
+#include "wme.h"
 #include "ieee80211_i.h"
 #include "mesh.h"
 
@@ -48,8 +49,10 @@ static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
 int mesh_paths_generation;
 
 /* This lock will have the grow table function as writer and add / delete nodes
- * as readers. When reading the table (i.e. doing lookups) we are well protected
- * by RCU
+ * as readers. RCU provides sufficient protection only when reading the table
+ * (i.e. doing lookups).  Adding or adding or removing nodes requires we take
+ * the read lock or we risk operating on an old table.  The write lock is only
+ * needed when modifying the number of buckets a table.
  */
 static DEFINE_RWLOCK(pathtbl_resize_lock);
 
@@ -210,6 +213,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
        struct ieee80211_hdr *hdr;
        struct sk_buff_head tmpq;
        unsigned long flags;
+       struct ieee80211_sub_if_data *sdata = mpath->sdata;
 
        rcu_assign_pointer(mpath->next_hop, sta);
 
@@ -220,6 +224,8 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
        while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) {
                hdr = (struct ieee80211_hdr *) skb->data;
                memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
+               skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
+               ieee80211_set_qos_hdr(sdata, skb);
                __skb_queue_tail(&tmpq, skb);
        }
 
@@ -333,25 +339,14 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath,
 }
 
 
-/**
- * mesh_path_lookup - look up a path in the mesh path table
- * @dst: hardware address (ETH_ALEN length) of destination
- * @sdata: local subif
- *
- * Returns: pointer to the mesh path structure, or NULL if not found
- *
- * Locking: must be called within a read rcu section.
- */
-struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
+static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst,
+                                         struct ieee80211_sub_if_data *sdata)
 {
        struct mesh_path *mpath;
        struct hlist_node *n;
        struct hlist_head *bucket;
-       struct mesh_table *tbl;
        struct mpath_node *node;
 
-       tbl = rcu_dereference(mesh_paths);
-
        bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
        hlist_for_each_entry_rcu(node, n, bucket, list) {
                mpath = node->mpath;
@@ -359,8 +354,7 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
                                memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
                        if (MPATH_EXPIRED(mpath)) {
                                spin_lock_bh(&mpath->state_lock);
-                               if (MPATH_EXPIRED(mpath))
-                                       mpath->flags &= ~MESH_PATH_ACTIVE;
+                               mpath->flags &= ~MESH_PATH_ACTIVE;
                                spin_unlock_bh(&mpath->state_lock);
                        }
                        return mpath;
@@ -369,31 +363,23 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
        return NULL;
 }
 
-struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
+/**
+ * mesh_path_lookup - look up a path in the mesh path table
+ * @dst: hardware address (ETH_ALEN length) of destination
+ * @sdata: local subif
+ *
+ * Returns: pointer to the mesh path structure, or NULL if not found
+ *
+ * Locking: must be called within a read rcu section.
+ */
+struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
 {
-       struct mesh_path *mpath;
-       struct hlist_node *n;
-       struct hlist_head *bucket;
-       struct mesh_table *tbl;
-       struct mpath_node *node;
-
-       tbl = rcu_dereference(mpp_paths);
+       return path_lookup(rcu_dereference(mesh_paths), dst, sdata);
+}
 
-       bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
-       hlist_for_each_entry_rcu(node, n, bucket, list) {
-               mpath = node->mpath;
-               if (mpath->sdata == sdata &&
-                   memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
-                       if (MPATH_EXPIRED(mpath)) {
-                               spin_lock_bh(&mpath->state_lock);
-                               if (MPATH_EXPIRED(mpath))
-                                       mpath->flags &= ~MESH_PATH_ACTIVE;
-                               spin_unlock_bh(&mpath->state_lock);
-                       }
-                       return mpath;
-               }
-       }
-       return NULL;
+struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
+{
+       return path_lookup(rcu_dereference(mpp_paths), dst, sdata);
 }
 
 
@@ -420,8 +406,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
                if (j++ == idx) {
                        if (MPATH_EXPIRED(node->mpath)) {
                                spin_lock_bh(&node->mpath->state_lock);
-                               if (MPATH_EXPIRED(node->mpath))
-                                       node->mpath->flags &= ~MESH_PATH_ACTIVE;
+                               node->mpath->flags &= ~MESH_PATH_ACTIVE;
                                spin_unlock_bh(&node->mpath->state_lock);
                        }
                        return node->mpath;
@@ -776,22 +761,47 @@ void mesh_plink_broken(struct sta_info *sta)
        tbl = rcu_dereference(mesh_paths);
        for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
-               spin_lock_bh(&mpath->state_lock);
                if (rcu_dereference(mpath->next_hop) == sta &&
                    mpath->flags & MESH_PATH_ACTIVE &&
                    !(mpath->flags & MESH_PATH_FIXED)) {
+                       spin_lock_bh(&mpath->state_lock);
                        mpath->flags &= ~MESH_PATH_ACTIVE;
                        ++mpath->sn;
                        spin_unlock_bh(&mpath->state_lock);
                        mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,
                                        mpath->dst, cpu_to_le32(mpath->sn),
                                        reason, bcast, sdata);
-               } else
-               spin_unlock_bh(&mpath->state_lock);
+               }
        }
        rcu_read_unlock();
 }
 
+static void mesh_path_node_reclaim(struct rcu_head *rp)
+{
+       struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
+       struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
+
+       del_timer_sync(&node->mpath->timer);
+       atomic_dec(&sdata->u.mesh.mpaths);
+       kfree(node->mpath);
+       kfree(node);
+}
+
+/* needs to be called with the corresponding hashwlock taken */
+static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
+{
+       struct mesh_path *mpath;
+       mpath = node->mpath;
+       spin_lock(&mpath->state_lock);
+       mpath->flags |= MESH_PATH_RESOLVING;
+       if (mpath->is_gate)
+               mesh_gate_del(tbl, mpath);
+       hlist_del_rcu(&node->list);
+       call_rcu(&node->rcu, mesh_path_node_reclaim);
+       spin_unlock(&mpath->state_lock);
+       atomic_dec(&tbl->entries);
+}
+
 /**
  * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
  *
@@ -812,42 +822,59 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
        int i;
 
        rcu_read_lock();
-       tbl = rcu_dereference(mesh_paths);
+       read_lock_bh(&pathtbl_resize_lock);
+       tbl = resize_dereference_mesh_paths();
        for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
-               if (rcu_dereference(mpath->next_hop) == sta)
-                       mesh_path_del(mpath->dst, mpath->sdata);
+               if (rcu_dereference(mpath->next_hop) == sta) {
+                       spin_lock_bh(&tbl->hashwlock[i]);
+                       __mesh_path_del(tbl, node);
+                       spin_unlock_bh(&tbl->hashwlock[i]);
+               }
        }
+       read_unlock_bh(&pathtbl_resize_lock);
        rcu_read_unlock();
 }
 
-void mesh_path_flush(struct ieee80211_sub_if_data *sdata)
+static void table_flush_by_iface(struct mesh_table *tbl,
+                                struct ieee80211_sub_if_data *sdata)
 {
-       struct mesh_table *tbl;
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_node *p;
        int i;
 
-       rcu_read_lock();
-       tbl = rcu_dereference(mesh_paths);
+       WARN_ON(!rcu_read_lock_held());
        for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
-               if (mpath->sdata == sdata)
-                       mesh_path_del(mpath->dst, mpath->sdata);
+               if (mpath->sdata != sdata)
+                       continue;
+               spin_lock_bh(&tbl->hashwlock[i]);
+               __mesh_path_del(tbl, node);
+               spin_unlock_bh(&tbl->hashwlock[i]);
        }
-       rcu_read_unlock();
 }
 
-static void mesh_path_node_reclaim(struct rcu_head *rp)
+/**
+ * mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface
+ *
+ * This function deletes both mesh paths as well as mesh portal paths.
+ *
+ * @sdata - interface data to match
+ *
+ */
+void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
 {
-       struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
-       struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
+       struct mesh_table *tbl;
 
-       del_timer_sync(&node->mpath->timer);
-       atomic_dec(&sdata->u.mesh.mpaths);
-       kfree(node->mpath);
-       kfree(node);
+       rcu_read_lock();
+       read_lock_bh(&pathtbl_resize_lock);
+       tbl = resize_dereference_mesh_paths();
+       table_flush_by_iface(tbl, sdata);
+       tbl = resize_dereference_mpp_paths();
+       table_flush_by_iface(tbl, sdata);
+       read_unlock_bh(&pathtbl_resize_lock);
+       rcu_read_unlock();
 }
 
 /**
@@ -878,14 +905,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
                mpath = node->mpath;
                if (mpath->sdata == sdata &&
                    memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
-                       spin_lock_bh(&mpath->state_lock);
-                       if (mpath->is_gate)
-                               mesh_gate_del(tbl, mpath);
-                       mpath->flags |= MESH_PATH_RESOLVING;
-                       hlist_del_rcu(&node->list);
-                       call_rcu(&node->rcu, mesh_path_node_reclaim);
-                       atomic_dec(&tbl->entries);
-                       spin_unlock_bh(&mpath->state_lock);
+                       __mesh_path_del(tbl, node);
                        goto enddel;
                }
        }
@@ -991,9 +1011,14 @@ void mesh_path_discard_frame(struct sk_buff *skb,
 
                da = hdr->addr3;
                ra = hdr->addr1;
+               rcu_read_lock();
                mpath = mesh_path_lookup(da, sdata);
-               if (mpath)
+               if (mpath) {
+                       spin_lock_bh(&mpath->state_lock);
                        sn = ++mpath->sn;
+                       spin_unlock_bh(&mpath->state_lock);
+               }
+               rcu_read_unlock();
                mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data,
                                   cpu_to_le32(sn), reason, ra, sdata);
        }
@@ -1074,6 +1099,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
 int mesh_pathtbl_init(void)
 {
        struct mesh_table *tbl_path, *tbl_mpp;
+       int ret;
 
        tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
        if (!tbl_path)
@@ -1082,18 +1108,26 @@ int mesh_pathtbl_init(void)
        tbl_path->copy_node = &mesh_path_node_copy;
        tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
        tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
+       if (!tbl_path->known_gates) {
+               ret = -ENOMEM;
+               goto free_path;
+       }
        INIT_HLIST_HEAD(tbl_path->known_gates);
 
 
        tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
        if (!tbl_mpp) {
-               mesh_table_free(tbl_path, true);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto free_path;
        }
        tbl_mpp->free_node = &mesh_path_node_free;
        tbl_mpp->copy_node = &mesh_path_node_copy;
        tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
        tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC);
+       if (!tbl_mpp->known_gates) {
+               ret = -ENOMEM;
+               goto free_mpp;
+       }
        INIT_HLIST_HEAD(tbl_mpp->known_gates);
 
        /* Need no locking since this is during init */
@@ -1101,6 +1135,12 @@ int mesh_pathtbl_init(void)
        RCU_INIT_POINTER(mpp_paths, tbl_mpp);
 
        return 0;
+
+free_mpp:
+       mesh_table_free(tbl_mpp, true);
+free_path:
+       mesh_table_free(tbl_path, true);
+       return ret;
 }
 
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
@@ -1117,14 +1157,10 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
                if (node->mpath->sdata != sdata)
                        continue;
                mpath = node->mpath;
-               spin_lock_bh(&mpath->state_lock);
                if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
                    (!(mpath->flags & MESH_PATH_FIXED)) &&
-                    time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) {
-                       spin_unlock_bh(&mpath->state_lock);
+                    time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
                        mesh_path_del(mpath->dst, mpath->sdata);
-               } else
-                       spin_unlock_bh(&mpath->state_lock);
        }
        rcu_read_unlock();
 }
index 1a00d0f701c36f64c3c6b99589044ae9b945a346..1213a23ff0fa7e28cfb547bbbcb29855891974f2 100644 (file)
@@ -43,6 +43,10 @@ enum plink_event {
        CLS_IGNR
 };
 
+static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
+               enum ieee80211_self_protected_actioncode action,
+               u8 *da, __le16 llid, __le16 plid, __le16 reason);
+
 static inline
 void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
 {
@@ -88,7 +92,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return NULL;
 
-       sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH;
+       sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME;
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
        rate_control_rate_init(sta);
 
@@ -133,6 +137,10 @@ void mesh_plink_deactivate(struct sta_info *sta)
 
        spin_lock_bh(&sta->lock);
        deactivated = __mesh_plink_deactivate(sta);
+       sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
+       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
+                           sta->sta.addr, sta->llid, sta->plid,
+                           sta->reason);
        spin_unlock_bh(&sta->lock);
 
        if (deactivated)
index 60a6f273cd3060293a3b601e76a8dfaa355e865a..1a59fb6630d4f063a1e1098a752ca1f4c9a9aff1 100644 (file)
@@ -160,7 +160,8 @@ static int ecw2cw(int ecw)
  */
 static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
                               struct ieee80211_ht_info *hti,
-                              const u8 *bssid, u16 ap_ht_cap_flags)
+                              const u8 *bssid, u16 ap_ht_cap_flags,
+                              bool beacon_htcap_ie)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
@@ -232,6 +233,21 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
                WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
        }
 
+       if (beacon_htcap_ie && (prev_chantype != channel_type)) {
+               /*
+                * Whenever the AP announces the HT mode change that can be
+                * 40MHz intolerant or etc., it would be safer to stop tx
+                * queues before doing hw config to avoid buffer overflow.
+                */
+               ieee80211_stop_queues_by_reason(&sdata->local->hw,
+                               IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
+
+               /* flush out all packets */
+               synchronize_net();
+
+               drv_flush(local, false);
+       }
+
        /* channel_type change automatically detected */
        ieee80211_hw_config(local, 0);
 
@@ -243,6 +259,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
                                                 IEEE80211_RC_HT_CHANGED,
                                                 channel_type);
                rcu_read_unlock();
+
+               if (beacon_htcap_ie)
+                       ieee80211_wake_queues_by_reason(&sdata->local->hw,
+                               IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
        }
 
        ht_opmode = le16_to_cpu(hti->operation_mode);
@@ -271,11 +291,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgmt *mgmt;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for "
-                      "deauth/disassoc frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
@@ -354,11 +372,9 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
                return;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30);
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr "
-                      "nullfunc frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
@@ -394,6 +410,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
                /* call "hw_config" only if doing sw channel switch */
                ieee80211_hw_config(sdata->local,
                        IEEE80211_CONF_CHANGE_CHANNEL);
+       } else {
+               /* update the device channel directly */
+               sdata->local->hw.conf.channel = sdata->local->oper_channel;
        }
 
        /* XXX: shouldn't really modify cfg80211-owned data! */
@@ -1589,7 +1608,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
            (sdata->local->hw.queues >= 4) &&
            !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
                changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
-                                              cbss->bssid, ap_ht_cap_flags);
+                                              cbss->bssid, ap_ht_cap_flags,
+                                              false);
 
        /* set AID and assoc capability,
         * ieee80211_set_associated() will tell the driver */
@@ -1923,7 +1943,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                rcu_read_unlock();
 
                changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
-                                              bssid, ap_ht_cap_flags);
+                                              bssid, ap_ht_cap_flags, true);
        }
 
        /* Note: country IE parsing is done for us by cfg80211 */
@@ -2441,11 +2461,8 @@ static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,
        int err;
 
        sta = sta_info_alloc(sdata, bssid, GFP_KERNEL);
-       if (!sta) {
-               printk(KERN_DEBUG "%s: failed to alloc STA entry for"
-                          " the AP\n", sdata->name);
+       if (!sta)
                return -ENOMEM;
-       }
 
        sta->dummy = true;
 
index 21588386a30207598d9d565841f8f4caaaa08d50..e19249b0f97124697a5d8c64c9c5e70ab397f0a1 100644 (file)
@@ -452,7 +452,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
 
        if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
                minstrel_ht_update_stats(mp, mi);
-               minstrel_aggr_check(mp, sta, skb);
+               if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
+                       minstrel_aggr_check(mp, sta, skb);
        }
 }
 
index f45fd2fedc2415b6f5f68a58b2c00439dc4a71e6..db46601e50bfaa4b88b82fa475ed6351beb9014d 100644 (file)
@@ -476,7 +476,6 @@ static ieee80211_rx_result
 ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-       unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
        char *dev_addr = rx->sdata->vif.addr;
 
        if (ieee80211_is_data(hdr->frame_control)) {
@@ -524,14 +523,6 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
        }
 
-#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
-
-       if (ieee80211_is_data(hdr->frame_control) &&
-           is_multicast_ether_addr(hdr->addr1) &&
-           mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
-               return RX_DROP_MONITOR;
-#undef msh_h_get
-
        return RX_CONTINUE;
 }
 
@@ -1840,6 +1831,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
+       /* frame is in RMC, don't forward */
+       if (ieee80211_is_data(hdr->frame_control) &&
+           is_multicast_ether_addr(hdr->addr1) &&
+           mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
+               return RX_DROP_MONITOR;
+
        if (!ieee80211_is_data(hdr->frame_control))
                return RX_CONTINUE;
 
@@ -1847,6 +1844,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                /* illegal frame */
                return RX_DROP_MONITOR;
 
+       if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) {
+               IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
+                                               dropped_frames_congestion);
+               return RX_DROP_MONITOR;
+       }
+
        if (mesh_hdr->flags & MESH_FLAGS_AE) {
                struct mesh_path *mppath;
                char *proxied_addr;
@@ -1902,13 +1905,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                        memset(info, 0, sizeof(*info));
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                        info->control.vif = &rx->sdata->vif;
-                       skb_set_queue_mapping(skb,
-                               ieee80211_select_queue(rx->sdata, fwd_skb));
-                       ieee80211_set_qos_hdr(local, skb);
-                       if (is_multicast_ether_addr(fwd_hdr->addr1))
+                       if (is_multicast_ether_addr(fwd_hdr->addr1)) {
                                IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
                                                                fwded_mcast);
-                       else {
+                               skb_set_queue_mapping(fwd_skb,
+                                       ieee80211_select_queue(sdata, fwd_skb));
+                               ieee80211_set_qos_hdr(sdata, fwd_skb);
+                       } else {
                                int err;
                                /*
                                 * Save TA to addr1 to send TA a path error if a
@@ -2569,12 +2572,12 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
                CALL_RXH(ieee80211_rx_h_ps_poll)
                CALL_RXH(ieee80211_rx_h_michael_mic_verify)
                /* must be after MMIC verify so header is counted in MPDU mic */
-               CALL_RXH(ieee80211_rx_h_remove_qos_control)
-               CALL_RXH(ieee80211_rx_h_amsdu)
 #ifdef CONFIG_MAC80211_MESH
                if (ieee80211_vif_is_mesh(&rx->sdata->vif))
                        CALL_RXH(ieee80211_rx_h_mesh_fwding);
 #endif
+               CALL_RXH(ieee80211_rx_h_remove_qos_control)
+               CALL_RXH(ieee80211_rx_h_amsdu)
                CALL_RXH(ieee80211_rx_h_data)
                CALL_RXH(ieee80211_rx_h_ctrl);
                CALL_RXH(ieee80211_rx_h_mgmt_check)
index 7733f66ee2c411021b2232b70cee1382e51492c7..578eea3fc04d27a25eeddc84f244fe6de24dc6a8 100644 (file)
@@ -32,12 +32,8 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
 
        skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom +
                                sizeof(struct ieee80211_msrment_ie));
-
-       if (!skb) {
-               printk(KERN_ERR "%s: failed to allocate buffer for "
-                               "measurement report frame\n", sdata->name);
+       if (!skb)
                return;
-       }
 
        skb_reserve(skb, local->hw.extra_tx_headroom);
        msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
index 17caba27040b49e9668dcaf869c18165b229fe75..c52e58c0a979a757574334f53061d2e610246fba 100644 (file)
@@ -691,14 +691,13 @@ void sta_info_clear_tim_bit(struct sta_info *sta)
        spin_unlock_irqrestore(&sta->local->sta_lock, flags);
 }
 
-static int sta_info_buffer_expired(struct sta_info *sta,
-                                  struct sk_buff *skb)
+static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info;
        int timeout;
 
        if (!skb)
-               return 0;
+               return false;
 
        info = IEEE80211_SKB_CB(skb);
 
@@ -718,9 +717,6 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
        unsigned long flags;
        struct sk_buff *skb;
 
-       if (skb_queue_empty(&sta->ps_tx_buf))
-               return false;
-
        for (;;) {
                spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
                skb = skb_peek(&sta->ps_tx_buf);
@@ -745,7 +741,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
                        sta_info_clear_tim_bit(sta);
        }
 
-       return true;
+       return !skb_queue_empty(&sta->ps_tx_buf);
 }
 
 static int __must_check __sta_info_destroy(struct sta_info *sta)
@@ -796,7 +792,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
                BUG_ON(!sdata->bss);
 
                atomic_dec(&sdata->bss->num_sta_ps);
-               __sta_info_clear_tim_bit(sdata->bss, sta);
+               sta_info_clear_tim_bit(sta);
        }
 
        local->num_sta--;
index e9eb565506da06ac3f5d8b5bd4a166f9483d6a79..56a3d38a2cd19479520f875d080d53127a37a73d 100644 (file)
@@ -86,6 +86,8 @@ enum ieee80211_sta_info_flags {
  * @stop_initiator: initiator of a session stop
  * @tx_stop: TX DelBA frame when stopping
  * @buf_size: reorder buffer size at receiver
+ * @failed_bar_ssn: ssn of the last failed BAR tx attempt
+ * @bar_pending: BAR needs to be re-sent
  *
  * This structure's lifetime is managed by RCU, assignments to
  * the array holding it must hold the aggregation mutex.
@@ -106,6 +108,9 @@ struct tid_ampdu_tx {
        u8 stop_initiator;
        bool tx_stop;
        u8 buf_size;
+
+       u16 failed_bar_ssn;
+       bool bar_pending;
 };
 
 /**
index e51bd2a1a0735de0adfff2566c5f1d6b584ef6de..d50358c45ab079bd6a023a1a2a764042bfd17cfc 100644 (file)
@@ -127,12 +127,32 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
        dev_kfree_skb(skb);
 }
 
+static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
+{
+       struct tid_ampdu_tx *tid_tx;
+
+       tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+       if (!tid_tx || !tid_tx->bar_pending)
+               return;
+
+       tid_tx->bar_pending = false;
+       ieee80211_send_bar(&sta->sdata->vif, addr, tid, tid_tx->failed_bar_ssn);
+}
+
 static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
 {
        struct ieee80211_mgmt *mgmt = (void *) skb->data;
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
 
+       if (ieee80211_is_data_qos(mgmt->frame_control)) {
+               struct ieee80211_hdr *hdr = (void *) skb->data;
+               u8 *qc = ieee80211_get_qos_ctl(hdr);
+               u16 tid = qc[0] & 0xf;
+
+               ieee80211_check_pending_bar(sta, hdr->addr1, tid);
+       }
+
        if (ieee80211_is_action(mgmt->frame_control) &&
            sdata->vif.type == NL80211_IFTYPE_STATION &&
            mgmt->u.action.category == WLAN_CATEGORY_HT &&
@@ -161,6 +181,18 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
        }
 }
 
+static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
+{
+       struct tid_ampdu_tx *tid_tx;
+
+       tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
+       if (!tid_tx)
+               return;
+
+       tid_tx->failed_bar_ssn = ssn;
+       tid_tx->bar_pending = true;
+}
+
 /*
  * Use a static threshold for now, best value to be determined
  * by testing ...
@@ -241,23 +273,28 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                        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);
                }
 
                if (!acked && ieee80211_is_back_req(fc)) {
+                       u16 control;
+
                        /*
-                        * BAR failed, let's tear down the BA session as a
-                        * last resort as some STAs (Intel 5100 on Windows)
-                        * can get stuck when the BA window isn't flushed
-                        * correctly.
+                        * BAR failed, store the last SSN and retry sending
+                        * the BAR when the next unicast transmission on the
+                        * same TID succeeds.
                         */
                        bar = (struct ieee80211_bar *) skb->data;
-                       if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
-                               tid = (bar->control &
+                       control = le16_to_cpu(bar->control);
+                       if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
+                               u16 ssn = le16_to_cpu(bar->start_seq_num);
+
+                               tid = (control &
                                       IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
                                      IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
-                               ieee80211_stop_tx_ba_session(&sta->sta, tid);
+
+                               ieee80211_set_bar_pending(sta, tid, ssn);
                        }
                }
 
index 01072639666fb77bccceda47aad242c6ec241405..7cd6c28968b282763fa4739fd13296ed3ad99550 100644 (file)
@@ -1232,7 +1232,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                tx->sta = sta_info_get(sdata, hdr->addr1);
 
        if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
-           (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
+           (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) &&
+           !(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) {
                struct tid_ampdu_tx *tid_tx;
 
                qc = ieee80211_get_qos_ctl(hdr);
@@ -1595,7 +1596,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
                                return;
                        }
 
-       ieee80211_set_qos_hdr(local, skb);
+       ieee80211_set_qos_hdr(sdata, skb);
        ieee80211_tx(sdata, skb, false);
        rcu_read_unlock();
 }
@@ -1878,6 +1879,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                rcu_read_unlock();
        }
 
+       /* For mesh, the use of the QoS header is mandatory */
+       if (ieee80211_vif_is_mesh(&sdata->vif))
+               sta_flags |= WLAN_STA_WME;
+
        /* receiver and we are QoS enabled, use a QoS type frame */
        if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) {
                fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
@@ -2365,11 +2370,9 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
        local = sdata->local;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for "
-                      "pspoll template\n", sdata->name);
+       if (!skb)
                return NULL;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
@@ -2405,11 +2408,9 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
        local = sdata->local;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
-                      "template\n", sdata->name);
+       if (!skb)
                return NULL;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
@@ -2444,11 +2445,8 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
                            ie_ssid_len + ie_len);
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
-                      "request template\n", sdata->name);
+       if (!skb)
                return NULL;
-       }
 
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
index ce916ff6ef089d54b0e98f31126e054f88b86992..4b1466d5b6a1da6bbbe286765c805d445c6465b8 100644 (file)
@@ -707,11 +707,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
                            sizeof(*mgmt) + 6 + extra_len);
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
-                      "frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
@@ -864,11 +862,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 
        /* FIXME: come up with a proper value */
        buf = kmalloc(200 + ie_len, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_DEBUG "%s: failed to allocate temporary IE "
-                      "buffer\n", sdata->name);
+       if (!buf)
                return NULL;
-       }
 
        /*
         * Do not send DS Channel parameter for directed probe requests
@@ -1082,6 +1077,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        changed |= BSS_CHANGED_IBSS;
                        /* fall through */
                case NL80211_IFTYPE_AP:
+                       changed |= BSS_CHANGED_SSID;
+                       /* fall through */
                case NL80211_IFTYPE_MESH_POINT:
                        changed |= BSS_CHANGED_BEACON |
                                   BSS_CHANGED_BEACON_ENABLED;
index 7a49532f14cbff932fbfdbfaddc53abc0c974c17..971004c9b04f62b6c59557966b2985591e6d63e6 100644 (file)
@@ -83,11 +83,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                break;
 #ifdef CONFIG_MAC80211_MESH
        case NL80211_IFTYPE_MESH_POINT:
-               /*
-                * XXX: This is clearly broken ... but already was before,
-                * because ieee80211_fill_mesh_addresses() would clear A1
-                * except for multicast addresses.
-                */
+               ra = skb->data;
                break;
 #endif
        case NL80211_IFTYPE_STATION:
@@ -139,7 +135,8 @@ u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
        return ieee802_1d_to_ac[skb->priority];
 }
 
-void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
+void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
+                          struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (void *)skb->data;
 
@@ -150,10 +147,11 @@ void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
 
                tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 
-               if (unlikely(local->wifi_wme_noack_test))
+               if (unlikely(sdata->local->wifi_wme_noack_test))
                        ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
-               /* qos header is 2 bytes, second reserved */
+               /* qos header is 2 bytes */
                *p++ = ack_policy | tid;
-               *p = 0;
+               *p = ieee80211_vif_is_mesh(&sdata->vif) ?
+                       (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0;
        }
 }
index faead6d0202659877f8b86c427805b5becb54999..34e166fbf4d4cbd595cc148ac53d6c81ded60d73 100644 (file)
@@ -17,7 +17,8 @@ extern const int ieee802_1d_to_ac[8];
 
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                           struct sk_buff *skb);
-void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb);
+void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
+                          struct sk_buff *skb);
 u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
                               struct sk_buff *skb);
 
index 380b9a7462b67dc426fa875db3ccafa54b7fb87e..bac34394c05ef9262e41df4bc1ce2bda6dcb188f 100644 (file)
@@ -229,11 +229,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
                        wk->ie_len + /* extra IEs */
                        9, /* WMM */
                        GFP_KERNEL);
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
-                      "frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        capab = WLAN_CAPABILITY_ESS;
index 33e095b124b323f93a94b873121f7a89e579bf24..58cddadf8e8e2dfb5a915d621bebdc42b032609e 100644 (file)
@@ -13,4 +13,6 @@ menuconfig NFC
          To compile this support as a module, choose M here: the module will
          be called nfc.
 
+source "net/nfc/nci/Kconfig"
+
 source "drivers/nfc/Kconfig"
index 16250c3538519bbc724d9ebdf9ea629fc576daa5..fbb550f2377b9298f755ee5a63428d9f93a06b69 100644 (file)
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_NFC) += nfc.o
+obj-$(CONFIG_NFC_NCI) += nci/
 
 nfc-objs := core.o netlink.o af_nfc.o rawsock.o
index 284e2f6a14ff490f287354bdd60058b87123d475..47e02c1b8c02eea81a67f4432e6d45311ba6bd73 100644 (file)
@@ -52,6 +52,80 @@ int nfc_printk(const char *level, const char *format, ...)
 }
 EXPORT_SYMBOL(nfc_printk);
 
+/**
+ * nfc_dev_up - turn on the NFC device
+ *
+ * @dev: The nfc device to be turned on
+ *
+ * The device remains up until the nfc_dev_down function is called.
+ */
+int nfc_dev_up(struct nfc_dev *dev)
+{
+       int rc = 0;
+
+       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (dev->dev_up) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       if (dev->ops->dev_up)
+               rc = dev->ops->dev_up(dev);
+
+       if (!rc)
+               dev->dev_up = true;
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
+/**
+ * nfc_dev_down - turn off the NFC device
+ *
+ * @dev: The nfc device to be turned off
+ */
+int nfc_dev_down(struct nfc_dev *dev)
+{
+       int rc = 0;
+
+       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (!dev->dev_up) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       if (dev->polling || dev->remote_activated) {
+               rc = -EBUSY;
+               goto error;
+       }
+
+       if (dev->ops->dev_down)
+               dev->ops->dev_down(dev);
+
+       dev->dev_up = false;
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
 /**
  * nfc_start_poll - start polling for nfc targets
  *
@@ -144,6 +218,8 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
        }
 
        rc = dev->ops->activate_target(dev, target_idx, protocol);
+       if (!rc)
+               dev->remote_activated = true;
 
 error:
        device_unlock(&dev->dev);
@@ -170,6 +246,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
        }
 
        dev->ops->deactivate_target(dev, target_idx);
+       dev->remote_activated = false;
 
 error:
        device_unlock(&dev->dev);
diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig
new file mode 100644 (file)
index 0000000..decdc49
--- /dev/null
@@ -0,0 +1,10 @@
+config NFC_NCI
+       depends on NFC && EXPERIMENTAL
+       tristate "NCI protocol support (EXPERIMENTAL)"
+       default n
+       help
+         NCI (NFC Controller Interface) is a communication protocol between
+         an NFC Controller (NFCC) and a Device Host (DH).
+
+         Say Y here to compile NCI support into the kernel or say M to
+         compile it as module (nci).
diff --git a/net/nfc/nci/Makefile b/net/nfc/nci/Makefile
new file mode 100644 (file)
index 0000000..cdb3a2e
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux NFC NCI layer.
+#
+
+obj-$(CONFIG_NFC_NCI) += nci.o
+
+nci-objs := core.o data.o lib.o ntf.o rsp.o
\ No newline at end of file
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
new file mode 100644 (file)
index 0000000..895e5fd
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on hci_core.c, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+
+#include "../nfc.h"
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/nfc.h>
+
+static void nci_cmd_work(struct work_struct *work);
+static void nci_rx_work(struct work_struct *work);
+static void nci_tx_work(struct work_struct *work);
+
+/* ---- NCI requests ---- */
+
+void nci_req_complete(struct nci_dev *ndev, int result)
+{
+       if (ndev->req_status == NCI_REQ_PEND) {
+               ndev->req_result = result;
+               ndev->req_status = NCI_REQ_DONE;
+               complete(&ndev->req_completion);
+       }
+}
+
+static void nci_req_cancel(struct nci_dev *ndev, int err)
+{
+       if (ndev->req_status == NCI_REQ_PEND) {
+               ndev->req_result = err;
+               ndev->req_status = NCI_REQ_CANCELED;
+               complete(&ndev->req_completion);
+       }
+}
+
+/* Execute request and wait for completion. */
+static int __nci_request(struct nci_dev *ndev,
+       void (*req)(struct nci_dev *ndev, unsigned long opt),
+       unsigned long opt,
+       __u32 timeout)
+{
+       int rc = 0;
+       unsigned long completion_rc;
+
+       ndev->req_status = NCI_REQ_PEND;
+
+       init_completion(&ndev->req_completion);
+       req(ndev, opt);
+       completion_rc = wait_for_completion_interruptible_timeout(
+                                                       &ndev->req_completion,
+                                                       timeout);
+
+       nfc_dbg("wait_for_completion return %ld", completion_rc);
+
+       if (completion_rc > 0) {
+               switch (ndev->req_status) {
+               case NCI_REQ_DONE:
+                       rc = nci_to_errno(ndev->req_result);
+                       break;
+
+               case NCI_REQ_CANCELED:
+                       rc = -ndev->req_result;
+                       break;
+
+               default:
+                       rc = -ETIMEDOUT;
+                       break;
+               }
+       } else {
+               nfc_err("wait_for_completion_interruptible_timeout failed %ld",
+                       completion_rc);
+
+               rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc));
+       }
+
+       ndev->req_status = ndev->req_result = 0;
+
+       return rc;
+}
+
+static inline int nci_request(struct nci_dev *ndev,
+               void (*req)(struct nci_dev *ndev, unsigned long opt),
+               unsigned long opt, __u32 timeout)
+{
+       int rc;
+
+       if (!test_bit(NCI_UP, &ndev->flags))
+               return -ENETDOWN;
+
+       /* Serialize all requests */
+       mutex_lock(&ndev->req_lock);
+       rc = __nci_request(ndev, req, opt, timeout);
+       mutex_unlock(&ndev->req_lock);
+
+       return rc;
+}
+
+static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
+{
+       nci_send_cmd(ndev, NCI_OP_CORE_RESET_CMD, 0, NULL);
+}
+
+static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
+{
+       nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+}
+
+static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
+{
+       struct nci_rf_disc_map_cmd cmd;
+       struct nci_core_conn_create_cmd conn_cmd;
+       int i;
+
+       /* create static rf connection */
+       conn_cmd.target_handle = 0;
+       conn_cmd.num_target_specific_params = 0;
+       nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, &conn_cmd);
+
+       /* set rf mapping configurations */
+       cmd.num_mapping_configs = 0;
+
+       /* by default mapping is set to NCI_RF_INTERFACE_FRAME */
+       for (i = 0; i < ndev->num_supported_rf_interfaces; i++) {
+               if (ndev->supported_rf_interfaces[i] ==
+                       NCI_RF_INTERFACE_ISO_DEP) {
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .rf_protocol = NCI_RF_PROTOCOL_ISO_DEP;
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .mode = NCI_DISC_MAP_MODE_BOTH;
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .rf_interface_type = NCI_RF_INTERFACE_ISO_DEP;
+                       cmd.num_mapping_configs++;
+               } else if (ndev->supported_rf_interfaces[i] ==
+                       NCI_RF_INTERFACE_NFC_DEP) {
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .rf_protocol = NCI_RF_PROTOCOL_NFC_DEP;
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .mode = NCI_DISC_MAP_MODE_BOTH;
+                       cmd.mapping_configs[cmd.num_mapping_configs]
+                       .rf_interface_type = NCI_RF_INTERFACE_NFC_DEP;
+                       cmd.num_mapping_configs++;
+               }
+
+               if (cmd.num_mapping_configs == NCI_MAX_NUM_MAPPING_CONFIGS)
+                       break;
+       }
+
+       nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD,
+               (1 + (cmd.num_mapping_configs*sizeof(struct disc_map_config))),
+               &cmd);
+}
+
+static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
+{
+       struct nci_rf_disc_cmd cmd;
+       __u32 protocols = opt;
+
+       cmd.num_disc_configs = 0;
+
+       if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
+               (protocols & NFC_PROTO_JEWEL_MASK
+               || protocols & NFC_PROTO_MIFARE_MASK
+               || protocols & NFC_PROTO_ISO14443_MASK
+               || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+               cmd.disc_configs[cmd.num_disc_configs].type =
+               NCI_DISCOVERY_TYPE_POLL_A_PASSIVE;
+               cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
+               cmd.num_disc_configs++;
+       }
+
+       if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
+               (protocols & NFC_PROTO_ISO14443_MASK)) {
+               cmd.disc_configs[cmd.num_disc_configs].type =
+               NCI_DISCOVERY_TYPE_POLL_B_PASSIVE;
+               cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
+               cmd.num_disc_configs++;
+       }
+
+       if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
+               (protocols & NFC_PROTO_FELICA_MASK
+               || protocols & NFC_PROTO_NFC_DEP_MASK)) {
+               cmd.disc_configs[cmd.num_disc_configs].type =
+               NCI_DISCOVERY_TYPE_POLL_F_PASSIVE;
+               cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
+               cmd.num_disc_configs++;
+       }
+
+       nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
+               (1 + (cmd.num_disc_configs*sizeof(struct disc_config))),
+               &cmd);
+}
+
+static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
+{
+       struct nci_rf_deactivate_cmd cmd;
+
+       cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE;
+
+       nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
+                       sizeof(struct nci_rf_deactivate_cmd),
+                       &cmd);
+}
+
+static int nci_open_device(struct nci_dev *ndev)
+{
+       int rc = 0;
+
+       mutex_lock(&ndev->req_lock);
+
+       if (test_bit(NCI_UP, &ndev->flags)) {
+               rc = -EALREADY;
+               goto done;
+       }
+
+       if (ndev->ops->open(ndev)) {
+               rc = -EIO;
+               goto done;
+       }
+
+       atomic_set(&ndev->cmd_cnt, 1);
+
+       set_bit(NCI_INIT, &ndev->flags);
+
+       rc = __nci_request(ndev, nci_reset_req, 0,
+                               msecs_to_jiffies(NCI_RESET_TIMEOUT));
+
+       if (!rc) {
+               rc = __nci_request(ndev, nci_init_req, 0,
+                               msecs_to_jiffies(NCI_INIT_TIMEOUT));
+       }
+
+       if (!rc) {
+               rc = __nci_request(ndev, nci_init_complete_req, 0,
+                               msecs_to_jiffies(NCI_INIT_TIMEOUT));
+       }
+
+       clear_bit(NCI_INIT, &ndev->flags);
+
+       if (!rc) {
+               set_bit(NCI_UP, &ndev->flags);
+       } else {
+               /* Init failed, cleanup */
+               skb_queue_purge(&ndev->cmd_q);
+               skb_queue_purge(&ndev->rx_q);
+               skb_queue_purge(&ndev->tx_q);
+
+               ndev->ops->close(ndev);
+               ndev->flags = 0;
+       }
+
+done:
+       mutex_unlock(&ndev->req_lock);
+       return rc;
+}
+
+static int nci_close_device(struct nci_dev *ndev)
+{
+       nci_req_cancel(ndev, ENODEV);
+       mutex_lock(&ndev->req_lock);
+
+       if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
+               del_timer_sync(&ndev->cmd_timer);
+               mutex_unlock(&ndev->req_lock);
+               return 0;
+       }
+
+       /* Drop RX and TX queues */
+       skb_queue_purge(&ndev->rx_q);
+       skb_queue_purge(&ndev->tx_q);
+
+       /* Flush RX and TX wq */
+       flush_workqueue(ndev->rx_wq);
+       flush_workqueue(ndev->tx_wq);
+
+       /* Reset device */
+       skb_queue_purge(&ndev->cmd_q);
+       atomic_set(&ndev->cmd_cnt, 1);
+
+       set_bit(NCI_INIT, &ndev->flags);
+       __nci_request(ndev, nci_reset_req, 0,
+                               msecs_to_jiffies(NCI_RESET_TIMEOUT));
+       clear_bit(NCI_INIT, &ndev->flags);
+
+       /* Flush cmd wq */
+       flush_workqueue(ndev->cmd_wq);
+
+       /* After this point our queues are empty
+        * and no works are scheduled. */
+       ndev->ops->close(ndev);
+
+       /* Clear flags */
+       ndev->flags = 0;
+
+       mutex_unlock(&ndev->req_lock);
+
+       return 0;
+}
+
+/* NCI command timer function */
+static void nci_cmd_timer(unsigned long arg)
+{
+       struct nci_dev *ndev = (void *) arg;
+
+       nfc_dbg("entry");
+
+       atomic_set(&ndev->cmd_cnt, 1);
+       queue_work(ndev->cmd_wq, &ndev->cmd_work);
+}
+
+static int nci_dev_up(struct nfc_dev *nfc_dev)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry");
+
+       return nci_open_device(ndev);
+}
+
+static int nci_dev_down(struct nfc_dev *nfc_dev)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry");
+
+       return nci_close_device(ndev);
+}
+
+static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+       int rc;
+
+       nfc_dbg("entry");
+
+       if (test_bit(NCI_DISCOVERY, &ndev->flags)) {
+               nfc_err("unable to start poll, since poll is already active");
+               return -EBUSY;
+       }
+
+       if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) {
+               nfc_dbg("target already active, first deactivate...");
+
+               rc = nci_request(ndev, nci_rf_deactivate_req, 0,
+                       msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+               if (rc)
+                       return -EBUSY;
+       }
+
+       rc = nci_request(ndev, nci_rf_discover_req, protocols,
+               msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
+
+       if (!rc)
+               ndev->poll_prots = protocols;
+
+       return rc;
+}
+
+static void nci_stop_poll(struct nfc_dev *nfc_dev)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry");
+
+       if (!test_bit(NCI_DISCOVERY, &ndev->flags)) {
+               nfc_err("unable to stop poll, since poll is not active");
+               return;
+       }
+
+       nci_request(ndev, nci_rf_deactivate_req, 0,
+               msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+}
+
+static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
+                               __u32 protocol)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry, target_idx %d, protocol 0x%x", target_idx, protocol);
+
+       if (!test_bit(NCI_POLL_ACTIVE, &ndev->flags)) {
+               nfc_err("there is no available target to activate");
+               return -EINVAL;
+       }
+
+       if (ndev->target_active_prot) {
+               nfc_err("there is already an active target");
+               return -EBUSY;
+       }
+
+       if (!(ndev->target_available_prots & (1 << protocol))) {
+               nfc_err("target does not support the requested protocol 0x%x",
+                       protocol);
+               return -EINVAL;
+       }
+
+       ndev->target_active_prot = protocol;
+       ndev->target_available_prots = 0;
+
+       return 0;
+}
+
+static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry, target_idx %d", target_idx);
+
+       if (!ndev->target_active_prot) {
+               nfc_err("unable to deactivate target, no active target");
+               return;
+       }
+
+       ndev->target_active_prot = 0;
+
+       if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) {
+               nci_request(ndev, nci_rf_deactivate_req, 0,
+                       msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
+       }
+}
+
+static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx,
+                                               struct sk_buff *skb,
+                                               data_exchange_cb_t cb,
+                                               void *cb_context)
+{
+       struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
+
+       nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len);
+
+       if (!ndev->target_active_prot) {
+               nfc_err("unable to exchange data, no active target");
+               return -EINVAL;
+       }
+
+       /* store cb and context to be used on receiving data */
+       ndev->data_exchange_cb = cb;
+       ndev->data_exchange_cb_context = cb_context;
+
+       return nci_send_data(ndev, ndev->conn_id, skb);
+}
+
+static struct nfc_ops nci_nfc_ops = {
+       .dev_up = nci_dev_up,
+       .dev_down = nci_dev_down,
+       .start_poll = nci_start_poll,
+       .stop_poll = nci_stop_poll,
+       .activate_target = nci_activate_target,
+       .deactivate_target = nci_deactivate_target,
+       .data_exchange = nci_data_exchange,
+};
+
+/* ---- Interface to NCI drivers ---- */
+
+/**
+ * nci_allocate_device - allocate a new nci device
+ *
+ * @ops: device operations
+ * @supported_protocols: NFC protocols supported by the device
+ */
+struct nci_dev *nci_allocate_device(struct nci_ops *ops,
+                                       __u32 supported_protocols,
+                                       int tx_headroom,
+                                       int tx_tailroom)
+{
+       struct nci_dev *ndev = NULL;
+
+       nfc_dbg("entry, supported_protocols 0x%x", supported_protocols);
+
+       if (!ops->open || !ops->close || !ops->send)
+               goto exit;
+
+       if (!supported_protocols)
+               goto exit;
+
+       ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL);
+       if (!ndev)
+               goto exit;
+
+       ndev->ops = ops;
+       ndev->tx_headroom = tx_headroom;
+       ndev->tx_tailroom = tx_tailroom;
+
+       ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
+                                               supported_protocols,
+                                               tx_headroom + NCI_DATA_HDR_SIZE,
+                                               tx_tailroom);
+       if (!ndev->nfc_dev)
+               goto free_exit;
+
+       nfc_set_drvdata(ndev->nfc_dev, ndev);
+
+       goto exit;
+
+free_exit:
+       kfree(ndev);
+
+exit:
+       return ndev;
+}
+EXPORT_SYMBOL(nci_allocate_device);
+
+/**
+ * nci_free_device - deallocate nci device
+ *
+ * @ndev: The nci device to deallocate
+ */
+void nci_free_device(struct nci_dev *ndev)
+{
+       nfc_dbg("entry");
+
+       nfc_free_device(ndev->nfc_dev);
+       kfree(ndev);
+}
+EXPORT_SYMBOL(nci_free_device);
+
+/**
+ * nci_register_device - register a nci device in the nfc subsystem
+ *
+ * @dev: The nci device to register
+ */
+int nci_register_device(struct nci_dev *ndev)
+{
+       int rc;
+       struct device *dev = &ndev->nfc_dev->dev;
+       char name[32];
+
+       nfc_dbg("entry");
+
+       rc = nfc_register_device(ndev->nfc_dev);
+       if (rc)
+               goto exit;
+
+       ndev->flags = 0;
+
+       INIT_WORK(&ndev->cmd_work, nci_cmd_work);
+       snprintf(name, sizeof(name), "%s_nci_cmd_wq", dev_name(dev));
+       ndev->cmd_wq = create_singlethread_workqueue(name);
+       if (!ndev->cmd_wq) {
+               rc = -ENOMEM;
+               goto unreg_exit;
+       }
+
+       INIT_WORK(&ndev->rx_work, nci_rx_work);
+       snprintf(name, sizeof(name), "%s_nci_rx_wq", dev_name(dev));
+       ndev->rx_wq = create_singlethread_workqueue(name);
+       if (!ndev->rx_wq) {
+               rc = -ENOMEM;
+               goto destroy_cmd_wq_exit;
+       }
+
+       INIT_WORK(&ndev->tx_work, nci_tx_work);
+       snprintf(name, sizeof(name), "%s_nci_tx_wq", dev_name(dev));
+       ndev->tx_wq = create_singlethread_workqueue(name);
+       if (!ndev->tx_wq) {
+               rc = -ENOMEM;
+               goto destroy_rx_wq_exit;
+       }
+
+       skb_queue_head_init(&ndev->cmd_q);
+       skb_queue_head_init(&ndev->rx_q);
+       skb_queue_head_init(&ndev->tx_q);
+
+       setup_timer(&ndev->cmd_timer, nci_cmd_timer,
+                       (unsigned long) ndev);
+
+       mutex_init(&ndev->req_lock);
+
+       goto exit;
+
+destroy_rx_wq_exit:
+       destroy_workqueue(ndev->rx_wq);
+
+destroy_cmd_wq_exit:
+       destroy_workqueue(ndev->cmd_wq);
+
+unreg_exit:
+       nfc_unregister_device(ndev->nfc_dev);
+
+exit:
+       return rc;
+}
+EXPORT_SYMBOL(nci_register_device);
+
+/**
+ * nci_unregister_device - unregister a nci device in the nfc subsystem
+ *
+ * @dev: The nci device to unregister
+ */
+void nci_unregister_device(struct nci_dev *ndev)
+{
+       nfc_dbg("entry");
+
+       nci_close_device(ndev);
+
+       destroy_workqueue(ndev->cmd_wq);
+       destroy_workqueue(ndev->rx_wq);
+       destroy_workqueue(ndev->tx_wq);
+
+       nfc_unregister_device(ndev->nfc_dev);
+}
+EXPORT_SYMBOL(nci_unregister_device);
+
+/**
+ * nci_recv_frame - receive frame from NCI drivers
+ *
+ * @skb: The sk_buff to receive
+ */
+int nci_recv_frame(struct sk_buff *skb)
+{
+       struct nci_dev *ndev = (struct nci_dev *) skb->dev;
+
+       nfc_dbg("entry, len %d", skb->len);
+
+       if (!ndev || (!test_bit(NCI_UP, &ndev->flags)
+               && !test_bit(NCI_INIT, &ndev->flags))) {
+               kfree_skb(skb);
+               return -ENXIO;
+       }
+
+       /* Queue frame for rx worker thread */
+       skb_queue_tail(&ndev->rx_q, skb);
+       queue_work(ndev->rx_wq, &ndev->rx_work);
+
+       return 0;
+}
+EXPORT_SYMBOL(nci_recv_frame);
+
+static int nci_send_frame(struct sk_buff *skb)
+{
+       struct nci_dev *ndev = (struct nci_dev *) skb->dev;
+
+       nfc_dbg("entry, len %d", skb->len);
+
+       if (!ndev) {
+               kfree_skb(skb);
+               return -ENODEV;
+       }
+
+       /* Get rid of skb owner, prior to sending to the driver. */
+       skb_orphan(skb);
+
+       return ndev->ops->send(skb);
+}
+
+/* Send NCI command */
+int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload)
+{
+       struct nci_ctrl_hdr *hdr;
+       struct sk_buff *skb;
+
+       nfc_dbg("entry, opcode 0x%x, plen %d", opcode, plen);
+
+       skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL);
+       if (!skb) {
+               nfc_err("no memory for command");
+               return -ENOMEM;
+       }
+
+       hdr = (struct nci_ctrl_hdr *) skb_put(skb, NCI_CTRL_HDR_SIZE);
+       hdr->gid = nci_opcode_gid(opcode);
+       hdr->oid = nci_opcode_oid(opcode);
+       hdr->plen = plen;
+
+       nci_mt_set((__u8 *)hdr, NCI_MT_CMD_PKT);
+       nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST);
+
+       if (plen)
+               memcpy(skb_put(skb, plen), payload, plen);
+
+       skb->dev = (void *) ndev;
+
+       skb_queue_tail(&ndev->cmd_q, skb);
+       queue_work(ndev->cmd_wq, &ndev->cmd_work);
+
+       return 0;
+}
+
+/* ---- NCI TX Data worker thread ---- */
+
+static void nci_tx_work(struct work_struct *work)
+{
+       struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work);
+       struct sk_buff *skb;
+
+       nfc_dbg("entry, credits_cnt %d", atomic_read(&ndev->credits_cnt));
+
+       /* Send queued tx data */
+       while (atomic_read(&ndev->credits_cnt)) {
+               skb = skb_dequeue(&ndev->tx_q);
+               if (!skb)
+                       return;
+
+               atomic_dec(&ndev->credits_cnt);
+
+               nfc_dbg("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d",
+                               nci_pbf(skb->data),
+                               nci_conn_id(skb->data),
+                               nci_plen(skb->data));
+
+               nci_send_frame(skb);
+       }
+}
+
+/* ----- NCI RX worker thread (data & control) ----- */
+
+static void nci_rx_work(struct work_struct *work)
+{
+       struct nci_dev *ndev = container_of(work, struct nci_dev, rx_work);
+       struct sk_buff *skb;
+
+       while ((skb = skb_dequeue(&ndev->rx_q))) {
+               /* Process frame */
+               switch (nci_mt(skb->data)) {
+               case NCI_MT_RSP_PKT:
+                       nci_rsp_packet(ndev, skb);
+                       break;
+
+               case NCI_MT_NTF_PKT:
+                       nci_ntf_packet(ndev, skb);
+                       break;
+
+               case NCI_MT_DATA_PKT:
+                       nci_rx_data_packet(ndev, skb);
+                       break;
+
+               default:
+                       nfc_err("unknown MT 0x%x", nci_mt(skb->data));
+                       kfree_skb(skb);
+                       break;
+               }
+       }
+}
+
+/* ----- NCI TX CMD worker thread ----- */
+
+static void nci_cmd_work(struct work_struct *work)
+{
+       struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work);
+       struct sk_buff *skb;
+
+       nfc_dbg("entry, cmd_cnt %d", atomic_read(&ndev->cmd_cnt));
+
+       /* Send queued command */
+       if (atomic_read(&ndev->cmd_cnt)) {
+               skb = skb_dequeue(&ndev->cmd_q);
+               if (!skb)
+                       return;
+
+               atomic_dec(&ndev->cmd_cnt);
+
+               nfc_dbg("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d",
+                               nci_pbf(skb->data),
+                               nci_opcode_gid(nci_opcode(skb->data)),
+                               nci_opcode_oid(nci_opcode(skb->data)),
+                               nci_plen(skb->data));
+
+               nci_send_frame(skb);
+
+               mod_timer(&ndev->cmd_timer,
+                       jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
+       }
+}
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
new file mode 100644 (file)
index 0000000..141790a
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+
+#include "../nfc.h"
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/nfc.h>
+
+/* Complete data exchange transaction and forward skb to nfc core */
+void nci_data_exchange_complete(struct nci_dev *ndev,
+                               struct sk_buff *skb,
+                               int err)
+{
+       data_exchange_cb_t cb = ndev->data_exchange_cb;
+       void *cb_context = ndev->data_exchange_cb_context;
+
+       nfc_dbg("entry, len %d, err %d", ((skb) ? (skb->len) : (0)), err);
+
+       if (cb) {
+               ndev->data_exchange_cb = NULL;
+               ndev->data_exchange_cb_context = 0;
+
+               /* forward skb to nfc core */
+               cb(cb_context, skb, err);
+       } else if (skb) {
+               nfc_err("no rx callback, dropping rx data...");
+
+               /* no waiting callback, free skb */
+               kfree_skb(skb);
+       }
+}
+
+/* ----------------- NCI TX Data ----------------- */
+
+static inline void nci_push_data_hdr(struct nci_dev *ndev,
+                                       __u8 conn_id,
+                                       struct sk_buff *skb,
+                                       __u8 pbf)
+{
+       struct nci_data_hdr *hdr;
+       int plen = skb->len;
+
+       hdr = (struct nci_data_hdr *) skb_push(skb, NCI_DATA_HDR_SIZE);
+       hdr->conn_id = conn_id;
+       hdr->rfu = 0;
+       hdr->plen = plen;
+
+       nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT);
+       nci_pbf_set((__u8 *)hdr, pbf);
+
+       skb->dev = (void *) ndev;
+}
+
+static int nci_queue_tx_data_frags(struct nci_dev *ndev,
+                                       __u8 conn_id,
+                                       struct sk_buff *skb) {
+       int total_len = skb->len;
+       unsigned char *data = skb->data;
+       unsigned long flags;
+       struct sk_buff_head frags_q;
+       struct sk_buff *skb_frag;
+       int frag_len;
+       int rc = 0;
+
+       nfc_dbg("entry, conn_id 0x%x, total_len %d", conn_id, total_len);
+
+       __skb_queue_head_init(&frags_q);
+
+       while (total_len) {
+               frag_len = min_t(int, total_len, ndev->max_pkt_payload_size);
+
+               skb_frag = nci_skb_alloc(ndev,
+                                       (NCI_DATA_HDR_SIZE + frag_len),
+                                       GFP_KERNEL);
+               if (skb_frag == NULL) {
+                       rc = -ENOMEM;
+                       goto free_exit;
+               }
+               skb_reserve(skb_frag, NCI_DATA_HDR_SIZE);
+
+               /* first, copy the data */
+               memcpy(skb_put(skb_frag, frag_len), data, frag_len);
+
+               /* second, set the header */
+               nci_push_data_hdr(ndev, conn_id, skb_frag,
+               ((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT)));
+
+               __skb_queue_tail(&frags_q, skb_frag);
+
+               data += frag_len;
+               total_len -= frag_len;
+
+               nfc_dbg("frag_len %d, remaining total_len %d",
+                       frag_len, total_len);
+       }
+
+       /* queue all fragments atomically */
+       spin_lock_irqsave(&ndev->tx_q.lock, flags);
+
+       while ((skb_frag = __skb_dequeue(&frags_q)) != NULL)
+               __skb_queue_tail(&ndev->tx_q, skb_frag);
+
+       spin_unlock_irqrestore(&ndev->tx_q.lock, flags);
+
+       /* free the original skb */
+       kfree_skb(skb);
+
+       goto exit;
+
+free_exit:
+       while ((skb_frag = __skb_dequeue(&frags_q)) != NULL)
+               kfree_skb(skb_frag);
+
+exit:
+       return rc;
+}
+
+/* Send NCI data */
+int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb)
+{
+       int rc = 0;
+
+       nfc_dbg("entry, conn_id 0x%x, plen %d", conn_id, skb->len);
+
+       /* check if the packet need to be fragmented */
+       if (skb->len <= ndev->max_pkt_payload_size) {
+               /* no need to fragment packet */
+               nci_push_data_hdr(ndev, conn_id, skb, NCI_PBF_LAST);
+
+               skb_queue_tail(&ndev->tx_q, skb);
+       } else {
+               /* fragment packet and queue the fragments */
+               rc = nci_queue_tx_data_frags(ndev, conn_id, skb);
+               if (rc) {
+                       nfc_err("failed to fragment tx data packet");
+                       goto free_exit;
+               }
+       }
+
+       queue_work(ndev->tx_wq, &ndev->tx_work);
+
+       goto exit;
+
+free_exit:
+       kfree_skb(skb);
+
+exit:
+       return rc;
+}
+
+/* ----------------- NCI RX Data ----------------- */
+
+static void nci_add_rx_data_frag(struct nci_dev *ndev,
+                               struct sk_buff *skb,
+                               __u8 pbf)
+{
+       int reassembly_len;
+       int err = 0;
+
+       if (ndev->rx_data_reassembly) {
+               reassembly_len = ndev->rx_data_reassembly->len;
+
+               /* first, make enough room for the already accumulated data */
+               if (skb_cow_head(skb, reassembly_len)) {
+                       nfc_err("error adding room for accumulated rx data");
+
+                       kfree_skb(skb);
+                       skb = 0;
+
+                       kfree_skb(ndev->rx_data_reassembly);
+                       ndev->rx_data_reassembly = 0;
+
+                       err = -ENOMEM;
+                       goto exit;
+               }
+
+               /* second, combine the two fragments */
+               memcpy(skb_push(skb, reassembly_len),
+                               ndev->rx_data_reassembly->data,
+                               reassembly_len);
+
+               /* third, free old reassembly */
+               kfree_skb(ndev->rx_data_reassembly);
+               ndev->rx_data_reassembly = 0;
+       }
+
+       if (pbf == NCI_PBF_CONT) {
+               /* need to wait for next fragment, store skb and exit */
+               ndev->rx_data_reassembly = skb;
+               return;
+       }
+
+exit:
+       nci_data_exchange_complete(ndev, skb, err);
+}
+
+/* Rx Data packet */
+void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       __u8 pbf = nci_pbf(skb->data);
+
+       nfc_dbg("entry, len %d", skb->len);
+
+       nfc_dbg("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d",
+                       nci_pbf(skb->data),
+                       nci_conn_id(skb->data),
+                       nci_plen(skb->data));
+
+       /* strip the nci data header */
+       skb_pull(skb, NCI_DATA_HDR_SIZE);
+
+       if (ndev->target_active_prot == NFC_PROTO_MIFARE) {
+               /* frame I/F => remove the status byte */
+               nfc_dbg("NFC_PROTO_MIFARE => remove the status byte");
+               skb_trim(skb, (skb->len - 1));
+       }
+
+       nci_add_rx_data_frag(ndev, skb, pbf);
+}
diff --git a/net/nfc/nci/lib.c b/net/nfc/nci/lib.c
new file mode 100644 (file)
index 0000000..b19dc2f
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on lib.c, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
+#include <net/nfc/nci.h>
+
+/* NCI status codes to Unix errno mapping */
+int nci_to_errno(__u8 code)
+{
+       switch (code) {
+       case NCI_STATUS_OK:
+               return 0;
+
+       case NCI_STATUS_REJECTED:
+               return -EBUSY;
+
+       case NCI_STATUS_MESSAGE_CORRUPTED:
+               return -EBADMSG;
+
+       case NCI_STATUS_BUFFER_FULL:
+               return -ENOBUFS;
+
+       case NCI_STATUS_NOT_INITIALIZED:
+               return -EHOSTDOWN;
+
+       case NCI_STATUS_SYNTAX_ERROR:
+       case NCI_STATUS_SEMANTIC_ERROR:
+       case NCI_STATUS_INVALID_PARAM:
+       case NCI_STATUS_RF_PROTOCOL_ERROR:
+       case NCI_STATUS_NFCEE_PROTOCOL_ERROR:
+               return -EPROTO;
+
+       case NCI_STATUS_UNKNOWN_GID:
+       case NCI_STATUS_UNKNOWN_OID:
+               return -EBADRQC;
+
+       case NCI_STATUS_MESSAGE_SIZE_EXCEEDED:
+               return -EMSGSIZE;
+
+       case NCI_STATUS_DISCOVERY_ALREADY_STARTED:
+               return -EALREADY;
+
+       case NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED:
+       case NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED:
+               return -ECONNREFUSED;
+
+       case NCI_STATUS_RF_TRANSMISSION_ERROR:
+       case NCI_STATUS_NFCEE_TRANSMISSION_ERROR:
+               return -ECOMM;
+
+       case NCI_STATUS_RF_TIMEOUT_ERROR:
+       case NCI_STATUS_NFCEE_TIMEOUT_ERROR:
+               return -ETIMEDOUT;
+
+       case NCI_STATUS_RF_LINK_LOSS_ERROR:
+               return -ENOLINK;
+
+       case NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED:
+               return -EDQUOT;
+
+       case NCI_STATUS_FAILED:
+       default:
+               return -ENOSYS;
+       }
+}
+EXPORT_SYMBOL(nci_to_errno);
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
new file mode 100644 (file)
index 0000000..8dd7535
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on hci_event.c, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+
+#include "../nfc.h"
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+#include <linux/nfc.h>
+
+/* Handle NCI Notification packets */
+
+static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
+                                               struct sk_buff *skb)
+{
+       struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
+       int i;
+
+       nfc_dbg("entry, num_entries %d", ntf->num_entries);
+
+       if (ntf->num_entries > NCI_MAX_NUM_CONN)
+               ntf->num_entries = NCI_MAX_NUM_CONN;
+
+       /* update the credits */
+       for (i = 0; i < ntf->num_entries; i++) {
+               nfc_dbg("entry[%d]: conn_id %d, credits %d", i,
+                       ntf->conn_entries[i].conn_id,
+                       ntf->conn_entries[i].credits);
+
+               if (ntf->conn_entries[i].conn_id == ndev->conn_id) {
+                       /* found static rf connection */
+                       atomic_add(ntf->conn_entries[i].credits,
+                               &ndev->credits_cnt);
+               }
+       }
+
+       /* trigger the next tx */
+       if (!skb_queue_empty(&ndev->tx_q))
+               queue_work(ndev->tx_wq, &ndev->tx_work);
+}
+
+static void nci_rf_field_info_ntf_packet(struct nci_dev *ndev,
+                                       struct sk_buff *skb)
+{
+       struct nci_rf_field_info_ntf *ntf = (void *) skb->data;
+
+       nfc_dbg("entry, rf_field_status %d", ntf->rf_field_status);
+}
+
+static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev,
+                       struct nci_rf_activate_ntf *ntf, __u8 *data)
+{
+       struct rf_tech_specific_params_nfca_poll *nfca_poll;
+       struct activation_params_nfca_poll_iso_dep *nfca_poll_iso_dep;
+
+       nfca_poll = &ntf->rf_tech_specific_params.nfca_poll;
+       nfca_poll_iso_dep = &ntf->activation_params.nfca_poll_iso_dep;
+
+       nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
+       data += 2;
+
+       nfca_poll->nfcid1_len = *data++;
+
+       nfc_dbg("sens_res 0x%x, nfcid1_len %d",
+               nfca_poll->sens_res,
+               nfca_poll->nfcid1_len);
+
+       memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len);
+       data += nfca_poll->nfcid1_len;
+
+       nfca_poll->sel_res_len = *data++;
+
+       if (nfca_poll->sel_res_len != 0)
+               nfca_poll->sel_res = *data++;
+
+       ntf->rf_interface_type = *data++;
+       ntf->activation_params_len = *data++;
+
+       nfc_dbg("sel_res_len %d, sel_res 0x%x, rf_interface_type %d, activation_params_len %d",
+               nfca_poll->sel_res_len,
+               nfca_poll->sel_res,
+               ntf->rf_interface_type,
+               ntf->activation_params_len);
+
+       switch (ntf->rf_interface_type) {
+       case NCI_RF_INTERFACE_ISO_DEP:
+               nfca_poll_iso_dep->rats_res_len = *data++;
+               if (nfca_poll_iso_dep->rats_res_len > 0) {
+                       memcpy(nfca_poll_iso_dep->rats_res,
+                               data,
+                               nfca_poll_iso_dep->rats_res_len);
+               }
+               break;
+
+       case NCI_RF_INTERFACE_FRAME:
+               /* no activation params */
+               break;
+
+       default:
+               nfc_err("unsupported rf_interface_type 0x%x",
+                       ntf->rf_interface_type);
+               return -EPROTO;
+       }
+
+       return 0;
+}
+
+static void nci_target_found(struct nci_dev *ndev,
+                               struct nci_rf_activate_ntf *ntf)
+{
+       struct nfc_target nfc_tgt;
+
+       if (ntf->rf_protocol == NCI_RF_PROTOCOL_T2T)    /* T2T MifareUL */
+               nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK;
+       else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP)   /* 4A */
+               nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK;
+
+       nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res;
+       nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res;
+
+       if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) {
+               nfc_dbg("the target found does not have the desired protocol");
+               return;
+       }
+
+       nfc_dbg("new target found,  supported_protocols 0x%x",
+               nfc_tgt.supported_protocols);
+
+       ndev->target_available_prots = nfc_tgt.supported_protocols;
+
+       nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1);
+}
+
+static void nci_rf_activate_ntf_packet(struct nci_dev *ndev,
+                                       struct sk_buff *skb)
+{
+       struct nci_rf_activate_ntf ntf;
+       __u8 *data = skb->data;
+       int rc = -1;
+
+       clear_bit(NCI_DISCOVERY, &ndev->flags);
+       set_bit(NCI_POLL_ACTIVE, &ndev->flags);
+
+       ntf.target_handle = *data++;
+       ntf.rf_protocol = *data++;
+       ntf.rf_tech_and_mode = *data++;
+       ntf.rf_tech_specific_params_len = *data++;
+
+       nfc_dbg("target_handle %d, rf_protocol 0x%x, rf_tech_and_mode 0x%x, rf_tech_specific_params_len %d",
+               ntf.target_handle,
+               ntf.rf_protocol,
+               ntf.rf_tech_and_mode,
+               ntf.rf_tech_specific_params_len);
+
+       switch (ntf.rf_tech_and_mode) {
+       case NCI_NFC_A_PASSIVE_POLL_MODE:
+               rc = nci_rf_activate_nfca_passive_poll(ndev, &ntf,
+                       data);
+               break;
+
+       default:
+               nfc_err("unsupported rf_tech_and_mode 0x%x",
+                       ntf.rf_tech_and_mode);
+               return;
+       }
+
+       if (!rc)
+               nci_target_found(ndev, &ntf);
+}
+
+static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
+                                       struct sk_buff *skb)
+{
+       __u8 type = skb->data[0];
+
+       nfc_dbg("entry, type 0x%x", type);
+
+       clear_bit(NCI_POLL_ACTIVE, &ndev->flags);
+       ndev->target_active_prot = 0;
+
+       /* drop tx data queue */
+       skb_queue_purge(&ndev->tx_q);
+
+       /* drop partial rx data packet */
+       if (ndev->rx_data_reassembly) {
+               kfree_skb(ndev->rx_data_reassembly);
+               ndev->rx_data_reassembly = 0;
+       }
+
+       /* complete the data exchange transaction, if exists */
+       if (ndev->data_exchange_cb)
+               nci_data_exchange_complete(ndev, NULL, -EIO);
+}
+
+void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       __u16 ntf_opcode = nci_opcode(skb->data);
+
+       nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d",
+                       nci_pbf(skb->data),
+                       nci_opcode_gid(ntf_opcode),
+                       nci_opcode_oid(ntf_opcode),
+                       nci_plen(skb->data));
+
+       /* strip the nci control header */
+       skb_pull(skb, NCI_CTRL_HDR_SIZE);
+
+       switch (ntf_opcode) {
+       case NCI_OP_CORE_CONN_CREDITS_NTF:
+               nci_core_conn_credits_ntf_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_FIELD_INFO_NTF:
+               nci_rf_field_info_ntf_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_ACTIVATE_NTF:
+               nci_rf_activate_ntf_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_DEACTIVATE_NTF:
+               nci_rf_deactivate_ntf_packet(ndev, skb);
+               break;
+
+       default:
+               nfc_err("unknown ntf opcode 0x%x", ntf_opcode);
+               break;
+       }
+
+       kfree_skb(skb);
+}
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
new file mode 100644 (file)
index 0000000..0403d4c
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ *  The NFC Controller Interface is the communication protocol between an
+ *  NFC Controller (NFCC) and a Device Host (DH).
+ *
+ *  Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ *  Written by Ilan Elias <[email protected]>
+ *
+ *  Acknowledgements:
+ *  This file is based on hci_event.c, which was written
+ *  by Maxim Krasnyansky.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+
+#include "../nfc.h"
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+
+/* Handle NCI Response packets */
+
+static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       struct nci_core_reset_rsp *rsp = (void *) skb->data;
+
+       nfc_dbg("entry, status 0x%x", rsp->status);
+
+       if (rsp->status == NCI_STATUS_OK)
+               ndev->nci_ver = rsp->nci_ver;
+
+       nfc_dbg("nci_ver 0x%x", ndev->nci_ver);
+
+       nci_req_complete(ndev, rsp->status);
+}
+
+static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
+       struct nci_core_init_rsp_2 *rsp_2;
+
+       nfc_dbg("entry, status 0x%x", rsp_1->status);
+
+       if (rsp_1->status != NCI_STATUS_OK)
+               return;
+
+       ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
+       ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
+
+       if (ndev->num_supported_rf_interfaces >
+               NCI_MAX_SUPPORTED_RF_INTERFACES) {
+               ndev->num_supported_rf_interfaces =
+                       NCI_MAX_SUPPORTED_RF_INTERFACES;
+       }
+
+       memcpy(ndev->supported_rf_interfaces,
+               rsp_1->supported_rf_interfaces,
+               ndev->num_supported_rf_interfaces);
+
+       rsp_2 = (void *) (skb->data + 6 + ndev->num_supported_rf_interfaces);
+
+       ndev->max_logical_connections =
+               rsp_2->max_logical_connections;
+       ndev->max_routing_table_size =
+               __le16_to_cpu(rsp_2->max_routing_table_size);
+       ndev->max_control_packet_payload_length =
+               rsp_2->max_control_packet_payload_length;
+       ndev->rf_sending_buffer_size =
+               __le16_to_cpu(rsp_2->rf_sending_buffer_size);
+       ndev->rf_receiving_buffer_size =
+               __le16_to_cpu(rsp_2->rf_receiving_buffer_size);
+       ndev->manufacturer_id =
+               __le16_to_cpu(rsp_2->manufacturer_id);
+
+       nfc_dbg("nfcc_features 0x%x",
+               ndev->nfcc_features);
+       nfc_dbg("num_supported_rf_interfaces %d",
+               ndev->num_supported_rf_interfaces);
+       nfc_dbg("supported_rf_interfaces[0] 0x%x",
+               ndev->supported_rf_interfaces[0]);
+       nfc_dbg("supported_rf_interfaces[1] 0x%x",
+               ndev->supported_rf_interfaces[1]);
+       nfc_dbg("supported_rf_interfaces[2] 0x%x",
+               ndev->supported_rf_interfaces[2]);
+       nfc_dbg("supported_rf_interfaces[3] 0x%x",
+               ndev->supported_rf_interfaces[3]);
+       nfc_dbg("max_logical_connections %d",
+               ndev->max_logical_connections);
+       nfc_dbg("max_routing_table_size %d",
+               ndev->max_routing_table_size);
+       nfc_dbg("max_control_packet_payload_length %d",
+               ndev->max_control_packet_payload_length);
+       nfc_dbg("rf_sending_buffer_size %d",
+               ndev->rf_sending_buffer_size);
+       nfc_dbg("rf_receiving_buffer_size %d",
+               ndev->rf_receiving_buffer_size);
+       nfc_dbg("manufacturer_id 0x%x",
+               ndev->manufacturer_id);
+
+       nci_req_complete(ndev, rsp_1->status);
+}
+
+static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
+                                               struct sk_buff *skb)
+{
+       struct nci_core_conn_create_rsp *rsp = (void *) skb->data;
+
+       nfc_dbg("entry, status 0x%x", rsp->status);
+
+       if (rsp->status != NCI_STATUS_OK)
+               return;
+
+       ndev->max_pkt_payload_size = rsp->max_pkt_payload_size;
+       ndev->initial_num_credits = rsp->initial_num_credits;
+       ndev->conn_id = rsp->conn_id;
+
+       atomic_set(&ndev->credits_cnt, ndev->initial_num_credits);
+
+       nfc_dbg("max_pkt_payload_size %d", ndev->max_pkt_payload_size);
+       nfc_dbg("initial_num_credits %d", ndev->initial_num_credits);
+       nfc_dbg("conn_id %d", ndev->conn_id);
+}
+
+static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
+                                       struct sk_buff *skb)
+{
+       __u8 status = skb->data[0];
+
+       nfc_dbg("entry, status 0x%x", status);
+
+       nci_req_complete(ndev, status);
+}
+
+static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       __u8 status = skb->data[0];
+
+       nfc_dbg("entry, status 0x%x", status);
+
+       if (status == NCI_STATUS_OK)
+               set_bit(NCI_DISCOVERY, &ndev->flags);
+
+       nci_req_complete(ndev, status);
+}
+
+static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
+                                       struct sk_buff *skb)
+{
+       __u8 status = skb->data[0];
+
+       nfc_dbg("entry, status 0x%x", status);
+
+       clear_bit(NCI_DISCOVERY, &ndev->flags);
+
+       nci_req_complete(ndev, status);
+}
+
+void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+       __u16 rsp_opcode = nci_opcode(skb->data);
+
+       /* we got a rsp, stop the cmd timer */
+       del_timer(&ndev->cmd_timer);
+
+       nfc_dbg("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d",
+                       nci_pbf(skb->data),
+                       nci_opcode_gid(rsp_opcode),
+                       nci_opcode_oid(rsp_opcode),
+                       nci_plen(skb->data));
+
+       /* strip the nci control header */
+       skb_pull(skb, NCI_CTRL_HDR_SIZE);
+
+       switch (rsp_opcode) {
+       case NCI_OP_CORE_RESET_RSP:
+               nci_core_reset_rsp_packet(ndev, skb);
+               break;
+
+       case NCI_OP_CORE_INIT_RSP:
+               nci_core_init_rsp_packet(ndev, skb);
+               break;
+
+       case NCI_OP_CORE_CONN_CREATE_RSP:
+               nci_core_conn_create_rsp_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_DISCOVER_MAP_RSP:
+               nci_rf_disc_map_rsp_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_DISCOVER_RSP:
+               nci_rf_disc_rsp_packet(ndev, skb);
+               break;
+
+       case NCI_OP_RF_DEACTIVATE_RSP:
+               nci_rf_deactivate_rsp_packet(ndev, skb);
+               break;
+
+       default:
+               nfc_err("unknown rsp opcode 0x%x", rsp_opcode);
+               break;
+       }
+
+       kfree_skb(skb);
+
+       /* trigger the next cmd */
+       atomic_set(&ndev->cmd_cnt, 1);
+       if (!skb_queue_empty(&ndev->cmd_q))
+               queue_work(ndev->cmd_wq, &ndev->cmd_work);
+}
index ccdff7953f7d888973d2fcb99c7554170e67f01b..03f8818e1f166a2b0eefe11862523df7e582ee33 100644 (file)
@@ -367,6 +367,52 @@ out_putdev:
        return rc;
 }
 
+static int nfc_genl_dev_up(struct sk_buff *skb, struct genl_info *info)
+{
+       struct nfc_dev *dev;
+       int rc;
+       u32 idx;
+
+       nfc_dbg("entry");
+
+       if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+               return -EINVAL;
+
+       idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+       dev = nfc_get_device(idx);
+       if (!dev)
+               return -ENODEV;
+
+       rc = nfc_dev_up(dev);
+
+       nfc_put_device(dev);
+       return rc;
+}
+
+static int nfc_genl_dev_down(struct sk_buff *skb, struct genl_info *info)
+{
+       struct nfc_dev *dev;
+       int rc;
+       u32 idx;
+
+       nfc_dbg("entry");
+
+       if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+               return -EINVAL;
+
+       idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+       dev = nfc_get_device(idx);
+       if (!dev)
+               return -ENODEV;
+
+       rc = nfc_dev_down(dev);
+
+       nfc_put_device(dev);
+       return rc;
+}
+
 static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
 {
        struct nfc_dev *dev;
@@ -440,6 +486,16 @@ static struct genl_ops nfc_genl_ops[] = {
                .done = nfc_genl_dump_devices_done,
                .policy = nfc_genl_policy,
        },
+       {
+               .cmd = NFC_CMD_DEV_UP,
+               .doit = nfc_genl_dev_up,
+               .policy = nfc_genl_policy,
+       },
+       {
+               .cmd = NFC_CMD_DEV_DOWN,
+               .doit = nfc_genl_dev_down,
+               .policy = nfc_genl_policy,
+       },
        {
                .cmd = NFC_CMD_START_POLL,
                .doit = nfc_genl_start_poll,
index aaf9832298f34d9c932c39060a4ca94fe1f5e208..b6753f45624e3e3fdd17c4338173778ee21b136b 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __LOCAL_NFC_H
 #define __LOCAL_NFC_H
 
-#include <net/nfc.h>
+#include <net/nfc/nfc.h>
 #include <net/sock.h>
 
 __attribute__((format (printf, 2, 3)))
@@ -101,6 +101,10 @@ static inline void nfc_device_iter_exit(struct class_dev_iter *iter)
        class_dev_iter_exit(iter);
 }
 
+int nfc_dev_up(struct nfc_dev *dev);
+
+int nfc_dev_down(struct nfc_dev *dev);
+
 int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
 
 int nfc_stop_poll(struct nfc_dev *dev);
index be90640a2774bfedb73a89ea340186428d2afdfd..5be19575c340886ff869e94dc7ae65c0e959e00c 100644 (file)
@@ -235,7 +235,7 @@ static bool __rfkill_set_hw_state(struct rfkill *rfkill,
        else
                rfkill->state &= ~RFKILL_BLOCK_HW;
        *change = prev != blocked;
-       any = rfkill->state & RFKILL_BLOCK_ANY;
+       any = !!(rfkill->state & RFKILL_BLOCK_ANY);
        spin_unlock_irqrestore(&rfkill->lock, flags);
 
        rfkill_led_trigger_event(rfkill);
index 18dc512a10f3b5a39886b99e0536c3d2df706f78..3ca7277a3c362db9b4f1499cf00fcc3897839393 100644 (file)
@@ -90,7 +90,6 @@ static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
                                pdata->type,
                                &rfkill_regulator_ops, rfkill_data);
        if (rf_kill == NULL) {
-               dev_err(&pdev->dev, "Cannot alloc rfkill device\n");
                ret = -ENOMEM;
                goto err_rfkill_alloc;
        }
index 645437cfc464d505a3673870f8c0a6eb73287535..220f3bd176f89cc33192b72ddcc11f296cba54fd 100644 (file)
@@ -582,7 +582,7 @@ int wiphy_register(struct wiphy *wiphy)
        }
 
        /* set up regulatory info */
-       wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
+       regulatory_update(wiphy, NL80211_REGDOM_SET_BY_CORE);
 
        list_add_rcu(&rdev->list, &cfg80211_rdev_list);
        cfg80211_rdev_list_generation++;
@@ -616,6 +616,9 @@ int wiphy_register(struct wiphy *wiphy)
        if (res)
                goto out_rm_dev;
 
+       rtnl_lock();
+       rdev->wiphy.registered = true;
+       rtnl_unlock();
        return 0;
 
 out_rm_dev:
@@ -647,6 +650,10 @@ void wiphy_unregister(struct wiphy *wiphy)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       rtnl_lock();
+       rdev->wiphy.registered = false;
+       rtnl_unlock();
+
        rfkill_unregister(rdev->rfkill);
 
        /* protect the device list */
index 8672e028022ffba288dc6166417aea9ae49391de..796a4bdf8b0d8901f571cc81436ab0719abbab17 100644 (file)
@@ -279,8 +279,6 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
                               char *newname);
 
 void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
-void wiphy_update_regulatory(struct wiphy *wiphy,
-                            enum nl80211_reg_initiator setby);
 
 void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
 void cfg80211_bss_age(struct cfg80211_registered_device *dev,
index dacb3b4b1bdbf5c786e18156064ef18253b2d46b..755738d26bb49b8b6df5537191a950c4f3ccb180 100644 (file)
@@ -77,8 +77,6 @@ static void *lib80211_ccmp_init(int key_idx)
 
        priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tfm)) {
-               printk(KERN_DEBUG "lib80211_crypt_ccmp: could not allocate "
-                      "crypto API aes\n");
                priv->tfm = NULL;
                goto fail;
        }
index 7ea4f2b0770ecbbbbcd9c98cbd9fe690534c2bb8..38734846c19e3d0b1c0d40548623a5920ff57531 100644 (file)
@@ -101,7 +101,6 @@ static void *lib80211_tkip_init(int key_idx)
        priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
                                                CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm_arc4)) {
-               printk(KERN_DEBUG pr_fmt("could not allocate crypto API arc4\n"));
                priv->tx_tfm_arc4 = NULL;
                goto fail;
        }
@@ -109,7 +108,6 @@ static void *lib80211_tkip_init(int key_idx)
        priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
                                                 CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm_michael)) {
-               printk(KERN_DEBUG pr_fmt("could not allocate crypto API michael_mic\n"));
                priv->tx_tfm_michael = NULL;
                goto fail;
        }
@@ -117,7 +115,6 @@ static void *lib80211_tkip_init(int key_idx)
        priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
                                                CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm_arc4)) {
-               printk(KERN_DEBUG pr_fmt("could not allocate crypto API arc4\n"));
                priv->rx_tfm_arc4 = NULL;
                goto fail;
        }
@@ -125,7 +122,6 @@ static void *lib80211_tkip_init(int key_idx)
        priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
                                                 CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm_michael)) {
-               printk(KERN_DEBUG pr_fmt("could not allocate crypto API michael_mic\n"));
                priv->rx_tfm_michael = NULL;
                goto fail;
        }
index 2f265e033ae271028fdb60c2addce519d6530456..c1304018fc1c5e08247cc7882496a5688c3dcb85 100644 (file)
@@ -50,16 +50,12 @@ static void *lib80211_wep_init(int keyidx)
 
        priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm)) {
-               printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
-                      "crypto API arc4\n");
                priv->tx_tfm = NULL;
                goto fail;
        }
 
        priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm)) {
-               printk(KERN_DEBUG "lib80211_crypt_wep: could not allocate "
-                      "crypto API arc4\n");
                priv->rx_tfm = NULL;
                goto fail;
        }
index 832f6574e4ed7dab26d949154d0aefe04303e98b..61adea540e02c0243869204322837a907a6f9204 100644 (file)
@@ -1095,3 +1095,14 @@ void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
        nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
 }
 EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
+
+void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
+                                    const u8 *bssid, bool preauth, gfp_t gfp)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct wiphy *wiphy = wdev->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+       nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
+}
+EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
index bddb5595c6598bf62d21bf1520fffa578d1eaf68..3c6427abdf3425f353d929168218b076b711b6da 100644 (file)
@@ -189,6 +189,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
                                         .len = IEEE80211_MAX_DATA_LEN },
        [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
                                         .len = IEEE80211_MAX_DATA_LEN },
+       [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
+       [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
 };
 
 /* policy for the key attributes */
@@ -231,6 +233,12 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
        [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
 };
 
+static const struct nla_policy
+nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
+       [NL80211_ATTR_SCHED_SCAN_MATCH_SSID] = { .type = NLA_BINARY,
+                                                .len = IEEE80211_MAX_SSID_LEN },
+};
+
 /* ifidx get helper */
 static int nl80211_get_ifidx(struct netlink_callback *cb)
 {
@@ -714,11 +722,18 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
                    dev->wiphy.max_scan_ie_len);
        NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
                    dev->wiphy.max_sched_scan_ie_len);
+       NLA_PUT_U8(msg, NL80211_ATTR_MAX_MATCH_SETS,
+                  dev->wiphy.max_match_sets);
 
        if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
                NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
        if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH)
                NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH);
+       if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD)
+               NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD);
+
+       if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)
+               NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT);
 
        NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
                sizeof(u32) * dev->wiphy.n_cipher_suites,
@@ -2597,7 +2612,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
 
        /* parse WME attributes if sta is WME capable */
-       if ((params.sta_flags_set & NL80211_STA_FLAG_WME) &&
+       if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
+           (params.sta_flags_set & NL80211_STA_FLAG_WME) &&
            info->attrs[NL80211_ATTR_STA_WME]) {
                struct nlattr *tb[NL80211_STA_WME_MAX + 1];
                struct nlattr *nla;
@@ -2611,10 +2627,15 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                if (tb[NL80211_STA_WME_UAPSD_QUEUES])
                        params.uapsd_queues =
                             nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]);
+               if (params.uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+                       return -EINVAL;
 
                if (tb[NL80211_STA_WME_MAX_SP])
                        params.max_sp =
                             nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
+
+               if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+                       return -EINVAL;
        }
 
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
@@ -3625,10 +3646,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
        struct net_device *dev = info->user_ptr[1];
        struct nlattr *attr;
        struct wiphy *wiphy;
-       int err, tmp, n_ssids = 0, n_channels, i;
+       int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
        u32 interval;
        enum ieee80211_band band;
        size_t ie_len;
+       struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
 
        if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
            !rdev->ops->sched_scan_start)
@@ -3667,6 +3689,15 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
        if (n_ssids > wiphy->max_sched_scan_ssids)
                return -EINVAL;
 
+       if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
+               nla_for_each_nested(attr,
+                                   info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+                                   tmp)
+                       n_match_sets++;
+
+       if (n_match_sets > wiphy->max_match_sets)
+               return -EINVAL;
+
        if (info->attrs[NL80211_ATTR_IE])
                ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        else
@@ -3684,6 +3715,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
 
        request = kzalloc(sizeof(*request)
                        + sizeof(*request->ssids) * n_ssids
+                       + sizeof(*request->match_sets) * n_match_sets
                        + sizeof(*request->channels) * n_channels
                        + ie_len, GFP_KERNEL);
        if (!request) {
@@ -3701,6 +3733,18 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
                        request->ie = (void *)(request->channels + n_channels);
        }
 
+       if (n_match_sets) {
+               if (request->ie)
+                       request->match_sets = (void *)(request->ie + ie_len);
+               else if (request->ssids)
+                       request->match_sets =
+                               (void *)(request->ssids + n_ssids);
+               else
+                       request->match_sets =
+                               (void *)(request->channels + n_channels);
+       }
+       request->n_match_sets = n_match_sets;
+
        i = 0;
        if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
                /* user specified, bail out if channel not found */
@@ -3765,6 +3809,31 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
                }
        }
 
+       i = 0;
+       if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+               nla_for_each_nested(attr,
+                                   info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+                                   tmp) {
+                       struct nlattr *ssid;
+
+                       nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+                                 nla_data(attr), nla_len(attr),
+                                 nl80211_match_policy);
+                       ssid = tb[NL80211_ATTR_SCHED_SCAN_MATCH_SSID];
+                       if (ssid) {
+                               if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
+                                       err = -EINVAL;
+                                       goto out_free;
+                               }
+                               memcpy(request->match_sets[i].ssid.ssid,
+                                      nla_data(ssid), nla_len(ssid));
+                               request->match_sets[i].ssid.ssid_len =
+                                       nla_len(ssid);
+                       }
+                       i++;
+               }
+       }
+
        if (info->attrs[NL80211_ATTR_IE]) {
                request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
                memcpy((void *)request->ie,
@@ -4458,8 +4527,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 
        wiphy = &rdev->wiphy;
 
-       if (info->attrs[NL80211_ATTR_MAC])
+       if (info->attrs[NL80211_ATTR_MAC]) {
                ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+               if (!is_valid_ether_addr(ibss.bssid))
+                       return -EINVAL;
+       }
        ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
        ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
 
@@ -7197,6 +7270,52 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
        nlmsg_free(msg);
 }
 
+void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
+                                   struct net_device *netdev, int index,
+                                   const u8 *bssid, bool preauth, gfp_t gfp)
+{
+       struct sk_buff *msg;
+       struct nlattr *attr;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE);
+       if (!hdr) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+
+       attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE);
+       if (!attr)
+               goto nla_put_failure;
+
+       NLA_PUT_U32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index);
+       NLA_PUT(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid);
+       if (preauth)
+               NLA_PUT_FLAG(msg, NL80211_PMKSA_CANDIDATE_PREAUTH);
+
+       nla_nest_end(msg, attr);
+
+       if (genlmsg_end(msg, hdr) < 0) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+                               nl80211_mlme_mcgrp.id, gfp);
+       return;
+
+ nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+
 void
 nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
                                struct net_device *netdev, const u8 *peer,
index 5d69c56400aedf2bf7e26e0c5294e1c120d3a070..f24a1fbeaf19a8bf3cee73a3ec8b3b33d6e0f0ad 100644 (file)
@@ -113,4 +113,8 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
                              struct net_device *netdev, const u8 *bssid,
                              const u8 *replay_ctr, gfp_t gfp);
 
+void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
+                                   struct net_device *netdev, int index,
+                                   const u8 *bssid, bool preauth, gfp_t gfp);
+
 #endif /* __NET_WIRELESS_NL80211_H */
index 9f3aa5cabdefec4102d2c3f5bca167c62cbc8bdf..2520a1b7e7db7947754dafe3c814405ea26798e7 100644 (file)
@@ -751,9 +751,10 @@ static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
                      chan->center_freq,
                      KHZ_TO_MHZ(desired_bw_khz));
 
-       REG_DBG_PRINT("%d KHz - %d KHz @  KHz), (%s mBi, %d mBm)\n",
+       REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n",
                      freq_range->start_freq_khz,
                      freq_range->end_freq_khz,
+                     freq_range->max_bandwidth_khz,
                      max_antenna_gain,
                      power_rule->max_eirp);
 }
@@ -850,6 +851,7 @@ static void handle_channel(struct wiphy *wiphy,
                return;
        }
 
+       chan->beacon_found = false;
        chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
        chan->max_antenna_gain = min(chan->orig_mag,
                (int) MBI_TO_DBI(power_rule->max_antenna_gain));
@@ -910,14 +912,6 @@ static bool ignore_reg_update(struct wiphy *wiphy,
        return false;
 }
 
-static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
-{
-       struct cfg80211_registered_device *rdev;
-
-       list_for_each_entry(rdev, &cfg80211_rdev_list, list)
-               wiphy_update_regulatory(&rdev->wiphy, initiator);
-}
-
 static void handle_reg_beacon(struct wiphy *wiphy,
                              unsigned int chan_idx,
                              struct reg_beacon *reg_beacon)
@@ -1117,11 +1111,13 @@ static void reg_process_ht_flags(struct wiphy *wiphy)
 
 }
 
-void wiphy_update_regulatory(struct wiphy *wiphy,
-                            enum nl80211_reg_initiator initiator)
+static void wiphy_update_regulatory(struct wiphy *wiphy,
+                                   enum nl80211_reg_initiator initiator)
 {
        enum ieee80211_band band;
 
+       assert_reg_lock();
+
        if (ignore_reg_update(wiphy, initiator))
                return;
 
@@ -1136,6 +1132,22 @@ void wiphy_update_regulatory(struct wiphy *wiphy,
                wiphy->reg_notifier(wiphy, last_request);
 }
 
+void regulatory_update(struct wiphy *wiphy,
+                      enum nl80211_reg_initiator setby)
+{
+       mutex_lock(&reg_mutex);
+       wiphy_update_regulatory(wiphy, setby);
+       mutex_unlock(&reg_mutex);
+}
+
+static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
+{
+       struct cfg80211_registered_device *rdev;
+
+       list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+               wiphy_update_regulatory(&rdev->wiphy, initiator);
+}
+
 static void handle_channel_custom(struct wiphy *wiphy,
                                  enum ieee80211_band band,
                                  unsigned int chan_idx,
index b67d1c3a2fb954eac3d282a4a9cf4ac5e1231670..4a56799d868d5fa7efc48ab8e21cbb67d3a8a473 100644 (file)
@@ -16,6 +16,8 @@ void regulatory_exit(void);
 
 int set_regdom(const struct ieee80211_regdomain *rd);
 
+void regulatory_update(struct wiphy *wiphy, enum nl80211_reg_initiator setby);
+
 /**
  * regulatory_hint_found_beacon - hints a beacon was found on a channel
  * @wiphy: the wireless device where the beacon was found on
index b0f0039669536164f0f9d67147030f3f43c8a0a0..0fb1424104047ced0d99949be89388509e05fc5c 100644 (file)
@@ -228,6 +228,33 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
 }
 EXPORT_SYMBOL(cfg80211_find_ie);
 
+const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
+                                 const u8 *ies, int len)
+{
+       struct ieee80211_vendor_ie *ie;
+       const u8 *pos = ies, *end = ies + len;
+       int ie_oui;
+
+       while (pos < end) {
+               pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
+                                      end - pos);
+               if (!pos)
+                       return NULL;
+
+               if (end - pos < sizeof(*ie))
+                       return NULL;
+
+               ie = (struct ieee80211_vendor_ie *)pos;
+               ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
+               if (ie_oui == oui && ie->oui_type == oui_type)
+                       return pos;
+
+               pos += 2 + ie->len;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(cfg80211_find_vendor_ie);
+
 static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
 {
        const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
index b7b6ff8be553a10f7a0191ac04f09eeaff06463c..6e86d5acf145bef1d7ba2e842fd61f1b50610c69 100644 (file)
@@ -110,15 +110,22 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
        else {
                int i = 0, j;
                enum ieee80211_band band;
+               struct ieee80211_supported_band *bands;
+               struct ieee80211_channel *channel;
 
                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-                       if (!wdev->wiphy->bands[band])
+                       bands = wdev->wiphy->bands[band];
+                       if (!bands)
                                continue;
-                       for (j = 0; j < wdev->wiphy->bands[band]->n_channels;
-                            i++, j++)
-                               request->channels[i] =
-                                       &wdev->wiphy->bands[band]->channels[j];
+                       for (j = 0; j < bands->n_channels; j++) {
+                               channel = &bands->channels[j];
+                               if (channel->flags & IEEE80211_CHAN_DISABLED)
+                                       continue;
+                               request->channels[i++] = channel;
+                       }
+                       request->rates[band] = (1 << bands->n_bitrates) - 1;
                }
+               n_channels = i;
        }
        request->n_channels = n_channels;
        request->ssids = (void *)&request->channels[n_channels];
index c6e4ca6a7d2e0b1fcc6e450b1255a0140ae64cff..ff574597a8544030ef18b2e2186354ef46511bc3 100644 (file)
@@ -93,7 +93,8 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
 
        if (rdev->ops->suspend) {
                rtnl_lock();
-               ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
+               if (rdev->wiphy.registered)
+                       ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan);
                rtnl_unlock();
        }
 
@@ -112,7 +113,8 @@ static int wiphy_resume(struct device *dev)
 
        if (rdev->ops->resume) {
                rtnl_lock();
-               ret = rdev->ops->resume(&rdev->wiphy);
+               if (rdev->wiphy.registered)
+                       ret = rdev->ops->resume(&rdev->wiphy);
                rtnl_unlock();
        }
 
index eef82f79554dba1fdce02daddcee9178635716e3..39dbf4ad7ca17cdca7581355b5a5b0aaa6221b48 100644 (file)
@@ -513,10 +513,9 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
                if (head_need)
                        skb_orphan(skb);
 
-               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
-                       pr_err("failed to reallocate Tx buffer\n");
+               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
                        return -ENOMEM;
-               }
+
                skb->truesize += head_need;
        }
 
This page took 1.293129 seconds and 4 git commands to generate.