Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi...
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 18 Dec 2013 20:09:58 +0000 (15:09 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 18 Dec 2013 20:09:58 +0000 (15:09 -0500)
225 files changed:
MAINTAINERS
drivers/bcma/host_pci.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btmrvl_drv.h
drivers/bluetooth/btmrvl_main.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.h
drivers/bluetooth/btusb.c
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.h
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/debug.h
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htt.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath5k/dma.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9340_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.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/reg.h
drivers/net/wireless/ath/ath9k/tx99.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel.h
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/atmel_pci.c
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/libertas/README
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/decl.h
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwifiex/sta_tx.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_txrx.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/p54/net2280.h
drivers/net/wireless/prism54/isl_38xx.c
drivers/net/wireless/prism54/isl_38xx.h
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.h
drivers/net/wireless/prism54/isl_oid.h
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_dev.h
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_eth.h
drivers/net/wireless/prism54/islpci_hotplug.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/prism54/islpci_mgt.h
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/prism54/oid_mgt.h
drivers/net/wireless/prism54/prismcompat.h
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500pci.h
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800lib.h
drivers/net/wireless/rt2x00/rt2800mmio.c
drivers/net/wireless/rt2x00/rt2800mmio.h
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800pci.h
drivers/net/wireless/rt2x00/rt2800soc.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2800usb.h
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00crypto.c
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rt2x00/rt2x00debug.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00dump.h
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rt2x00/rt2x00leds.c
drivers/net/wireless/rt2x00/rt2x00leds.h
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00link.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00mmio.c
drivers/net/wireless/rt2x00/rt2x00mmio.h
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00reg.h
drivers/net/wireless/rt2x00/rt2x00soc.c
drivers/net/wireless/rt2x00/rt2x00soc.h
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rt2x00/rt2x00usb.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_def.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_rf.c
drivers/net/wireless/zd1211rw/zd_rf.h
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/nfc/mei_phy.c
drivers/nfc/microread/i2c.c
drivers/nfc/microread/mei.c
drivers/nfc/microread/microread.c
drivers/nfc/microread/microread.h
drivers/nfc/nfcwilink.c
drivers/nfc/pn533.c
drivers/nfc/pn544/i2c.c
drivers/nfc/pn544/mei.c
drivers/nfc/pn544/pn544.c
drivers/nfc/pn544/pn544.h
include/linux/ath9k_platform.h
include/linux/platform_data/pn544.h
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/mac80211.h
include/uapi/linux/nl80211.h
net/bluetooth/af_bluetooth.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bluetooth/smp.h
net/mac80211/cfg.c
net/mac80211/driver-ops.h
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh_sync.c
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/nfc/af_nfc.c
net/nfc/core.c
net/nfc/hci/command.c
net/nfc/hci/core.c
net/nfc/hci/hci.h
net/nfc/hci/hcp.c
net/nfc/hci/llc.c
net/nfc/hci/llc.h
net/nfc/hci/llc_nop.c
net/nfc/hci/llc_shdlc.c
net/nfc/llcp.h
net/nfc/llcp_commands.c
net/nfc/llcp_core.c
net/nfc/llcp_sock.c
net/nfc/nci/core.c
net/nfc/nci/data.c
net/nfc/nci/lib.c
net/nfc/nci/ntf.c
net/nfc/nci/rsp.c
net/nfc/netlink.c
net/nfc/nfc.h
net/nfc/rawsock.c
net/rfkill/core.c
net/wireless/core.c
net/wireless/core.h
net/wireless/mesh.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c

index 6d7cf3b..bdf13e4 100644 (file)
@@ -8553,12 +8553,11 @@ S:      Maintained
 F:     sound/soc/codecs/twl4030*
 
 TI WILINK WIRELESS DRIVERS
-M:     Luciano Coelho <luca@coelho.fi>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/wl12xx
 W:     http://wireless.kernel.org/en/users/Drivers/wl1251
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/ti/
 F:     include/linux/wl12xx.h
 
index 12a4ff7..e333305 100644 (file)
@@ -269,7 +269,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
 
 #endif /* CONFIG_PM_SLEEP */
 
-static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
+static const struct pci_device_id bcma_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
index 6bfc1bb..d3fdc32 100644 (file)
@@ -83,6 +83,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x3005) },
        { USB_DEVICE(0x04CA, 0x3006) },
        { USB_DEVICE(0x04CA, 0x3008) },
+       { USB_DEVICE(0x04CA, 0x300b) },
        { USB_DEVICE(0x13d3, 0x3362) },
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
@@ -96,6 +97,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3402) },
        { USB_DEVICE(0x0cf3, 0x3121) },
        { USB_DEVICE(0x0cf3, 0xe003) },
+       { USB_DEVICE(0x0489, 0xe05f) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -125,6 +127,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
@@ -138,6 +141,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
index f9d1833..7399303 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <net/bluetooth/bluetooth.h>
-#include <linux/ctype.h>
-#include <linux/firmware.h>
 
 #define BTM_HEADER_LEN                 4
 #define BTM_UPLD_SIZE                  2312
@@ -43,8 +41,6 @@ struct btmrvl_thread {
 struct btmrvl_device {
        void *card;
        struct hci_dev *hcidev;
-       struct device *dev;
-       const char *cal_data;
 
        u8 dev_type;
 
@@ -90,12 +86,12 @@ struct btmrvl_private {
 
 #define MRVL_VENDOR_PKT                        0xFE
 
-/* Bluetooth commands  */
-#define BT_CMD_AUTO_SLEEP_MODE         0x23
-#define BT_CMD_HOST_SLEEP_CONFIG       0x59
-#define BT_CMD_HOST_SLEEP_ENABLE       0x5A
-#define BT_CMD_MODULE_CFG_REQ          0x5B
-#define BT_CMD_LOAD_CONFIG_DATA                0x61
+/* Vendor specific Bluetooth commands */
+#define BT_CMD_AUTO_SLEEP_MODE         0xFC23
+#define BT_CMD_HOST_SLEEP_CONFIG       0xFC59
+#define BT_CMD_HOST_SLEEP_ENABLE       0xFC5A
+#define BT_CMD_MODULE_CFG_REQ          0xFC5B
+#define BT_CMD_LOAD_CONFIG_DATA                0xFC61
 
 /* Sub-commands: Module Bringup/Shutdown Request/Response */
 #define MODULE_BRINGUP_REQ             0xF1
@@ -104,6 +100,11 @@ struct btmrvl_private {
 
 #define MODULE_SHUTDOWN_REQ            0xF2
 
+/* Vendor specific Bluetooth events */
+#define BT_EVENT_AUTO_SLEEP_MODE       0x23
+#define BT_EVENT_HOST_SLEEP_CONFIG     0x59
+#define BT_EVENT_HOST_SLEEP_ENABLE     0x5A
+#define BT_EVENT_MODULE_CFG_REQ                0x5B
 #define BT_EVENT_POWER_STATE           0x20
 
 /* Bluetooth Power States */
@@ -111,8 +112,6 @@ struct btmrvl_private {
 #define BT_PS_DISABLE                  0x03
 #define BT_PS_SLEEP                    0x01
 
-#define OGF                            0x3F
-
 /* Host Sleep states */
 #define HS_ACTIVATED                   0x01
 #define HS_DEACTIVATED                 0x00
@@ -121,7 +120,7 @@ struct btmrvl_private {
 #define PS_SLEEP                       0x01
 #define PS_AWAKE                       0x00
 
-#define BT_CMD_DATA_SIZE               32
+#define BT_CAL_HDR_LEN                 4
 #define BT_CAL_DATA_SIZE               28
 
 struct btmrvl_event {
index 5cf31c4..1e0320a 100644 (file)
@@ -19,7 +19,7 @@
  **/
 
 #include <linux/module.h>
-
+#include <linux/of.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
@@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 
        if (hdr->evt == HCI_EV_CMD_COMPLETE) {
                struct hci_ev_cmd_complete *ec;
-               u16 opcode, ocf, ogf;
+               u16 opcode;
 
                ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
                opcode = __le16_to_cpu(ec->opcode);
-               ocf = hci_opcode_ocf(opcode);
-               ogf = hci_opcode_ogf(opcode);
 
                if (priv->btmrvl_dev.sendcmdflag) {
                        priv->btmrvl_dev.sendcmdflag = false;
@@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
                        wake_up_interruptible(&priv->adapter->cmd_wait_q);
                }
 
-               if (ogf == OGF) {
-                       BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
-                              ogf, ocf);
+               if (hci_opcode_ogf(opcode) == 0x3F) {
+                       BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
                        kfree_skb(skb);
                        return false;
                }
@@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
        }
 
        switch (event->data[0]) {
-       case BT_CMD_AUTO_SLEEP_MODE:
+       case BT_EVENT_AUTO_SLEEP_MODE:
                if (!event->data[2]) {
                        if (event->data[1] == BT_PS_ENABLE)
                                adapter->psmode = 1;
@@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                }
                break;
 
-       case BT_CMD_HOST_SLEEP_CONFIG:
+       case BT_EVENT_HOST_SLEEP_CONFIG:
                if (!event->data[3])
                        BT_DBG("gpio=%x, gap=%x", event->data[1],
                                                        event->data[2]);
@@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                        BT_DBG("HSCFG command failed");
                break;
 
-       case BT_CMD_HOST_SLEEP_ENABLE:
+       case BT_EVENT_HOST_SLEEP_ENABLE:
                if (!event->data[1]) {
                        adapter->hs_state = HS_ACTIVATED;
                        if (adapter->psmode)
@@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                }
                break;
 
-       case BT_CMD_MODULE_CFG_REQ:
+       case BT_EVENT_MODULE_CFG_REQ:
                if (priv->btmrvl_dev.sendcmdflag &&
                                event->data[1] == MODULE_BRINGUP_REQ) {
                        BT_DBG("EVENT:%s",
@@ -166,7 +163,7 @@ exit:
 }
 EXPORT_SYMBOL_GPL(btmrvl_process_event);
 
-static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
+static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
                                const void *param, u8 len)
 {
        struct sk_buff *skb;
@@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
        }
 
        hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
-       hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
+       hdr->opcode = cpu_to_le16(opcode);
        hdr->plen = len;
 
        if (len)
@@ -417,127 +414,62 @@ static int btmrvl_open(struct hci_dev *hdev)
        return 0;
 }
 
-/*
- * This function parses provided calibration data input. It should contain
- * hex bytes separated by space or new line character. Here is an example.
- * 00 1C 01 37 FF FF FF FF 02 04 7F 01
- * CE BA 00 00 00 2D C6 C0 00 00 00 00
- * 00 F0 00 00
- */
-static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
+static int btmrvl_download_cal_data(struct btmrvl_private *priv,
+                                   u8 *data, int len)
 {
-       const u8 *s = src;
-       u8 *d = dst;
        int ret;
-       u8 tmp[3];
-
-       tmp[2] = '\0';
-       while ((s - src) <= len - 2) {
-               if (isspace(*s)) {
-                       s++;
-                       continue;
-               }
-
-               if (isxdigit(*s)) {
-                       if ((d - dst) >= dst_size) {
-                               BT_ERR("calibration data file too big!!!");
-                               return -EINVAL;
-                       }
-
-                       memcpy(tmp, s, 2);
-
-                       ret = kstrtou8(tmp, 16, d++);
-                       if (ret < 0)
-                               return ret;
-
-                       s += 2;
-               } else {
-                       return -EINVAL;
-               }
-       }
-       if (d == dst)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int btmrvl_load_cal_data(struct btmrvl_private *priv,
-                               u8 *config_data)
-{
-       int i, ret;
-       u8 data[BT_CMD_DATA_SIZE];
 
        data[0] = 0x00;
        data[1] = 0x00;
        data[2] = 0x00;
-       data[3] = BT_CMD_DATA_SIZE - 4;
-
-       /* Swap cal-data bytes. Each four bytes are swapped. Considering 4
-        * byte SDIO header offset, mapping of input and output bytes will be
-        * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4},
-        * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */
-       for (i = 4; i < BT_CMD_DATA_SIZE; i++)
-               data[i] = config_data[(i / 4) * 8 - 1 - i];
+       data[3] = len;
 
        print_hex_dump_bytes("Calibration data: ",
-                            DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE);
+                            DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len);
 
        ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
-                                  BT_CMD_DATA_SIZE);
+                                  BT_CAL_HDR_LEN + len);
        if (ret)
                BT_ERR("Failed to download caibration data\n");
 
        return 0;
 }
 
-static int
-btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
+static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
 {
-       u8 cal_data[BT_CAL_DATA_SIZE];
+       struct device_node *dt_node;
+       u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
+       const char name[] = "btmrvl_caldata";
+       const char property[] = "btmrvl,caldata";
        int ret;
 
-       ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
+       dt_node = of_find_node_by_name(NULL, name);
+       if (!dt_node)
+               return -ENODEV;
+
+       ret = of_property_read_u8_array(dt_node, property,
+                                       cal_data + BT_CAL_HDR_LEN,
+                                       BT_CAL_DATA_SIZE);
        if (ret)
                return ret;
 
-       ret = btmrvl_load_cal_data(priv, cal_data);
+       BT_DBG("Use cal data from device tree");
+       ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
        if (ret) {
-               BT_ERR("Fail to load calibrate data");
+               BT_ERR("Fail to download calibrate data");
                return ret;
        }
 
        return 0;
 }
 
-static int btmrvl_cal_data_config(struct btmrvl_private *priv)
-{
-       const struct firmware *cfg;
-       int ret;
-       const char *cal_data = priv->btmrvl_dev.cal_data;
-
-       if (!cal_data)
-               return 0;
-
-       ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
-       if (ret < 0) {
-               BT_DBG("Failed to get %s file, skipping cal data download",
-                      cal_data);
-               return 0;
-       }
-
-       ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
-       release_firmware(cfg);
-       return ret;
-}
-
 static int btmrvl_setup(struct hci_dev *hdev)
 {
        struct btmrvl_private *priv = hci_get_drvdata(hdev);
 
        btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
 
-       if (btmrvl_cal_data_config(priv))
-               BT_ERR("Set cal data failed");
+       btmrvl_cal_data_dt(priv);
 
        priv->btmrvl_dev.psmode = 1;
        btmrvl_enable_ps(priv);
index fabcf5b..1b52c9f 100644 (file)
@@ -18,6 +18,7 @@
  * this warranty disclaimer.
  **/
 
+#include <linux/firmware.h>
 #include <linux/slab.h>
 
 #include <linux/mmc/sdio_ids.h>
@@ -101,7 +102,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
        .helper         = "mrvl/sd8688_helper.bin",
        .firmware       = "mrvl/sd8688.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_8688,
        .sd_blksz_fw_dl = 64,
 };
@@ -109,7 +109,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8787_uapsta.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_87xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -117,7 +116,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8797_uapsta.bin",
-       .cal_data       = "mrvl/sd8797_caldata.conf",
        .reg            = &btmrvl_reg_87xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -125,7 +123,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8897_uapsta.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_88xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -1007,7 +1004,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
                struct btmrvl_sdio_device *data = (void *) id->driver_data;
                card->helper = data->helper;
                card->firmware = data->firmware;
-               card->cal_data = data->cal_data;
                card->reg = data->reg;
                card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
        }
@@ -1036,8 +1032,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
        }
 
        card->priv = priv;
-       priv->btmrvl_dev.dev = &card->func->dev;
-       priv->btmrvl_dev.cal_data = card->cal_data;
 
        /* Initialize the interface specific function pointers */
        priv->hw_host_to_card = btmrvl_sdio_host_to_card;
@@ -1220,5 +1214,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
 MODULE_FIRMWARE("mrvl/sd8688.bin");
 MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
-MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
 MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
index 6872d9e..43d35a6 100644 (file)
@@ -85,7 +85,6 @@ struct btmrvl_sdio_card {
        u32 ioport;
        const char *helper;
        const char *firmware;
-       const char *cal_data;
        const struct btmrvl_sdio_card_reg *reg;
        u16 sd_blksz_fw_dl;
        u8 rx_unit;
@@ -95,7 +94,6 @@ struct btmrvl_sdio_card {
 struct btmrvl_sdio_device {
        const char *helper;
        const char *firmware;
-       const char *cal_data;
        const struct btmrvl_sdio_card_reg *reg;
        u16 sd_blksz_fw_dl;
 };
index c0ff34f..bfbcc5a 100644 (file)
@@ -150,6 +150,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
@@ -163,6 +164,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -223,6 +225,7 @@ static const struct usb_device_id blacklist_table[] = {
 
        /* Intel Bluetooth device */
        { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
+       { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
 
        { }     /* Terminating entry */
 };
@@ -1435,8 +1438,10 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_BCM92035)
                hdev->setup = btusb_setup_bcm92035;
 
-       if (id->driver_info & BTUSB_INTEL)
+       if (id->driver_info & BTUSB_INTEL) {
+               usb_enable_autosuspend(data->udev);
                hdev->setup = btusb_setup_intel;
+       }
 
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
index e46951b..d44d618 100644 (file)
@@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
                           misc_ie_addr | CE_ERROR_MASK);
 }
 
+static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
+                                               u32 ce_ctrl_addr)
+{
+       u32 misc_ie_addr = ath10k_pci_read32(ar,
+                                            ce_ctrl_addr + MISC_IE_ADDRESS);
+
+       ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
+                          misc_ie_addr & ~CE_ERROR_MASK);
+}
+
 static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
                                                     u32 ce_ctrl_addr,
                                                     unsigned int mask)
@@ -731,7 +741,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
 
 void ath10k_ce_per_engine_service_any(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ce_id, ret;
        u32 intr_summary;
 
@@ -741,7 +750,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
 
        intr_summary = CE_INTERRUPT_SUMMARY(ar);
 
-       for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) {
+       for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
                if (intr_summary & (1 << ce_id))
                        intr_summary &= ~(1 << ce_id);
                else
@@ -783,22 +792,25 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
        ath10k_pci_sleep(ar);
 }
 
-void ath10k_ce_disable_interrupts(struct ath10k *ar)
+int ath10k_ce_disable_interrupts(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ce_id, ret;
 
        ret = ath10k_pci_wake(ar);
        if (ret)
-               return;
+               return ret;
 
-       for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) {
-               struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-               u32 ctrl_addr = ce_state->ctrl_addr;
+       for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
+               u32 ctrl_addr = ath10k_ce_base_address(ce_id);
 
                ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
+               ath10k_ce_error_intr_disable(ar, ctrl_addr);
+               ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
        }
+
        ath10k_pci_sleep(ar);
+
+       return 0;
 }
 
 void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
@@ -1047,9 +1059,19 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                                const struct ce_attr *attr)
 {
        struct ath10k_ce_pipe *ce_state;
-       u32 ctrl_addr = ath10k_ce_base_address(ce_id);
        int ret;
 
+       /*
+        * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
+        * additional TX locking checks.
+        *
+        * For the lack of a better place do the check here.
+        */
+       BUILD_BUG_ON(TARGET_NUM_MSDU_DESC >
+                    (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+       BUILD_BUG_ON(TARGET_10X_NUM_MSDU_DESC >
+                    (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+
        ret = ath10k_pci_wake(ar);
        if (ret)
                return NULL;
@@ -1057,7 +1079,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
        ce_state = ath10k_ce_init_state(ar, ce_id, attr);
        if (!ce_state) {
                ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id);
-               return NULL;
+               goto out;
        }
 
        if (attr->src_nentries) {
@@ -1066,7 +1088,8 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                        ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
                                   ce_id, ret);
                        ath10k_ce_deinit(ce_state);
-                       return NULL;
+                       ce_state = NULL;
+                       goto out;
                }
        }
 
@@ -1076,15 +1099,13 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                        ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
                                   ce_id, ret);
                        ath10k_ce_deinit(ce_state);
-                       return NULL;
+                       ce_state = NULL;
+                       goto out;
                }
        }
 
-       /* Enable CE error interrupts */
-       ath10k_ce_error_intr_enable(ar, ctrl_addr);
-
+out:
        ath10k_pci_sleep(ar);
-
        return ce_state;
 }
 
index 15d45b5..67dbde6 100644 (file)
@@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state);
 /*==================CE Interrupt Handlers====================*/
 void ath10k_ce_per_engine_service_any(struct ath10k *ar);
 void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
-void ath10k_ce_disable_interrupts(struct ath10k *ar);
+int ath10k_ce_disable_interrupts(struct ath10k *ar);
 
 /* ce_attr.flags values */
 /* Use NonSnooping PCIe accesses? */
index 1129994..3b59af3 100644 (file)
@@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar)
                return ret;
        }
 
-       if (!uart_print) {
-               ath10k_info("UART prints disabled\n");
+       if (!uart_print)
                return 0;
-       }
 
        ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
        if (ret) {
@@ -645,8 +643,8 @@ static int ath10k_init_hw_params(struct ath10k *ar)
 
        ar->hw_params = *hw_params;
 
-       ath10k_info("Hardware name %s version 0x%x\n",
-                   ar->hw_params.name, ar->target_version);
+       ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
+                  ar->hw_params.name, ar->target_version);
 
        return 0;
 }
@@ -664,7 +662,8 @@ static void ath10k_core_restart(struct work_struct *work)
                ieee80211_restart_hw(ar->hw);
                break;
        case ATH10K_STATE_OFF:
-               /* this can happen if driver is being unloaded */
+               /* this can happen if driver is being unloaded
+                * or if the crash happens during FW probing */
                ath10k_warn("cannot restart a device that hasn't been started\n");
                break;
        case ATH10K_STATE_RESTARTING:
@@ -737,8 +736,6 @@ EXPORT_SYMBOL(ath10k_core_create);
 
 void ath10k_core_destroy(struct ath10k *ar)
 {
-       ath10k_debug_destroy(ar);
-
        flush_workqueue(ar->workqueue);
        destroy_workqueue(ar->workqueue);
 
@@ -786,21 +783,30 @@ int ath10k_core_start(struct ath10k *ar)
                goto err;
        }
 
-       status = ath10k_htc_wait_target(&ar->htc);
-       if (status)
+       status = ath10k_hif_start(ar);
+       if (status) {
+               ath10k_err("could not start HIF: %d\n", status);
                goto err_wmi_detach;
+       }
+
+       status = ath10k_htc_wait_target(&ar->htc);
+       if (status) {
+               ath10k_err("failed to connect to HTC: %d\n", status);
+               goto err_hif_stop;
+       }
 
        status = ath10k_htt_attach(ar);
        if (status) {
                ath10k_err("could not attach htt (%d)\n", status);
-               goto err_wmi_detach;
+               goto err_hif_stop;
        }
 
        status = ath10k_init_connect_htc(ar);
        if (status)
                goto err_htt_detach;
 
-       ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version);
+       ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
+                  ar->hw->wiphy->fw_version);
 
        status = ath10k_wmi_cmd_init(ar);
        if (status) {
@@ -826,12 +832,23 @@ int ath10k_core_start(struct ath10k *ar)
        ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
        INIT_LIST_HEAD(&ar->arvifs);
 
+       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n",
+                           ar->hw_params.name, ar->target_version,
+                           ar->hw->wiphy->fw_version, ar->fw_api,
+                           ar->htt.target_version_major,
+                           ar->htt.target_version_minor);
+
+       __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
+
        return 0;
 
 err_disconnect_htc:
        ath10k_htc_stop(&ar->htc);
 err_htt_detach:
        ath10k_htt_detach(&ar->htt);
+err_hif_stop:
+       ath10k_hif_stop(ar);
 err_wmi_detach:
        ath10k_wmi_detach(ar);
 err:
@@ -985,6 +1002,8 @@ void ath10k_core_unregister(struct ath10k *ar)
        ath10k_mac_unregister(ar);
 
        ath10k_core_free_firmware_files(ar);
+
+       ath10k_debug_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_unregister);
 
index 0934f76..79726e0 100644 (file)
@@ -30,6 +30,7 @@
 #include "wmi.h"
 #include "../ath.h"
 #include "../regd.h"
+#include "../dfs_pattern_detector.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -43,7 +44,7 @@
 /* Antenna noise floor */
 #define ATH10K_DEFAULT_NOISE_FLOOR -95
 
-#define ATH10K_MAX_NUM_MGMT_PENDING 16
+#define ATH10K_MAX_NUM_MGMT_PENDING 128
 
 struct ath10k;
 
@@ -192,6 +193,14 @@ struct ath10k_target_stats {
 
 };
 
+struct ath10k_dfs_stats {
+       u32 phy_errors;
+       u32 pulses_total;
+       u32 pulses_detected;
+       u32 pulses_discarded;
+       u32 radar_detected;
+};
+
 #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
 
 struct ath10k_peer {
@@ -261,6 +270,8 @@ struct ath10k_debug {
 
        unsigned long htt_stats_mask;
        struct delayed_work htt_stats_dwork;
+       struct ath10k_dfs_stats dfs_stats;
+       struct ath_dfs_pool_stats dfs_pool_stats;
 };
 
 enum ath10k_state {
@@ -299,6 +310,12 @@ enum ath10k_fw_features {
        ATH10K_FW_FEATURE_COUNT,
 };
 
+enum ath10k_dev_flags {
+       /* Indicates that ath10k device is during CAC phase of DFS */
+       ATH10K_CAC_RUNNING,
+       ATH10K_FLAG_FIRST_BOOT_DONE,
+};
+
 struct ath10k {
        struct ath_common ath_common;
        struct ieee80211_hw *hw;
@@ -392,6 +409,8 @@ struct ath10k {
        bool monitor_enabled;
        bool monitor_present;
        unsigned int filter_flags;
+       unsigned long dev_flags;
+       u32 dfs_block_radar_events;
 
        struct wmi_pdev_set_wmm_params_arg wmm_params;
        struct completion install_key_done;
@@ -428,6 +447,8 @@ struct ath10k {
        u32 survey_last_cycle_count;
        struct survey_info survey[ATH10K_NUM_CHANS];
 
+       struct dfs_pattern_detector *dfs_detector;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
        struct ath10k_debug debug;
 #endif
index 760ff22..6bdfad3 100644 (file)
@@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar)
                cancel_delayed_work(&ar->debug.htt_stats_dwork);
 }
 
+static ssize_t ath10k_write_simulate_radar(struct file *file,
+                                          const char __user *user_buf,
+                                          size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+
+       ieee80211_radar_detected(ar->hw);
+
+       return count;
+}
+
+static const struct file_operations fops_simulate_radar = {
+       .write = ath10k_write_simulate_radar,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#define ATH10K_DFS_STAT(s, p) (\
+       len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
+                        ar->debug.dfs_stats.p))
+
+#define ATH10K_DFS_POOL_STAT(s, p) (\
+       len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
+                        ar->debug.dfs_pool_stats.p))
+
+static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       int retval = 0, len = 0;
+       const int size = 8000;
+       struct ath10k *ar = file->private_data;
+       char *buf;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       if (!ar->dfs_detector) {
+               len += scnprintf(buf + len, size - len, "DFS not enabled\n");
+               goto exit;
+       }
+
+       ar->debug.dfs_pool_stats =
+                       ar->dfs_detector->get_stats(ar->dfs_detector);
+
+       len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
+
+       ATH10K_DFS_STAT("reported phy errors", phy_errors);
+       ATH10K_DFS_STAT("pulse events reported", pulses_total);
+       ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
+       ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
+       ATH10K_DFS_STAT("Radars detected", radar_detected);
+
+       len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
+       ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
+       ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
+       ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
+       ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
+       ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
+       ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
+       ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
+
+exit:
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_dfs_stats = {
+       .read = ath10k_read_dfs_stats,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -667,6 +747,20 @@ int ath10k_debug_create(struct ath10k *ar)
        debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_htt_stats_mask);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+               debugfs_create_file("dfs_simulate_radar", S_IWUSR,
+                                   ar->debug.debugfs_phy, ar,
+                                   &fops_simulate_radar);
+
+               debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
+                                   ar->debug.debugfs_phy,
+                                   &ar->dfs_block_radar_events);
+
+               debugfs_create_file("dfs_stats", S_IRUSR,
+                                   ar->debug.debugfs_phy, ar,
+                                   &fops_dfs_stats);
+       }
+
        return 0;
 }
 
index 3cfe3ee..1773c36 100644 (file)
@@ -33,6 +33,7 @@ enum ath10k_debug_mask {
        ATH10K_DBG_MGMT         = 0x00000100,
        ATH10K_DBG_DATA         = 0x00000200,
        ATH10K_DBG_BMI          = 0x00000400,
+       ATH10K_DBG_REGULATORY   = 0x00000800,
        ATH10K_DBG_ANY          = 0xffffffff,
 };
 
@@ -53,6 +54,8 @@ void ath10k_debug_read_service_map(struct ath10k *ar,
 void ath10k_debug_read_target_stats(struct ath10k *ar,
                                    struct wmi_stats_event *ev);
 
+#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
+
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
 {
@@ -82,6 +85,9 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
                                                  struct wmi_stats_event *ev)
 {
 }
+
+#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
+
 #endif /* CONFIG_ATH10K_DEBUGFS */
 
 #ifdef CONFIG_ATH10K_DEBUG
index edae50b..edc57ab 100644 (file)
@@ -191,6 +191,11 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
        struct ath10k_htc *htc = &ar->htc;
        struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 
+       if (!skb) {
+               ath10k_warn("invalid sk_buff completion - NULL pointer. firmware crashed?\n");
+               return 0;
+       }
+
        ath10k_htc_notify_tx_completion(ep, skb);
        /* the skb now belongs to the completion handler */
 
@@ -534,14 +539,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
        u16 credit_count;
        u16 credit_size;
 
-       reinit_completion(&htc->ctl_resp);
-
-       status = ath10k_hif_start(htc->ar);
-       if (status) {
-               ath10k_err("could not start HIF (%d)\n", status);
-               goto err_start;
-       }
-
        status = wait_for_completion_timeout(&htc->ctl_resp,
                                             ATH10K_HTC_WAIT_TIMEOUT_HZ);
        if (status <= 0) {
@@ -549,15 +546,13 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
                        status = -ETIMEDOUT;
 
                ath10k_err("ctl_resp never came in (%d)\n", status);
-               goto err_target;
+               return status;
        }
 
        if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
                ath10k_err("Invalid HTC ready msg len:%d\n",
                           htc->control_resp_len);
-
-               status = -ECOMM;
-               goto err_target;
+               return -ECOMM;
        }
 
        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
@@ -567,8 +562,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
        if (message_id != ATH10K_HTC_MSG_READY_ID) {
                ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
-               status = -ECOMM;
-               goto err_target;
+               return -ECOMM;
        }
 
        htc->total_transmit_credits = credit_count;
@@ -581,9 +575,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
        if ((htc->total_transmit_credits == 0) ||
            (htc->target_credit_size == 0)) {
-               status = -ECOMM;
                ath10k_err("Invalid credit size received\n");
-               goto err_target;
+               return -ECOMM;
        }
 
        ath10k_htc_setup_target_buffer_assignments(htc);
@@ -600,14 +593,10 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
        status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
        if (status) {
                ath10k_err("could not connect to htc service (%d)\n", status);
-               goto err_target;
+               return status;
        }
 
        return 0;
-err_target:
-       ath10k_hif_stop(htc->ar);
-err_start:
-       return status;
 }
 
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
index 5f7eeeb..69697af 100644 (file)
@@ -104,8 +104,8 @@ err_htc_attach:
 
 static int ath10k_htt_verify_version(struct ath10k_htt *htt)
 {
-       ath10k_info("htt target version %d.%d\n",
-                   htt->target_version_major, htt->target_version_minor);
+       ath10k_dbg(ATH10K_DBG_BOOT, "htt target version %d.%d\n",
+                  htt->target_version_major, htt->target_version_minor);
 
        if (htt->target_version_major != 2 &&
            htt->target_version_major != 3) {
index 1a337e9..7fc7919 100644 (file)
@@ -1182,6 +1182,7 @@ struct htt_rx_info {
                u32 info2;
        } rate;
        bool fcs_err;
+       bool amsdu_more;
 };
 
 struct ath10k_htt {
index 90d4f74..fcb534f 100644 (file)
@@ -659,23 +659,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        memcpy(hdr_buf, hdr, hdr_len);
        hdr = (struct ieee80211_hdr *)hdr_buf;
 
-       /* FIXME: Hopefully this is a temporary measure.
-        *
-        * Reporting individual A-MSDU subframes means each reported frame
-        * shares the same sequence number.
-        *
-        * mac80211 drops frames it recognizes as duplicates, i.e.
-        * retransmission flag is set and sequence number matches sequence
-        * number from a previous frame (as per IEEE 802.11-2012: 9.3.2.10
-        * "Duplicate detection and recovery")
-        *
-        * To avoid frames being dropped clear retransmission flag for all
-        * received A-MSDUs.
-        *
-        * Worst case: actual duplicate frames will be reported but this should
-        * still be handled gracefully by other OSI/ISO layers. */
-       hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_RETRY);
-
        first = skb;
        while (skb) {
                void *decap_hdr;
@@ -746,6 +729,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                skb = skb->next;
                info->skb->next = NULL;
 
+               if (skb)
+                       info->amsdu_more = true;
+
                ath10k_process_rx(htt->ar, info);
        }
 
@@ -959,6 +945,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
                                continue;
                        }
 
+                       if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
+                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                               continue;
+                       }
+
                        /* FIXME: we do not support chaining yet.
                         * this needs investigation */
                        if (msdu_chaining) {
index d9335e9..f1d36d2 100644 (file)
@@ -85,16 +85,13 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
 
 int ath10k_htt_tx_attach(struct ath10k_htt *htt)
 {
-       u8 pipe;
-
        spin_lock_init(&htt->tx_lock);
        init_waitqueue_head(&htt->empty_tx_wq);
 
-       /* At the beginning free queue number should hint us the maximum
-        * queue length */
-       pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id;
-       htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar,
-                                                                  pipe);
+       if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
+               htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
+       else
+               htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
 
        ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
                   htt->max_num_pending_tx);
index 8aeb46d..9535eaa 100644 (file)
@@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode {
 #define CORE_CTRL_CPU_INTR_MASK                        0x00002000
 #define CORE_CTRL_ADDRESS                      0x0000
 #define PCIE_INTR_ENABLE_ADDRESS               0x0008
+#define PCIE_INTR_CAUSE_ADDRESS                        0x000c
 #define PCIE_INTR_CLR_ADDRESS                  0x0014
 #define SCRATCH_3_ADDRESS                      0x0030
 
index 06fe2b8..ce9ef34 100644 (file)
@@ -322,12 +322,16 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
        lockdep_assert_held(&ar->conf_mutex);
 
        ret = ath10k_wmi_peer_create(ar, vdev_id, addr);
-       if (ret)
+       if (ret) {
+               ath10k_warn("Failed to create wmi peer: %i\n", ret);
                return ret;
+       }
 
        ret = ath10k_wait_for_peer_created(ar, vdev_id, addr);
-       if (ret)
+       if (ret) {
+               ath10k_warn("Failed to wait for created wmi peer: %i\n", ret);
                return ret;
+       }
 
        return 0;
 }
@@ -450,15 +454,19 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
 
        arg.channel.mode = chan_to_phymode(&conf->chandef);
 
-       arg.channel.min_power = channel->max_power * 3;
-       arg.channel.max_power = channel->max_power * 4;
-       arg.channel.max_reg_power = channel->max_reg_power * 4;
-       arg.channel.max_antenna_gain = channel->max_antenna_gain;
+       arg.channel.min_power = 0;
+       arg.channel.max_power = channel->max_power * 2;
+       arg.channel.max_reg_power = channel->max_reg_power * 2;
+       arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
 
        if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
                arg.ssid = arvif->u.ap.ssid;
                arg.ssid_len = arvif->u.ap.ssid_len;
                arg.hidden_ssid = arvif->u.ap.hidden_ssid;
+
+               /* For now allow DFS for AP mode */
+               arg.channel.chan_radar =
+                       !!(channel->flags & IEEE80211_CHAN_RADAR);
        } else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
                arg.ssid = arvif->vif->bss_conf.ssid;
                arg.ssid_len = arvif->vif->bss_conf.ssid_len;
@@ -516,6 +524,11 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
 
        lockdep_assert_held(&ar->conf_mutex);
 
+       if (!ar->monitor_present) {
+               ath10k_warn("mac montor stop -- monitor is not present\n");
+               return -EINVAL;
+       }
+
        arg.vdev_id = vdev_id;
        arg.channel.freq = channel->center_freq;
        arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1;
@@ -523,11 +536,13 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
        /* TODO setup this dynamically, what in case we
           don't have any vifs? */
        arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef);
+       arg.channel.chan_radar =
+                       !!(channel->flags & IEEE80211_CHAN_RADAR);
 
-       arg.channel.min_power = channel->max_power * 3;
-       arg.channel.max_power = channel->max_power * 4;
-       arg.channel.max_reg_power = channel->max_reg_power * 4;
-       arg.channel.max_antenna_gain = channel->max_antenna_gain;
+       arg.channel.min_power = 0;
+       arg.channel.max_power = channel->max_power * 2;
+       arg.channel.max_reg_power = channel->max_reg_power * 2;
+       arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
 
        ret = ath10k_wmi_vdev_start(ar, &arg);
        if (ret) {
@@ -566,6 +581,16 @@ static int ath10k_monitor_stop(struct ath10k *ar)
 
        lockdep_assert_held(&ar->conf_mutex);
 
+       if (!ar->monitor_present) {
+               ath10k_warn("mac montor stop -- monitor is not present\n");
+               return -EINVAL;
+       }
+
+       if (!ar->monitor_enabled) {
+               ath10k_warn("mac montor stop -- monitor is not enabled\n");
+               return -EINVAL;
+       }
+
        ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id);
        if (ret)
                ath10k_warn("Monitor vdev down failed: %d\n", ret);
@@ -647,6 +672,107 @@ static int ath10k_monitor_destroy(struct ath10k *ar)
        return ret;
 }
 
+static int ath10k_start_cac(struct ath10k *ar)
+{
+       int ret;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+       ret = ath10k_monitor_create(ar);
+       if (ret) {
+               clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+               return ret;
+       }
+
+       ret = ath10k_monitor_start(ar, ar->monitor_vdev_id);
+       if (ret) {
+               clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+               ath10k_monitor_destroy(ar);
+               return ret;
+       }
+
+       ath10k_dbg(ATH10K_DBG_MAC, "mac cac start monitor vdev %d\n",
+                  ar->monitor_vdev_id);
+
+       return 0;
+}
+
+static int ath10k_stop_cac(struct ath10k *ar)
+{
+       lockdep_assert_held(&ar->conf_mutex);
+
+       /* CAC is not running - do nothing */
+       if (!test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags))
+               return 0;
+
+       ath10k_monitor_stop(ar);
+       ath10k_monitor_destroy(ar);
+       clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+       ath10k_dbg(ATH10K_DBG_MAC, "mac cac finished\n");
+
+       return 0;
+}
+
+static const char *ath10k_dfs_state(enum nl80211_dfs_state dfs_state)
+{
+       switch (dfs_state) {
+       case NL80211_DFS_USABLE:
+               return "USABLE";
+       case NL80211_DFS_UNAVAILABLE:
+               return "UNAVAILABLE";
+       case NL80211_DFS_AVAILABLE:
+               return "AVAILABLE";
+       default:
+               WARN_ON(1);
+               return "bug";
+       }
+}
+
+static void ath10k_config_radar_detection(struct ath10k *ar)
+{
+       struct ieee80211_channel *chan = ar->hw->conf.chandef.chan;
+       bool radar = ar->hw->conf.radar_enabled;
+       bool chan_radar = !!(chan->flags & IEEE80211_CHAN_RADAR);
+       enum nl80211_dfs_state dfs_state = chan->dfs_state;
+       int ret;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       ath10k_dbg(ATH10K_DBG_MAC,
+                  "mac radar config update: chan %dMHz radar %d chan radar %d chan state %s\n",
+                  chan->center_freq, radar, chan_radar,
+                  ath10k_dfs_state(dfs_state));
+
+       /*
+        * It's safe to call it even if CAC is not started.
+        * This call here guarantees changing channel, etc. will stop CAC.
+        */
+       ath10k_stop_cac(ar);
+
+       if (!radar)
+               return;
+
+       if (!chan_radar)
+               return;
+
+       if (dfs_state != NL80211_DFS_USABLE)
+               return;
+
+       ret = ath10k_start_cac(ar);
+       if (ret) {
+               /*
+                * Not possible to start CAC on current channel so starting
+                * radiation is not allowed, make this channel DFS_UNAVAILABLE
+                * by indicating that radar was detected.
+                */
+               ath10k_warn("failed to start CAC (%d)\n", ret);
+               ieee80211_radar_detected(ar->hw);
+       }
+}
+
 static void ath10k_control_beaconing(struct ath10k_vif *arvif,
                                struct ieee80211_bss_conf *info)
 {
@@ -1356,14 +1482,17 @@ static int ath10k_update_channel_list(struct ath10k *ar)
                        ch->ht40plus =
                                !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS);
 
+                       ch->chan_radar =
+                               !!(channel->flags & IEEE80211_CHAN_RADAR);
+
                        passive = channel->flags & IEEE80211_CHAN_NO_IR;
                        ch->passive = passive;
 
                        ch->freq = channel->center_freq;
-                       ch->min_power = channel->max_power * 3;
-                       ch->max_power = channel->max_power * 4;
-                       ch->max_reg_power = channel->max_reg_power * 4;
-                       ch->max_antenna_gain = channel->max_antenna_gain;
+                       ch->min_power = 0;
+                       ch->max_power = channel->max_power * 2;
+                       ch->max_reg_power = channel->max_reg_power * 2;
+                       ch->max_antenna_gain = channel->max_antenna_gain * 2;
                        ch->reg_class_id = 0; /* FIXME */
 
                        /* FIXME: why use only legacy modes, why not any
@@ -1423,9 +1552,20 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
 {
        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
        struct ath10k *ar = hw->priv;
+       bool result;
 
        ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
+                          request->dfs_region);
+               result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector,
+                                                         request->dfs_region);
+               if (!result)
+                       ath10k_warn("dfs region 0x%X not supported, will trigger radar for every pulse\n",
+                                   request->dfs_region);
+       }
+
        mutex_lock(&ar->conf_mutex);
        if (ar->state == ATH10K_STATE_ON)
                ath10k_regd_update(ar);
@@ -1714,8 +1854,10 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
                        break;
 
                ret = ath10k_wmi_mgmt_tx(ar, skb);
-               if (ret)
+               if (ret) {
                        ath10k_warn("wmi mgmt_tx failed (%d)\n", ret);
+                       ieee80211_free_txskb(ar->hw, skb);
+               }
        }
 }
 
@@ -1889,6 +2031,7 @@ void ath10k_halt(struct ath10k *ar)
 {
        lockdep_assert_held(&ar->conf_mutex);
 
+       ath10k_stop_cac(ar);
        del_timer_sync(&ar->scan.timeout);
        ath10k_offchan_tx_purge(ar);
        ath10k_mgmt_over_wmi_tx_purge(ar);
@@ -1943,7 +2086,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
                ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n",
                            ret);
 
-       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 0);
+       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1);
        if (ret)
                ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
                            ret);
@@ -1998,15 +2141,40 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
        struct ath10k *ar = hw->priv;
        struct ieee80211_conf *conf = &hw->conf;
        int ret = 0;
+       u32 param;
 
        mutex_lock(&ar->conf_mutex);
 
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-               ath10k_dbg(ATH10K_DBG_MAC, "mac config channel %d mhz\n",
-                          conf->chandef.chan->center_freq);
+               ath10k_dbg(ATH10K_DBG_MAC,
+                          "mac config channel %d mhz flags 0x%x\n",
+                          conf->chandef.chan->center_freq,
+                          conf->chandef.chan->flags);
+
                spin_lock_bh(&ar->data_lock);
                ar->rx_channel = conf->chandef.chan;
                spin_unlock_bh(&ar->data_lock);
+
+               ath10k_config_radar_detection(ar);
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
+               ath10k_dbg(ATH10K_DBG_MAC, "mac config power %d\n",
+                          hw->conf.power_level);
+
+               param = ar->wmi.pdev_param->txpower_limit2g;
+               ret = ath10k_wmi_pdev_set_param(ar, param,
+                                               hw->conf.power_level * 2);
+               if (ret)
+                       ath10k_warn("mac failed to set 2g txpower %d (%d)\n",
+                                   hw->conf.power_level, ret);
+
+               param = ar->wmi.pdev_param->txpower_limit5g;
+               ret = ath10k_wmi_pdev_set_param(ar, param,
+                                               hw->conf.power_level * 2);
+               if (ret)
+                       ath10k_warn("mac failed to set 5g txpower %d (%d)\n",
+                                   hw->conf.power_level, ret);
        }
 
        if (changed & IEEE80211_CONF_CHANGE_PS)
@@ -2049,6 +2217,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        arvif->vif = vif;
 
        INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work);
+       INIT_LIST_HEAD(&arvif->list);
 
        if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) {
                ath10k_warn("Only one monitor interface allowed\n");
@@ -2265,8 +2434,14 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
        *total_flags &= SUPPORTED_FILTERS;
        ar->filter_flags = *total_flags;
 
+       /* Monitor must not be started if it wasn't created first.
+        * Promiscuous mode may be started on a non-monitor interface - in
+        * such case the monitor vdev is not created so starting the
+        * monitor makes no sense. Since ath10k uses no special RX filters
+        * (only BSS filter in STA mode) there's no need for any special
+        * action here. */
        if ((ar->filter_flags & FIF_PROMISC_IN_BSS) &&
-           !ar->monitor_enabled) {
+           !ar->monitor_enabled && ar->monitor_present) {
                ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d start\n",
                           ar->monitor_vdev_id);
 
@@ -2274,7 +2449,7 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
                if (ret)
                        ath10k_warn("Unable to start monitor mode\n");
        } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) &&
-                  ar->monitor_enabled) {
+                  ar->monitor_enabled && ar->monitor_present) {
                ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d stop\n",
                           ar->monitor_vdev_id);
 
@@ -2360,8 +2535,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
                        ret = ath10k_peer_create(ar, arvif->vdev_id,
                                                 info->bssid);
                        if (ret)
-                               ath10k_warn("Failed to add peer: %pM for VDEV: %d\n",
-                                           info->bssid, arvif->vdev_id);
+                               ath10k_warn("Failed to add peer %pM for vdev %d when changin bssid: %i\n",
+                                           info->bssid, arvif->vdev_id, ret);
 
                        if (vif->type == NL80211_IFTYPE_STATION) {
                                /*
@@ -2542,6 +2717,44 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw,
        mutex_unlock(&ar->conf_mutex);
 }
 
+static void ath10k_set_key_h_def_keyidx(struct ath10k *ar,
+                                       struct ath10k_vif *arvif,
+                                       enum set_key_cmd cmd,
+                                       struct ieee80211_key_conf *key)
+{
+       u32 vdev_param = arvif->ar->wmi.vdev_param->def_keyid;
+       int ret;
+
+       /* 10.1 firmware branch requires default key index to be set to group
+        * key index after installing it. Otherwise FW/HW Txes corrupted
+        * frames with multi-vif APs. This is not required for main firmware
+        * branch (e.g. 636).
+        *
+        * FIXME: This has been tested only in AP. It remains unknown if this
+        * is required for multi-vif STA interfaces on 10.1 */
+
+       if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+               return;
+
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP40)
+               return;
+
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP104)
+               return;
+
+       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+               return;
+
+       if (cmd != SET_KEY)
+               return;
+
+       ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+                                       key->keyidx);
+       if (ret)
+               ath10k_warn("failed to set group key as default key: %d\n",
+                           ret);
+}
+
 static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                          struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                          struct ieee80211_key_conf *key)
@@ -2603,6 +2816,8 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                goto exit;
        }
 
+       ath10k_set_key_h_def_keyidx(ar, arvif, cmd, key);
+
        spin_lock_bh(&ar->data_lock);
        peer = ath10k_peer_find(ar, arvif->vdev_id, peer_addr);
        if (peer && cmd == SET_KEY)
@@ -2643,8 +2858,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 
                ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
                if (ret)
-                       ath10k_warn("Failed to add peer: %pM for VDEV: %d\n",
-                                   sta->addr, arvif->vdev_id);
+                       ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n",
+                                   sta->addr, arvif->vdev_id, ret);
        } else if ((old_state == IEEE80211_STA_NONE &&
                    new_state == IEEE80211_STA_NOTEXIST)) {
                /*
@@ -3249,12 +3464,36 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
        },
 };
 
-static const struct ieee80211_iface_combination ath10k_if_comb = {
-       .limits = ath10k_if_limits,
-       .n_limits = ARRAY_SIZE(ath10k_if_limits),
-       .max_interfaces = 8,
-       .num_different_channels = 1,
-       .beacon_int_infra_match = true,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+static const struct ieee80211_iface_limit ath10k_if_dfs_limits[] = {
+       {
+       .max    = 8,
+       .types  = BIT(NL80211_IFTYPE_AP)
+       },
+};
+#endif
+
+static const struct ieee80211_iface_combination ath10k_if_comb[] = {
+       {
+               .limits = ath10k_if_limits,
+               .n_limits = ARRAY_SIZE(ath10k_if_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+       },
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+       {
+               .limits = ath10k_if_dfs_limits,
+               .n_limits = ARRAY_SIZE(ath10k_if_dfs_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+               .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                       BIT(NL80211_CHAN_WIDTH_20) |
+                                       BIT(NL80211_CHAN_WIDTH_40) |
+                                       BIT(NL80211_CHAN_WIDTH_80),
+       }
+#endif
 };
 
 static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
@@ -3478,11 +3717,21 @@ int ath10k_mac_register(struct ath10k *ar)
         */
        ar->hw->queues = 4;
 
-       ar->hw->wiphy->iface_combinations = &ath10k_if_comb;
-       ar->hw->wiphy->n_iface_combinations = 1;
+       ar->hw->wiphy->iface_combinations = ath10k_if_comb;
+       ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb);
 
        ar->hw->netdev_features = NETIF_F_HW_CSUM;
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+               /* Init ath dfs pattern detector */
+               ar->ath_common.debug_mask = ATH_DBG_DFS;
+               ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common,
+                                                            NL80211_DFS_UNSET);
+
+               if (!ar->dfs_detector)
+                       ath10k_warn("dfs pattern detector init failed\n");
+       }
+
        ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
                            ath10k_reg_notifier);
        if (ret) {
@@ -3518,6 +3767,9 @@ void ath10k_mac_unregister(struct ath10k *ar)
 {
        ieee80211_unregister_hw(ar->hw);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+               ar->dfs_detector->exit(ar->dfs_detector);
+
        kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
        kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
 
index 9e86a81..29fd197 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/bitops.h>
 
 #include "core.h"
 #include "debug.h"
 #include "ce.h"
 #include "pci.h"
 
+enum ath10k_pci_irq_mode {
+       ATH10K_PCI_IRQ_AUTO = 0,
+       ATH10K_PCI_IRQ_LEGACY = 1,
+       ATH10K_PCI_IRQ_MSI = 2,
+};
+
 static unsigned int ath10k_target_ps;
+static unsigned int ath10k_pci_irq_mode = ATH10K_PCI_IRQ_AUTO;
+
 module_param(ath10k_target_ps, uint, 0644);
 MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option");
 
+module_param_named(irq_mode, ath10k_pci_irq_mode, uint, 0644);
+MODULE_PARM_DESC(irq_mode, "0: auto, 1: legacy, 2: msi (default: 0)");
+
 #define QCA988X_2_0_DEVICE_ID  (0x003c)
 
 static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
@@ -52,10 +64,16 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                                             int num);
 static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info);
 static void ath10k_pci_stop_ce(struct ath10k *ar);
-static void ath10k_pci_device_reset(struct ath10k *ar);
-static int ath10k_pci_reset_target(struct ath10k *ar);
-static int ath10k_pci_start_intr(struct ath10k *ar);
-static void ath10k_pci_stop_intr(struct ath10k *ar);
+static int ath10k_pci_device_reset(struct ath10k *ar);
+static int ath10k_pci_wait_for_target_init(struct ath10k *ar);
+static int ath10k_pci_init_irq(struct ath10k *ar);
+static int ath10k_pci_deinit_irq(struct ath10k *ar);
+static int ath10k_pci_request_irq(struct ath10k *ar);
+static void ath10k_pci_free_irq(struct ath10k *ar);
+static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+                              struct ath10k_ce_pipe *rx_pipe,
+                              struct bmi_xfer *xfer);
+static void ath10k_pci_cleanup_ce(struct ath10k *ar);
 
 static const struct ce_attr host_ce_config_wlan[] = {
        /* CE0: host->target HTC control and raw streams */
@@ -200,6 +218,87 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
        /* CE7 used only by Host */
 };
 
+static bool ath10k_pci_irq_pending(struct ath10k *ar)
+{
+       u32 cause;
+
+       /* Check if the shared legacy irq is for us */
+       cause = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                 PCIE_INTR_CAUSE_ADDRESS);
+       if (cause & (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL))
+               return true;
+
+       return false;
+}
+
+static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar)
+{
+       /* IMPORTANT: INTR_CLR register has to be set after
+        * INTR_ENABLE is set to 0, otherwise interrupt can not be
+        * really cleared. */
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          0);
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_CLR_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+
+       /* IMPORTANT: this extra read transaction is required to
+        * flush the posted write buffer. */
+       (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                PCIE_INTR_ENABLE_ADDRESS);
+}
+
+static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
+{
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+                          PCIE_INTR_ENABLE_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+
+       /* IMPORTANT: this extra read transaction is required to
+        * flush the posted write buffer. */
+       (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                PCIE_INTR_ENABLE_ADDRESS);
+}
+
+static irqreturn_t ath10k_pci_early_irq_handler(int irq, void *arg)
+{
+       struct ath10k *ar = arg;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       if (ar_pci->num_msi_intrs == 0) {
+               if (!ath10k_pci_irq_pending(ar))
+                       return IRQ_NONE;
+
+               ath10k_pci_disable_and_clear_legacy_irq(ar);
+       }
+
+       tasklet_schedule(&ar_pci->early_irq_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static int ath10k_pci_request_early_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
+
+       /* Regardless whether MSI-X/MSI/legacy irqs have been set up the first
+        * interrupt from irq vector is triggered in all cases for FW
+        * indication/errors */
+       ret = request_irq(ar_pci->pdev->irq, ath10k_pci_early_irq_handler,
+                         IRQF_SHARED, "ath10k_pci (early)", ar);
+       if (ret) {
+               ath10k_warn("failed to request early irq: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ath10k_pci_free_early_irq(struct ath10k *ar)
+{
+       free_irq(ath10k_pci_priv(ar)->pdev->irq, ar);
+}
+
 /*
  * Diagnostic read/write access is provided for startup/config/debug usage.
  * Caller must guarantee proper alignment, when applicable, and single user
@@ -526,17 +625,6 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar)
        return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON);
 }
 
-static void ath10k_pci_wait(struct ath10k *ar)
-{
-       int n = 100;
-
-       while (n-- && !ath10k_pci_target_is_awake(ar))
-               msleep(10);
-
-       if (n < 0)
-               ath10k_warn("Unable to wakeup target\n");
-}
-
 int ath10k_do_pci_wake(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -723,7 +811,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
        ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id,
                             flags);
        if (ret)
-               ath10k_warn("CE send failed: %p\n", nbuf);
+               ath10k_warn("failed to send sk_buff to CE: %p\n", nbuf);
 
        return ret;
 }
@@ -750,9 +838,10 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                   ar->fw_version_build);
 
        host_addr = host_interest_item_address(HI_ITEM(hi_failure_state));
-       if (ath10k_pci_diag_read_mem(ar, host_addr,
-                                    &reg_dump_area, sizeof(u32)) != 0) {
-               ath10k_warn("could not read hi_failure_state\n");
+       ret = ath10k_pci_diag_read_mem(ar, host_addr,
+                                      &reg_dump_area, sizeof(u32));
+       if (ret) {
+               ath10k_err("failed to read FW dump area address: %d\n", ret);
                return;
        }
 
@@ -762,7 +851,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                                       &reg_dump_values[0],
                                       REG_DUMP_COUNT_QCA988X * sizeof(u32));
        if (ret != 0) {
-               ath10k_err("could not dump FW Dump Area\n");
+               ath10k_err("failed to read FW dump area: %d\n", ret);
                return;
        }
 
@@ -777,7 +866,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                           reg_dump_values[i + 2],
                           reg_dump_values[i + 3]);
 
-       ieee80211_queue_work(ar->hw, &ar->restart_work);
+       queue_work(ar->workqueue, &ar->restart_work);
 }
 
 static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
@@ -815,53 +904,41 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
               sizeof(ar_pci->msg_callbacks_current));
 }
 
-static int ath10k_pci_start_ce(struct ath10k *ar)
+static int ath10k_pci_alloc_compl(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       struct ath10k_ce_pipe *ce_diag = ar_pci->ce_diag;
        const struct ce_attr *attr;
        struct ath10k_pci_pipe *pipe_info;
        struct ath10k_pci_compl *compl;
-       int i, pipe_num, completions, disable_interrupts;
+       int i, pipe_num, completions;
 
        spin_lock_init(&ar_pci->compl_lock);
        INIT_LIST_HEAD(&ar_pci->compl_process);
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
 
                spin_lock_init(&pipe_info->pipe_lock);
                INIT_LIST_HEAD(&pipe_info->compl_free);
 
                /* Handle Diagnostic CE specially */
-               if (pipe_info->ce_hdl == ce_diag)
+               if (pipe_info->ce_hdl == ar_pci->ce_diag)
                        continue;
 
                attr = &host_ce_config_wlan[pipe_num];
                completions = 0;
 
-               if (attr->src_nentries) {
-                       disable_interrupts = attr->flags & CE_ATTR_DIS_INTR;
-                       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
-                                                  ath10k_pci_ce_send_done,
-                                                  disable_interrupts);
+               if (attr->src_nentries)
                        completions += attr->src_nentries;
-               }
 
-               if (attr->dest_nentries) {
-                       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
-                                                  ath10k_pci_ce_recv_data);
+               if (attr->dest_nentries)
                        completions += attr->dest_nentries;
-               }
-
-               if (completions == 0)
-                       continue;
 
                for (i = 0; i < completions; i++) {
                        compl = kmalloc(sizeof(*compl), GFP_KERNEL);
                        if (!compl) {
                                ath10k_warn("No memory for completion state\n");
-                               ath10k_pci_stop_ce(ar);
+                               ath10k_pci_cleanup_ce(ar);
                                return -ENOMEM;
                        }
 
@@ -873,20 +950,55 @@ static int ath10k_pci_start_ce(struct ath10k *ar)
        return 0;
 }
 
-static void ath10k_pci_stop_ce(struct ath10k *ar)
+static int ath10k_pci_setup_ce_irq(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       struct ath10k_pci_compl *compl;
-       struct sk_buff *skb;
-       int i;
+       const struct ce_attr *attr;
+       struct ath10k_pci_pipe *pipe_info;
+       int pipe_num, disable_interrupts;
 
-       ath10k_ce_disable_interrupts(ar);
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
+               pipe_info = &ar_pci->pipe_info[pipe_num];
+
+               /* Handle Diagnostic CE specially */
+               if (pipe_info->ce_hdl == ar_pci->ce_diag)
+                       continue;
+
+               attr = &host_ce_config_wlan[pipe_num];
+
+               if (attr->src_nentries) {
+                       disable_interrupts = attr->flags & CE_ATTR_DIS_INTR;
+                       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
+                                                  ath10k_pci_ce_send_done,
+                                                  disable_interrupts);
+               }
+
+               if (attr->dest_nentries)
+                       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
+                                                  ath10k_pci_ce_recv_data);
+       }
+
+       return 0;
+}
+
+static void ath10k_pci_kill_tasklet(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int i;
 
-       /* Cancel the pending tasklet */
        tasklet_kill(&ar_pci->intr_tq);
+       tasklet_kill(&ar_pci->msi_fw_err);
+       tasklet_kill(&ar_pci->early_irq_tasklet);
 
        for (i = 0; i < CE_COUNT; i++)
                tasklet_kill(&ar_pci->pipe_info[i].intr);
+}
+
+static void ath10k_pci_stop_ce(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       struct ath10k_pci_compl *compl;
+       struct sk_buff *skb;
 
        /* Mark pending completions as aborted, so that upper layers free up
         * their associated resources */
@@ -920,7 +1032,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar)
        spin_unlock_bh(&ar_pci->compl_lock);
 
        /* Free unused completions for each pipe. */
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
 
                spin_lock_bh(&pipe_info->pipe_lock);
@@ -974,8 +1086,8 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
                case ATH10K_PCI_COMPL_RECV:
                        ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1);
                        if (ret) {
-                               ath10k_warn("Unable to post recv buffer for pipe: %d\n",
-                                           compl->pipe_info->pipe_num);
+                               ath10k_warn("failed to post RX buffer for pipe %d: %d\n",
+                                           compl->pipe_info->pipe_num, ret);
                                break;
                        }
 
@@ -1114,7 +1226,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
        for (i = 0; i < num; i++) {
                skb = dev_alloc_skb(pipe_info->buf_sz);
                if (!skb) {
-                       ath10k_warn("could not allocate skbuff for pipe %d\n",
+                       ath10k_warn("failed to allocate skbuff for pipe %d\n",
                                    num);
                        ret = -ENOMEM;
                        goto err;
@@ -1127,7 +1239,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                                         DMA_FROM_DEVICE);
 
                if (unlikely(dma_mapping_error(ar->dev, ce_data))) {
-                       ath10k_warn("could not dma map skbuff\n");
+                       ath10k_warn("failed to DMA map sk_buff\n");
                        dev_kfree_skb_any(skb);
                        ret = -EIO;
                        goto err;
@@ -1142,7 +1254,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                ret = ath10k_ce_recv_buf_enqueue(ce_state, (void *)skb,
                                                 ce_data);
                if (ret) {
-                       ath10k_warn("could not enqueue to pipe %d (%d)\n",
+                       ath10k_warn("failed to enqueue to pipe %d: %d\n",
                                    num, ret);
                        goto err;
                }
@@ -1162,7 +1274,7 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
        const struct ce_attr *attr;
        int pipe_num, ret = 0;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                attr = &host_ce_config_wlan[pipe_num];
 
@@ -1172,8 +1284,8 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
                ret = ath10k_pci_post_rx_pipe(pipe_info,
                                              attr->dest_nentries - 1);
                if (ret) {
-                       ath10k_warn("Unable to replenish recv buffers for pipe: %d\n",
-                                   pipe_num);
+                       ath10k_warn("failed to post RX buffer for pipe %d: %d\n",
+                                   pipe_num, ret);
 
                        for (; pipe_num >= 0; pipe_num--) {
                                pipe_info = &ar_pci->pipe_info[pipe_num];
@@ -1189,23 +1301,58 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
 static int ath10k_pci_hif_start(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int ret;
+       int ret, ret_early;
 
-       ret = ath10k_pci_start_ce(ar);
+       ath10k_pci_free_early_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+
+       ret = ath10k_pci_alloc_compl(ar);
        if (ret) {
-               ath10k_warn("could not start CE (%d)\n", ret);
-               return ret;
+               ath10k_warn("failed to allocate CE completions: %d\n", ret);
+               goto err_early_irq;
+       }
+
+       ret = ath10k_pci_request_irq(ar);
+       if (ret) {
+               ath10k_warn("failed to post RX buffers for all pipes: %d\n",
+                           ret);
+               goto err_free_compl;
+       }
+
+       ret = ath10k_pci_setup_ce_irq(ar);
+       if (ret) {
+               ath10k_warn("failed to setup CE interrupts: %d\n", ret);
+               goto err_stop;
        }
 
        /* Post buffers once to start things off. */
        ret = ath10k_pci_post_rx(ar);
        if (ret) {
-               ath10k_warn("could not post rx pipes (%d)\n", ret);
-               return ret;
+               ath10k_warn("failed to post RX buffers for all pipes: %d\n",
+                           ret);
+               goto err_stop;
        }
 
        ar_pci->started = 1;
        return 0;
+
+err_stop:
+       ath10k_ce_disable_interrupts(ar);
+       ath10k_pci_free_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+       ath10k_pci_stop_ce(ar);
+       ath10k_pci_process_ce(ar);
+err_free_compl:
+       ath10k_pci_cleanup_ce(ar);
+err_early_irq:
+       /* Though there should be no interrupts (device was reset)
+        * power_down() expects the early IRQ to be installed as per the
+        * driver lifecycle. */
+       ret_early = ath10k_pci_request_early_irq(ar);
+       if (ret_early)
+               ath10k_warn("failed to re-enable early irq: %d\n", ret_early);
+
+       return ret;
 }
 
 static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
@@ -1271,6 +1418,13 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
                 * Indicate the completion to higer layer to free
                 * the buffer
                 */
+
+               if (!netbuf) {
+                       ath10k_warn("invalid sk_buff on CE %d - NULL pointer. firmware crashed?\n",
+                                   ce_hdl->id);
+                       continue;
+               }
+
                ATH10K_SKB_CB(netbuf)->is_aborted = true;
                ar_pci->msg_callbacks_current.tx_completion(ar,
                                                            netbuf,
@@ -1291,7 +1445,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                struct ath10k_pci_pipe *pipe_info;
 
                pipe_info = &ar_pci->pipe_info[pipe_num];
@@ -1306,7 +1460,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar)
        struct ath10k_pci_pipe *pipe_info;
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                if (pipe_info->ce_hdl) {
                        ath10k_ce_deinit(pipe_info->ce_hdl);
@@ -1316,27 +1470,25 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar)
        }
 }
 
-static void ath10k_pci_disable_irqs(struct ath10k *ar)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int i;
-
-       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
-               disable_irq(ar_pci->pdev->irq + i);
-}
-
 static void ath10k_pci_hif_stop(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
 
        ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
 
-       /* Irqs are never explicitly re-enabled. They are implicitly re-enabled
-        * by ath10k_pci_start_intr(). */
-       ath10k_pci_disable_irqs(ar);
+       ret = ath10k_ce_disable_interrupts(ar);
+       if (ret)
+               ath10k_warn("failed to disable CE interrupts: %d\n", ret);
 
+       ath10k_pci_free_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
        ath10k_pci_stop_ce(ar);
 
+       ret = ath10k_pci_request_early_irq(ar);
+       if (ret)
+               ath10k_warn("failed to re-enable early irq: %d\n", ret);
+
        /* At this point, asynchronous threads are stopped, the target should
         * not DMA nor interrupt. We process the leftovers and then free
         * everything else up. */
@@ -1345,6 +1497,13 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
        ath10k_pci_cleanup_ce(ar);
        ath10k_pci_buffer_cleanup(ar);
 
+       /* Make the sure the device won't access any structures on the host by
+        * resetting it. The device was fed with PCI CE ringbuffer
+        * configuration during init. If ringbuffers are freed and the device
+        * were to access them this could lead to memory corruption on the
+        * host. */
+       ath10k_pci_device_reset(ar);
+
        ar_pci->started = 0;
 }
 
@@ -1363,6 +1522,8 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
        void *treq, *tresp = NULL;
        int ret = 0;
 
+       might_sleep();
+
        if (resp && !resp_len)
                return -EINVAL;
 
@@ -1403,14 +1564,12 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
        if (ret)
                goto err_resp;
 
-       ret = wait_for_completion_timeout(&xfer.done,
-                                         BMI_COMMUNICATION_TIMEOUT_HZ);
-       if (ret <= 0) {
+       ret = ath10k_pci_bmi_wait(ce_tx, ce_rx, &xfer);
+       if (ret) {
                u32 unused_buffer;
                unsigned int unused_nbytes;
                unsigned int unused_id;
 
-               ret = -ETIMEDOUT;
                ath10k_ce_cancel_send_next(ce_tx, NULL, &unused_buffer,
                                           &unused_nbytes, &unused_id);
        } else {
@@ -1478,6 +1637,25 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
        complete(&xfer->done);
 }
 
+static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+                              struct ath10k_ce_pipe *rx_pipe,
+                              struct bmi_xfer *xfer)
+{
+       unsigned long timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+
+       while (time_before_eq(jiffies, timeout)) {
+               ath10k_pci_bmi_send_done(tx_pipe);
+               ath10k_pci_bmi_recv_data(rx_pipe);
+
+               if (completion_done(&xfer->done))
+                       return 0;
+
+               schedule();
+       }
+
+       return -ETIMEDOUT;
+}
+
 /*
  * Map from service/endpoint to Copy Engine.
  * This table is derived from the CE_PCI TABLE, above.
@@ -1587,7 +1765,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
                                              CORE_CTRL_ADDRESS,
                                          &core_ctrl);
        if (ret) {
-               ath10k_warn("Unable to read core ctrl\n");
+               ath10k_warn("failed to read core_ctrl: %d\n", ret);
                return ret;
        }
 
@@ -1597,10 +1775,13 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
        ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS |
                                               CORE_CTRL_ADDRESS,
                                           core_ctrl);
-       if (ret)
-               ath10k_warn("Unable to set interrupt mask\n");
+       if (ret) {
+               ath10k_warn("failed to set target CPU interrupt mask: %d\n",
+                           ret);
+               return ret;
+       }
 
-       return ret;
+       return 0;
 }
 
 static int ath10k_pci_init_config(struct ath10k *ar)
@@ -1751,7 +1932,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
        const struct ce_attr *attr;
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                pipe_info->pipe_num = pipe_num;
                pipe_info->hif_ce_state = ar;
@@ -1759,7 +1940,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
 
                pipe_info->ce_hdl = ath10k_ce_init(ar, pipe_num, attr);
                if (pipe_info->ce_hdl == NULL) {
-                       ath10k_err("Unable to initialize CE for pipe: %d\n",
+                       ath10k_err("failed to initialize CE for pipe: %d\n",
                                   pipe_num);
 
                        /* It is safe to call it here. It checks if ce_hdl is
@@ -1768,31 +1949,18 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
                        return -1;
                }
 
-               if (pipe_num == ar_pci->ce_count - 1) {
+               if (pipe_num == CE_COUNT - 1) {
                        /*
                         * Reserve the ultimate CE for
                         * diagnostic Window support
                         */
-                       ar_pci->ce_diag =
-                       ar_pci->pipe_info[ar_pci->ce_count - 1].ce_hdl;
+                       ar_pci->ce_diag = pipe_info->ce_hdl;
                        continue;
                }
 
                pipe_info->buf_sz = (size_t) (attr->src_sz_max);
        }
 
-       /*
-        * Initially, establish CE completion handlers for use with BMI.
-        * These are overwritten with generic handlers after we exit BMI phase.
-        */
-       pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG];
-       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
-                                  ath10k_pci_bmi_send_done, 0);
-
-       pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST];
-       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
-                                  ath10k_pci_bmi_recv_data);
-
        return 0;
 }
 
@@ -1828,14 +1996,9 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       const char *irq_mode;
        int ret;
 
-       ret = ath10k_pci_start_intr(ar);
-       if (ret) {
-               ath10k_err("could not start interrupt handling (%d)\n", ret);
-               goto err;
-       }
-
        /*
         * Bring the target up cleanly.
         *
@@ -1846,39 +2009,80 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
         * is in an unexpected state. We try to catch that here in order to
         * reset the Target and retry the probe.
         */
-       ath10k_pci_device_reset(ar);
-
-       ret = ath10k_pci_reset_target(ar);
-       if (ret)
-               goto err_irq;
+       ret = ath10k_pci_device_reset(ar);
+       if (ret) {
+               ath10k_err("failed to reset target: %d\n", ret);
+               goto err;
+       }
 
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
                /* Force AWAKE forever */
                ath10k_do_pci_wake(ar);
 
        ret = ath10k_pci_ce_init(ar);
-       if (ret)
+       if (ret) {
+               ath10k_err("failed to initialize CE: %d\n", ret);
                goto err_ps;
+       }
 
-       ret = ath10k_pci_init_config(ar);
-       if (ret)
+       ret = ath10k_ce_disable_interrupts(ar);
+       if (ret) {
+               ath10k_err("failed to disable CE interrupts: %d\n", ret);
                goto err_ce;
+       }
 
-       ret = ath10k_pci_wake_target_cpu(ar);
+       ret = ath10k_pci_init_irq(ar);
        if (ret) {
-               ath10k_err("could not wake up target CPU (%d)\n", ret);
+               ath10k_err("failed to init irqs: %d\n", ret);
                goto err_ce;
        }
 
+       ret = ath10k_pci_request_early_irq(ar);
+       if (ret) {
+               ath10k_err("failed to request early irq: %d\n", ret);
+               goto err_deinit_irq;
+       }
+
+       ret = ath10k_pci_wait_for_target_init(ar);
+       if (ret) {
+               ath10k_err("failed to wait for target to init: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       ret = ath10k_pci_init_config(ar);
+       if (ret) {
+               ath10k_err("failed to setup init config: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       ret = ath10k_pci_wake_target_cpu(ar);
+       if (ret) {
+               ath10k_err("could not wake up target CPU: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       if (ar_pci->num_msi_intrs > 1)
+               irq_mode = "MSI-X";
+       else if (ar_pci->num_msi_intrs == 1)
+               irq_mode = "MSI";
+       else
+               irq_mode = "legacy";
+
+       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("pci irq %s\n", irq_mode);
+
        return 0;
 
+err_free_early_irq:
+       ath10k_pci_free_early_irq(ar);
+err_deinit_irq:
+       ath10k_pci_deinit_irq(ar);
 err_ce:
        ath10k_pci_ce_deinit(ar);
+       ath10k_pci_device_reset(ar);
 err_ps:
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
                ath10k_do_pci_sleep(ar);
-err_irq:
-       ath10k_pci_stop_intr(ar);
 err:
        return ret;
 }
@@ -1887,7 +2091,10 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
-       ath10k_pci_stop_intr(ar);
+       ath10k_pci_free_early_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+       ath10k_pci_deinit_irq(ar);
+       ath10k_pci_device_reset(ar);
 
        ath10k_pci_ce_deinit(ar);
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
@@ -2023,25 +2230,10 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
        if (ar_pci->num_msi_intrs == 0) {
-               /*
-                * IMPORTANT: INTR_CLR regiser has to be set after
-                * INTR_ENABLE is set to 0, otherwise interrupt can not be
-                * really cleared.
-                */
-               iowrite32(0, ar_pci->mem +
-                         (SOC_CORE_BASE_ADDRESS |
-                          PCIE_INTR_ENABLE_ADDRESS));
-               iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                         PCIE_INTR_CE_MASK_ALL,
-                         ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                        PCIE_INTR_CLR_ADDRESS));
-               /*
-                * IMPORTANT: this extra read transaction is required to
-                * flush the posted write buffer.
-                */
-               (void) ioread32(ar_pci->mem +
-                               (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
+               if (!ath10k_pci_irq_pending(ar))
+                       return IRQ_NONE;
+
+               ath10k_pci_disable_and_clear_legacy_irq(ar);
        }
 
        tasklet_schedule(&ar_pci->intr_tq);
@@ -2049,6 +2241,34 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+static void ath10k_pci_early_irq_tasklet(unsigned long data)
+{
+       struct ath10k *ar = (struct ath10k *)data;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 fw_ind;
+       int ret;
+
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target in early irq tasklet: %d\n",
+                           ret);
+               return;
+       }
+
+       fw_ind = ath10k_pci_read32(ar, ar_pci->fw_indicator_address);
+       if (fw_ind & FW_IND_EVENT_PENDING) {
+               ath10k_pci_write32(ar, ar_pci->fw_indicator_address,
+                                  fw_ind & ~FW_IND_EVENT_PENDING);
+
+               /* Some structures are unavailable during early boot or at
+                * driver teardown so just print that the device has crashed. */
+               ath10k_warn("device crashed - no diagnostics available\n");
+       }
+
+       ath10k_pci_sleep(ar);
+       ath10k_pci_enable_legacy_irq(ar);
+}
+
 static void ath10k_pci_tasklet(unsigned long data)
 {
        struct ath10k *ar = (struct ath10k *)data;
@@ -2057,40 +2277,22 @@ static void ath10k_pci_tasklet(unsigned long data)
        ath10k_pci_fw_interrupt_handler(ar); /* FIXME: Handle FW error */
        ath10k_ce_per_engine_service_any(ar);
 
-       if (ar_pci->num_msi_intrs == 0) {
-               /* Enable Legacy PCI line interrupts */
-               iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                         PCIE_INTR_CE_MASK_ALL,
-                         ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                        PCIE_INTR_ENABLE_ADDRESS));
-               /*
-                * IMPORTANT: this extra read transaction is required to
-                * flush the posted write buffer
-                */
-               (void) ioread32(ar_pci->mem +
-                               (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
-       }
+       /* Re-enable legacy irq that was disabled in the irq handler */
+       if (ar_pci->num_msi_intrs == 0)
+               ath10k_pci_enable_legacy_irq(ar);
 }
 
-static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num)
+static int ath10k_pci_request_irq_msix(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int ret;
-       int i;
-
-       ret = pci_enable_msi_block(ar_pci->pdev, num);
-       if (ret)
-               return ret;
+       int ret, i;
 
        ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW,
                          ath10k_pci_msi_fw_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
        if (ret) {
-               ath10k_warn("request_irq(%d) failed %d\n",
+               ath10k_warn("failed to request MSI-X fw irq %d: %d\n",
                            ar_pci->pdev->irq + MSI_ASSIGN_FW, ret);
-
-               pci_disable_msi(ar_pci->pdev);
                return ret;
        }
 
@@ -2099,44 +2301,38 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num)
                                  ath10k_pci_per_engine_handler,
                                  IRQF_SHARED, "ath10k_pci", ar);
                if (ret) {
-                       ath10k_warn("request_irq(%d) failed %d\n",
+                       ath10k_warn("failed to request MSI-X ce irq %d: %d\n",
                                    ar_pci->pdev->irq + i, ret);
 
                        for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--)
                                free_irq(ar_pci->pdev->irq + i, ar);
 
                        free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar);
-                       pci_disable_msi(ar_pci->pdev);
                        return ret;
                }
        }
 
-       ath10k_info("MSI-X interrupt handling (%d intrs)\n", num);
        return 0;
 }
 
-static int ath10k_pci_start_intr_msi(struct ath10k *ar)
+static int ath10k_pci_request_irq_msi(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
 
-       ret = pci_enable_msi(ar_pci->pdev);
-       if (ret < 0)
-               return ret;
-
        ret = request_irq(ar_pci->pdev->irq,
                          ath10k_pci_interrupt_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
-       if (ret < 0) {
-               pci_disable_msi(ar_pci->pdev);
+       if (ret) {
+               ath10k_warn("failed to request MSI irq %d: %d\n",
+                           ar_pci->pdev->irq, ret);
                return ret;
        }
 
-       ath10k_info("MSI interrupt handling\n");
        return 0;
 }
 
-static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
+static int ath10k_pci_request_irq_legacy(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
@@ -2144,112 +2340,165 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
        ret = request_irq(ar_pci->pdev->irq,
                          ath10k_pci_interrupt_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
-       if (ret < 0)
+       if (ret) {
+               ath10k_warn("failed to request legacy irq %d: %d\n",
+                           ar_pci->pdev->irq, ret);
                return ret;
+       }
 
-       /*
-        * Make sure to wake the Target before enabling Legacy
-        * Interrupt.
-        */
-       iowrite32(PCIE_SOC_WAKE_V_MASK,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
+       return 0;
+}
+
+static int ath10k_pci_request_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
-       ath10k_pci_wait(ar);
+       switch (ar_pci->num_msi_intrs) {
+       case 0:
+               return ath10k_pci_request_irq_legacy(ar);
+       case 1:
+               return ath10k_pci_request_irq_msi(ar);
+       case MSI_NUM_REQUEST:
+               return ath10k_pci_request_irq_msix(ar);
+       }
 
-       /*
-        * A potential race occurs here: The CORE_BASE write
-        * depends on target correctly decoding AXI address but
-        * host won't know when target writes BAR to CORE_CTRL.
-        * This write might get lost if target has NOT written BAR.
-        * For now, fix the race by repeating the write in below
-        * synchronization checking.
-        */
-       iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                 PCIE_INTR_CE_MASK_ALL,
-                 ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
-       iowrite32(PCIE_SOC_WAKE_RESET,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       ath10k_info("legacy interrupt handling\n");
-       return 0;
+       ath10k_warn("unknown irq configuration upon request\n");
+       return -EINVAL;
 }
 
-static int ath10k_pci_start_intr(struct ath10k *ar)
+static void ath10k_pci_free_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int i;
+
+       /* There's at least one interrupt irregardless whether its legacy INTR
+        * or MSI or MSI-X */
+       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
+               free_irq(ar_pci->pdev->irq + i, ar);
+}
+
+static void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int num = MSI_NUM_REQUEST;
-       int ret;
        int i;
 
-       tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long) ar);
+       tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
        tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet,
-                    (unsigned long) ar);
+                    (unsigned long)ar);
+       tasklet_init(&ar_pci->early_irq_tasklet, ath10k_pci_early_irq_tasklet,
+                    (unsigned long)ar);
 
        for (i = 0; i < CE_COUNT; i++) {
                ar_pci->pipe_info[i].ar_pci = ar_pci;
-               tasklet_init(&ar_pci->pipe_info[i].intr,
-                            ath10k_pci_ce_tasklet,
+               tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet,
                             (unsigned long)&ar_pci->pipe_info[i]);
        }
+}
+
+static int ath10k_pci_init_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       bool msix_supported = test_bit(ATH10K_PCI_FEATURE_MSI_X,
+                                      ar_pci->features);
+       int ret;
 
-       if (!test_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features))
-               num = 1;
+       ath10k_pci_init_irq_tasklets(ar);
 
-       if (num > 1) {
-               ret = ath10k_pci_start_intr_msix(ar, num);
+       if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO &&
+           !test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("limiting irq mode to: %d\n", ath10k_pci_irq_mode);
+
+       /* Try MSI-X */
+       if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) {
+               ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
+               ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs);
                if (ret == 0)
-                       goto exit;
+                       return 0;
+               if (ret > 0)
+                       pci_disable_msi(ar_pci->pdev);
 
-               ath10k_warn("MSI-X didn't succeed (%d), trying MSI\n", ret);
-               num = 1;
+               /* fall-through */
        }
 
-       if (num == 1) {
-               ret = ath10k_pci_start_intr_msi(ar);
+       /* Try MSI */
+       if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) {
+               ar_pci->num_msi_intrs = 1;
+               ret = pci_enable_msi(ar_pci->pdev);
                if (ret == 0)
-                       goto exit;
+                       return 0;
 
-               ath10k_warn("MSI didn't succeed (%d), trying legacy INTR\n",
-                           ret);
-               num = 0;
+               /* fall-through */
        }
 
-       ret = ath10k_pci_start_intr_legacy(ar);
+       /* Try legacy irq
+        *
+        * A potential race occurs here: The CORE_BASE write
+        * depends on target correctly decoding AXI address but
+        * host won't know when target writes BAR to CORE_CTRL.
+        * This write might get lost if target has NOT written BAR.
+        * For now, fix the race by repeating the write in below
+        * synchronization checking. */
+       ar_pci->num_msi_intrs = 0;
 
-exit:
-       ar_pci->num_msi_intrs = num;
-       ar_pci->ce_count = CE_COUNT;
-       return ret;
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target: %d\n", ret);
+               return ret;
+       }
+
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+       ath10k_pci_sleep(ar);
+
+       return 0;
 }
 
-static void ath10k_pci_stop_intr(struct ath10k *ar)
+static int ath10k_pci_deinit_irq_legacy(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int i;
+       int ret;
 
-       /* There's at least one interrupt irregardless whether its legacy INTR
-        * or MSI or MSI-X */
-       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
-               free_irq(ar_pci->pdev->irq + i, ar);
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target: %d\n", ret);
+               return ret;
+       }
 
-       if (ar_pci->num_msi_intrs > 0)
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          0);
+       ath10k_pci_sleep(ar);
+
+       return 0;
+}
+
+static int ath10k_pci_deinit_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       switch (ar_pci->num_msi_intrs) {
+       case 0:
+               return ath10k_pci_deinit_irq_legacy(ar);
+       case 1:
+               /* fall-through */
+       case MSI_NUM_REQUEST:
                pci_disable_msi(ar_pci->pdev);
+               return 0;
+       }
+
+       ath10k_warn("unknown irq configuration upon deinit\n");
+       return -EINVAL;
 }
 
-static int ath10k_pci_reset_target(struct ath10k *ar)
+static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int wait_limit = 300; /* 3 sec */
+       int ret;
 
-       /* Wait for Target to finish initialization before we proceed. */
-       iowrite32(PCIE_SOC_WAKE_V_MASK,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       ath10k_pci_wait(ar);
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_err("failed to wake up target: %d\n", ret);
+               return ret;
+       }
 
        while (wait_limit-- &&
               !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) &
@@ -2264,34 +2513,26 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
        }
 
        if (wait_limit < 0) {
-               ath10k_err("Target stalled\n");
-               iowrite32(PCIE_SOC_WAKE_RESET,
-                         ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                         PCIE_SOC_WAKE_ADDRESS);
-               return -EIO;
+               ath10k_err("target stalled\n");
+               ret = -EIO;
+               goto out;
        }
 
-       iowrite32(PCIE_SOC_WAKE_RESET,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       return 0;
+out:
+       ath10k_pci_sleep(ar);
+       return ret;
 }
 
-static void ath10k_pci_device_reset(struct ath10k *ar)
+static int ath10k_pci_device_reset(struct ath10k *ar)
 {
-       int i;
+       int i, ret;
        u32 val;
 
-       if (!SOC_GLOBAL_RESET_ADDRESS)
-               return;
-
-       ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
-                              PCIE_SOC_WAKE_V_MASK);
-       for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
-               if (ath10k_pci_target_is_awake(ar))
-                       break;
-               msleep(1);
+       ret = ath10k_do_pci_wake(ar);
+       if (ret) {
+               ath10k_err("failed to wake up target: %d\n",
+                          ret);
+               return ret;
        }
 
        /* Put Target, including PCIe, into RESET. */
@@ -2317,7 +2558,8 @@ static void ath10k_pci_device_reset(struct ath10k *ar)
                msleep(1);
        }
 
-       ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET);
+       ath10k_do_pci_sleep(ar);
+       return 0;
 }
 
 static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
@@ -2374,7 +2616,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
        if (!ar) {
-               ath10k_err("ath10k_core_create failed!\n");
+               ath10k_err("failed to create driver core\n");
                ret = -EINVAL;
                goto err_ar_pci;
        }
@@ -2393,20 +2635,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
         */
        ret = pci_assign_resource(pdev, BAR_NUM);
        if (ret) {
-               ath10k_err("cannot assign PCI space: %d\n", ret);
+               ath10k_err("failed to assign PCI space: %d\n", ret);
                goto err_ar;
        }
 
        ret = pci_enable_device(pdev);
        if (ret) {
-               ath10k_err("cannot enable PCI device: %d\n", ret);
+               ath10k_err("failed to enable PCI device: %d\n", ret);
                goto err_ar;
        }
 
        /* Request MMIO resources */
        ret = pci_request_region(pdev, BAR_NUM, "ath");
        if (ret) {
-               ath10k_err("PCI MMIO reservation error: %d\n", ret);
+               ath10k_err("failed to request MMIO region: %d\n", ret);
                goto err_device;
        }
 
@@ -2416,13 +2658,13 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
         */
        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               ath10k_err("32-bit DMA not available: %d\n", ret);
+               ath10k_err("failed to set DMA mask to 32-bit: %d\n", ret);
                goto err_region;
        }
 
        ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               ath10k_err("cannot enable 32-bit consistent DMA\n");
+               ath10k_err("failed to set consistent DMA mask to 32-bit\n");
                goto err_region;
        }
 
@@ -2439,7 +2681,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        /* Arrange for access to Target SoC registers. */
        mem = pci_iomap(pdev, BAR_NUM, 0);
        if (!mem) {
-               ath10k_err("PCI iomap error\n");
+               ath10k_err("failed to perform IOMAP for BAR%d\n", BAR_NUM);
                ret = -EIO;
                goto err_master;
        }
@@ -2451,11 +2693,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        ret = ath10k_do_pci_wake(ar);
        if (ret) {
                ath10k_err("Failed to get chip id: %d\n", ret);
-               return ret;
+               goto err_iomap;
        }
 
-       chip_id = ath10k_pci_read32(ar,
-                                   RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS);
+       chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
 
        ath10k_do_pci_sleep(ar);
 
@@ -2463,7 +2704,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        ret = ath10k_core_register(ar, chip_id);
        if (ret) {
-               ath10k_err("could not register driver core (%d)\n", ret);
+               ath10k_err("failed to register driver core: %d\n", ret);
                goto err_iomap;
        }
 
@@ -2529,7 +2770,7 @@ static int __init ath10k_pci_init(void)
 
        ret = pci_register_driver(&ath10k_pci_driver);
        if (ret)
-               ath10k_err("pci_register_driver failed [%d]\n", ret);
+               ath10k_err("failed to register PCI driver: %d\n", ret);
 
        return ret;
 }
index 52fb7b9..a4f3203 100644 (file)
@@ -198,9 +198,7 @@ struct ath10k_pci {
 
        struct tasklet_struct intr_tq;
        struct tasklet_struct msi_fw_err;
-
-       /* Number of Copy Engines supported */
-       unsigned int ce_count;
+       struct tasklet_struct early_irq_tasklet;
 
        int started;
 
@@ -318,6 +316,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
        return ioread32(ar_pci->mem + offset);
 }
 
+static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
+{
+       return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
+}
+
+static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
+}
+
 int ath10k_do_pci_wake(struct ath10k *ar);
 void ath10k_do_pci_sleep(struct ath10k *ar);
 
index 5ae373a..2282980 100644 (file)
@@ -75,6 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
        ath10k_report_offchan_tx(htt->ar, msdu);
 
        info = IEEE80211_SKB_CB(msdu);
+       memset(&info->status, 0, sizeof(info->status));
 
        if (tx_done->discard) {
                ieee80211_free_txskb(htt->ar->hw, msdu);
@@ -183,7 +184,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
                /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
                   TODO check this */
                mcs = (info2 >> 4) & 0x0F;
-               nss = (info1 >> 10) & 0x07;
+               nss = ((info1 >> 10) & 0x07) + 1;
                bw = info1 & 3;
                sgi = info2 & 1;
 
@@ -236,6 +237,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
        if (info->fcs_err)
                status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
+       if (info->amsdu_more)
+               status->flag |= RX_FLAG_AMSDU_MORE;
+
        status->signal = info->signal;
 
        spin_lock_bh(&ar->data_lock);
index ccf3597..1260a8d 100644 (file)
@@ -674,10 +674,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
 
        /* Send the management frame buffer to the target */
        ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
-       if (ret) {
-               dev_kfree_skb_any(skb);
+       if (ret)
                return ret;
-       }
 
        /* TODO: report tx status to mac80211 - temporary just ACK */
        info->flags |= IEEE80211_TX_STAT_ACK;
@@ -909,6 +907,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        ath10k_dbg(ATH10K_DBG_MGMT,
                   "event mgmt rx status %08x\n", rx_status);
 
+       if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
        if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
                dev_kfree_skb(skb);
                return 0;
@@ -1383,9 +1386,259 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar,
        ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
 }
 
+static void ath10k_dfs_radar_report(struct ath10k *ar,
+                                   struct wmi_single_phyerr_rx_event *event,
+                                   struct phyerr_radar_report *rr,
+                                   u64 tsf)
+{
+       u32 reg0, reg1, tsf32l;
+       struct pulse_event pe;
+       u64 tsf64;
+       u8 rssi, width;
+
+       reg0 = __le32_to_cpu(rr->reg0);
+       reg1 = __le32_to_cpu(rr->reg1);
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n",
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH),
+                  MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n",
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n",
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_DUR));
+
+       if (!ar->dfs_detector)
+               return;
+
+       /* report event to DFS pattern detector */
+       tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
+       tsf64 = tsf & (~0xFFFFFFFFULL);
+       tsf64 |= tsf32l;
+
+       width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
+       rssi = event->hdr.rssi_combined;
+
+       /* hardware store this as 8 bit signed value,
+        * set to zero if negative number
+        */
+       if (rssi & 0x80)
+               rssi = 0;
+
+       pe.ts = tsf64;
+       pe.freq = ar->hw->conf.chandef.chan->center_freq;
+       pe.width = width;
+       pe.rssi = rssi;
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n",
+                  pe.freq, pe.width, pe.rssi, pe.ts);
+
+       ATH10K_DFS_STAT_INC(ar, pulses_detected);
+
+       if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY,
+                          "dfs no pulse pattern detected, yet\n");
+               return;
+       }
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n");
+       ATH10K_DFS_STAT_INC(ar, radar_detected);
+
+       /* Control radar events reporting in debugfs file
+          dfs_block_radar_events */
+       if (ar->dfs_block_radar_events) {
+               ath10k_info("DFS Radar detected, but ignored as requested\n");
+               return;
+       }
+
+       ieee80211_radar_detected(ar->hw);
+}
+
+static int ath10k_dfs_fft_report(struct ath10k *ar,
+                                struct wmi_single_phyerr_rx_event *event,
+                                struct phyerr_fft_report *fftr,
+                                u64 tsf)
+{
+       u32 reg0, reg1;
+       u8 rssi, peak_mag;
+
+       reg0 = __le32_to_cpu(fftr->reg0);
+       reg1 = __le32_to_cpu(fftr->reg1);
+       rssi = event->hdr.rssi_combined;
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n",
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB));
+
+       peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+
+       /* false event detection */
+       if (rssi == DFS_RSSI_POSSIBLY_FALSE &&
+           peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs false pulse detected\n");
+               ATH10K_DFS_STAT_INC(ar, pulses_discarded);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void ath10k_wmi_event_dfs(struct ath10k *ar,
+                                struct wmi_single_phyerr_rx_event *event,
+                                u64 tsf)
+{
+       int buf_len, tlv_len, res, i = 0;
+       struct phyerr_tlv *tlv;
+       struct phyerr_radar_report *rr;
+       struct phyerr_fft_report *fftr;
+       u8 *tlv_buf;
+
+       buf_len = __le32_to_cpu(event->hdr.buf_len);
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
+                  event->hdr.phy_err_code, event->hdr.rssi_combined,
+                  __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
+
+       /* Skip event if DFS disabled */
+       if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
+               return;
+
+       ATH10K_DFS_STAT_INC(ar, pulses_total);
+
+       while (i < buf_len) {
+               if (i + sizeof(*tlv) > buf_len) {
+                       ath10k_warn("too short buf for tlv header (%d)\n", i);
+                       return;
+               }
+
+               tlv = (struct phyerr_tlv *)&event->bufp[i];
+               tlv_len = __le16_to_cpu(tlv->len);
+               tlv_buf = &event->bufp[i + sizeof(*tlv)];
+               ath10k_dbg(ATH10K_DBG_REGULATORY,
+                          "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
+                          tlv_len, tlv->tag, tlv->sig);
+
+               switch (tlv->tag) {
+               case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY:
+                       if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) {
+                               ath10k_warn("too short radar pulse summary (%d)\n",
+                                           i);
+                               return;
+                       }
+
+                       rr = (struct phyerr_radar_report *)tlv_buf;
+                       ath10k_dfs_radar_report(ar, event, rr, tsf);
+                       break;
+               case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+                       if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
+                               ath10k_warn("too short fft report (%d)\n", i);
+                               return;
+                       }
+
+                       fftr = (struct phyerr_fft_report *)tlv_buf;
+                       res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
+                       if (res)
+                               return;
+                       break;
+               }
+
+               i += sizeof(*tlv) + tlv_len;
+       }
+}
+
+static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
+                               struct wmi_single_phyerr_rx_event *event,
+                               u64 tsf)
+{
+       ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+}
+
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 {
-       ath10k_dbg(ATH10K_DBG_WMI, "WMI_PHYERR_EVENTID\n");
+       struct wmi_comb_phyerr_rx_event *comb_event;
+       struct wmi_single_phyerr_rx_event *event;
+       u32 count, i, buf_len, phy_err_code;
+       u64 tsf;
+       int left_len = skb->len;
+
+       ATH10K_DFS_STAT_INC(ar, phy_errors);
+
+       /* Check if combined event available */
+       if (left_len < sizeof(*comb_event)) {
+               ath10k_warn("wmi phyerr combined event wrong len\n");
+               return;
+       }
+
+       left_len -= sizeof(*comb_event);
+
+       /* Check number of included events */
+       comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
+       count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
+
+       tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
+       tsf <<= 32;
+       tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
+
+       ath10k_dbg(ATH10K_DBG_WMI,
+                  "wmi event phyerr count %d tsf64 0x%llX\n",
+                  count, tsf);
+
+       event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
+       for (i = 0; i < count; i++) {
+               /* Check if we can read event header */
+               if (left_len < sizeof(*event)) {
+                       ath10k_warn("single event (%d) wrong head len\n", i);
+                       return;
+               }
+
+               left_len -= sizeof(*event);
+
+               buf_len = __le32_to_cpu(event->hdr.buf_len);
+               phy_err_code = event->hdr.phy_err_code;
+
+               if (left_len < buf_len) {
+                       ath10k_warn("single event (%d) wrong buf len\n", i);
+                       return;
+               }
+
+               left_len -= buf_len;
+
+               switch (phy_err_code) {
+               case PHY_ERROR_RADAR:
+                       ath10k_wmi_event_dfs(ar, event, tsf);
+                       break;
+               case PHY_ERROR_SPECTRAL_SCAN:
+                       ath10k_wmi_event_spectral_scan(ar, event, tsf);
+                       break;
+               case PHY_ERROR_FALSE_RADAR_EXT:
+                       ath10k_wmi_event_dfs(ar, event, tsf);
+                       ath10k_wmi_event_spectral_scan(ar, event, tsf);
+                       break;
+               default:
+                       break;
+               }
+
+               event += sizeof(*event) + buf_len;
+       }
 }
 
 static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
@@ -2062,6 +2315,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
 {
        struct wmi_set_channel_cmd *cmd;
        struct sk_buff *skb;
+       u32 ch_flags = 0;
 
        if (arg->passive)
                return -EINVAL;
@@ -2070,10 +2324,14 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
        if (!skb)
                return -ENOMEM;
 
+       if (arg->chan_radar)
+               ch_flags |= WMI_CHAN_FLAG_DFS;
+
        cmd = (struct wmi_set_channel_cmd *)skb->data;
        cmd->chan.mhz               = __cpu_to_le32(arg->freq);
        cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
        cmd->chan.mode              = arg->mode;
+       cmd->chan.flags            |= __cpu_to_le32(ch_flags);
        cmd->chan.min_power         = arg->min_power;
        cmd->chan.max_power         = arg->max_power;
        cmd->chan.reg_power         = arg->max_reg_power;
@@ -2211,7 +2469,7 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
        }
 
        ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-                  __cpu_to_le32(ar->wmi.num_mem_chunks));
+                  ar->wmi.num_mem_chunks);
 
        cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
 
@@ -2224,10 +2482,10 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
                        __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
 
                ath10k_dbg(ATH10K_DBG_WMI,
-                          "wmi chunk %d len %d requested, addr 0x%x\n",
+                          "wmi chunk %d len %d requested, addr 0x%llx\n",
                           i,
-                          cmd->host_mem_chunks[i].size,
-                          cmd->host_mem_chunks[i].ptr);
+                          ar->wmi.mem_chunks[i].len,
+                          (unsigned long long)ar->wmi.mem_chunks[i].paddr);
        }
 out:
        memcpy(&cmd->resource_config, &config, sizeof(config));
@@ -2302,7 +2560,7 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
        }
 
        ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-                  __cpu_to_le32(ar->wmi.num_mem_chunks));
+                  ar->wmi.num_mem_chunks);
 
        cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
 
@@ -2315,10 +2573,10 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
                        __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
 
                ath10k_dbg(ATH10K_DBG_WMI,
-                          "wmi chunk %d len %d requested, addr 0x%x\n",
+                          "wmi chunk %d len %d requested, addr 0x%llx\n",
                           i,
-                          cmd->host_mem_chunks[i].size,
-                          cmd->host_mem_chunks[i].ptr);
+                          ar->wmi.mem_chunks[i].len,
+                          (unsigned long long)ar->wmi.mem_chunks[i].paddr);
        }
 out:
        memcpy(&cmd->resource_config, &config, sizeof(config));
@@ -2622,6 +2880,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
        struct sk_buff *skb;
        const char *cmdname;
        u32 flags = 0;
+       u32 ch_flags = 0;
 
        if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
            cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
@@ -2648,6 +2907,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
                flags |= WMI_VDEV_START_HIDDEN_SSID;
        if (arg->pmf_enabled)
                flags |= WMI_VDEV_START_PMF_ENABLED;
+       if (arg->channel.chan_radar)
+               ch_flags |= WMI_CHAN_FLAG_DFS;
 
        cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
        cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
@@ -2669,6 +2930,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
                __cpu_to_le32(arg->channel.band_center_freq1);
 
        cmd->chan.mode = arg->channel.mode;
+       cmd->chan.flags |= __cpu_to_le32(ch_flags);
        cmd->chan.min_power = arg->channel.min_power;
        cmd->chan.max_power = arg->channel.max_power;
        cmd->chan.reg_power = arg->channel.max_reg_power;
@@ -2676,9 +2938,10 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
        cmd->chan.antenna_max = arg->channel.max_antenna_gain;
 
        ath10k_dbg(ATH10K_DBG_WMI,
-                  "wmi vdev %s id 0x%x freq %d, mode %d, ch_flags: 0x%0X,"
-                  "max_power: %d\n", cmdname, arg->vdev_id, arg->channel.freq,
-                  arg->channel.mode, flags, arg->channel.max_power);
+                  "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, "
+                  "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id,
+                  flags, arg->channel.freq, arg->channel.mode,
+                  cmd->chan.flags, arg->channel.max_power);
 
        return ath10k_wmi_cmd_send(ar, skb, cmd_id);
 }
@@ -3012,6 +3275,8 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
                        flags |= WMI_CHAN_FLAG_ALLOW_VHT;
                if (ch->ht40plus)
                        flags |= WMI_CHAN_FLAG_HT40_PLUS;
+               if (ch->chan_radar)
+                       flags |= WMI_CHAN_FLAG_DFS;
 
                ci->mhz               = __cpu_to_le32(ch->freq);
                ci->band_center_freq1 = __cpu_to_le32(ch->freq);
@@ -3094,6 +3359,7 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
 {
        struct wmi_bcn_tx_cmd *cmd;
        struct sk_buff *skb;
+       int ret;
 
        skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len);
        if (!skb)
@@ -3106,7 +3372,11 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
        cmd->hdr.bcn_len  = __cpu_to_le32(arg->bcn_len);
        memcpy(cmd->bcn, arg->bcn, arg->bcn_len);
 
-       return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
+       ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
+       if (ret)
+               dev_kfree_skb(skb);
+
+       return ret;
 }
 
 static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
index 78c991a..0087d69 100644 (file)
@@ -893,6 +893,7 @@ struct wmi_channel {
        union {
                __le32 reginfo0;
                struct {
+                       /* note: power unit is 0.5 dBm */
                        u8 min_power;
                        u8 max_power;
                        u8 reg_power;
@@ -915,7 +916,8 @@ struct wmi_channel_arg {
        bool allow_ht;
        bool allow_vht;
        bool ht40plus;
-       /* note: power unit is 1/4th of dBm */
+       bool chan_radar;
+       /* note: power unit is 0.5 dBm */
        u32 min_power;
        u32 max_power;
        u32 max_reg_power;
@@ -1977,6 +1979,10 @@ struct wmi_mgmt_rx_event_v2 {
 #define WMI_RX_STATUS_ERR_MIC                  0x10
 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS       0x20
 
+#define PHY_ERROR_SPECTRAL_SCAN                0x26
+#define PHY_ERROR_FALSE_RADAR_EXT              0x24
+#define PHY_ERROR_RADAR                                0x05
+
 struct wmi_single_phyerr_rx_hdr {
        /* TSF timestamp */
        __le32 tsf_timestamp;
@@ -2068,6 +2074,87 @@ struct wmi_comb_phyerr_rx_event {
        u8 bufp[0];
 } __packed;
 
+#define PHYERR_TLV_SIG                         0xBB
+#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT       0xFB
+#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY     0xF8
+
+struct phyerr_radar_report {
+       __le32 reg0; /* RADAR_REPORT_REG0_* */
+       __le32 reg1; /* REDAR_REPORT_REG1_* */
+} __packed;
+
+#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_MASK          0x80000000
+#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_LSB           31
+
+#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_MASK      0x40000000
+#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_LSB       30
+
+#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_MASK          0x3FF00000
+#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_LSB           20
+
+#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_MASK                0x000F0000
+#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_LSB         16
+
+#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_MASK                0x0000FC00
+#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_LSB         10
+
+#define RADAR_REPORT_REG0_PULSE_SIDX_MASK              0x000003FF
+#define RADAR_REPORT_REG0_PULSE_SIDX_LSB               0
+
+#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_MASK    0x80000000
+#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_LSB     31
+
+#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_MASK       0x7F000000
+#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_LSB                24
+
+#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_MASK      0x00FF0000
+#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_LSB       16
+
+#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_MASK                0x0000FF00
+#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_LSB         8
+
+#define RADAR_REPORT_REG1_PULSE_DUR_MASK               0x000000FF
+#define RADAR_REPORT_REG1_PULSE_DUR_LSB                        0
+
+struct phyerr_fft_report {
+       __le32 reg0; /* SEARCH_FFT_REPORT_REG0_ * */
+       __le32 reg1; /* SEARCH_FFT_REPORT_REG1_ * */
+} __packed;
+
+#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_MASK      0xFF800000
+#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_LSB       23
+
+#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_MASK                0x007FC000
+#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_LSB         14
+
+#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_MASK                0x00003000
+#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_LSB         12
+
+#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_MASK          0x00000FFF
+#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_LSB           0
+
+#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_MASK          0xFC000000
+#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_LSB           26
+
+#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_MASK          0x03FC0000
+#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_LSB           18
+
+#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_MASK           0x0003FF00
+#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_LSB            8
+
+#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK    0x000000FF
+#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB     0
+
+
+struct phyerr_tlv {
+       __le16 len;
+       u8 tag;
+       u8 sig;
+} __packed;
+
+#define DFS_RSSI_POSSIBLY_FALSE                        50
+#define DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE      40
+
 struct wmi_mgmt_tx_hdr {
        __le32 vdev_id;
        struct wmi_mac_addr peer_macaddr;
@@ -2233,7 +2320,12 @@ enum wmi_pdev_param {
         * 0: no protection 1:use CTS-to-self 2: use RTS/CTS
         */
        WMI_PDEV_PARAM_PROTECTION_MODE,
-       /* Dynamic bandwidth 0: disable 1: enable */
+       /*
+        * Dynamic bandwidth - 0: disable, 1: enable
+        *
+        * When enabled HW rate control tries different bandwidths when
+        * retransmitting frames.
+        */
        WMI_PDEV_PARAM_DYNAMIC_BW,
        /* Non aggregrate/ 11g sw retry threshold.0-disable */
        WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
index ba200b2..e6c52f7 100644 (file)
@@ -616,7 +616,16 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
                 * SISRs will also clear PISR so no need to worry here.
                 */
 
-               pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS;
+               /* XXX: There seems to be  an issue on some cards
+                *      with tx interrupt flags not being updated
+                *      on PISR despite that all Tx interrupt bits
+                *      are cleared on SISRs. Since we handle all
+                *      Tx queues all together it shouldn't be an
+                *      issue if we clear Tx interrupt flags also
+                *      on PISR to avoid that.
+                */
+               pisr_clear = (pisr & ~AR5K_ISR_BITS_FROM_SISRS) |
+                                       (pisr & AR5K_INT_TX_ALL);
 
                /*
                 * Write to clear them...
index 546d5da..4f16d79 100644 (file)
@@ -2754,9 +2754,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
                                mask->control[band].legacy << 4;
 
                /* copy mcs rate mask */
-               mcsrate = mask->control[band].mcs[1];
+               mcsrate = mask->control[band].ht_mcs[1];
                mcsrate <<= 8;
-               mcsrate |= mask->control[band].mcs[0];
+               mcsrate |= mask->control[band].ht_mcs[0];
                ratemask[band] |= mcsrate << 12;
                ratemask[band] |= mcsrate << 28;
        }
@@ -2806,7 +2806,7 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
                                mask->control[band].legacy << 4;
 
                /* copy mcs rate mask */
-               mcsrate = mask->control[band].mcs[0];
+               mcsrate = mask->control[band].ht_mcs[0];
                ratemask[band] |= mcsrate << 12;
                ratemask[band] |= mcsrate << 20;
        }
index e7cdf11..0a6163e 100644 (file)
@@ -303,7 +303,7 @@ static const u32 ar9300_2p2_mac_postamble[][5] = {
        {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
        {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
        {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x00008120, 0x18f04800, 0x18f04800, 0x18f04810, 0x18f04810},
        {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
        {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
 };
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][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},
+       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
-       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
-       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
-       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
-       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
-       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
-       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
-       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
-       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
-       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
-       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
-       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
-       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
-       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
-       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
-       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
-       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
-       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
-       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
-       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
-       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
-       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
-       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
-       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
-       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
-       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
-       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
-       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
-       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
-       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
-       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
-       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
-       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
-       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
-       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
-       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
-       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
-       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
-       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
-       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
-       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
-       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
-       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
-       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
-       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
-       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
-       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
-       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {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, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5e88442e, 0x5e88442e, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x628a4431, 0x628a4431, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
        {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, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
@@ -1745,4 +1745,11 @@ static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = {
        {0x0000a3a0, 0xca9228ee},
 };
 
+static const u32 ar9300_2p2_baseband_postamble_dfs_channel[][3] = {
+       /* Addr      5G          2G        */
+       {0x00009824, 0x5ac668d0, 0x5ac668d0},
+       {0x00009e0c, 0x6d4000e2, 0x6d4000e2},
+       {0x00009e14, 0x37b9625e, 0x37b9625e},
+};
+
 #endif /* INITVALS_9003_2P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h
new file mode 100644 (file)
index 0000000..59cf738
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros 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_9003_BUFFALO_H
+#define INITVALS_9003_BUFFALO_H
+
+static const u32 ar9300Modes_high_power_tx_gain_table_buffalo[][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, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {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, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+#endif /* INITVALS_9003_BUFFALO_H */
index aa01272..97e09d5 100644 (file)
@@ -898,7 +898,7 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
 
 static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
 {
-       int offset[8], total = 0, test;
+       int offset[8] = {0}, total = 0, test;
        int agc_out, i;
 
        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
@@ -923,12 +923,18 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
                      AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
-       if (is_2g)
-               REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                             AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
-       else
+
+       if (AR_SREV_9330_11(ah)) {
                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                             AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
+                             AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
+       } else {
+               if (is_2g)
+                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                                     AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
+               else
+                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                                     AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
+       }
 
        for (i = 6; i > 0; i--) {
                offset[i] = BIT(i - 1);
@@ -964,9 +970,9 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
 }
 
-static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
-                                        struct ath9k_channel *chan,
-                                        bool run_rtt_cal)
+static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
+                                              struct ath9k_channel *chan,
+                                              bool run_rtt_cal)
 {
        struct ath9k_hw_cal_data *caldata = ah->caldata;
        int i;
@@ -1145,7 +1151,7 @@ skip_tx_iqcal:
                                       AR_PHY_AGC_CONTROL_CAL,
                                       0, AH_WAIT_TIMEOUT);
 
-               ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal);
+               ar9003_hw_do_pcoem_manual_peak_cal(ah, chan, run_rtt_cal);
        }
 
        if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
@@ -1267,6 +1273,9 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 
 skip_tx_iqcal:
        if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
+               if (AR_SREV_9330_11(ah))
+                       ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
+
                /* Calibrate the AGC */
                REG_WRITE(ah, AR_PHY_AGC_CONTROL,
                          REG_READ(ah, AR_PHY_AGC_CONTROL) |
index 130657d..ec317d6 100644 (file)
@@ -3965,7 +3965,7 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
 
-       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9340(ah))
                return;
 
        if (eep->baseEepHeader.featureEnable & 0x40) {
@@ -4122,7 +4122,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
        ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
        ar9003_hw_atten_apply(ah, chan);
        ar9003_hw_quick_drop_apply(ah, chan->channel);
-       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah))
+       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
index d8c1eee..29613eb 100644 (file)
@@ -17,6 +17,7 @@
 #include "hw.h"
 #include "ar9003_mac.h"
 #include "ar9003_2p2_initvals.h"
+#include "ar9003_buffalo_initvals.h"
 #include "ar9485_initvals.h"
 #include "ar9340_initvals.h"
 #include "ar9330_1p1_initvals.h"
@@ -152,6 +153,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                               ar9340Modes_fast_clock_1p0);
                INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
                               ar9340_1p0_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9340_1p0_baseband_postamble_dfs_channel);
 
                if (!ah->is_clk_25mhz)
                        INIT_INI_ARRAY(&ah->iniAdditional,
@@ -340,6 +343,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                               ar9580_1p0_modes_fast_clock);
                INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
                               ar9580_1p0_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9580_1p0_baseband_postamble_dfs_channel);
        } else if (AR_SREV_9565_11_OR_LATER(ah)) {
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
                               ar9565_1p1_mac_core);
@@ -458,6 +463,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                               ar9300Modes_fast_clock_2p2);
                INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
                               ar9300_2p2_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9300_2p2_baseband_postamble_dfs_channel);
        }
 }
 
@@ -586,9 +593,14 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                               ar9565_1p0_modes_high_power_tx_gain_table);
-       else
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9300Modes_high_power_tx_gain_table_2p2);
+       else {
+               if (ah->config.tx_gain_buffalo)
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      ar9300Modes_high_power_tx_gain_table_buffalo);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      ar9300Modes_high_power_tx_gain_table_2p2);
+       }
 }
 
 static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
index 39b71b3..9f051a0 100644 (file)
@@ -1332,6 +1332,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
 static void ar9003_hw_set_radar_params(struct ath_hw *ah,
                                       struct ath_hw_radar_conf *conf)
 {
+       unsigned int regWrites = 0;
        u32 radar_0 = 0, radar_1 = 0;
 
        if (!conf) {
@@ -1358,6 +1359,11 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah,
                REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
        else
                REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+
+       if (AR_SREV_9300(ah) || AR_SREV_9340(ah) || AR_SREV_9580(ah)) {
+               REG_WRITE_ARRAY(&ah->ini_dfs,
+                               IS_CHAN_HT40(ah->curchan) ? 2 : 1, regWrites);
+       }
 }
 
 static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
index 2af667b..bbbfc4d 100644 (file)
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
 
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100
+
 #define AR_PHY_CCA_NOM_VAL_9462_2GHZ          -127
 #define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ     -127
 #define AR_PHY_CCA_MAX_GOOD_VAL_9462_2GHZ     -60
-#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ -95
 #define AR_PHY_CCA_NOM_VAL_9462_5GHZ          -127
 #define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ     -127
 #define AR_PHY_CCA_MAX_GOOD_VAL_9462_5GHZ     -60
-#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ -100
 
 #define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
 
index 6e1756b..f76139b 100644 (file)
 #ifndef INITVALS_9330_1P1_H
 #define INITVALS_9330_1P1_H
 
+#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
+#define ar9331_modes_high_power_tx_gain_1p1 ar9331_modes_lowest_ob_db_tx_gain_1p1
+
 static const u32 ar9331_1p1_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
@@ -55,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -252,7 +256,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
        {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
        {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
        {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
-       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d4, 0x000050d4},
        {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
        {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
        {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
@@ -337,8 +341,6 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
        {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
 };
 
-#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
-
 static const u32 ar9331_1p1_xtal_25M[][2] = {
        /* Addr      allmodes  */
        {0x00007038, 0x000002f8},
@@ -373,17 +375,17 @@ static const u32 ar9331_1p1_radio_core[][2] = {
        {0x000160b4, 0x92480040},
        {0x000160c0, 0x006db6db},
        {0x000160c4, 0x0186db60},
-       {0x000160c8, 0x6db4db6c},
+       {0x000160c8, 0x6db6db6c},
        {0x000160cc, 0x6de6c300},
        {0x000160d0, 0x14500820},
        {0x00016100, 0x04cb0001},
        {0x00016104, 0xfff80015},
        {0x00016108, 0x00080010},
        {0x0001610c, 0x00170000},
-       {0x00016140, 0x10800000},
+       {0x00016140, 0x50804000},
        {0x00016144, 0x01884080},
        {0x00016148, 0x000080c0},
-       {0x00016280, 0x01000015},
+       {0x00016280, 0x01001015},
        {0x00016284, 0x14d20000},
        {0x00016288, 0x00318000},
        {0x0001628c, 0x50000000},
@@ -622,12 +624,12 @@ static const u32 ar9331_1p1_baseband_core[][2] = {
        {0x0000a370, 0x00000000},
        {0x0000a390, 0x00000001},
        {0x0000a394, 0x00000444},
-       {0x0000a398, 0x001f0e0f},
-       {0x0000a39c, 0x0075393f},
-       {0x0000a3a0, 0xb79f6427},
-       {0x0000a3a4, 0x00000000},
-       {0x0000a3a8, 0xaaaaaaaa},
-       {0x0000a3ac, 0x3c466478},
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x210d0401},
+       {0x0000a3a0, 0xab9a7144},
+       {0x0000a3a4, 0x00000011},
+       {0x0000a3a8, 0x3c3c003d},
+       {0x0000a3ac, 0x30310030},
        {0x0000a3c0, 0x20202020},
        {0x0000a3c4, 0x22222220},
        {0x0000a3c8, 0x20200020},
@@ -686,100 +688,18 @@ static const u32 ar9331_1p1_baseband_core[][2] = {
        {0x0000a7dc, 0x00000001},
 };
 
-static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+static const u32 ar9331_1p1_mac_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
-       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
-       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
-       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
-       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
-       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
-       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
-       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
-       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
-       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
-       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
-       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
-       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
-       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
-       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
-       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
-       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
-       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
-       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
-       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
-       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
-       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
-       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
-       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
-       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
-       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
-       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
-       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
-       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
-       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
-       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
-       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
-       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
-       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
-       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
-       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
-       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
-       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
-       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
-       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
-       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
-       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
-       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
-       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
-       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
-       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
-       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
-       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
-       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
-       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {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, 0x02008802, 0x02008802},
-       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
-       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
-       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
-       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+       {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},
 };
 
-#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
-
 static const u32 ar9331_1p1_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x00007020, 0x00000000},
index 57ed8a1..0ac8be9 100644 (file)
 #ifndef INITVALS_9330_1P2_H
 #define INITVALS_9330_1P2_H
 
+#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
+
+#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
+
+#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
+
+#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
+
+#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
+
+#define ar9331_1p2_mac_core ar9331_1p1_mac_core
+
+#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+
 static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
@@ -103,57 +125,6 @@ static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
        {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
 };
 
-#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
-
-#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2
-
-#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2
-
-static const u32 ar9331_1p2_baseband_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
-       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
-       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
-       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
-       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
-       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
-       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
-       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
-       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
-       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
-       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
-       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
-       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
-       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
-       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
-       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
-       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
-       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
-       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
-       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
-       {0x0000a234, 0x00000fff, 0x00000fff, 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, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
-       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
-       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
-       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
-       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
-       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-};
-
 static const u32 ar9331_1p2_radio_core[][2] = {
        /* Addr      allmodes  */
        {0x00016000, 0x36db6db6},
@@ -219,24 +190,318 @@ static const u32 ar9331_1p2_radio_core[][2] = {
        {0x000163d4, 0x00000000},
 };
 
-#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
-
-#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
-
-#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
-
-#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core
-
-#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
-
-#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
-
-#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
-
-#define ar9331_1p2_mac_core ar9331_1p1_mac_core
+static const u32 ar9331_1p2_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 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, 0x0cdbd380},
+       {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, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+};
 
-#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 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, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
 
-#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1
+static const u32 ar9331_common_rx_gain_1p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x01800082},
+       {0x0000a014, 0x01820181},
+       {0x0000a018, 0x01840183},
+       {0x0000a01c, 0x01880185},
+       {0x0000a020, 0x018a0189},
+       {0x0000a024, 0x02850284},
+       {0x0000a028, 0x02890288},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {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, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x21212128},
+       {0x0000a098, 0x171c1c1c},
+       {0x0000a09c, 0x02020212},
+       {0x0000a0a0, 0x00000202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x111f1100},
+       {0x0000a0c8, 0x111d111e},
+       {0x0000a0cc, 0x111b111c},
+       {0x0000a0d0, 0x22032204},
+       {0x0000a0d4, 0x22012202},
+       {0x0000a0d8, 0x221f2200},
+       {0x0000a0dc, 0x221d221e},
+       {0x0000a0e0, 0x33013302},
+       {0x0000a0e4, 0x331f3300},
+       {0x0000a0e8, 0x4402331e},
+       {0x0000a0ec, 0x44004401},
+       {0x0000a0f0, 0x441e441f},
+       {0x0000a0f4, 0x55015502},
+       {0x0000a0f8, 0x551f5500},
+       {0x0000a0fc, 0x6602551e},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {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, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {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, 0x00000296},
+};
 
 #endif /* INITVALS_9330_1P2_H */
index 7f22cb2..a01f0ed 100644 (file)
@@ -30,6 +30,8 @@
 
 #define ar9340_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
 
+#define ar9340_1p0_baseband_postamble_dfs_channel ar9300_2p2_baseband_postamble_dfs_channel
+
 static const u32 ar9340_1p0_radio_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800},
index 7390943..1cc1356 100644 (file)
 
 /* AR9462 2.0 */
 
+#define ar9462_2p0_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9462_2p0_common_wo_xlna_rx_gain ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar9462_2p0_common_5g_xlna_only_rxgain ar9462_2p0_common_mixed_rx_gain
+
+#define ar9462_2p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar9462_2p0_modes_fast_clock[][3] = {
        /* Addr      5G_HT20     5G_HT40   */
        {0x00001030, 0x00000268, 0x000004d0},
@@ -366,348 +374,81 @@ static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
        {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
 };
 
-static const u32 ar9462_2p0_common_wo_xlna_rx_gain[][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 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
-static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][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 ar9462_2p0_soc_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
-};
-
-static const u32 ar9462_2p0_baseband_core[][2] = {
+static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][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 ar9462_2p0_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
+};
+
+static const u32 ar9462_2p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
        {0x00009804, 0xfd14e000},
@@ -1226,18 +967,6 @@ static const u32 ar9462_2p0_mac_core[][2] = {
        {0x000083d0, 0x000301ff},
 };
 
-static const u32 ar9462_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 ar9462_2p0_common_mixed_rx_gain[][2] = {
        /* Addr      allmodes  */
        {0x0000a000, 0x00010000},
@@ -1503,266 +1232,6 @@ static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = {
        {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
 };
 
-static const u32 ar9462_2p0_common_5g_xlna_only_rxgain[][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 ar9462_2p0_baseband_core_mix_rxgain[][2] = {
        /* Addr      allmodes  */
        {0x00009fd0, 0x0a2d6b93},
index 7c18452..ce83ce4 100644 (file)
 
 /* AR9485 1.1 */
 
-static const u32 ar9485_1_1_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},
-};
+#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
+
+#define ar9485_1_1_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
 
 static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
        /* Addr      allmodes  */
@@ -546,100 +540,6 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
        {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
 };
 
-static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
-       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
-       {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
-       {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
-       {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
-       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
-       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
-       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
-       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
-       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
-       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
-       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
-       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
-       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
-       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
-       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
-       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
-       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
-       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
-       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
-       {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
-       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
-       {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
-       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
-       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
-       {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
-       {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
-       {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
-       {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
-       {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
-       {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
-       {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
-       {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
-       {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
-       {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
-       {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
-       {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
-};
-
 static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
@@ -1323,13 +1223,6 @@ static const u32 ar9485_1_1_mac_core[][2] = {
        {0x000083d0, 0x000301ff},
 };
 
-static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
        {0x00018c00, 0x18013e5e},
index ccc5b6c..74d8bc0 100644 (file)
 
 /* AR955X 1.0 */
 
+#define ar955x_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define ar955x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2
+
+#define ar955x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar955x_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar955x_1p0_radio_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330},
@@ -37,13 +45,6 @@ static const u32 ar955x_1p0_radio_postamble[][5] = {
        {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
 };
 
-static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 static const u32 ar955x_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
@@ -473,266 +474,6 @@ static const u32 ar955x_1p0_mac_core[][2] = {
        {0x000083d0, 0x8c7901ff},
 };
 
-static const u32 ar955x_1p0_common_rx_gain_table[][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, 0x23232323},
-       {0x0000b084, 0x21232323},
-       {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 ar955x_1p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
@@ -891,266 +632,6 @@ static const u32 ar955x_1p0_baseband_core[][2] = {
        {0x0000c420, 0x00000000},
 };
 
-static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][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 ar955x_1p0_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x00007000, 0x00000000},
@@ -1263,11 +744,6 @@ static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = {
        {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
 };
 
-static const u32 ar955x_1p0_soc_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
-
 static const u32 ar955x_1p0_modes_fast_clock[][3] = {
        /* Addr      5G_HT20     5G_HT40   */
        {0x00001030, 0x00000268, 0x000004d0},
index a8c757b..10d4a6c 100644 (file)
 
 /* AR9565 1.0 */
 
+#define ar9565_1p0_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9565_1p0_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table
+
+#define ar9565_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar9565_1p0_mac_core[][2] = {
        /* Addr      allmodes  */
        {0x00000008, 0x00000000},
@@ -182,18 +188,6 @@ static const u32 ar9565_1p0_mac_core[][2] = {
        {0x000083d0, 0x800301ff},
 };
 
-static const u32 ar9565_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 ar9565_1p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
@@ -711,66 +705,6 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
        {0x0000b1fc, 0x00000196},
 };
 
-static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0xfc0a9380, 0xfc0a9380, 0xfdab5b52, 0xfdab5b52},
-       {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
-       {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
-       {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
-       {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, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a618, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a61c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a620, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a624, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a628, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a62c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a630, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a634, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a638, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a63c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016048, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-};
-
 static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
        {0x00018c00, 0x18212ede},
@@ -1231,11 +1165,4 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
        {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 };
 
-static const u32 ar9565_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 #endif /* INITVALS_9565_1P0_H */
index 75bef11..e6aec2c 100644 (file)
@@ -57,8 +57,6 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
        {0x00009804, 0xfd14e000},
        {0x00009808, 0x9c0a9f6b},
        {0x0000980c, 0x04900000},
-       {0x00009814, 0x3280c00a},
-       {0x00009818, 0x00000000},
        {0x0000981c, 0x00020028},
        {0x00009834, 0x6400a190},
        {0x00009838, 0x0108ecff},
@@ -1133,6 +1131,8 @@ static const u32 ar9580_1p0_rx_gain_table[][2] = {
 static const u32 ar9580_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009814, 0x3280c00a, 0x3280c00a, 0x3280c00a, 0x3280c00a},
+       {0x00009818, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
        {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
        {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
@@ -1207,4 +1207,13 @@ static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = {
        {0x00004044, 0x00000000},
 };
 
+static const u32 ar9580_1p0_baseband_postamble_dfs_channel[][3] = {
+       /* Addr      5G          2G        */
+       {0x00009814, 0x3400c00f, 0x3400c00f},
+       {0x00009824, 0x5ac668d0, 0x5ac668d0},
+       {0x00009828, 0x06903080, 0x06903080},
+       {0x00009e0c, 0x6d4000e2, 0x6d4000e2},
+       {0x00009e14, 0x37b9625e, 0x37b9625e},
+};
+
 #endif /* INITVALS_9580_1P0_H */
index 779d38a..4ee24b1 100644 (file)
@@ -548,11 +548,11 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
         * EEPROM needs to be initialized before we do this.
         * This is required for regulatory compliance.
         */
-       if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
                u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
                if ((regdmn & 0xF0) == CTL_FCC) {
-                       ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ;
-                       ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ;
+                       ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ;
+                       ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ;
                }
        }
 
index e508436..b1ff546 100644 (file)
@@ -316,6 +316,7 @@ struct ath9k_ops_config {
        bool xatten_margin_cfg;
        bool alt_mingainidx;
        bool no_pll_pwrsave;
+       bool tx_gain_buffalo;
 };
 
 enum ath9k_int {
@@ -864,6 +865,7 @@ struct ath_hw {
        u32 gpio_mask;
        u32 gpio_val;
 
+       struct ar5416IniArray ini_dfs;
        struct ar5416IniArray iniModes;
        struct ar5416IniArray iniCommon;
        struct ar5416IniArray iniBB_RfGain;
index 8f4c167..609b7e1 100644 (file)
@@ -554,7 +554,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
        sc->spec_config.fft_period = 0xF;
 }
 
-static void ath9k_init_platform(struct ath_softc *sc)
+static void ath9k_init_pcoem_platform(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -664,6 +664,27 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
        release_firmware(sc->sc_ah->eeprom_blob);
 }
 
+static int ath9k_init_soc_platform(struct ath_softc *sc)
+{
+       struct ath9k_platform_data *pdata = sc->dev->platform_data;
+       struct ath_hw *ah = sc->sc_ah;
+       int ret = 0;
+
+       if (!pdata)
+               return 0;
+
+       if (pdata->eeprom_name) {
+               ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdata->tx_gain_buffalo)
+               ah->config.tx_gain_buffalo = true;
+
+       return ret;
+}
+
 static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                            const struct ath_bus_ops *bus_ops)
 {
@@ -717,7 +738,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        /*
         * Platform quirks.
         */
-       ath9k_init_platform(sc);
+       ath9k_init_pcoem_platform(sc);
+
+       ret = ath9k_init_soc_platform(sc);
+       if (ret)
+               return ret;
 
        /*
         * Enable WLAN/BT RX Antenna diversity only when:
@@ -731,7 +756,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                common->bt_ant_diversity = 1;
 
        spin_lock_init(&common->cc_lock);
-
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
@@ -753,12 +777,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        ath_read_cachesize(common, &csz);
        common->cachelsz = csz << 2; /* convert to bytes */
 
-       if (pdata && pdata->eeprom_name) {
-               ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
-               if (ret)
-                       return ret;
-       }
-
        /* Initializes the hardware for all supported chipsets */
        ret = ath9k_hw_init(ah);
        if (ret)
@@ -856,6 +874,9 @@ static const struct ieee80211_iface_limit if_limits[] = {
 
 static const struct ieee80211_iface_limit if_dfs_limits[] = {
        { .max = 1,     .types = BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+                                BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
                                 BIT(NL80211_IFTYPE_ADHOC) },
 };
 
index 259a4b3..9ad0073 100644 (file)
 
 #define AR_SREV_9330(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
-#define AR_SREV_9330_10(_ah) \
-       (AR_SREV_9330((_ah)) && \
-        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
 #define AR_SREV_9330_11(_ah) \
        (AR_SREV_9330((_ah)) && \
         ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
index 57d7757..b686a74 100644 (file)
@@ -48,7 +48,9 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
                               0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3,
                               0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0};
        u32 len = 1200;
+       struct ieee80211_tx_rate *rate;
        struct ieee80211_hw *hw = sc->hw;
+       struct ath_hw *ah = sc->sc_ah;
        struct ieee80211_hdr *hdr;
        struct ieee80211_tx_info *tx_info;
        struct sk_buff *skb;
@@ -73,10 +75,16 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
 
        tx_info = IEEE80211_SKB_CB(skb);
        memset(tx_info, 0, sizeof(*tx_info));
+       rate = &tx_info->control.rates[0];
        tx_info->band = hw->conf.chandef.chan->band;
        tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
        tx_info->control.vif = sc->tx99_vif;
-       tx_info->control.rates[0].count = 1;
+       rate->count = 1;
+       if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
+               rate->flags |= IEEE80211_TX_RC_MCS;
+               if (IS_CHAN_HT40(ah->curchan))
+                       rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+       }
 
        memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data));
 
index 823631c..8f37562 100644 (file)
@@ -1151,14 +1151,14 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
                /* STA */
                bss->oper_mode = 1;
                bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
-       } else if (vif->type == NL80211_IFTYPE_AP) {
+       } else if (vif->type == NL80211_IFTYPE_AP ||
+                  vif->type == NL80211_IFTYPE_MESH_POINT) {
                bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
 
                /* AP */
                bss->oper_mode = 0;
                bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
-       } else if (vif->type == NL80211_IFTYPE_ADHOC ||
-                  vif->type == NL80211_IFTYPE_MESH_POINT) {
+       } else if (vif->type == NL80211_IFTYPE_ADHOC) {
                bss->bss_type = WCN36XX_HAL_IBSS_MODE;
 
                /* STA */
@@ -1309,7 +1309,11 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
        memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
 
        /* TODO need to find out why this is needed? */
-       msg_body.tim_ie_offset = tim_off+4;
+       if (vif->type == NL80211_IFTYPE_MESH_POINT)
+               /* mesh beacon don't need this, so push further down */
+               msg_body.tim_ie_offset = 256;
+       else
+               msg_body.tim_ie_offset = tim_off+4;
        msg_body.p2p_ie_offset = p2p_off;
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
index 0d950f2..b73b7e3 100644 (file)
@@ -28,8 +28,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
     For all queries about this code, please contact the current author,
     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
@@ -4278,8 +4278,7 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with AtmelMACFW; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with AtmelMACFW; if not, see <http://www.gnu.org/licenses/>.
 
 ****************************************************************************/
 /* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E        */
index b9b3e5b..96f7318 100644 (file)
@@ -15,8 +15,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 
index 5225722..5e2749d 100644 (file)
@@ -24,8 +24,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 
index c1b159e..64d5973 100644 (file)
@@ -15,8 +15,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 #include <linux/pci.h>
index 747adff..b866757 100644 (file)
@@ -242,14 +242,17 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
        if (vif->type == NL80211_IFTYPE_STATION &&
            ap_sta_id != IWL_MVM_STATION_COUNT) {
                struct ieee80211_sta *sta;
-               struct iwl_mvm_sta *mvm_sta;
 
                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
                                                lockdep_is_held(&mvm->mutex));
-               mvm_sta = (void *)sta->drv_priv;
-               pos += scnprintf(buf+pos, bufsz-pos,
-                                "ap_sta_id %d - reduced Tx power %d\n",
-                                ap_sta_id, mvm_sta->bt_reduced_txpower);
+               if (!IS_ERR_OR_NULL(sta)) {
+                       struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
+
+                       pos += scnprintf(buf+pos, bufsz-pos,
+                                        "ap_sta_id %d - reduced Tx power %d\n",
+                                        ap_sta_id,
+                                        mvm_sta->bt_reduced_txpower);
+               }
        }
 
        rcu_read_lock();
index b61d5a2..2f52693 100644 (file)
@@ -1181,6 +1181,28 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
        }
 }
 
+static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_sta *sta)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
+
+       /*
+        * This is called before mac80211 does RCU synchronisation,
+        * so here we already invalidate our internal RCU-protected
+        * station pointer. The rest of the code will thus no longer
+        * be able to find the station this way, and we don't rely
+        * on further RCU synchronisation after the sta_state()
+        * callback deleted the station.
+        */
+       mutex_lock(&mvm->mutex);
+       if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id]))
+               rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
+                                  ERR_PTR(-ENOENT));
+       mutex_unlock(&mvm->mutex);
+}
+
 static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                                 struct ieee80211_vif *vif,
                                 struct ieee80211_sta *sta,
@@ -1856,6 +1878,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
        .bss_info_changed = iwl_mvm_bss_info_changed,
        .hw_scan = iwl_mvm_mac_hw_scan,
        .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
+       .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove,
        .sta_state = iwl_mvm_mac_sta_state,
        .sta_notify = iwl_mvm_mac_sta_notify,
        .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
index 0b541ca..0a8af20 100644 (file)
@@ -452,8 +452,15 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk)
                        rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
                                                  lockdep_is_held(&mvm->mutex));
 
-               /* This station is in use */
-               if (!IS_ERR(sta))
+               /*
+                * This station is in use or RCU-removed; the latter happens in
+                * managed mode, where mac80211 removes the station before we
+                * can remove it from firmware (we can only do that after the
+                * MAC is marked unassociated), and possibly while the deauth
+                * frame to disconnect from the AP is still queued. Then, the
+                * station pointer is -ENOENT when the last skb is reclaimed.
+                */
+               if (!IS_ERR(sta) || PTR_ERR(sta) == -ENOENT)
                        continue;
 
                if (PTR_ERR(sta) == -EINVAL) {
index 91f2ca9..1a554a6 100644 (file)
@@ -8,9 +8,8 @@
  Ltd. under the terms of the GNU General Public License Version 2, June 1991
  (the "License").  You may use, redistribute and/or modify this File in
  accordance with the terms and conditions of the License, a copy of which
- is available along with the File in the license.txt file or by writing to
- the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ is available along with the File in the license.txt file or on the worldwide
+ web at http://www.gnu.org/licenses/gpl.txt.
 
  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
index 1214c58..6321170 100644 (file)
@@ -69,9 +69,9 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
        memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset);
 
        /* Copy SNAP header */
-       snap.snap_type =
-               le16_to_cpu(*(__le16 *) ((u8 *)skb_src->data + dt_offset));
-       dt_offset += sizeof(u16);
+       snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto;
+
+       dt_offset += sizeof(__be16);
 
        memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr));
 
index d9b7330..3ff28c2 100644 (file)
@@ -222,6 +222,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = pkt_len;
 
        mwifiex_form_mgmt_frame(skb, buf, len);
        mwifiex_queue_tx_pkt(priv, skb);
@@ -1170,10 +1171,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
        else
                bitmap_rates[1] = mask->control[band].legacy;
 
-       /* Fill MCS rates */
-       bitmap_rates[2] = mask->control[band].mcs[0];
+       /* Fill HT MCS rates */
+       bitmap_rates[2] = mask->control[band].ht_mcs[0];
        if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2)
-               bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
+               bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
 
        return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
                                     HostCmd_ACT_GEN_SET, 0, bitmap_rates);
index e47f4e3..1ddc8b2 100644 (file)
@@ -312,14 +312,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
        }
        if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY))
            == MWIFIEX_BSS_ROLE_STA) {
-               if (!sleep_cfm_buf->resp_ctrl)
+               if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
                        /* Response is not needed for sleep
                           confirm command */
                        adapter->ps_state = PS_STATE_SLEEP;
                else
                        adapter->ps_state = PS_STATE_SLEEP_CFM;
 
-               if (!sleep_cfm_buf->resp_ctrl &&
+               if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
                    (adapter->is_hs_configured &&
                     !adapter->sleep_period.period)) {
                        adapter->pm_wakeup_card_req = true;
index 5c85d78..3a21bd0 100644 (file)
@@ -130,6 +130,7 @@ struct mwifiex_txinfo {
        u8 flags;
        u8 bss_num;
        u8 bss_type;
+       u32 pkt_len;
 };
 
 enum mwifiex_wmm_ac_e {
index c8385ec..8fcb500 100644 (file)
@@ -30,7 +30,7 @@ struct rfc_1042_hdr {
        u8 llc_ssap;
        u8 llc_ctrl;
        u8 snap_oui[3];
-       u16 snap_type;
+       __be16 snap_type;
 };
 
 struct rx_packet_hdr {
@@ -610,12 +610,12 @@ struct mwifiex_ie_types_tsf_timestamp {
 struct mwifiex_cf_param_set {
        u8 cfp_cnt;
        u8 cfp_period;
-       u16 cfp_max_duration;
-       u16 cfp_duration_remaining;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
 } __packed;
 
 struct mwifiex_ibss_param_set {
-       u16 atim_window;
+       __le16 atim_window;
 } __packed;
 
 struct mwifiex_ie_types_ss_param_set {
@@ -627,7 +627,7 @@ struct mwifiex_ie_types_ss_param_set {
 } __packed;
 
 struct mwifiex_fh_param_set {
-       u16 dwell_time;
+       __le16 dwell_time;
        u8 hop_set;
        u8 hop_pattern;
        u8 hop_index;
@@ -684,10 +684,10 @@ struct host_cmd_ds_802_11_key_material {
 } __packed;
 
 struct host_cmd_ds_gen {
-       u16 command;
-       u16 size;
-       u16 seq_num;
-       u16 result;
+       __le16 command;
+       __le16 size;
+       __le16 seq_num;
+       __le16 result;
 };
 
 #define S_DS_GEN        sizeof(struct host_cmd_ds_gen)
@@ -820,8 +820,8 @@ struct ieee_types_cf_param_set {
        u8 len;
        u8 cfp_cnt;
        u8 cfp_period;
-       u16 cfp_max_duration;
-       u16 cfp_duration_remaining;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
 } __packed;
 
 struct ieee_types_ibss_param_set {
@@ -957,7 +957,7 @@ struct mwifiex_hs_config_param {
 } __packed;
 
 struct hs_activate_param {
-       u16 resp_ctrl;
+       __le16 resp_ctrl;
 } __packed;
 
 struct host_cmd_ds_802_11_hs_cfg_enh {
@@ -1131,7 +1131,7 @@ struct host_cmd_ds_802_11_bg_scan_query {
 } __packed;
 
 struct host_cmd_ds_802_11_bg_scan_query_rsp {
-       u32 report_condition;
+       __le32 report_condition;
        struct host_cmd_ds_802_11_scan_rsp scan_resp;
 } __packed;
 
@@ -1230,7 +1230,7 @@ struct mwifiex_ie_types_wmm_queue_status {
        struct mwifiex_ie_types_header header;
        u8 queue_index;
        u8 disabled;
-       u16 medium_time;
+       __le16 medium_time;
        u8 flow_required;
        u8 flow_created;
        u32 reserved;
@@ -1310,7 +1310,7 @@ struct mwifiex_ie_types_vht_oper {
        u8 chan_center_freq_1;
        u8 chan_center_freq_2;
        /* Basic MCS set map, each 2 bits stands for a NSS */
-       u16 basic_mcs_map;
+       __le16 basic_mcs_map;
 } __packed;
 
 struct mwifiex_ie_types_wmmcap {
index 6499117..1d0a817 100644 (file)
@@ -643,7 +643,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
                        if (priv)
                                priv->stats.rx_dropped++;
 
-                       adapter->if_ops.data_complete(adapter, skb);
+                       dev_kfree_skb_any(skb);
+                       adapter->if_ops.data_complete(adapter);
                }
        }
 
index 78e8a66..6bf58ab 100644 (file)
@@ -648,6 +648,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = skb->len;
 
        /* Record the current time the packet was queued; used to
         * determine the amount of time the packet was queued in
@@ -991,12 +992,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
                rtnl_unlock();
        }
 
-       priv = adapter->priv[0];
-       if (!priv || !priv->wdev)
-               goto exit_remove;
-
-       wiphy_unregister(priv->wdev->wiphy);
-       wiphy_free(priv->wdev->wiphy);
+       wiphy_unregister(adapter->wiphy);
+       wiphy_free(adapter->wiphy);
 
        mwifiex_terminate_workqueue(adapter);
 
index 1d72f13..dc34457 100644 (file)
@@ -615,7 +615,7 @@ struct mwifiex_if_ops {
        void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
        int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
        int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
-       int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *);
+       int (*data_complete) (struct mwifiex_adapter *);
        int (*init_fw_port) (struct mwifiex_adapter *);
        int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
        void (*card_reset) (struct mwifiex_adapter *);
index 2181ee2..1efa43e 100644 (file)
@@ -354,7 +354,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
        }
        if (hs_activate) {
                hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
-               hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
+               hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
        } else {
                hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
                hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
index bb22664..0bb510d 100644 (file)
@@ -36,12 +36,12 @@ mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
                               struct sk_buff *skb)
 {
        const struct mwifiex_arp_eth_header *arp;
-       struct ethhdr *eth_hdr;
+       struct ethhdr *eth;
        struct ipv6hdr *ipv6;
        struct icmp6hdr *icmpv6;
 
-       eth_hdr = (struct ethhdr *)skb->data;
-       switch (ntohs(eth_hdr->h_proto)) {
+       eth = (struct ethhdr *)skb->data;
+       switch (ntohs(eth->h_proto)) {
        case ETH_P_ARP:
                arp = (void *)(skb->data + sizeof(struct ethhdr));
                if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
@@ -87,16 +87,19 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
        struct rx_packet_hdr *rx_pkt_hdr;
        struct rxpd *local_rx_pd;
        int hdr_chop;
-       struct ethhdr *eth_hdr;
-       u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+       struct ethhdr *eth;
 
        local_rx_pd = (struct rxpd *) (skb->data);
 
        rx_pkt_hdr = (void *)local_rx_pd +
                     le16_to_cpu(local_rx_pd->rx_pkt_offset);
 
-       if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
-                   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
                /*
                 *  Replace the 803 header and rfc1042 header (llc/snap) with an
                 *    EthernetII header, keep the src/dst and snap_type
@@ -106,7 +109,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
                 *  To create the Ethernet II, just move the src, dst address
                 *    right before the snap_type.
                 */
-               eth_hdr = (struct ethhdr *)
+               eth = (struct ethhdr *)
                        ((u8 *) &rx_pkt_hdr->eth803_hdr
                         + sizeof(rx_pkt_hdr->eth803_hdr) +
                         sizeof(rx_pkt_hdr->rfc1042_hdr)
@@ -114,14 +117,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
                         - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
                         - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
 
-               memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source,
-                      sizeof(eth_hdr->h_source));
-               memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
-                      sizeof(eth_hdr->h_dest));
+               memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
+                      sizeof(eth->h_source));
+               memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
+                      sizeof(eth->h_dest));
 
                /* Chop off the rxpd + the excess memory from the 802.2/llc/snap
                   header that was removed. */
-               hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd;
+               hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
        } else {
                /* Chop off the rxpd */
                hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
@@ -185,12 +188,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
                        "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
                        skb->len, rx_pkt_offset, rx_pkt_length);
                priv->stats.rx_dropped++;
-
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-
+               dev_kfree_skb_any(skb);
                return ret;
        }
 
@@ -244,12 +242,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
        ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
                                         ta, (u8) rx_pkt_type, skb);
 
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-       }
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
 
        if (ret)
                priv->stats.rx_dropped++;
index 7b581af..354d64c 100644 (file)
@@ -148,6 +148,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
        skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
        skb_push(skb, sizeof(struct txpd));
 
index 8f923d0..37f26af 100644 (file)
@@ -40,6 +40,7 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
                mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
        struct rxpd *local_rx_pd;
        struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+       int ret;
 
        local_rx_pd = (struct rxpd *) (skb->data);
        /* Get the BSS number from rxpd, get corresponding priv */
@@ -58,9 +59,15 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
        rx_info->bss_type = priv->bss_type;
 
        if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-               return mwifiex_process_uap_rx_packet(priv, skb);
+               ret = mwifiex_process_uap_rx_packet(priv, skb);
+       else
+               ret = mwifiex_process_sta_rx_packet(priv, skb);
+
+       /* Decrement RX pending counter for each packet */
+       if (adapter->if_ops.data_complete)
+               adapter->if_ops.data_complete(adapter);
 
-       return mwifiex_process_sta_rx_packet(priv, skb);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
 
@@ -105,7 +112,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 
        switch (ret) {
        case -ENOSR:
-               dev_err(adapter->dev, "data: -ENOSR is returned\n");
+               dev_dbg(adapter->dev, "data: -ENOSR is returned\n");
                break;
        case -EBUSY:
                if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
@@ -168,7 +175,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
        mwifiex_set_trans_start(priv->netdev);
        if (!status) {
                priv->stats.tx_packets++;
-               priv->stats.tx_bytes += skb->len;
+               priv->stats.tx_bytes += tx_info->pkt_len;
                if (priv->tx_timeout_cnt)
                        priv->tx_timeout_cnt = 0;
        } else {
index 92f76d6..3c74eb2 100644 (file)
@@ -98,7 +98,6 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        int hdr_chop;
        struct timeval tv;
        struct ethhdr *p_ethhdr;
-       u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
        uap_rx_pd = (struct uap_rxpd *)(skb->data);
        rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
@@ -112,8 +111,12 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
                return;
        }
 
-       if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
-                   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
                /* Replace the 803 header and rfc1042 header (llc/snap) with
                 * an Ethernet II header, keep the src/dst and snap_type
                 * (ethertype).
@@ -144,7 +147,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
                hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
        }
 
-       /* Chop off the leading header bytes so the it points
+       /* Chop off the leading header bytes so that it points
         * to the start of either the reconstructed EthII frame
         * or the 802.2/llc/snap frame.
         */
@@ -176,6 +179,19 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        tx_info->bss_type = priv->bss_type;
        tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
 
+       if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
+               /* Update bridge packet statistics as the
+                * packet is not going to kernel/upper layer.
+                */
+               priv->stats.rx_bytes += skb->len;
+               priv->stats.rx_packets++;
+
+               /* Sending bridge packet to TX queue, so save the packet
+                * length in TXCB to update statistics in TX complete.
+                */
+               tx_info->pkt_len = skb->len;
+       }
+
        do_gettimeofday(&tv);
        skb->tstamp = timeval_to_ktime(tv);
        mwifiex_wmm_add_buf_txqueue(priv, skb);
@@ -264,12 +280,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                        skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
                        le16_to_cpu(uap_rx_pd->rx_pkt_length));
                priv->stats.rx_dropped++;
-
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-
+               dev_kfree_skb_any(skb);
                return 0;
        }
 
@@ -323,12 +334,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                                         uap_rx_pd->priority, ta, pkt_type,
                                         skb);
 
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-       }
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
 
        if (ret)
                priv->stats.rx_dropped++;
index edf5b7a..a9240a2 100644 (file)
@@ -938,11 +938,9 @@ static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
        return 0;
 }
 
-static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter,
-                                    struct sk_buff *skb)
+static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter)
 {
        atomic_dec(&adapter->rx_pending);
-       dev_kfree_skb_any(skb);
 
        return 0;
 }
index 5d9e150..9b82e22 100644 (file)
@@ -191,6 +191,9 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
        if (!skb)
                return -1;
 
+       priv->stats.rx_bytes += skb->len;
+       priv->stats.rx_packets++;
+
        skb->dev = priv->netdev;
        skb->protocol = eth_type_trans(skb, priv->netdev);
        skb->ip_summed = CHECKSUM_NONE;
@@ -217,8 +220,6 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
            (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
                skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
-       priv->stats.rx_bytes += skb->len;
-       priv->stats.rx_packets++;
        if (in_interrupt())
                netif_rx(skb);
        else
index e3ed893..aedfaf2 100644 (file)
@@ -20,8 +20,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*-------------------------------------------------------------------------*/
index 02fc67b..333c1a2 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 19c33d3..547ab88 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 8863a6c..df784fe 100644 (file)
@@ -14,8 +14,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index a34bceb..842a254 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 59e3125..83fec55 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 7fa2898..931cf44 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index c404038..f6f088e 100644 (file)
@@ -14,8 +14,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 799e148..674658f 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 6ca30a5..80f50f1 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index d7b9e63..1105a12 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 9f19cce..0de14df 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 0db93db..700c434 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 056af38..47b34bf 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 92c8a2d..cf5141d 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index aa1d174..bc1401e 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 9b557a1..cbf0a58 100644 (file)
@@ -17,8 +17,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Changes:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
index 8169a85..c3cdda1 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *  Portions of this file are based on NDISwrapper project,
  *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
index 38ed9a3..4ad0de9 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e4b07f0..0fd3a9d 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 0ac5c58..4f61ffb 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9c10068..573e87b 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 85acc79..1bb7693 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1b91a4c..afba073 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index aab6b5e..a394a9a 100644 (file)
@@ -21,9 +21,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 5ee5b29..b8f5b06 100644 (file)
@@ -24,9 +24,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a94ba44..3019db6 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef RT2800LIB_H
index a8cc736..de4790b 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800mmio
index 6a10de3..b63312c 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800mmio
index b504455..a5b32ca 100644 (file)
@@ -20,9 +20,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a81c9ee..9dfef46 100644 (file)
@@ -20,9 +20,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1359227..f6d1bf5 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800soc
index a81ceb6..49ff178 100644 (file)
@@ -18,9 +18,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 671ea35..ea7cac0 100644 (file)
@@ -17,9 +17,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e4ba2ce..e3b885d 100644 (file)
@@ -15,9 +15,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 8cb43f8..1122dc4 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 3db0d99..a2fd05b 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7f7baae..2e3d164 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e11d39b..e65712c 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9dd92a7..00c3fae 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 063ebcc..4c0e01b 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1b4254b..fbae279 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 997a6c8..c681d04 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 3b46f0c..b2c5269 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7f40ab8..fb7c349 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index c2b3b66..9b941c0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 2183e79..ddeb5a7 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 64b06c6..6f236ea 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index cda3dbc..701c312 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index af72183..d93db4b 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 60d90b2..bc0ca5f 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a5d38e8..5642ccc 100644 (file)
@@ -15,9 +15,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index ebe1172..c48125b 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 6f867ee..3cc541d 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9271a5f..69a0cda 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 474cbfc..9948d35 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 4e12162..1057245 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 323ca7b..e7bcf62 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a5b69cb..b76f604 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9bc6b60..1442075 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1baf9c8..ade88d7 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7577e0b..4a4f235 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index fd7e4a7..eb78fd8 100644 (file)
@@ -567,7 +567,7 @@ static void rtl92c_dm_dig(struct ieee80211_hw *hw)
 
        if (rtlpriv->dm.dm_initialgain_enable == false)
                return;
-       if (!rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG)
+       if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
                return;
 
        rtl92c_dm_ctrl_initgain_by_twoport(hw);
index 71ab320..73a49b8 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /* This file implements all the hardware specific functions for the ZD1211
index 7ab9222..b03786c 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_CHIP_H
index 9a1b013..41bd755 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_DEF_H
index c6208a7..eff79a3 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/netdevice.h>
index c01eca8..5a48423 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_MAC_H
index c875ee0..dc179c4 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/errno.h>
index 725b7c9..8f14e25 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_RF_H
index 12babcb..99aed7d 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 385c670..5fea485 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 784d9cc..a93f657 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index c4d324e..61b9240 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 84d94f5..a912dc0 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 45e3bb2..a9075f2 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_USB_H
index 85f9009..1d78605 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 696e346..df85cd3 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 72fafec..2d1395b 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 970ded6..f868333 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 64b447a..f538641 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_MICROREAD_H_
index 7130864..683671a 100644 (file)
@@ -22,8 +22,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 #include <linux/platform_device.h>
index 2daf04c..3df19e6 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/device.h>
index b158ee1..d6185ff 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index ee67de5..330cd40 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 74cfa0a..51e21a8 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 01020e5..491bf45 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_PN544_H_
index fcdd81b..8598f8e 100644 (file)
@@ -32,6 +32,8 @@ struct ath9k_platform_data {
        u32 gpio_val;
 
        bool is_clk_25mhz;
+       bool tx_gain_buffalo;
+
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
 };
index 713bfd7..5ce1ab9 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _PN544_H_
index 2a628b2..f4f9ee4 100644 (file)
@@ -115,6 +115,9 @@ struct bt_voice {
 #define BT_VOICE_TRANSPARENT                   0x0003
 #define BT_VOICE_CVSD_16BIT                    0x0060
 
+#define BT_SNDMTU              12
+#define BT_RCVMTU              13
+
 __printf(1, 2)
 int bt_info(const char *fmt, ...);
 __printf(1, 2)
index 1784c48..cc2da73 100644 (file)
@@ -275,6 +275,12 @@ enum {
 #define LMP_EXTFEATURES        0x80
 
 /* Extended LMP features */
+#define LMP_CSB_MASTER 0x01
+#define LMP_CSB_SLAVE  0x02
+#define LMP_SYNC_TRAIN 0x04
+#define LMP_SYNC_SCAN  0x08
+
+/* Host features */
 #define LMP_HOST_SSP           0x01
 #define LMP_HOST_LE            0x02
 #define LMP_HOST_LE_BREDR      0x04
index f8555ad..b796161 100644 (file)
@@ -798,6 +798,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
 
 /* ----- Extended LMP capabilities ----- */
+#define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
+#define lmp_csb_slave_capable(dev)  ((dev)->features[2][0] & LMP_CSB_SLAVE)
+#define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN)
+#define lmp_sync_scan_capable(dev)  ((dev)->features[2][0] & LMP_SYNC_SCAN)
+
+/* ----- Host capabilities ----- */
 #define lmp_host_ssp_capable(dev)  ((dev)->features[1][0] & LMP_HOST_SSP)
 #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
 #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
index c853b16..e149e99 100644 (file)
@@ -112,6 +112,9 @@ struct l2cap_conninfo {
 #define L2CAP_MOVE_CHAN_CFM_RSP        0x11
 #define L2CAP_CONN_PARAM_UPDATE_REQ    0x12
 #define L2CAP_CONN_PARAM_UPDATE_RSP    0x13
+#define L2CAP_LE_CONN_REQ      0x14
+#define L2CAP_LE_CONN_RSP      0x15
+#define L2CAP_LE_CREDITS       0x16
 
 /* L2CAP extended feature mask */
 #define L2CAP_FEAT_FLOWCTL     0x00000001
@@ -249,6 +252,7 @@ struct l2cap_conn_rsp {
 #define L2CAP_CID_SMP          0x0006
 #define L2CAP_CID_DYN_START    0x0040
 #define L2CAP_CID_DYN_END      0xffff
+#define L2CAP_CID_LE_DYN_END   0x007f
 
 /* connect/create channel results */
 #define L2CAP_CR_SUCCESS       0x0000
@@ -257,6 +261,10 @@ struct l2cap_conn_rsp {
 #define L2CAP_CR_SEC_BLOCK     0x0003
 #define L2CAP_CR_NO_MEM                0x0004
 #define L2CAP_CR_BAD_AMP       0x0005
+#define L2CAP_CR_AUTHENTICATION        0x0005
+#define L2CAP_CR_AUTHORIZATION 0x0006
+#define L2CAP_CR_BAD_KEY_SIZE  0x0007
+#define L2CAP_CR_ENCRYPTION    0x0008
 
 /* connect/create channel status */
 #define L2CAP_CS_NO_INFO       0x0000
@@ -321,6 +329,12 @@ struct l2cap_conf_rfc {
 #define L2CAP_MODE_ERTM                0x03
 #define L2CAP_MODE_STREAMING   0x04
 
+/* Unlike the above this one doesn't actually map to anything that would
+ * ever be sent over the air. Therefore, use a value that's unlikely to
+ * ever be used in the BR/EDR configuration phase.
+ */
+#define L2CAP_MODE_LE_FLOWCTL  0x80
+
 struct l2cap_conf_efs {
        __u8    id;
        __u8    stype;
@@ -423,6 +437,30 @@ struct l2cap_conn_param_update_rsp {
 #define L2CAP_CONN_PARAM_ACCEPTED      0x0000
 #define L2CAP_CONN_PARAM_REJECTED      0x0001
 
+#define L2CAP_LE_MAX_CREDITS           10
+#define L2CAP_LE_DEFAULT_MPS           230
+
+struct l2cap_le_conn_req {
+       __le16     psm;
+       __le16     scid;
+       __le16     mtu;
+       __le16     mps;
+       __le16     credits;
+} __packed;
+
+struct l2cap_le_conn_rsp {
+       __le16     dcid;
+       __le16     mtu;
+       __le16     mps;
+       __le16     credits;
+       __le16     result;
+} __packed;
+
+struct l2cap_le_credits {
+       __le16     cid;
+       __le16     credits;
+} __packed;
+
 /* ----- L2CAP channels and connections ----- */
 struct l2cap_seq_list {
        __u16   head;
@@ -477,6 +515,9 @@ struct l2cap_chan {
        __u16           monitor_timeout;
        __u16           mps;
 
+       __u16           tx_credits;
+       __u16           rx_credits;
+
        __u8            tx_state;
        __u8            rx_state;
 
@@ -553,6 +594,7 @@ struct l2cap_ops {
        void                    (*ready) (struct l2cap_chan *chan);
        void                    (*defer) (struct l2cap_chan *chan);
        void                    (*resume) (struct l2cap_chan *chan);
+       void                    (*suspend) (struct l2cap_chan *chan);
        void                    (*set_shutdown) (struct l2cap_chan *chan);
        long                    (*get_sndtimeo) (struct l2cap_chan *chan);
        struct sk_buff          *(*alloc_skb) (struct l2cap_chan *chan,
@@ -654,6 +696,7 @@ enum {
        FLAG_EXT_CTRL,
        FLAG_EFS_ENABLE,
        FLAG_DEFER_SETUP,
+       FLAG_LE_CONN_REQ_SENT,
 };
 
 enum {
@@ -809,11 +852,13 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
 }
 
 extern bool disable_ertm;
+extern bool enable_lecoc;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 bool l2cap_is_socket(struct socket *sock);
 
+void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan);
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
index e9abc7b..80a1021 100644 (file)
@@ -747,6 +747,8 @@ enum station_parameters_apply_mask {
  * @supported_channels_len: number of supported channels
  * @supported_oper_classes: supported oper classes in IEEE 802.11 format
  * @supported_oper_classes_len: number of supported operating classes
+ * @opmode_notif: operating mode field from Operating Mode Notification
+ * @opmode_notif_used: information if operating mode field is used
  */
 struct station_parameters {
        const u8 *supported_rates;
@@ -770,6 +772,8 @@ struct station_parameters {
        u8 supported_channels_len;
        const u8 *supported_oper_classes;
        u8 supported_oper_classes_len;
+       u8 opmode_notif;
+       bool opmode_notif_used;
 };
 
 /**
@@ -1762,7 +1766,8 @@ enum wiphy_params_flags {
 struct cfg80211_bitrate_mask {
        struct {
                u32 legacy;
-               u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+               u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
+               u16 vht_mcs[NL80211_VHT_NSS_MAX];
        } control[IEEE80211_NUM_BANDS];
 };
 /**
@@ -2676,6 +2681,34 @@ struct wiphy_coalesce_support {
 };
 
 /**
+ * enum wiphy_vendor_command_flags - validation flags for vendor commands
+ * @WIPHY_VENDOR_CMD_NEED_WDEV: vendor command requires wdev
+ * @WIPHY_VENDOR_CMD_NEED_NETDEV: vendor command requires netdev
+ * @WIPHY_VENDOR_CMD_NEED_RUNNING: interface/wdev must be up & running
+ *     (must be combined with %_WDEV or %_NETDEV)
+ */
+enum wiphy_vendor_command_flags {
+       WIPHY_VENDOR_CMD_NEED_WDEV = BIT(0),
+       WIPHY_VENDOR_CMD_NEED_NETDEV = BIT(1),
+       WIPHY_VENDOR_CMD_NEED_RUNNING = BIT(2),
+};
+
+/**
+ * struct wiphy_vendor_command - vendor command definition
+ * @info: vendor command identifying information, as used in nl80211
+ * @flags: flags, see &enum wiphy_vendor_command_flags
+ * @doit: callback for the operation, note that wdev is %NULL if the
+ *     flags didn't ask for a wdev and non-%NULL otherwise; the data
+ *     pointer may be %NULL if userspace provided no data at all
+ */
+struct wiphy_vendor_command {
+       struct nl80211_vendor_cmd_info info;
+       u32 flags;
+       int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev,
+                   const void *data, int data_len);
+};
+
+/**
  * struct wiphy - wireless hardware description
  * @reg_notifier: the driver's regulatory notification callback,
  *     note that if your driver uses wiphy_apply_custom_regulatory()
@@ -2788,6 +2821,9 @@ struct wiphy_coalesce_support {
  * @extended_capabilities_mask: mask of the valid values
  * @extended_capabilities_len: length of the extended capabilities
  * @coalesce: packet coalescing support information
+ *
+ * @vendor_commands: array of vendor commands supported by the hardware
+ * @n_vendor_commands: number of vendor commands
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -2899,6 +2935,9 @@ struct wiphy {
 
        const struct wiphy_coalesce_support *coalesce;
 
+       const struct wiphy_vendor_command *vendor_commands;
+       int n_vendor_commands;
+
        char priv[0] __aligned(NETDEV_ALIGN);
 };
 
@@ -3843,6 +3882,75 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy);
  */
 void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
 
+/**
+ * DOC: Vendor commands
+ *
+ * Occasionally, there are special protocol or firmware features that
+ * can't be implemented very openly. For this and similar cases, the
+ * vendor command functionality allows implementing the features with
+ * (typically closed-source) userspace and firmware, using nl80211 as
+ * the configuration mechanism.
+ *
+ * A driver supporting vendor commands must register them as an array
+ * in struct wiphy, with handlers for each one, each command has an
+ * OUI and sub command ID to identify it.
+ *
+ * Note that this feature should not be (ab)used to implement protocol
+ * features that could openly be shared across drivers. In particular,
+ * it must never be required to use vendor commands to implement any
+ * "normal" functionality that higher-level userspace like connection
+ * managers etc. need.
+ */
+
+struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int approxlen);
+
+/**
+ * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ *     be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * a vendor command. Since it is intended for a reply, calling
+ * it outside of a vendor command's doit() operation is invalid.
+ *
+ * The returned skb is pre-filled with some identifying data in
+ * a way that any data that is put into the skb (with skb_put(),
+ * nla_put() or similar) will end up being within the
+ * %NL80211_ATTR_VENDOR_DATA attribute, so all that needs to be done
+ * with the skb is adding data for the corresponding userspace tool
+ * which can then read that data out of the vendor data attribute.
+ * You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_vendor_cmd_reply() with the skb and return
+ * its error code as the result of the doit() operation.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
+ */
+static inline struct sk_buff *
+cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
+{
+       return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_VENDOR,
+                                         NL80211_ATTR_VENDOR_DATA, approxlen);
+}
+
+/**
+ * cfg80211_vendor_cmd_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ *     cfg80211_vendor_cmd_alloc_reply_skb()
+ *
+ * Since calling this function will usually be the last thing
+ * before returning from the vendor command doit() you should
+ * return the error code.  Note that this function consumes the
+ * skb regardless of the return value.
+ *
+ * Return: An error code or 0 on success.
+ */
+int cfg80211_vendor_cmd_reply(struct sk_buff *skb);
+
 #ifdef CONFIG_NL80211_TESTMODE
 /**
  * DOC: Test mode
@@ -3878,8 +3986,12 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
  *
  * Return: An allocated and pre-filled skb. %NULL if any errors happen.
  */
-struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
-                                                 int approxlen);
+static inline struct sk_buff *
+cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
+{
+       return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_TESTMODE,
+                                         NL80211_ATTR_TESTDATA, approxlen);
+}
 
 /**
  * cfg80211_testmode_reply - send the reply skb
@@ -3893,7 +4005,10 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
  *
  * Return: An error code or 0 on success.
  */
-int cfg80211_testmode_reply(struct sk_buff *skb);
+static inline int cfg80211_testmode_reply(struct sk_buff *skb)
+{
+       return cfg80211_vendor_cmd_reply(skb);
+}
 
 /**
  * cfg80211_testmode_alloc_event_skb - allocate testmode event
index 3cd408b..531785f 100644 (file)
@@ -1163,6 +1163,19 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
 }
 
 /**
+ * wdev_to_ieee80211_vif - return a vif struct from a wdev
+ * @wdev: the wdev to get the vif for
+ *
+ * This can be used by mac80211 drivers with direct cfg80211 APIs
+ * (like the vendor commands) that get a wdev.
+ *
+ * Note that this function may return %NULL if the given wdev isn't
+ * associated with a vif that the driver knows about (e.g. monitor
+ * or AP_VLAN interfaces.)
+ */
+struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
+
+/**
  * enum ieee80211_key_flags - key flags
  *
  * These flags are used for communication about keys between the driver
@@ -1600,6 +1613,9 @@ enum ieee80211_hw_flags {
  * @extra_tx_headroom: headroom to reserve in each transmit skb
  *     for use by the driver (e.g. for transmit headers.)
  *
+ * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
+ *     Can be used by drivers to add extra IEs.
+ *
  * @channel_change_time: time (in microseconds) it takes to change channels.
  *
  * @max_signal: Maximum value for signal (rssi) in RX information, used
@@ -1682,6 +1698,7 @@ struct ieee80211_hw {
        void *priv;
        u32 flags;
        unsigned int extra_tx_headroom;
+       unsigned int extra_beacon_tailroom;
        int channel_change_time;
        int vif_data_size;
        int sta_data_size;
@@ -2398,9 +2415,6 @@ enum ieee80211_roc_type {
  *     See the section "Frame filtering" for more information.
  *     This callback must be implemented and can sleep.
  *
- * @set_multicast_list: Configure the device's interface specific RX multicast
- *     filter. This callback is optional. This callback must be atomic.
- *
  * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
  *     must be set or cleared for a given STA. Must be atomic.
  *
@@ -2485,7 +2499,11 @@ enum ieee80211_roc_type {
  *     AP, IBSS/WDS/mesh peer etc. This callback can sleep.
  *
  * @sta_remove: Notifies low level driver about removal of an associated
- *     station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
+ *     station, AP, IBSS/WDS/mesh peer etc. Note that after the callback
+ *     returns it isn't safe to use the pointer, not even RCU protected;
+ *     no RCU grace period is guaranteed between returning here and freeing
+ *     the station. See @sta_pre_rcu_remove if needed.
+ *     This callback can sleep.
  *
  * @sta_add_debugfs: Drivers can use this callback to add debugfs files
  *     when a station is added to mac80211's station list. This callback
@@ -2504,7 +2522,17 @@ enum ieee80211_roc_type {
  *     station (which can be the AP, a client, IBSS/WDS/mesh peer etc.)
  *     This callback is mutually exclusive with @sta_add/@sta_remove.
  *     It must not fail for down transitions but may fail for transitions
- *     up the list of states.
+ *     up the list of states. Also note that after the callback returns it
+ *     isn't safe to use the pointer, not even RCU protected - no RCU grace
+ *     period is guaranteed between returning here and freeing the station.
+ *     See @sta_pre_rcu_remove if needed.
+ *     The callback can sleep.
+ *
+ * @sta_pre_rcu_remove: Notify driver about station removal before RCU
+ *     synchronisation. This is useful if a driver needs to have station
+ *     pointers protected using RCU, it can then use this call to clear
+ *     the pointers instead of waiting for an RCU grace period to elapse
+ *     in @sta_state.
  *     The callback can sleep.
  *
  * @sta_rc_update: Notifies the driver of changes to the bitrates that can be
@@ -2764,10 +2792,6 @@ struct ieee80211_ops {
                                 unsigned int changed_flags,
                                 unsigned int *total_flags,
                                 u64 multicast);
-       void (*set_multicast_list)(struct ieee80211_hw *hw,
-                                  struct ieee80211_vif *vif, bool allmulti,
-                                  struct netdev_hw_addr_list *mc_list);
-
        int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
                       bool set);
        int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -2821,6 +2845,9 @@ struct ieee80211_ops {
                         struct ieee80211_sta *sta,
                         enum ieee80211_sta_state old_state,
                         enum ieee80211_sta_state new_state);
+       void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_sta *sta);
        void (*sta_rc_update)(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif,
                              struct ieee80211_sta *sta,
index 129b7b0..e130790 100644 (file)
  *     other station that transmission must be blocked until the channel
  *     switch is complete.
  *
+ * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified
+ *     by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in
+ *     %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in
+ *     %NL80211_ATTR_VENDOR_DATA.
+ *     For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is
+ *     used in the wiphy data as a nested attribute containing descriptions
+ *     (&struct nl80211_vendor_cmd_info) of the supported vendor commands.
+ *     This may also be sent as an event with the same attributes.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -860,6 +869,8 @@ enum nl80211_commands {
 
        NL80211_CMD_CHANNEL_SWITCH,
 
+       NL80211_CMD_VENDOR,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -1520,6 +1531,16 @@ enum nl80211_commands {
  * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
  *     10 MHz channel bandwidth.
  *
+ * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
+ *     Notification Element based on association request when used with
+ *     %NL80211_CMD_NEW_STATION; u8 attribute.
+ *
+ * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
+ *     %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
+ * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command
+ * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this
+ *     attribute is also used for vendor command feature advertisement
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1839,6 +1860,12 @@ enum nl80211_attrs {
        NL80211_ATTR_SUPPORT_5_MHZ,
        NL80211_ATTR_SUPPORT_10_MHZ,
 
+       NL80211_ATTR_OPMODE_NOTIF,
+
+       NL80211_ATTR_VENDOR_ID,
+       NL80211_ATTR_VENDOR_SUBCMD,
+       NL80211_ATTR_VENDOR_DATA,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -3083,21 +3110,35 @@ enum nl80211_key_attributes {
  *     in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
  *     1 = 500 kbps) but without the IE length restriction (at most
  *     %NL80211_MAX_SUPP_RATES in a single array).
- * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection
+ * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection
  *     in an array of MCS numbers.
+ * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
+ *     see &struct nl80211_txrate_vht
  * @__NL80211_TXRATE_AFTER_LAST: internal
  * @NL80211_TXRATE_MAX: highest TX rate attribute
  */
 enum nl80211_tx_rate_attributes {
        __NL80211_TXRATE_INVALID,
        NL80211_TXRATE_LEGACY,
-       NL80211_TXRATE_MCS,
+       NL80211_TXRATE_HT,
+       NL80211_TXRATE_VHT,
 
        /* keep last */
        __NL80211_TXRATE_AFTER_LAST,
        NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
 };
 
+#define NL80211_TXRATE_MCS NL80211_TXRATE_HT
+#define NL80211_VHT_NSS_MAX            8
+
+/**
+ * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap
+ * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
+ */
+struct nl80211_txrate_vht {
+       __u16 mcs[NL80211_VHT_NSS_MAX];
+};
+
 /**
  * enum nl80211_band - Frequency band
  * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
@@ -3959,4 +4000,24 @@ enum nl80211_rxmgmt_flags {
        NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
 };
 
+/*
+ * If this flag is unset, the lower 24 bits are an OUI, if set
+ * a Linux nl80211 vendor ID is used (no such IDs are allocated
+ * yet, so that's not valid so far)
+ */
+#define NL80211_VENDOR_ID_IS_LINUX     0x80000000
+
+/**
+ * struct nl80211_vendor_cmd_info - vendor command data
+ * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the
+ *     value is a 24-bit OUI; if it is set then a separately allocated ID
+ *     may be used, but no such IDs are allocated yet. New IDs should be
+ *     added to this file when needed.
+ * @subcmd: sub-command ID for the command
+ */
+struct nl80211_vendor_cmd_info {
+       __u32 vendor_id;
+       __u32 subcmd;
+};
+
 #endif /* __LINUX_NL80211_H */
index 56ca494..0c5866b 100644 (file)
@@ -31,7 +31,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <linux/proc_fs.h>
 
-#define VERSION "2.17"
+#define VERSION "2.18"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO   8
index 6ccc4eb..8b8b5f8 100644 (file)
@@ -1228,7 +1228,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req)
        /* If Connectionless Slave Broadcast master role is supported
         * enable all necessary events for it.
         */
-       if (hdev->features[2][0] & 0x01) {
+       if (lmp_csb_master_capable(hdev)) {
                events[1] |= 0x40;      /* Triggered Clock Capture */
                events[1] |= 0x80;      /* Synchronization Train Complete */
                events[2] |= 0x10;      /* Slave Page Response Timeout */
@@ -1238,7 +1238,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req)
        /* If Connectionless Slave Broadcast slave role is supported
         * enable all necessary events for it.
         */
-       if (hdev->features[2][0] & 0x02) {
+       if (lmp_csb_slave_capable(hdev)) {
                events[2] |= 0x01;      /* Synchronization Train Received */
                events[2] |= 0x02;      /* CSB Receive */
                events[2] |= 0x04;      /* CSB Timeout */
@@ -1275,15 +1275,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
                hci_setup_link_policy(req);
 
        if (lmp_le_capable(hdev)) {
-               /* If the controller has a public BD_ADDR, then by
-                * default use that one. If this is a LE only
-                * controller without one, default to the random
-                * address.
-                */
-               if (bacmp(&hdev->bdaddr, BDADDR_ANY))
-                       hdev->own_addr_type = ADDR_LE_DEV_PUBLIC;
-               else
-                       hdev->own_addr_type = ADDR_LE_DEV_RANDOM;
+               if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
+                       /* If the controller has a public BD_ADDR, then
+                        * by default use that one. If this is a LE only
+                        * controller without a public address, default
+                        * to the random address.
+                        */
+                       if (bacmp(&hdev->bdaddr, BDADDR_ANY))
+                               hdev->own_addr_type = ADDR_LE_DEV_PUBLIC;
+                       else
+                               hdev->own_addr_type = ADDR_LE_DEV_RANDOM;
+               }
 
                hci_set_le_support(req);
        }
@@ -1307,7 +1309,7 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
                hci_set_event_mask_page_2(req);
 
        /* Check for Synchronization Train support */
-       if (hdev->features[2][0] & 0x04)
+       if (lmp_sync_train_capable(hdev))
                hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
 }
 
index 5935f74..5fb3df6 100644 (file)
@@ -486,7 +486,10 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
 
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-       if (!rp->status)
+       if (rp->status)
+               return;
+
+       if (test_bit(HCI_SETUP, &hdev->dev_flags))
                memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
 }
 
@@ -538,12 +541,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
 
        if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
                hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
-
-       BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
-              hdev->features[0][0], hdev->features[0][1],
-              hdev->features[0][2], hdev->features[0][3],
-              hdev->features[0][4], hdev->features[0][5],
-              hdev->features[0][6], hdev->features[0][7]);
 }
 
 static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
@@ -1782,7 +1779,9 @@ static u8 hci_to_mgmt_reason(u8 err)
 static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_disconn_complete *ev = (void *) skb->data;
+       u8 reason = hci_to_mgmt_reason(ev->reason);
        struct hci_conn *conn;
+       u8 type;
 
        BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -1792,43 +1791,38 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (!conn)
                goto unlock;
 
-       if (ev->status == 0)
-               conn->state = BT_CLOSED;
+       if (ev->status) {
+               mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
+                                      conn->dst_type, ev->status);
+               goto unlock;
+       }
 
-       if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
-           (conn->type == ACL_LINK || conn->type == LE_LINK)) {
-               if (ev->status) {
-                       mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
-                                              conn->dst_type, ev->status);
-               } else {
-                       u8 reason = hci_to_mgmt_reason(ev->reason);
+       conn->state = BT_CLOSED;
 
-                       mgmt_device_disconnected(hdev, &conn->dst, conn->type,
-                                                conn->dst_type, reason);
-               }
-       }
+       if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_disconnected(hdev, &conn->dst, conn->type,
+                                        conn->dst_type, reason);
 
-       if (ev->status == 0) {
-               u8 type = conn->type;
+       if (conn->type == ACL_LINK && conn->flush_key)
+               hci_remove_link_key(hdev, &conn->dst);
 
-               if (type == ACL_LINK && conn->flush_key)
-                       hci_remove_link_key(hdev, &conn->dst);
-               hci_proto_disconn_cfm(conn, ev->reason);
-               hci_conn_del(conn);
+       type = conn->type;
 
-               /* Re-enable advertising if necessary, since it might
-                * have been disabled by the connection. From the
-                * HCI_LE_Set_Advertise_Enable command description in
-                * the core specification (v4.0):
-                * "The Controller shall continue advertising until the Host
-                * issues an LE_Set_Advertise_Enable command with
-                * Advertising_Enable set to 0x00 (Advertising is disabled)
-                * or until a connection is created or until the Advertising
-                * is timed out due to Directed Advertising."
-                */
-               if (type == LE_LINK)
-                       mgmt_reenable_advertising(hdev);
-       }
+       hci_proto_disconn_cfm(conn, ev->reason);
+       hci_conn_del(conn);
+
+       /* Re-enable advertising if necessary, since it might
+        * have been disabled by the connection. From the
+        * HCI_LE_Set_Advertise_Enable command description in
+        * the core specification (v4.0):
+        * "The Controller shall continue advertising until the Host
+        * issues an LE_Set_Advertise_Enable command with
+        * Advertising_Enable set to 0x00 (Advertising is disabled)
+        * or until a connection is created or until the Advertising
+        * is timed out due to Directed Advertising."
+        */
+       if (type == LE_LINK)
+               mgmt_reenable_advertising(hdev);
 
 unlock:
        hci_dev_unlock(hdev);
index 4af3821..b6bca64 100644 (file)
@@ -49,6 +49,9 @@ static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
 static LIST_HEAD(chan_list);
 static DEFINE_RWLOCK(chan_list_lock);
 
+static u16 le_max_credits = L2CAP_LE_MAX_CREDITS;
+static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS;
+
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
                                       u8 code, u8 ident, u16 dlen, void *data);
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
@@ -213,9 +216,14 @@ int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 
 static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 {
-       u16 cid = L2CAP_CID_DYN_START;
+       u16 cid, dyn_end;
+
+       if (conn->hcon->type == LE_LINK)
+               dyn_end = L2CAP_CID_LE_DYN_END;
+       else
+               dyn_end = L2CAP_CID_DYN_END;
 
-       for (; cid < L2CAP_CID_DYN_END; cid++) {
+       for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
                if (!__l2cap_get_chan_by_scid(conn, cid))
                        return cid;
        }
@@ -490,6 +498,18 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
        set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
 
+static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
+{
+       chan->sdu = NULL;
+       chan->sdu_last_frag = NULL;
+       chan->sdu_len = 0;
+       chan->tx_credits = 0;
+       chan->rx_credits = le_max_credits;
+       chan->mps = min_t(u16, chan->imtu, L2CAP_LE_DEFAULT_MPS);
+
+       skb_queue_head_init(&chan->tx_q);
+}
+
 void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
@@ -502,12 +522,12 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
        switch (chan->chan_type) {
        case L2CAP_CHAN_CONN_ORIENTED:
                if (conn->hcon->type == LE_LINK) {
-                       /* LE connection */
-                       chan->omtu = L2CAP_DEFAULT_MTU;
-                       if (chan->dcid == L2CAP_CID_ATT)
+                       if (chan->dcid == L2CAP_CID_ATT) {
+                               chan->omtu = L2CAP_DEFAULT_MTU;
                                chan->scid = L2CAP_CID_ATT;
-                       else
+                       } else {
                                chan->scid = l2cap_alloc_cid(conn);
+                       }
                } else {
                        /* Alloc CID for connection-oriented socket */
                        chan->scid = l2cap_alloc_cid(conn);
@@ -597,6 +617,10 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        case L2CAP_MODE_BASIC:
                break;
 
+       case L2CAP_MODE_LE_FLOWCTL:
+               skb_queue_purge(&chan->tx_q);
+               break;
+
        case L2CAP_MODE_ERTM:
                __clear_retrans_timer(chan);
                __clear_monitor_timer(chan);
@@ -617,6 +641,50 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        return;
 }
 
+static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_conn_rsp rsp;
+       u16 result;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+               result = L2CAP_CR_AUTHORIZATION;
+       else
+               result = L2CAP_CR_BAD_PSM;
+
+       l2cap_state_change(chan, BT_DISCONN);
+
+       rsp.dcid    = cpu_to_le16(chan->scid);
+       rsp.mtu     = cpu_to_le16(chan->imtu);
+       rsp.mps     = cpu_to_le16(chan->mps);
+       rsp.credits = cpu_to_le16(chan->rx_credits);
+       rsp.result  = cpu_to_le16(result);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
+                      &rsp);
+}
+
+static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_conn_rsp rsp;
+       u16 result;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+               result = L2CAP_CR_SEC_BLOCK;
+       else
+               result = L2CAP_CR_BAD_PSM;
+
+       l2cap_state_change(chan, BT_DISCONN);
+
+       rsp.scid   = cpu_to_le16(chan->dcid);
+       rsp.dcid   = cpu_to_le16(chan->scid);
+       rsp.result = cpu_to_le16(result);
+       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+}
+
 void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 {
        struct l2cap_conn *conn = chan->conn;
@@ -630,8 +698,10 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 
        case BT_CONNECTED:
        case BT_CONFIG:
-               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                   conn->hcon->type == ACL_LINK) {
+               /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
+                * check for chan->psm.
+                */
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
                        __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
                        l2cap_send_disconn_req(chan, reason);
                } else
@@ -639,24 +709,11 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                break;
 
        case BT_CONNECT2:
-               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                   conn->hcon->type == ACL_LINK) {
-                       struct l2cap_conn_rsp rsp;
-                       __u16 result;
-
-                       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-                               result = L2CAP_CR_SEC_BLOCK;
-                       else
-                               result = L2CAP_CR_BAD_PSM;
-
-                       l2cap_state_change(chan, BT_DISCONN);
-
-                       rsp.scid   = cpu_to_le16(chan->dcid);
-                       rsp.dcid   = cpu_to_le16(chan->scid);
-                       rsp.result = cpu_to_le16(result);
-                       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
-                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                      sizeof(rsp), &rsp);
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
+                       if (conn->hcon->type == ACL_LINK)
+                               l2cap_chan_connect_reject(chan);
+                       else if (conn->hcon->type == LE_LINK)
+                               l2cap_chan_le_connect_reject(chan);
                }
 
                l2cap_chan_del(chan, reason);
@@ -726,6 +783,9 @@ int l2cap_chan_check_security(struct l2cap_chan *chan)
        struct l2cap_conn *conn = chan->conn;
        __u8 auth_type;
 
+       if (conn->hcon->type == LE_LINK)
+               return smp_conn_security(conn->hcon, chan->sec_level);
+
        auth_type = l2cap_get_auth_type(chan);
 
        return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
@@ -1152,16 +1212,57 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
        chan->conf_state = 0;
        __clear_chan_timer(chan);
 
+       if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits)
+               chan->ops->suspend(chan);
+
        chan->state = BT_CONNECTED;
 
        chan->ops->ready(chan);
 }
 
+static void l2cap_le_connect(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_conn_req req;
+
+       if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       req.psm     = chan->psm;
+       req.scid    = cpu_to_le16(chan->scid);
+       req.mtu     = cpu_to_le16(chan->imtu);
+       req.mps     = cpu_to_le16(chan->mps);
+       req.credits = cpu_to_le16(chan->rx_credits);
+
+       chan->ident = l2cap_get_ident(conn);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
+                      sizeof(req), &req);
+}
+
+static void l2cap_le_start(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+
+       if (!smp_conn_security(conn->hcon, chan->sec_level))
+               return;
+
+       if (!chan->psm) {
+               l2cap_chan_ready(chan);
+               return;
+       }
+
+       if (chan->state == BT_CONNECT)
+               l2cap_le_connect(chan);
+}
+
 static void l2cap_start_connection(struct l2cap_chan *chan)
 {
        if (__amp_capable(chan)) {
                BT_DBG("chan %p AMP capable: discover AMPs", chan);
                a2mp_discover_amp(chan);
+       } else if (chan->conn->hcon->type == LE_LINK) {
+               l2cap_le_start(chan);
        } else {
                l2cap_send_conn_req(chan);
        }
@@ -1172,7 +1273,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
        struct l2cap_conn *conn = chan->conn;
 
        if (conn->hcon->type == LE_LINK) {
-               l2cap_chan_ready(chan);
+               l2cap_le_start(chan);
                return;
        }
 
@@ -1430,9 +1531,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                }
 
                if (hcon->type == LE_LINK) {
-                       if (smp_conn_security(hcon, chan->sec_level))
-                               l2cap_chan_ready(chan);
-
+                       l2cap_le_start(chan);
                } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
                        l2cap_chan_ready(chan);
 
@@ -1703,7 +1802,8 @@ EXPORT_SYMBOL(l2cap_conn_put);
  */
 static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                                                   bdaddr_t *src,
-                                                  bdaddr_t *dst)
+                                                  bdaddr_t *dst,
+                                                  u8 link_type)
 {
        struct l2cap_chan *c, *c1 = NULL;
 
@@ -1713,6 +1813,12 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                if (state && c->state != state)
                        continue;
 
+               if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
+                       continue;
+
+               if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
+                       continue;
+
                if (c->psm == psm) {
                        int src_match, dst_match;
                        int src_any, dst_any;
@@ -1739,6 +1845,18 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
        return c1;
 }
 
+static bool is_valid_psm(u16 psm, u8 dst_type)
+{
+       if (!psm)
+               return false;
+
+       if (bdaddr_type_is_le(dst_type))
+               return (psm <= 0x00ff);
+
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       return ((psm & 0x0101) == 0x0001);
+}
+
 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                       bdaddr_t *dst, u8 dst_type)
 {
@@ -1759,8 +1877,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 
        l2cap_chan_lock(chan);
 
-       /* PSM must be odd and lsb of upper byte must be 0 */
-       if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
+       if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
            chan->chan_type != L2CAP_CHAN_RAW) {
                err = -EINVAL;
                goto done;
@@ -1774,6 +1891,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
        switch (chan->mode) {
        case L2CAP_MODE_BASIC:
                break;
+       case L2CAP_MODE_LE_FLOWCTL:
+               l2cap_le_flowctl_init(chan);
+               break;
        case L2CAP_MODE_ERTM:
        case L2CAP_MODE_STREAMING:
                if (!disable_ertm)
@@ -2432,6 +2552,89 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
        return 0;
 }
 
+static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
+                                                  struct msghdr *msg,
+                                                  size_t len, u16 sdulen)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct sk_buff *skb;
+       int err, count, hlen;
+       struct l2cap_hdr *lh;
+
+       BT_DBG("chan %p len %zu", chan, len);
+
+       if (!conn)
+               return ERR_PTR(-ENOTCONN);
+
+       hlen = L2CAP_HDR_SIZE;
+
+       if (sdulen)
+               hlen += L2CAP_SDULEN_SIZE;
+
+       count = min_t(unsigned int, (conn->mtu - hlen), len);
+
+       skb = chan->ops->alloc_skb(chan, count + hlen,
+                                  msg->msg_flags & MSG_DONTWAIT);
+       if (IS_ERR(skb))
+               return skb;
+
+       /* Create L2CAP header */
+       lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+       lh->cid = cpu_to_le16(chan->dcid);
+       lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+
+       if (sdulen)
+               put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
+
+       err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
+       if (unlikely(err < 0)) {
+               kfree_skb(skb);
+               return ERR_PTR(err);
+       }
+
+       return skb;
+}
+
+static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
+                               struct sk_buff_head *seg_queue,
+                               struct msghdr *msg, size_t len)
+{
+       struct sk_buff *skb;
+       size_t pdu_len;
+       u16 sdu_len;
+
+       BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
+
+       pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE;
+
+       pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
+
+       sdu_len = len;
+       pdu_len -= L2CAP_SDULEN_SIZE;
+
+       while (len > 0) {
+               if (len <= pdu_len)
+                       pdu_len = len;
+
+               skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
+               if (IS_ERR(skb)) {
+                       __skb_queue_purge(seg_queue);
+                       return PTR_ERR(skb);
+               }
+
+               __skb_queue_tail(seg_queue, skb);
+
+               len -= pdu_len;
+
+               if (sdu_len) {
+                       sdu_len = 0;
+                       pdu_len += L2CAP_SDULEN_SIZE;
+               }
+       }
+
+       return 0;
+}
+
 int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
                    u32 priority)
 {
@@ -2453,6 +2656,40 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
        }
 
        switch (chan->mode) {
+       case L2CAP_MODE_LE_FLOWCTL:
+               /* Check outgoing MTU */
+               if (len > chan->omtu)
+                       return -EMSGSIZE;
+
+               if (!chan->tx_credits)
+                       return -EAGAIN;
+
+               __skb_queue_head_init(&seg_queue);
+
+               err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
+
+               if (chan->state != BT_CONNECTED) {
+                       __skb_queue_purge(&seg_queue);
+                       err = -ENOTCONN;
+               }
+
+               if (err)
+                       return err;
+
+               skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
+
+               while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
+                       l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
+                       chan->tx_credits--;
+               }
+
+               if (!chan->tx_credits)
+                       chan->ops->suspend(chan);
+
+               err = len;
+
+               break;
+
        case L2CAP_MODE_BASIC:
                /* Check outgoing MTU */
                if (len > chan->omtu)
@@ -3592,6 +3829,23 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
        return ptr - data;
 }
 
+void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
+{
+       struct l2cap_le_conn_rsp rsp;
+       struct l2cap_conn *conn = chan->conn;
+
+       BT_DBG("chan %p", chan);
+
+       rsp.dcid    = cpu_to_le16(chan->scid);
+       rsp.mtu     = cpu_to_le16(chan->imtu);
+       rsp.mps     = cpu_to_le16(chan->mps);
+       rsp.credits = cpu_to_le16(chan->rx_credits);
+       rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
+                      &rsp);
+}
+
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
 {
        struct l2cap_conn_rsp rsp;
@@ -3713,7 +3967,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
        /* Check if we have socket listening on psm */
        pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
-                                        &conn->hcon->dst);
+                                        &conn->hcon->dst, ACL_LINK);
        if (!pchan) {
                result = L2CAP_CR_BAD_PSM;
                goto sendresp;
@@ -5155,18 +5409,17 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
 
 static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
                                              struct l2cap_cmd_hdr *cmd,
-                                             u8 *data)
+                                             u16 cmd_len, u8 *data)
 {
        struct hci_conn *hcon = conn->hcon;
        struct l2cap_conn_param_update_req *req;
        struct l2cap_conn_param_update_rsp rsp;
-       u16 min, max, latency, to_multiplier, cmd_len;
+       u16 min, max, latency, to_multiplier;
        int err;
 
        if (!(hcon->link_mode & HCI_LM_MASTER))
                return -EINVAL;
 
-       cmd_len = __le16_to_cpu(cmd->len);
        if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
                return -EPROTO;
 
@@ -5196,6 +5449,65 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
        return 0;
 }
 
+static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
+                               struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                               u8 *data)
+{
+       struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
+       u16 dcid, mtu, mps, credits, result;
+       struct l2cap_chan *chan;
+       int err;
+
+       if (cmd_len < sizeof(*rsp))
+               return -EPROTO;
+
+       dcid    = __le16_to_cpu(rsp->dcid);
+       mtu     = __le16_to_cpu(rsp->mtu);
+       mps     = __le16_to_cpu(rsp->mps);
+       credits = __le16_to_cpu(rsp->credits);
+       result  = __le16_to_cpu(rsp->result);
+
+       if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
+               return -EPROTO;
+
+       BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
+              dcid, mtu, mps, credits, result);
+
+       mutex_lock(&conn->chan_lock);
+
+       chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
+       if (!chan) {
+               err = -EBADSLT;
+               goto unlock;
+       }
+
+       err = 0;
+
+       l2cap_chan_lock(chan);
+
+       switch (result) {
+       case L2CAP_CR_SUCCESS:
+               chan->ident = 0;
+               chan->dcid = dcid;
+               chan->omtu = mtu;
+               chan->remote_mps = mps;
+               chan->tx_credits = credits;
+               l2cap_chan_ready(chan);
+               break;
+
+       default:
+               l2cap_chan_del(chan, ECONNREFUSED);
+               break;
+       }
+
+       l2cap_chan_unlock(chan);
+
+unlock:
+       mutex_unlock(&conn->chan_lock);
+
+       return err;
+}
+
 static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
                                      u8 *data)
@@ -5276,23 +5588,235 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
        return err;
 }
 
+static int l2cap_le_connect_req(struct l2cap_conn *conn,
+                               struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                               u8 *data)
+{
+       struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
+       struct l2cap_le_conn_rsp rsp;
+       struct l2cap_chan *chan, *pchan;
+       u16 dcid, scid, credits, mtu, mps;
+       __le16 psm;
+       u8 result;
+
+       if (cmd_len != sizeof(*req))
+               return -EPROTO;
+
+       scid = __le16_to_cpu(req->scid);
+       mtu  = __le16_to_cpu(req->mtu);
+       mps  = __le16_to_cpu(req->mps);
+       psm  = req->psm;
+       dcid = 0;
+       credits = 0;
+
+       if (mtu < 23 || mps < 23)
+               return -EPROTO;
+
+       BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
+              scid, mtu, mps);
+
+       /* Check if we have socket listening on psm */
+       pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
+                                        &conn->hcon->dst, LE_LINK);
+       if (!pchan) {
+               result = L2CAP_CR_BAD_PSM;
+               chan = NULL;
+               goto response;
+       }
+
+       mutex_lock(&conn->chan_lock);
+       l2cap_chan_lock(pchan);
+
+       if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
+               result = L2CAP_CR_AUTHENTICATION;
+               chan = NULL;
+               goto response_unlock;
+       }
+
+       /* Check if we already have channel with that dcid */
+       if (__l2cap_get_chan_by_dcid(conn, scid)) {
+               result = L2CAP_CR_NO_MEM;
+               chan = NULL;
+               goto response_unlock;
+       }
+
+       chan = pchan->ops->new_connection(pchan);
+       if (!chan) {
+               result = L2CAP_CR_NO_MEM;
+               goto response_unlock;
+       }
+
+       l2cap_le_flowctl_init(chan);
+
+       bacpy(&chan->src, &conn->hcon->src);
+       bacpy(&chan->dst, &conn->hcon->dst);
+       chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
+       chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
+       chan->psm  = psm;
+       chan->dcid = scid;
+       chan->omtu = mtu;
+       chan->remote_mps = mps;
+       chan->tx_credits = __le16_to_cpu(req->credits);
+
+       __l2cap_chan_add(conn, chan);
+       dcid = chan->scid;
+       credits = chan->rx_credits;
+
+       __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
+
+       chan->ident = cmd->ident;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
+               l2cap_state_change(chan, BT_CONNECT2);
+               result = L2CAP_CR_PEND;
+               chan->ops->defer(chan);
+       } else {
+               l2cap_chan_ready(chan);
+               result = L2CAP_CR_SUCCESS;
+       }
+
+response_unlock:
+       l2cap_chan_unlock(pchan);
+       mutex_unlock(&conn->chan_lock);
+
+       if (result == L2CAP_CR_PEND)
+               return 0;
+
+response:
+       if (chan) {
+               rsp.mtu = cpu_to_le16(chan->imtu);
+               rsp.mps = cpu_to_le16(chan->mps);
+       } else {
+               rsp.mtu = 0;
+               rsp.mps = 0;
+       }
+
+       rsp.dcid    = cpu_to_le16(dcid);
+       rsp.credits = cpu_to_le16(credits);
+       rsp.result  = cpu_to_le16(result);
+
+       l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
+
+       return 0;
+}
+
+static inline int l2cap_le_credits(struct l2cap_conn *conn,
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
+{
+       struct l2cap_le_credits *pkt;
+       struct l2cap_chan *chan;
+       u16 cid, credits;
+
+       if (cmd_len != sizeof(*pkt))
+               return -EPROTO;
+
+       pkt = (struct l2cap_le_credits *) data;
+       cid     = __le16_to_cpu(pkt->cid);
+       credits = __le16_to_cpu(pkt->credits);
+
+       BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
+
+       chan = l2cap_get_chan_by_dcid(conn, cid);
+       if (!chan)
+               return -EBADSLT;
+
+       chan->tx_credits += credits;
+
+       while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
+               l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
+               chan->tx_credits--;
+       }
+
+       if (chan->tx_credits)
+               chan->ops->resume(chan);
+
+       l2cap_chan_unlock(chan);
+
+       return 0;
+}
+
+static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
+                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                      u8 *data)
+{
+       struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
+       struct l2cap_chan *chan;
+
+       if (cmd_len < sizeof(*rej))
+               return -EPROTO;
+
+       mutex_lock(&conn->chan_lock);
+
+       chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
+       if (!chan)
+               goto done;
+
+       l2cap_chan_lock(chan);
+       l2cap_chan_del(chan, ECONNREFUSED);
+       l2cap_chan_unlock(chan);
+
+done:
+       mutex_unlock(&conn->chan_lock);
+       return 0;
+}
+
 static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
-                                  struct l2cap_cmd_hdr *cmd, u8 *data)
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
 {
+       int err = 0;
+
+       if (!enable_lecoc) {
+               switch (cmd->code) {
+               case L2CAP_LE_CONN_REQ:
+               case L2CAP_LE_CONN_RSP:
+               case L2CAP_LE_CREDITS:
+               case L2CAP_DISCONN_REQ:
+               case L2CAP_DISCONN_RSP:
+                       return -EINVAL;
+               }
+       }
+
        switch (cmd->code) {
        case L2CAP_COMMAND_REJ:
-               return 0;
+               l2cap_le_command_rej(conn, cmd, cmd_len, data);
+               break;
 
        case L2CAP_CONN_PARAM_UPDATE_REQ:
-               return l2cap_conn_param_update_req(conn, cmd, data);
+               err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
+               break;
 
        case L2CAP_CONN_PARAM_UPDATE_RSP:
-               return 0;
+               break;
+
+       case L2CAP_LE_CONN_RSP:
+               l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_LE_CONN_REQ:
+               err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_LE_CREDITS:
+               err = l2cap_le_credits(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_DISCONN_REQ:
+               err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_DISCONN_RSP:
+               l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
+               break;
 
        default:
                BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
-               return -EINVAL;
+               err = -EINVAL;
+               break;
        }
+
+       return err;
 }
 
 static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
@@ -5321,7 +5845,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
                goto drop;
        }
 
-       err = l2cap_le_sig_cmd(conn, cmd, skb->data);
+       err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
        if (err) {
                struct l2cap_cmd_rej_unk rej;
 
@@ -6312,6 +6836,121 @@ drop:
        return 0;
 }
 
+static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_credits pkt;
+       u16 return_credits;
+
+       /* We return more credits to the sender only after the amount of
+        * credits falls below half of the initial amount.
+        */
+       if (chan->rx_credits >= (le_max_credits + 1) / 2)
+               return;
+
+       return_credits = le_max_credits - chan->rx_credits;
+
+       BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
+
+       chan->rx_credits += return_credits;
+
+       pkt.cid     = cpu_to_le16(chan->scid);
+       pkt.credits = cpu_to_le16(return_credits);
+
+       chan->ident = l2cap_get_ident(conn);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
+}
+
+static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+       int err;
+
+       if (!chan->rx_credits) {
+               BT_ERR("No credits to receive LE L2CAP data");
+               return -ENOBUFS;
+       }
+
+       if (chan->imtu < skb->len) {
+               BT_ERR("Too big LE L2CAP PDU");
+               return -ENOBUFS;
+       }
+
+       chan->rx_credits--;
+       BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
+
+       l2cap_chan_le_send_credits(chan);
+
+       err = 0;
+
+       if (!chan->sdu) {
+               u16 sdu_len;
+
+               sdu_len = get_unaligned_le16(skb->data);
+               skb_pull(skb, L2CAP_SDULEN_SIZE);
+
+               BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
+                      sdu_len, skb->len, chan->imtu);
+
+               if (sdu_len > chan->imtu) {
+                       BT_ERR("Too big LE L2CAP SDU length received");
+                       err = -EMSGSIZE;
+                       goto failed;
+               }
+
+               if (skb->len > sdu_len) {
+                       BT_ERR("Too much LE L2CAP data received");
+                       err = -EINVAL;
+                       goto failed;
+               }
+
+               if (skb->len == sdu_len)
+                       return chan->ops->recv(chan, skb);
+
+               chan->sdu = skb;
+               chan->sdu_len = sdu_len;
+               chan->sdu_last_frag = skb;
+
+               return 0;
+       }
+
+       BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
+              chan->sdu->len, skb->len, chan->sdu_len);
+
+       if (chan->sdu->len + skb->len > chan->sdu_len) {
+               BT_ERR("Too much LE L2CAP data received");
+               err = -EINVAL;
+               goto failed;
+       }
+
+       append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
+       skb = NULL;
+
+       if (chan->sdu->len == chan->sdu_len) {
+               err = chan->ops->recv(chan, chan->sdu);
+               if (!err) {
+                       chan->sdu = NULL;
+                       chan->sdu_last_frag = NULL;
+                       chan->sdu_len = 0;
+               }
+       }
+
+failed:
+       if (err) {
+               kfree_skb(skb);
+               kfree_skb(chan->sdu);
+               chan->sdu = NULL;
+               chan->sdu_last_frag = NULL;
+               chan->sdu_len = 0;
+       }
+
+       /* We can't return an error here since we took care of the skb
+        * freeing internally. An error return would cause the caller to
+        * do a double-free of the skb.
+        */
+       return 0;
+}
+
 static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
                               struct sk_buff *skb)
 {
@@ -6341,6 +6980,12 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
                goto drop;
 
        switch (chan->mode) {
+       case L2CAP_MODE_LE_FLOWCTL:
+               if (l2cap_le_data_rcv(chan, skb) < 0)
+                       goto drop;
+
+               goto done;
+
        case L2CAP_MODE_BASIC:
                /* If socket recv buffers overflows we drop data here
                 * which is *bad* because L2CAP has to be reliable.
@@ -6380,7 +7025,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
        if (hcon->type != ACL_LINK)
                goto drop;
 
-       chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst);
+       chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
+                                       ACL_LINK);
        if (!chan)
                goto drop;
 
@@ -6612,11 +7258,10 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                }
 
                if (chan->state == BT_CONNECT) {
-                       if (!status) {
+                       if (!status)
                                l2cap_start_connection(chan);
-                       } else {
+                       else
                                __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-                       }
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
                        __u16 res, stat;
@@ -6817,6 +7462,11 @@ int __init l2cap_init(void)
        l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
                                            NULL, &l2cap_debugfs_fops);
 
+       debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs,
+                          &le_max_credits);
+       debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
+                          &le_default_mps);
+
        return 0;
 }
 
index 7cc24d2..e7806e6 100644 (file)
@@ -27,6 +27,7 @@
 
 /* Bluetooth L2CAP sockets. */
 
+#include <linux/module.h>
 #include <linux/export.h>
 
 #include <net/bluetooth/bluetooth.h>
@@ -35,6 +36,8 @@
 
 #include "smp.h"
 
+bool enable_lecoc;
+
 static struct bt_sock_list l2cap_sk_list = {
        .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
 };
@@ -50,6 +53,32 @@ bool l2cap_is_socket(struct socket *sock)
 }
 EXPORT_SYMBOL(l2cap_is_socket);
 
+static int l2cap_validate_bredr_psm(u16 psm)
+{
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       if ((psm & 0x0101) != 0x0001)
+               return -EINVAL;
+
+       /* Restrict usage of well-known PSMs */
+       if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       return 0;
+}
+
+static int l2cap_validate_le_psm(u16 psm)
+{
+       /* Valid LE_PSM ranges are defined only until 0x00ff */
+       if (psm > 0x00ff)
+               return -EINVAL;
+
+       /* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */
+       if (psm <= 0x007f && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       return 0;
+}
+
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
        struct sock *sk = sock->sk;
@@ -73,11 +102,11 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
                return -EINVAL;
 
        if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
-               /* Connection oriented channels are not supported on LE */
-               if (la.l2_psm)
+               if (!enable_lecoc && la.l2_psm)
                        return -EINVAL;
                /* We only allow ATT user space socket */
-               if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+               if (la.l2_cid &&
+                   la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
                        return -EINVAL;
        }
 
@@ -91,17 +120,13 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        if (la.l2_psm) {
                __u16 psm = __le16_to_cpu(la.l2_psm);
 
-               /* PSM must be odd and lsb of upper byte must be 0 */
-               if ((psm & 0x0101) != 0x0001) {
-                       err = -EINVAL;
-                       goto done;
-               }
+               if (la.l2_bdaddr_type == BDADDR_BREDR)
+                       err = l2cap_validate_bredr_psm(psm);
+               else
+                       err = l2cap_validate_le_psm(psm);
 
-               /* Restrict usage of well-known PSMs */
-               if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
-                       err = -EACCES;
+               if (err)
                        goto done;
-               }
        }
 
        if (la.l2_cid)
@@ -127,6 +152,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        bacpy(&chan->src, &la.l2_bdaddr);
        chan->src_type = la.l2_bdaddr_type;
 
+       if (chan->psm && bdaddr_type_is_le(chan->src_type))
+               chan->mode = L2CAP_MODE_LE_FLOWCTL;
+
        chan->state = BT_BOUND;
        sk->sk_state = BT_BOUND;
 
@@ -189,14 +217,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
                return -EINVAL;
 
        if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
-               /* Connection oriented channels are not supported on LE */
-               if (la.l2_psm)
+               if (!enable_lecoc && la.l2_psm)
                        return -EINVAL;
                /* We only allow ATT user space socket */
-               if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+               if (la.l2_cid &&
+                   la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
                        return -EINVAL;
        }
 
+       if (chan->psm && bdaddr_type_is_le(chan->src_type))
+               chan->mode = L2CAP_MODE_LE_FLOWCTL;
+
        err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
                                 &la.l2_bdaddr, la.l2_bdaddr_type);
        if (err)
@@ -234,6 +265,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 
        switch (chan->mode) {
        case L2CAP_MODE_BASIC:
+       case L2CAP_MODE_LE_FLOWCTL:
                break;
        case L2CAP_MODE_ERTM:
        case L2CAP_MODE_STREAMING:
@@ -360,6 +392,16 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               /* LE sockets should use BT_SNDMTU/BT_RCVMTU, but since
+                * legacy ATT code depends on getsockopt for
+                * L2CAP_OPTIONS we need to let this pass.
+                */
+               if (bdaddr_type_is_le(chan->src_type) &&
+                   chan->scid != L2CAP_CID_ATT) {
+                       err = -EINVAL;
+                       break;
+               }
+
                memset(&opts, 0, sizeof(opts));
                opts.imtu     = chan->imtu;
                opts.omtu     = chan->omtu;
@@ -514,6 +556,41 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
                        err = -EFAULT;
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state != BT_CONNECTED) {
+                       err = -ENOTCONN;
+                       break;
+               }
+
+               if (put_user(chan->omtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (put_user(chan->imtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -554,6 +631,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               if (bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
                if (sk->sk_state == BT_CONNECTED) {
                        err = -EINVAL;
                        break;
@@ -585,6 +667,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
 
                chan->mode = opts.mode;
                switch (chan->mode) {
+               case L2CAP_MODE_LE_FLOWCTL:
+                       break;
                case L2CAP_MODE_BASIC:
                        clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
                        break;
@@ -807,6 +891,47 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               /* Setting is not supported as it's the remote side that
+                * decides this.
+                */
+               err = -EPERM;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state == BT_CONNECTED) {
+                       err = -EISCONN;
+                       break;
+               }
+
+               if (get_user(opt, (u32 __user *) optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               chan->imtu = opt;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -859,10 +984,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
                                                    &bt_sk(sk)->flags)) {
-               sk->sk_state = BT_CONFIG;
-               pi->chan->state = BT_CONFIG;
+               if (bdaddr_type_is_le(pi->chan->src_type)) {
+                       sk->sk_state = BT_CONNECTED;
+                       pi->chan->state = BT_CONNECTED;
+                       __l2cap_le_connect_rsp_defer(pi->chan);
+               } else {
+                       sk->sk_state = BT_CONFIG;
+                       pi->chan->state = BT_CONFIG;
+                       __l2cap_connect_rsp_defer(pi->chan);
+               }
 
-               __l2cap_connect_rsp_defer(pi->chan);
                err = 0;
                goto done;
        }
@@ -1236,6 +1367,14 @@ static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan)
        return sk->sk_sndtimeo;
 }
 
+static void l2cap_sock_suspend_cb(struct l2cap_chan *chan)
+{
+       struct sock *sk = chan->data;
+
+       set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
+       sk->sk_state_change(sk);
+}
+
 static struct l2cap_ops l2cap_chan_ops = {
        .name           = "L2CAP Socket Interface",
        .new_connection = l2cap_sock_new_connection_cb,
@@ -1246,6 +1385,7 @@ static struct l2cap_ops l2cap_chan_ops = {
        .ready          = l2cap_sock_ready_cb,
        .defer          = l2cap_sock_defer_cb,
        .resume         = l2cap_sock_resume_cb,
+       .suspend        = l2cap_sock_suspend_cb,
        .set_shutdown   = l2cap_sock_set_shutdown_cb,
        .get_sndtimeo   = l2cap_sock_get_sndtimeo_cb,
        .alloc_skb      = l2cap_sock_alloc_skb_cb,
@@ -1303,6 +1443,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->tx_win_max = pchan->tx_win_max;
                chan->sec_level = pchan->sec_level;
                chan->flags = pchan->flags;
+               chan->tx_credits = pchan->tx_credits;
+               chan->rx_credits = pchan->rx_credits;
 
                security_sk_clone(parent, sk);
        } else {
@@ -1469,3 +1611,6 @@ void l2cap_cleanup_sockets(void)
        bt_sock_unregister(BTPROTO_L2CAP);
        proto_unregister(&l2cap_proto);
 }
+
+module_param(enable_lecoc, bool, 0644);
+MODULE_PARM_DESC(enable_lecoc, "Enable support for LE CoC");
index 074d836..a03ca3c 100644 (file)
@@ -1264,7 +1264,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 
                if (cp->val == 0x02) {
                        /* Limited discoverable mode */
-                       hci_cp.num_iac = 2;
+                       hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
                        hci_cp.iac_lap[0] = 0x00;       /* LIAC */
                        hci_cp.iac_lap[1] = 0x8b;
                        hci_cp.iac_lap[2] = 0x9e;
@@ -4595,6 +4595,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
        struct mgmt_ev_device_disconnected ev;
        struct sock *sk = NULL;
 
+       if (link_type != ACL_LINK && link_type != LE_LINK)
+               return;
+
        mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
 
        bacpy(&ev.addr.bdaddr, bdaddr);
@@ -4613,6 +4616,8 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
                            u8 link_type, u8 addr_type, u8 status)
 {
+       u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
+       struct mgmt_cp_disconnect *cp;
        struct mgmt_rp_disconnect rp;
        struct pending_cmd *cmd;
 
@@ -4623,8 +4628,16 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
        if (!cmd)
                return;
 
+       cp = cmd->param;
+
+       if (bacmp(bdaddr, &cp->addr.bdaddr))
+               return;
+
+       if (cp->addr.type != bdaddr_type)
+               return;
+
        bacpy(&rp.addr.bdaddr, bdaddr);
-       rp.addr.type = link_to_bdaddr(link_type, addr_type);
+       rp.addr.type = bdaddr_type;
 
        cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
                     mgmt_status(status), &rp, sizeof(rp));
index 4b07acb..4500736 100644 (file)
@@ -53,8 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 {
        struct blkcipher_desc desc;
        struct scatterlist sg;
-       int err, iv_len;
-       unsigned char iv[128];
+       int err;
 
        if (tfm == NULL) {
                BT_ERR("tfm %p", tfm);
@@ -72,12 +71,6 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 
        sg_init_one(&sg, r, 16);
 
-       iv_len = crypto_blkcipher_ivsize(tfm);
-       if (iv_len) {
-               memset(&iv, 0xff, iv_len);
-               crypto_blkcipher_set_iv(tfm, iv, iv_len);
-       }
-
        err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
        if (err)
                BT_ERR("Encrypt data error %d", err);
@@ -143,13 +136,6 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
        return err;
 }
 
-static int smp_rand(u8 *buf)
-{
-       get_random_bytes(buf, 16);
-
-       return 0;
-}
-
 static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
                                     u16 dlen, void *data)
 {
@@ -257,11 +243,11 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
        return 0;
 }
 
-static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
+static void smp_failure(struct l2cap_conn *conn, u8 reason)
 {
        struct hci_conn *hcon = conn->hcon;
 
-       if (send)
+       if (reason)
                smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
                             &reason);
 
@@ -406,7 +392,7 @@ static void confirm_work(struct work_struct *work)
        return;
 
 error:
-       smp_failure(conn, reason, 1);
+       smp_failure(conn, reason);
 }
 
 static void random_work(struct work_struct *work)
@@ -490,7 +476,7 @@ static void random_work(struct work_struct *work)
        return;
 
 error:
-       smp_failure(conn, reason, 1);
+       smp_failure(conn, reason);
 }
 
 static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
@@ -555,10 +541,10 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
                break;
        case MGMT_OP_USER_PASSKEY_NEG_REPLY:
        case MGMT_OP_USER_CONFIRM_NEG_REPLY:
-               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
                return 0;
        default:
-               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
                return -EOPNOTSUPP;
        }
 
@@ -606,9 +592,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
        if (check_enc_key_size(conn, key_size))
                return SMP_ENC_KEY_SIZE;
 
-       ret = smp_rand(smp->prnd);
-       if (ret)
-               return SMP_UNSPECIFIED;
+       get_random_bytes(smp->prnd, sizeof(smp->prnd));
 
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
@@ -644,9 +628,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
        if (check_enc_key_size(conn, key_size))
                return SMP_ENC_KEY_SIZE;
 
-       ret = smp_rand(smp->prnd);
-       if (ret)
-               return SMP_UNSPECIFIED;
+       get_random_bytes(smp->prnd, sizeof(smp->prnd));
 
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
@@ -768,6 +750,17 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        return 0;
 }
 
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
+{
+       if (sec_level == BT_SECURITY_LOW)
+               return true;
+
+       if (hcon->sec_level >= sec_level)
+               return true;
+
+       return false;
+}
+
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
@@ -779,10 +772,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
        if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
                return 1;
 
-       if (sec_level == BT_SECURITY_LOW)
-               return 1;
-
-       if (hcon->sec_level >= sec_level)
+       if (smp_sufficient_security(hcon, sec_level))
                return 1;
 
        if (hcon->link_mode & HCI_LM_MASTER)
@@ -895,7 +885,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
                break;
 
        case SMP_CMD_PAIRING_FAIL:
-               smp_failure(conn, skb->data[0], 0);
+               smp_failure(conn, 0);
                reason = 0;
                err = -EPERM;
                break;
@@ -941,7 +931,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
 done:
        if (reason)
-               smp_failure(conn, reason, 1);
+               smp_failure(conn, reason);
 
        kfree_skb(skb);
        return err;
index f8ba07f..a700bcb 100644 (file)
@@ -136,6 +136,7 @@ struct smp_chan {
 };
 
 /* SMP Commands */
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
 int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
 int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
index f80e8c4..ac18528 100644 (file)
@@ -301,9 +301,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                if (!sta)
                        goto out;
 
-               if (pairwise)
+               if (pairwise && key_idx < NUM_DEFAULT_KEYS)
                        key = rcu_dereference(sta->ptk[key_idx]);
-               else if (key_idx < NUM_DEFAULT_KEYS)
+               else if (!pairwise &&
+                        key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
                        key = rcu_dereference(sta->gtk[key_idx]);
        } else
                key = rcu_dereference(sdata->keys[key_idx]);
@@ -873,8 +874,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
-                           struct cfg80211_beacon_data *params)
+static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
+                                  struct cfg80211_beacon_data *params)
 {
        struct beacon_data *new, *old;
        int new_head_len, new_tail_len;
@@ -1097,17 +1098,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        if (old_probe_resp)
                kfree_rcu(old_probe_resp, rcu_head);
 
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-               sta_info_flush_defer(vlan);
-       sta_info_flush_defer(sdata);
-       synchronize_net();
-       rcu_barrier();
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
-               sta_info_flush_cleanup(vlan);
-               ieee80211_free_keys(vlan);
-       }
-       sta_info_flush_cleanup(sdata);
-       ieee80211_free_keys(sdata);
+       __sta_info_flush(sdata, true);
+       ieee80211_free_keys(sdata, true);
 
        sdata->vif.bss_conf.enable_beacon = false;
        sdata->vif.bss_conf.ssid_len = 0;
@@ -2587,8 +2579,8 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
                int j;
 
                sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
-               memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
-                      sizeof(mask->control[i].mcs));
+               memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].ht_mcs,
+                      sizeof(mask->control[i].ht_mcs));
 
                sdata->rc_has_mcs_mask[i] = false;
                if (!sband)
@@ -3047,8 +3039,8 @@ unlock:
        sdata_unlock(sdata);
 }
 
-static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-                                   struct cfg80211_csa_settings *params)
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                            struct cfg80211_csa_settings *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index 5d03c47..ef8b385 100644 (file)
@@ -242,22 +242,6 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
        return ret;
 }
 
-static inline void drv_set_multicast_list(struct ieee80211_local *local,
-                                         struct ieee80211_sub_if_data *sdata,
-                                         struct netdev_hw_addr_list *mc_list)
-{
-       bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
-
-       trace_drv_set_multicast_list(local, sdata, mc_list->count);
-
-       check_sdata_in_driver(sdata);
-
-       if (local->ops->set_multicast_list)
-               local->ops->set_multicast_list(&local->hw, &sdata->vif,
-                                              allmulti, mc_list);
-       trace_drv_return_void(local);
-}
-
 static inline void drv_configure_filter(struct ieee80211_local *local,
                                        unsigned int changed_flags,
                                        unsigned int *total_flags,
@@ -550,6 +534,22 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
 }
 #endif
 
+static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
+                                         struct ieee80211_sub_if_data *sdata,
+                                         struct sta_info *sta)
+{
+       might_sleep();
+
+       sdata = get_bss_sdata(sdata);
+       check_sdata_in_driver(sdata);
+
+       trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
+       if (local->ops->sta_pre_rcu_remove)
+               local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif,
+                                              &sta->sta);
+       trace_drv_return_void(local);
+}
+
 static inline __must_check
 int drv_sta_state(struct ieee80211_local *local,
                  struct ieee80211_sub_if_data *sdata,
index 2eda7b1..d6ba841 100644 (file)
@@ -522,7 +522,7 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
        if (csa_settings)
                ieee80211_send_action_csa(sdata, csa_settings);
 
-       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
+       return BSS_CHANGED_BEACON;
  out:
        return ret;
 }
@@ -534,7 +534,8 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
        int err;
        u16 capability;
 
-       sdata_lock(sdata);
+       sdata_assert_lock(sdata);
+
        /* update cfg80211 bss information with the new channel */
        if (!is_zero_ether_addr(ifibss->bssid)) {
                capability = WLAN_CAPABILITY_IBSS;
@@ -559,10 +560,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
 
        /* generate the beacon */
        err = ieee80211_ibss_csa_beacon(sdata, NULL);
-       sdata_unlock(sdata);
        if (err < 0)
                return err;
 
+       if (err)
+               ieee80211_bss_info_change_notify(sdata, err);
+
        return 0;
 }
 
@@ -753,12 +756,16 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work)
                container_of(work, struct ieee80211_sub_if_data,
                             u.ibss.csa_connection_drop_work);
 
+       sdata_lock(sdata);
+
        ieee80211_ibss_disconnect(sdata);
        synchronize_rcu();
        skb_queue_purge(&sdata->skb_queue);
 
        /* trigger a scan to find another IBSS network to join */
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+
+       sdata_unlock(sdata);
 }
 
 static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
@@ -784,18 +791,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        struct cfg80211_csa_settings params;
        struct ieee80211_csa_ie csa_ie;
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-       struct ieee80211_chanctx *chanctx;
        enum nl80211_channel_type ch_type;
-       int err, num_chanctx;
+       int err;
        u32 sta_flags;
 
-       if (sdata->vif.csa_active)
-               return true;
-
-       if (!sdata->vif.bss_conf.ibss_joined)
-               return false;
-
        sta_flags = IEEE80211_STA_DISABLE_VHT;
        switch (ifibss->chandef.width) {
        case NL80211_CHAN_WIDTH_5:
@@ -830,9 +829,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        params.count = csa_ie.count;
        params.chandef = csa_ie.chandef;
 
-       if (ifibss->chandef.chan->band != params.chandef.chan->band)
-               goto disconnect;
-
        switch (ifibss->chandef.width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
@@ -888,28 +884,12 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                params.radar_required = true;
        }
 
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-       if (!chanctx_conf) {
-               rcu_read_unlock();
-               goto disconnect;
-       }
-
-       /* don't handle for multi-VIF cases */
-       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
-       if (chanctx->refcount > 1) {
-               rcu_read_unlock();
-               goto disconnect;
-       }
-       num_chanctx = 0;
-       list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
-               num_chanctx++;
-
-       if (num_chanctx > 1) {
-               rcu_read_unlock();
-               goto disconnect;
+       if (cfg80211_chandef_identical(&params.chandef,
+                                      &sdata->vif.bss_conf.chandef)) {
+               ibss_dbg(sdata,
+                        "received csa with an identical chandef, ignoring\n");
+               return true;
        }
-       rcu_read_unlock();
 
        /* all checks done, now perform the channel switch. */
        ibss_dbg(sdata,
@@ -918,19 +898,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
        params.block_tx = !!csa_ie.mode;
 
-       ieee80211_ibss_csa_beacon(sdata, &params);
-       sdata->csa_radar_required = params.radar_required;
-
-       if (params.block_tx)
-               ieee80211_stop_queues_by_reason(&sdata->local->hw,
-                               IEEE80211_MAX_QUEUE_MAP,
-                               IEEE80211_QUEUE_STOP_REASON_CSA);
-
-       sdata->csa_chandef = params.chandef;
-       sdata->vif.csa_active = true;
-
-       ieee80211_bss_info_change_notify(sdata, err);
-       drv_channel_switch_beacon(sdata, &params.chandef);
+       if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
+                                    &params))
+               goto disconnect;
 
        ieee80211_ibss_csa_mark_radar(sdata);
 
@@ -966,7 +936,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
        if (len < required_len)
                return;
 
-       ieee80211_ibss_process_chanswitch(sdata, elems, false);
+       if (!sdata->vif.csa_active)
+               ieee80211_ibss_process_chanswitch(sdata, elems, false);
 }
 
 static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
@@ -1147,7 +1118,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                goto put_bss;
 
        /* process channel switch */
-       if (ieee80211_ibss_process_chanswitch(sdata, elems, true))
+       if (sdata->vif.csa_active ||
+           ieee80211_ibss_process_chanswitch(sdata, elems, true))
                goto put_bss;
 
        /* same BSSID */
index ed5bf8b..fb5dbcb 100644 (file)
@@ -232,6 +232,7 @@ struct ieee80211_rx_data {
 struct beacon_data {
        u8 *head, *tail;
        int head_len, tail_len;
+       struct ieee80211_meshconf_ie *meshconf;
        struct rcu_head rcu_head;
 };
 
@@ -540,7 +541,10 @@ struct ieee80211_mesh_sync_ops {
                             struct ieee80211_mgmt *mgmt,
                             struct ieee802_11_elems *elems,
                             struct ieee80211_rx_status *rx_status);
-       void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata);
+
+       /* should be called with beacon_data under RCU read lock */
+       void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata,
+                           struct beacon_data *beacon);
        /* add other framework functions here */
 };
 
@@ -614,6 +618,9 @@ struct ieee80211_if_mesh {
        bool chsw_init;
        u8 chsw_ttl;
        u16 pre_value;
+
+       /* offset from skb->data while building IE */
+       int meshconf_offset;
 };
 
 #ifdef CONFIG_MAC80211_MESH
@@ -776,10 +783,6 @@ struct ieee80211_sub_if_data {
                u32 mntr_flags;
        } u;
 
-       spinlock_t cleanup_stations_lock;
-       struct list_head cleanup_stations;
-       struct work_struct cleanup_stations_wk;
-
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct {
                struct dentry *subdir_stations;
@@ -1117,6 +1120,7 @@ struct ieee80211_local {
 
        struct work_struct sched_scan_stopped_work;
        struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
+       struct cfg80211_sched_scan_request *sched_scan_req;
 
        unsigned long leave_oper_channel_time;
        enum mac80211_scan_state next_scan_state;
@@ -1425,6 +1429,9 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
                          struct ieee80211_bss *bss);
 
 /* scheduled scan handling */
+int
+__ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                    struct cfg80211_sched_scan_request *req);
 int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
                                       struct cfg80211_sched_scan_request *req);
 int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
@@ -1443,6 +1450,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
 /* channel switch handling */
 void ieee80211_csa_finalize_work(struct work_struct *work);
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+                            struct cfg80211_csa_settings *params);
 
 /* interface handling */
 int ieee80211_iface_init(void);
@@ -1465,8 +1474,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
 
 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
-int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
-                           struct cfg80211_beacon_data *params);
 
 static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
 {
index 7aa9f9d..3d2168c 100644 (file)
@@ -786,10 +786,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
         * This is relevant only in WDS mode, in all other modes we've
         * already removed all stations when disconnecting or similar,
         * so warn otherwise.
-        *
-        * We call sta_info_flush_cleanup() later, to combine RCU waits.
         */
-       flushed = sta_info_flush_defer(sdata);
+       flushed = sta_info_flush(sdata);
        WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
                     (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
 
@@ -891,23 +889,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                cancel_work_sync(&sdata->work);
                /*
                 * When we get here, the interface is marked down.
+                * Free the remaining keys, if there are any
+                * (shouldn't be, except maybe in WDS mode?)
                 *
-                * sta_info_flush_cleanup() requires rcu_barrier()
-                * first to wait for the station call_rcu() calls
-                * to complete, and we also need synchronize_rcu()
-                * to wait for the RX path in case it is using the
-                * interface and enqueuing frames at this very time on
+                * Force the key freeing to always synchronize_net()
+                * to wait for the RX path in case it is using this
+                * interface enqueuing frames * at this very time on
                 * another CPU.
                 */
-               synchronize_rcu();
-               rcu_barrier();
-               sta_info_flush_cleanup(sdata);
-
-               /*
-                * Free all remaining keys, there shouldn't be any,
-                * except maybe in WDS mode?
-                */
-               ieee80211_free_keys(sdata);
+               ieee80211_free_keys(sdata, true);
 
                /* fall through */
        case NL80211_IFTYPE_AP:
@@ -1018,17 +1008,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
                        atomic_dec(&local->iff_promiscs);
                sdata->flags ^= IEEE80211_SDATA_PROMISC;
        }
-
-       /*
-        * TODO: If somebody needs this on AP interfaces,
-        *       it can be enabled easily but multicast
-        *       addresses from VLANs need to be synced.
-        */
-       if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
-           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-           sdata->vif.type != NL80211_IFTYPE_AP)
-               drv_set_multicast_list(local, sdata, &dev->mc);
-
        spin_lock_bh(&local->filter_lock);
        __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
        spin_unlock_bh(&local->filter_lock);
@@ -1044,7 +1023,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
        int i;
 
        /* free extra data */
-       ieee80211_free_keys(sdata);
+       ieee80211_free_keys(sdata, false);
 
        ieee80211_debugfs_remove_netdev(sdata);
 
@@ -1579,15 +1558,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
        mutex_unlock(&local->iflist_mtx);
 }
 
-static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
-
-       ieee80211_cleanup_sdata_stas(sdata);
-}
-
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                     struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params)
@@ -1660,9 +1630,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
        INIT_LIST_HEAD(&sdata->key_list);
 
-       spin_lock_init(&sdata->cleanup_stations_lock);
-       INIT_LIST_HEAD(&sdata->cleanup_stations);
-       INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
        INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
                          ieee80211_dfs_cac_timer_work);
        INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
index e568d98..6ff65a1 100644 (file)
@@ -589,14 +589,10 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_iter_keys);
 
-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
+                                     struct list_head *keys)
 {
        struct ieee80211_key *key, *tmp;
-       LIST_HEAD(keys);
-
-       cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
-
-       mutex_lock(&sdata->local->key_mtx);
 
        sdata->crypto_tx_tailroom_needed_cnt -=
                sdata->crypto_tx_tailroom_pending_dec;
@@ -608,28 +604,51 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add_tail(&key->list, &keys);
+               list_add_tail(&key->list, keys);
        }
 
        ieee80211_debugfs_key_update_default(sdata);
+}
 
-       if (!list_empty(&keys)) {
-               synchronize_net();
-               list_for_each_entry_safe(key, tmp, &keys, list)
-                       __ieee80211_key_destroy(key, false);
+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
+                        bool force_synchronize)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *vlan;
+       struct ieee80211_key *key, *tmp;
+       LIST_HEAD(keys);
+
+       cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
+
+       mutex_lock(&local->key_mtx);
+
+       ieee80211_free_keys_iface(sdata, &keys);
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       ieee80211_free_keys_iface(vlan, &keys);
        }
 
+       if (!list_empty(&keys) || force_synchronize)
+               synchronize_net();
+       list_for_each_entry_safe(key, tmp, &keys, list)
+               __ieee80211_key_destroy(key, false);
+
        WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
                     sdata->crypto_tx_tailroom_pending_dec);
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
+               list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+                       WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt ||
+                                    vlan->crypto_tx_tailroom_pending_dec);
+       }
 
-       mutex_unlock(&sdata->local->key_mtx);
+       mutex_unlock(&local->key_mtx);
 }
 
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
                             struct sta_info *sta)
 {
-       struct ieee80211_key *key, *tmp;
-       LIST_HEAD(keys);
+       struct ieee80211_key *key;
        int i;
 
        mutex_lock(&local->key_mtx);
@@ -640,7 +659,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add(&key->list, &keys);
+               __ieee80211_key_destroy(key, true);
        }
 
        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
@@ -650,17 +669,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
-               list_add(&key->list, &keys);
-       }
-
-       /*
-        * NB: the station code relies on this being
-        * done even if there aren't any keys
-        */
-       synchronize_net();
-
-       list_for_each_entry_safe(key, tmp, &keys, list)
                __ieee80211_key_destroy(key, true);
+       }
 
        mutex_unlock(&local->key_mtx);
 }
index 0aebb88..19db686 100644 (file)
@@ -136,7 +136,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
                               bool uni, bool multi);
 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
                                    int idx);
-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
+                        bool force_synchronize);
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
                             struct sta_info *sta);
 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
index fa34cd2..2bd5b55 100644 (file)
@@ -250,12 +250,8 @@ static void ieee80211_restart_work(struct work_struct *work)
        /* wait for scan work complete */
        flush_workqueue(local->workqueue);
 
-       mutex_lock(&local->mtx);
-       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-            rcu_dereference_protected(local->sched_scan_sdata,
-                                      lockdep_is_held(&local->mtx)),
-               "%s called with hardware scan in progress\n", __func__);
-       mutex_unlock(&local->mtx);
+       WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+            "%s called with hardware scan in progress\n", __func__);
 
        rtnl_lock();
        ieee80211_scan_cancel(local);
index 89df62b..5a74b24 100644 (file)
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
        *pos++ = WLAN_EID_MESH_CONFIG;
        *pos++ = meshconf_len;
 
+       /* save a pointer for quick updates in pre-tbtt */
+       ifmsh->meshconf_offset = pos - skb->data;
+
        /* Active path selection protocol ID */
        *pos++ = ifmsh->mesh_pp_id;
        /* Active path selection metric ID   */
@@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
 
        bcn->tail_len = skb->len;
        memcpy(bcn->tail, skb->data, bcn->tail_len);
+       bcn->meshconf = (struct ieee80211_meshconf_ie *)
+                                       (bcn->tail + ifmsh->meshconf_offset);
 
        dev_kfree_skb(skb);
        rcu_assign_pointer(ifmsh->beacon, bcn);
index d1cf2d5..2bc5dc2 100644 (file)
@@ -164,12 +164,15 @@ no_sync:
        rcu_read_unlock();
 }
 
-static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
+static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata,
+                                        struct beacon_data *beacon)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       u8 cap;
 
        WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
        BUG_ON(!rcu_read_lock_held());
+       cap = beacon->meshconf->meshconf_cap;
 
        spin_lock_bh(&ifmsh->sync_offset_lock);
 
@@ -194,6 +197,10 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
                ifmsh->adjusting_tbtt = false;
        }
        spin_unlock_bh(&ifmsh->sync_offset_lock);
+
+       beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ?
+                       IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap :
+                       ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap;
 }
 
 static const struct sync_method sync_methods[] = {
index 900ead3..9c2c7ee 100644 (file)
@@ -1698,7 +1698,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        memset(ifmgd->bssid, 0, ETH_ALEN);
 
        /* remove AP and TDLS peers */
-       sta_info_flush_defer(sdata);
+       sta_info_flush(sdata);
 
        /* finally reset all BSS / config parameters */
        changed |= ieee80211_reset_erp_info(sdata);
index 3401262..af64fb8 100644 (file)
@@ -37,9 +37,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                                        IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
-       /* flush out all packets and station cleanup call_rcu()s */
+       /* flush out all packets */
        synchronize_net();
-       rcu_barrier();
 
        ieee80211_flush_queues(local, NULL);
 
index 2dfa755..5a2afe9 100644 (file)
@@ -1963,20 +1963,17 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                }
        }
 
-       if (skb) {
-               int align __maybe_unused;
-
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-               /*
-                * 'align' will only take the values 0 or 2 here
-                * since all frames are required to be aligned
-                * to 2-byte boundaries when being passed to
-                * mac80211; the code here works just as well if
-                * that isn't true, but mac80211 assumes it can
-                * access fields as 2-byte aligned (e.g. for
-                * compare_ether_addr)
+       if (skb) {
+               /* 'align' will only take the values 0 or 2 here since all
+                * frames are required to be aligned to 2-byte boundaries
+                * when being passed to mac80211; the code here works just
+                * as well if that isn't true, but mac80211 assumes it can
+                * access fields as 2-byte aligned (e.g. for ether_addr_equal)
                 */
-               align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;
+               int align;
+
+               align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3;
                if (align) {
                        if (WARN_ON(skb_headroom(skb) < 3)) {
                                dev_kfree_skb(skb);
@@ -1989,14 +1986,14 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                                skb_set_tail_pointer(skb, len);
                        }
                }
+       }
 #endif
 
-               if (skb) {
-                       /* deliver to local stack */
-                       skb->protocol = eth_type_trans(skb, dev);
-                       memset(skb->cb, 0, sizeof(skb->cb));
-                       netif_receive_skb(skb);
-               }
+       if (skb) {
+               /* deliver to local stack */
+               skb->protocol = eth_type_trans(skb, dev);
+               memset(skb->cb, 0, sizeof(skb->cb));
+               netif_receive_skb(skb);
        }
 
        if (xmit_skb) {
index 4d73c46..88c8161 100644 (file)
@@ -271,10 +271,11 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
        return true;
 }
 
-static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
-                                      bool was_hw_scan)
+static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       bool hw_scan = local->ops->hw_scan;
+       bool was_scanning = local->scanning;
 
        lockdep_assert_held(&local->mtx);
 
@@ -290,7 +291,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        if (WARN_ON(!local->scan_req))
                return;
 
-       if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
+       if (hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
                int rc;
 
                rc = drv_hw_scan(local,
@@ -316,7 +317,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        /* Set power back to normal operating levels. */
        ieee80211_hw_config(local, 0);
 
-       if (!was_hw_scan) {
+       if (!hw_scan) {
                ieee80211_configure_filter(local);
                drv_sw_scan_complete(local);
                ieee80211_offchannel_return(local);
@@ -327,7 +328,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
        ieee80211_mlme_notify_scan_completed(local);
        ieee80211_ibss_notify_scan_completed(local);
        ieee80211_mesh_notify_scan_completed(local);
-       ieee80211_start_next_roc(local);
+       if (was_scanning)
+               ieee80211_start_next_roc(local);
 }
 
 void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
@@ -747,7 +749,7 @@ void ieee80211_scan_work(struct work_struct *work)
                container_of(work, struct ieee80211_local, scan_work.work);
        struct ieee80211_sub_if_data *sdata;
        unsigned long next_delay = 0;
-       bool aborted, hw_scan;
+       bool aborted;
 
        mutex_lock(&local->mtx);
 
@@ -786,14 +788,6 @@ void ieee80211_scan_work(struct work_struct *work)
        }
 
        /*
-        * Avoid re-scheduling when the sdata is going away.
-        */
-       if (!ieee80211_sdata_running(sdata)) {
-               aborted = true;
-               goto out_complete;
-       }
-
-       /*
         * as long as no delay is required advance immediately
         * without scheduling a new work
         */
@@ -834,8 +828,7 @@ void ieee80211_scan_work(struct work_struct *work)
        goto out;
 
 out_complete:
-       hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
-       __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
+       __ieee80211_scan_completed(&local->hw, aborted);
 out:
        mutex_unlock(&local->mtx);
 }
@@ -973,13 +966,13 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
         */
        cancel_delayed_work(&local->scan_work);
        /* and clean up */
-       __ieee80211_scan_completed(&local->hw, true, false);
+       __ieee80211_scan_completed(&local->hw, true);
 out:
        mutex_unlock(&local->mtx);
 }
 
-int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
-                                      struct cfg80211_sched_scan_request *req)
+int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                       struct cfg80211_sched_scan_request *req)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_sched_scan_ies sched_scan_ies = {};
@@ -989,17 +982,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
                  local->scan_ies_len + req->ie_len;
 
-       mutex_lock(&local->mtx);
-
-       if (rcu_access_pointer(local->sched_scan_sdata)) {
-               ret = -EBUSY;
-               goto out;
-       }
+       lockdep_assert_held(&local->mtx);
 
-       if (!local->ops->sched_scan_start) {
-               ret = -ENOTSUPP;
-               goto out;
-       }
+       if (!local->ops->sched_scan_start)
+               return -ENOTSUPP;
 
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
                if (!local->hw.wiphy->bands[i])
@@ -1020,13 +1006,39 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        }
 
        ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
-       if (ret == 0)
+       if (ret == 0) {
                rcu_assign_pointer(local->sched_scan_sdata, sdata);
+               local->sched_scan_req = req;
+       }
 
 out_free:
        while (i > 0)
                kfree(sched_scan_ies.ie[--i]);
-out:
+
+       if (ret) {
+               /* Clean in case of failure after HW restart or upon resume. */
+               rcu_assign_pointer(local->sched_scan_sdata, NULL);
+               local->sched_scan_req = NULL;
+       }
+
+       return ret;
+}
+
+int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+                                      struct cfg80211_sched_scan_request *req)
+{
+       struct ieee80211_local *local = sdata->local;
+       int ret;
+
+       mutex_lock(&local->mtx);
+
+       if (rcu_access_pointer(local->sched_scan_sdata)) {
+               mutex_unlock(&local->mtx);
+               return -EBUSY;
+       }
+
+       ret = __ieee80211_request_sched_scan_start(sdata, req);
+
        mutex_unlock(&local->mtx);
        return ret;
 }
@@ -1043,6 +1055,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
                goto out;
        }
 
+       /* We don't want to restart sched scan anymore. */
+       local->sched_scan_req = NULL;
+
        if (rcu_access_pointer(local->sched_scan_sdata))
                drv_sched_scan_stop(local, sdata);
 
@@ -1077,6 +1092,9 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
 
        rcu_assign_pointer(local->sched_scan_sdata, NULL);
 
+       /* If sched scan was aborted by the driver. */
+       local->sched_scan_req = NULL;
+
        mutex_unlock(&local->mtx);
 
        cfg80211_sched_scan_stopped(local->hw.wiphy);
index 8ed97f7..4576ba0 100644 (file)
@@ -99,23 +99,6 @@ static void cleanup_single_sta(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct ps_data *ps;
 
-       /*
-        * At this point, when being called as call_rcu callback,
-        * neither mac80211 nor the driver can reference this
-        * sta struct any more except by still existing timers
-        * associated with this station that we clean up below.
-        *
-        * Note though that this still uses the sdata and even
-        * calls the driver in AP and mesh mode, so interfaces
-        * of those types mush use call sta_info_flush_cleanup()
-        * (typically via sta_info_flush()) before deconfiguring
-        * the driver.
-        *
-        * In station mode, nothing happens here so it doesn't
-        * have to (and doesn't) do that, this is intentional to
-        * speed up roaming.
-        */
-
        if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
                if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
                    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -160,37 +143,6 @@ static void cleanup_single_sta(struct sta_info *sta)
        sta_info_free(local, sta);
 }
 
-void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata)
-{
-       struct sta_info *sta;
-
-       spin_lock_bh(&sdata->cleanup_stations_lock);
-       while (!list_empty(&sdata->cleanup_stations)) {
-               sta = list_first_entry(&sdata->cleanup_stations,
-                                      struct sta_info, list);
-               list_del(&sta->list);
-               spin_unlock_bh(&sdata->cleanup_stations_lock);
-
-               cleanup_single_sta(sta);
-
-               spin_lock_bh(&sdata->cleanup_stations_lock);
-       }
-
-       spin_unlock_bh(&sdata->cleanup_stations_lock);
-}
-
-static void free_sta_rcu(struct rcu_head *h)
-{
-       struct sta_info *sta = container_of(h, struct sta_info, rcu_head);
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-
-       spin_lock(&sdata->cleanup_stations_lock);
-       list_add_tail(&sta->list, &sdata->cleanup_stations);
-       spin_unlock(&sdata->cleanup_stations_lock);
-
-       ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk);
-}
-
 /* protected by RCU */
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
                              const u8 *addr)
@@ -842,7 +794,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
        return have_buffered;
 }
 
-int __must_check __sta_info_destroy(struct sta_info *sta)
+static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
 {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
@@ -868,12 +820,35 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
 
        ret = sta_info_hash_del(local, sta);
-       if (ret)
+       if (WARN_ON(ret))
                return ret;
 
        list_del_rcu(&sta->list);
 
-       /* this always calls synchronize_net() */
+       drv_sta_pre_rcu_remove(local, sta->sdata, sta);
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+           rcu_access_pointer(sdata->u.vlan.sta) == sta)
+               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
+
+       return 0;
+}
+
+static void __sta_info_destroy_part2(struct sta_info *sta)
+{
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       int ret;
+
+       /*
+        * NOTE: This assumes at least synchronize_net() was done
+        *       after _part1 and before _part2!
+        */
+
+       might_sleep();
+       lockdep_assert_held(&local->sta_mtx);
+
+       /* now keys can no longer be reached */
        ieee80211_free_sta_keys(local, sta);
 
        sta->dead = true;
@@ -881,9 +856,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        local->num_sta--;
        local->sta_generation++;
 
-       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
-
        while (sta->sta_state > IEEE80211_STA_NONE) {
                ret = sta_info_move_state(sta, sta->sta_state - 1);
                if (ret) {
@@ -906,7 +878,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        ieee80211_sta_debugfs_remove(sta);
        ieee80211_recalc_min_chandef(sdata);
 
-       call_rcu(&sta->rcu_head, free_sta_rcu);
+       cleanup_single_sta(sta);
+}
+
+int __must_check __sta_info_destroy(struct sta_info *sta)
+{
+       int err = __sta_info_destroy_part1(sta);
+
+       if (err)
+               return err;
+
+       synchronize_net();
+
+       __sta_info_destroy_part2(sta);
 
        return 0;
 }
@@ -976,32 +960,38 @@ void sta_info_stop(struct ieee80211_local *local)
 }
 
 
-int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata)
+int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta, *tmp;
+       LIST_HEAD(free_list);
        int ret = 0;
 
        might_sleep();
 
+       WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP);
+       WARN_ON(vlans && !sdata->bss);
+
        mutex_lock(&local->sta_mtx);
        list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-               if (sdata == sta->sdata) {
-                       WARN_ON(__sta_info_destroy(sta));
+               if (sdata == sta->sdata ||
+                   (vlans && sdata->bss == sta->sdata->bss)) {
+                       if (!WARN_ON(__sta_info_destroy_part1(sta)))
+                               list_add(&sta->free_list, &free_list);
                        ret++;
                }
        }
+
+       if (!list_empty(&free_list)) {
+               synchronize_net();
+               list_for_each_entry_safe(sta, tmp, &free_list, free_list)
+                       __sta_info_destroy_part2(sta);
+       }
        mutex_unlock(&local->sta_mtx);
 
        return ret;
 }
 
-void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata)
-{
-       ieee80211_cleanup_sdata_stas(sdata);
-       cancel_work_sync(&sdata->cleanup_stations_wk);
-}
-
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
                          unsigned long exp_time)
 {
index 0218caf..d77ff70 100644 (file)
@@ -247,6 +247,7 @@ struct ieee80211_tx_latency_stat {
  * mac80211 is communicating with.
  *
  * @list: global linked list entry
+ * @free_list: list entry for keeping track of stations to free
  * @hnext: hash table linked list pointer
  * @local: pointer to the global information
  * @sdata: virtual interface this station belongs to
@@ -329,7 +330,7 @@ struct ieee80211_tx_latency_stat {
  */
 struct sta_info {
        /* General information, mostly static */
-       struct list_head list;
+       struct list_head list, free_list;
        struct rcu_head rcu_head;
        struct sta_info __rcu *hnext;
        struct ieee80211_local *local;
@@ -605,21 +606,6 @@ void sta_info_recalc_tim(struct sta_info *sta);
 
 void sta_info_init(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
-int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata);
-
-/**
- * sta_info_flush_cleanup - flush the sta_info cleanup queue
- * @sdata: the interface
- *
- * Flushes the sta_info cleanup queue for a given interface;
- * this is necessary before the interface is removed or, for
- * AP/mesh interfaces, before it is deconfigured.
- *
- * Note an rcu_barrier() must precede the function, after all
- * stations have been flushed/removed to ensure the call_rcu()
- * calls that add stations to the cleanup queue have completed.
- */
-void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
 
 /**
  * sta_info_flush - flush matching STA entries from the STA table
@@ -627,15 +613,13 @@ void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
  * Returns the number of removed STA entries.
  *
  * @sdata: sdata to remove all stations from
+ * @vlans: if the given interface is an AP interface, also flush VLANs
  */
+int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans);
+
 static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
 {
-       int ret = sta_info_flush_defer(sdata);
-
-       rcu_barrier();
-       sta_info_flush_cleanup(sdata);
-
-       return ret;
+       return __sta_info_flush(sdata, false);
 }
 
 void sta_set_rate_info_tx(struct sta_info *sta,
@@ -651,6 +635,4 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
-void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
-
 #endif /* STA_INFO_H */
index e9ccf22..3a669d7 100644 (file)
@@ -443,30 +443,6 @@ TRACE_EVENT(drv_prepare_multicast,
        )
 );
 
-TRACE_EVENT(drv_set_multicast_list,
-       TP_PROTO(struct ieee80211_local *local,
-                struct ieee80211_sub_if_data *sdata, int mc_count),
-
-       TP_ARGS(local, sdata, mc_count),
-
-       TP_STRUCT__entry(
-               LOCAL_ENTRY
-               __field(bool, allmulti)
-               __field(int, mc_count)
-       ),
-
-       TP_fast_assign(
-               LOCAL_ASSIGN;
-               __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
-               __entry->mc_count = mc_count;
-       ),
-
-       TP_printk(
-               LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d",
-               LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti
-       )
-);
-
 TRACE_EVENT(drv_configure_filter,
        TP_PROTO(struct ieee80211_local *local,
                 unsigned int changed_flags,
@@ -790,7 +766,7 @@ TRACE_EVENT(drv_sta_rc_update,
        )
 );
 
-TRACE_EVENT(drv_sta_add,
+DECLARE_EVENT_CLASS(sta_event,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,
                 struct ieee80211_sta *sta),
@@ -815,29 +791,25 @@ TRACE_EVENT(drv_sta_add,
        )
 );
 
-TRACE_EVENT(drv_sta_remove,
+DEFINE_EVENT(sta_event, drv_sta_add,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata,
                 struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
+);
 
-       TP_ARGS(local, sdata, sta),
-
-       TP_STRUCT__entry(
-               LOCAL_ENTRY
-               VIF_ENTRY
-               STA_ENTRY
-       ),
-
-       TP_fast_assign(
-               LOCAL_ASSIGN;
-               VIF_ASSIGN;
-               STA_ASSIGN;
-       ),
+DEFINE_EVENT(sta_event, drv_sta_remove,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
+);
 
-       TP_printk(
-               LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT,
-               LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
-       )
+DEFINE_EVENT(sta_event, drv_sta_pre_rcu_remove,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta),
+       TP_ARGS(local, sdata, sta)
 );
 
 TRACE_EVENT(drv_conf_tx,
index 6d59e21..2f0e176 100644 (file)
@@ -2549,7 +2549,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         */
                        skb = dev_alloc_skb(local->tx_headroom +
                                            beacon->head_len +
-                                           beacon->tail_len + 256);
+                                           beacon->tail_len + 256 +
+                                           local->hw.extra_beacon_tailroom);
                        if (!skb)
                                goto out;
 
@@ -2581,7 +2582,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, presp);
 
 
-               skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
+               skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);
@@ -2602,13 +2604,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        ieee80211_update_csa(sdata, bcn);
 
                if (ifmsh->sync_ops)
-                       ifmsh->sync_ops->adjust_tbtt(
-                                               sdata);
+                       ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
 
                skb = dev_alloc_skb(local->tx_headroom +
                                    bcn->head_len +
                                    256 + /* TIM IE */
-                                   bcn->tail_len);
+                                   bcn->tail_len +
+                                   local->hw.extra_beacon_tailroom);
                if (!skb)
                        goto out;
                skb_reserve(skb, local->tx_headroom);
index 875e172..591b46b 100644 (file)
@@ -642,6 +642,17 @@ void ieee80211_iterate_active_interfaces_rtnl(
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
 
+struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+       if (!ieee80211_sdata_running(sdata) ||
+           !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
+               return NULL;
+       return &sdata->vif;
+}
+EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif);
+
 /*
  * Nothing should have been stuffed into the workqueue during
  * the suspend->resume cycle. If this WARN is seen then there
@@ -1451,6 +1462,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        struct sta_info *sta;
        int res, i;
        bool reconfig_due_to_wowlan = false;
+       struct ieee80211_sub_if_data *sched_scan_sdata;
+       bool sched_scan_stopped = false;
 
 #ifdef CONFIG_PM
        if (local->suspended)
@@ -1754,6 +1767,27 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 #else
        WARN_ON(1);
 #endif
+
+       /*
+        * Reconfigure sched scan if it was interrupted by FW restart or
+        * suspend.
+        */
+       mutex_lock(&local->mtx);
+       sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
+                                               lockdep_is_held(&local->mtx));
+       if (sched_scan_sdata && local->sched_scan_req)
+               /*
+                * Sched scan stopped, but we don't want to report it. Instead,
+                * we're trying to reschedule.
+                */
+               if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
+                                                        local->sched_scan_req))
+                       sched_scan_stopped = true;
+       mutex_unlock(&local->mtx);
+
+       if (sched_scan_stopped)
+               cfg80211_sched_scan_stopped(local->hw.wiphy);
+
        return 0;
 }
 
index 9d68441..2277276 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/nfc.h>
index 8725291..02ab341 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index 64f922b..a9f4d2e 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index d07ca4c..3b96100 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index b274d12..c3d2e2c 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_HCI_H
index b6b4109..e9de151 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index fe5e966..a07d2b8 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <net/nfc/llc.h>
index 7be0b7f..5dad4c5 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_LLC_H_
index 87b1029..d0435d5 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/types.h>
index 27b313b..719ad0a 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "shdlc: %s: " fmt, __func__
index f4d48b5..de1789e 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 enum llcp_state {
index 1017894..693cd1a 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index 81cd341..1349074 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index 824c605..69fbc8d 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index b943d46..f0e955e 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 2a9399d..6c3aef8 100644 (file)
@@ -16,8 +16,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 6b7fd26..ed774a2 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index b2aa98e..1e90509 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index dd072f3..041de51 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index a9b2342..ebbf6fb 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index aaf606f..9d6e74f 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_NFC_H
index 66bcd2e..c27a6e8 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index 1bacc10..ed7e0b4 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 06db6eb..d89dee2 100644 (file)
@@ -203,17 +203,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 
        rdev->opencount--;
 
-       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-               /*
-                * If the scan request wasn't notified as done, set it
-                * to aborted and leak it after a warning. The driver
-                * should have notified us that it ended at the latest
-                * during rdev_stop_p2p_device().
-                */
-               if (WARN_ON(!rdev->scan_req->notified))
-                       rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, !rdev->scan_req->notified);
-       }
+       WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+               !rdev->scan_req->notified);
 }
 
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -765,13 +756,16 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 {
        struct net_device *dev = wdev->netdev;
 
+       ASSERT_RTNL();
+
        switch (wdev->iftype) {
        case NL80211_IFTYPE_ADHOC:
                cfg80211_leave_ibss(rdev, dev, true);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
-               __cfg80211_stop_sched_scan(rdev, false);
+               if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
+                       __cfg80211_stop_sched_scan(rdev, false);
 
                wdev_lock(wdev);
 #ifdef CONFIG_CFG80211_WEXT
@@ -865,11 +859,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-                       if (WARN_ON(!rdev->scan_req->notified))
-                               rdev->scan_req->aborted = true;
-                       ___cfg80211_scan_done(rdev, true);
-               }
+               WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+                       !rdev->scan_req->notified);
 
                if (WARN_ON(rdev->sched_scan_req &&
                            rdev->sched_scan_req->dev == wdev->netdev)) {
index 0a277c3..37ec16d 100644 (file)
@@ -67,9 +67,7 @@ struct cfg80211_registered_device {
        struct work_struct scan_done_wk;
        struct work_struct sched_scan_results_wk;
 
-#ifdef CONFIG_NL80211_TESTMODE
-       struct genl_info *testmode_info;
-#endif
+       struct genl_info *cur_cmd_info;
 
        struct work_struct conn_work;
        struct work_struct event_work;
@@ -363,7 +361,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
                                   struct key_params *params, int key_idx,
                                   bool pairwise, const u8 *mac_addr);
 void __cfg80211_scan_done(struct work_struct *wk);
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
 void __cfg80211_sched_scan_results(struct work_struct *wk);
 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
                               bool driver_initiated);
index b0e1869..9c7a11a 100644 (file)
@@ -99,6 +99,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
                         const struct mesh_config *conf)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
+       u8 radar_detect_width = 0;
        int err;
 
        BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
@@ -177,8 +178,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
                return -EINVAL;
 
-       err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan,
-                                   CHAN_MODE_SHARED);
+       err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef);
+       if (err < 0)
+               return err;
+       if (err)
+               radar_detect_width = BIT(setup->chandef.width);
+
+       err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
+                                          setup->chandef.chan,
+                                          CHAN_MODE_SHARED,
+                                          radar_detect_width);
        if (err)
                return err;
 
index a693f86..04681a4 100644 (file)
@@ -376,6 +376,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
        [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
        [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
+       [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
+       [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
+       [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
+       [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
 };
 
 /* policy for the key attributes */
@@ -1184,6 +1188,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
        struct nlattr *nl_bands, *nl_band;
        struct nlattr *nl_freqs, *nl_freq;
        struct nlattr *nl_cmds;
+       struct nlattr *nl_vendor_cmds;
        enum ieee80211_band band;
        struct ieee80211_channel *chan;
        int i;
@@ -1579,6 +1584,19 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
                    (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
                     nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
                        goto nla_put_failure;
+               state->split_start++;
+               break;
+       case 11:
+               nl_vendor_cmds = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+               if (!nl_vendor_cmds)
+                       goto nla_put_failure;
+
+               for (i = 0; i < dev->wiphy.n_vendor_commands; i++)
+                       if (nla_put(msg, i + 1,
+                                   sizeof(struct nl80211_vendor_cmd_info),
+                                   &dev->wiphy.vendor_commands[i].info))
+                               goto nla_put_failure;
+               nla_nest_end(msg, nl_vendor_cmds);
 
                /* done */
                state->split_start = 0;
@@ -4151,6 +4169,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                params.vht_capa =
                        nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 
+       if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
+               params.opmode_notif_used = true;
+               params.opmode_notif =
+                       nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
+       }
+
        if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
                params.plink_action =
                        nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
@@ -5667,8 +5691,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        struct net_device *dev = info->user_ptr[1];
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_chan_def chandef;
+       enum nl80211_dfs_regions dfs_region;
        int err;
 
+       dfs_region = reg_get_dfs_region(wdev->wiphy);
+       if (dfs_region == NL80211_DFS_UNSET)
+               return -EINVAL;
+
        err = nl80211_parse_chandef(rdev, info, &chandef);
        if (err)
                return err;
@@ -6693,6 +6722,40 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
        return err;
 }
 
+static struct sk_buff *
+__cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
+                           int approxlen, u32 portid, u32 seq,
+                           enum nl80211_commands cmd,
+                           enum nl80211_attrs attr, gfp_t gfp)
+{
+       struct sk_buff *skb;
+       void *hdr;
+       struct nlattr *data;
+
+       skb = nlmsg_new(approxlen + 100, gfp);
+       if (!skb)
+               return NULL;
+
+       hdr = nl80211hdr_put(skb, portid, seq, 0, cmd);
+       if (!hdr) {
+               kfree_skb(skb);
+               return NULL;
+       }
+
+       if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+               goto nla_put_failure;
+       data = nla_nest_start(skb, attr);
+
+       ((void **)skb->cb)[0] = rdev;
+       ((void **)skb->cb)[1] = hdr;
+       ((void **)skb->cb)[2] = data;
+
+       return skb;
+
+ nla_put_failure:
+       kfree_skb(skb);
+       return NULL;
+}
 
 #ifdef CONFIG_NL80211_TESTMODE
 static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
@@ -6717,11 +6780,11 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
        if (!info->attrs[NL80211_ATTR_TESTDATA])
                return -EINVAL;
 
-       rdev->testmode_info = info;
+       rdev->cur_cmd_info = info;
        err = rdev_testmode_cmd(rdev, wdev,
                                nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
                                nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
-       rdev->testmode_info = NULL;
+       rdev->cur_cmd_info = NULL;
 
        return err;
 }
@@ -6821,77 +6884,14 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
        return err;
 }
 
-static struct sk_buff *
-__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
-                             int approxlen, u32 portid, u32 seq, gfp_t gfp)
-{
-       struct sk_buff *skb;
-       void *hdr;
-       struct nlattr *data;
-
-       skb = nlmsg_new(approxlen + 100, gfp);
-       if (!skb)
-               return NULL;
-
-       hdr = nl80211hdr_put(skb, portid, seq, 0, NL80211_CMD_TESTMODE);
-       if (!hdr) {
-               kfree_skb(skb);
-               return NULL;
-       }
-
-       if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
-               goto nla_put_failure;
-       data = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
-
-       ((void **)skb->cb)[0] = rdev;
-       ((void **)skb->cb)[1] = hdr;
-       ((void **)skb->cb)[2] = data;
-
-       return skb;
-
- nla_put_failure:
-       kfree_skb(skb);
-       return NULL;
-}
-
-struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
-                                                 int approxlen)
-{
-       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-
-       if (WARN_ON(!rdev->testmode_info))
-               return NULL;
-
-       return __cfg80211_testmode_alloc_skb(rdev, approxlen,
-                               rdev->testmode_info->snd_portid,
-                               rdev->testmode_info->snd_seq,
-                               GFP_KERNEL);
-}
-EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb);
-
-int cfg80211_testmode_reply(struct sk_buff *skb)
-{
-       struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
-       void *hdr = ((void **)skb->cb)[1];
-       struct nlattr *data = ((void **)skb->cb)[2];
-
-       if (WARN_ON(!rdev->testmode_info)) {
-               kfree_skb(skb);
-               return -EINVAL;
-       }
-
-       nla_nest_end(skb, data);
-       genlmsg_end(skb, hdr);
-       return genlmsg_reply(skb, rdev->testmode_info);
-}
-EXPORT_SYMBOL(cfg80211_testmode_reply);
-
 struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
                                                  int approxlen, gfp_t gfp)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
-       return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp);
+       return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0,
+                                          NL80211_CMD_TESTMODE,
+                                          NL80211_ATTR_TESTDATA, gfp);
 }
 EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
 
@@ -7328,11 +7328,72 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband,
        return true;
 }
 
+static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map)
+{
+       u16 mcs_mask = 0;
+
+       switch (vht_mcs_map) {
+       case IEEE80211_VHT_MCS_NOT_SUPPORTED:
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_7:
+               mcs_mask = 0x00FF;
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_8:
+               mcs_mask = 0x01FF;
+               break;
+       case IEEE80211_VHT_MCS_SUPPORT_0_9:
+               mcs_mask = 0x03FF;
+               break;
+       default:
+               break;
+       }
+
+       return mcs_mask;
+}
+
+static void vht_build_mcs_mask(u16 vht_mcs_map,
+                              u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+{
+       u8 nss;
+
+       for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) {
+               vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03);
+               vht_mcs_map >>= 2;
+       }
+}
+
+static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
+                            struct nl80211_txrate_vht *txrate,
+                            u16 mcs[NL80211_VHT_NSS_MAX])
+{
+       u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
+       u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {};
+       u8 i;
+
+       if (!sband->vht_cap.vht_supported)
+               return false;
+
+       memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX);
+
+       /* Build vht_mcs_mask from VHT capabilities */
+       vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
+
+       for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
+               if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
+                       mcs[i] = txrate->mcs[i];
+               else
+                       return false;
+       }
+
+       return true;
+}
+
 static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
        [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
                                    .len = NL80211_MAX_SUPP_RATES },
-       [NL80211_TXRATE_MCS] = { .type = NLA_BINARY,
-                                .len = NL80211_MAX_SUPP_HT_RATES },
+       [NL80211_TXRATE_HT] = { .type = NLA_BINARY,
+                               .len = NL80211_MAX_SUPP_HT_RATES },
+       [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)},
 };
 
 static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
@@ -7345,9 +7406,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
        struct net_device *dev = info->user_ptr[1];
        struct nlattr *tx_rates;
        struct ieee80211_supported_band *sband;
-
-       if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
-               return -EINVAL;
+       u16 vht_tx_mcs_map;
 
        if (!rdev->ops->set_bitrate_mask)
                return -EOPNOTSUPP;
@@ -7356,17 +7415,26 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
        /* Default to all rates enabled */
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
                sband = rdev->wiphy.bands[i];
-               mask.control[i].legacy =
-                       sband ? (1 << sband->n_bitrates) - 1 : 0;
-               if (sband)
-                       memcpy(mask.control[i].mcs,
-                              sband->ht_cap.mcs.rx_mask,
-                              sizeof(mask.control[i].mcs));
-               else
-                       memset(mask.control[i].mcs, 0,
-                              sizeof(mask.control[i].mcs));
+
+               if (!sband)
+                       continue;
+
+               mask.control[i].legacy = (1 << sband->n_bitrates) - 1;
+               memcpy(mask.control[i].ht_mcs,
+                      sband->ht_cap.mcs.rx_mask,
+                      sizeof(mask.control[i].ht_mcs));
+
+               if (!sband->vht_cap.vht_supported)
+                       continue;
+
+               vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
+               vht_build_mcs_mask(vht_tx_mcs_map, mask.control[i].vht_mcs);
        }
 
+       /* if no rates are given set it back to the defaults */
+       if (!info->attrs[NL80211_ATTR_TX_RATES])
+               goto out;
+
        /*
         * The nested attribute uses enum nl80211_band as the index. This maps
         * directly to the enum ieee80211_band values used in cfg80211.
@@ -7391,31 +7459,44 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
                            nla_len(tb[NL80211_TXRATE_LEGACY]))
                                return -EINVAL;
                }
-               if (tb[NL80211_TXRATE_MCS]) {
+               if (tb[NL80211_TXRATE_HT]) {
                        if (!ht_rateset_to_mask(
                                        sband,
-                                       nla_data(tb[NL80211_TXRATE_MCS]),
-                                       nla_len(tb[NL80211_TXRATE_MCS]),
-                                       mask.control[band].mcs))
+                                       nla_data(tb[NL80211_TXRATE_HT]),
+                                       nla_len(tb[NL80211_TXRATE_HT]),
+                                       mask.control[band].ht_mcs))
+                               return -EINVAL;
+               }
+               if (tb[NL80211_TXRATE_VHT]) {
+                       if (!vht_set_mcs_mask(
+                                       sband,
+                                       nla_data(tb[NL80211_TXRATE_VHT]),
+                                       mask.control[band].vht_mcs))
                                return -EINVAL;
                }
 
                if (mask.control[band].legacy == 0) {
-                       /* don't allow empty legacy rates if HT
-                        * is not even supported. */
-                       if (!rdev->wiphy.bands[band]->ht_cap.ht_supported)
+                       /* don't allow empty legacy rates if HT or VHT
+                        * are not even supported.
+                        */
+                       if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
+                             rdev->wiphy.bands[band]->vht_cap.vht_supported))
                                return -EINVAL;
 
                        for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
-                               if (mask.control[band].mcs[i])
-                                       break;
+                               if (mask.control[band].ht_mcs[i])
+                                       goto out;
+
+                       for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
+                               if (mask.control[band].vht_mcs[i])
+                                       goto out;
 
                        /* legacy and mcs rates may not be both empty */
-                       if (i == IEEE80211_HT_MCS_MASK_LEN)
-                               return -EINVAL;
+                       return -EINVAL;
                }
        }
 
+out:
        return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
 }
 
@@ -8875,6 +8956,111 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,
        return 0;
 }
 
+static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct wireless_dev *wdev =
+               __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
+       int i, err;
+       u32 vid, subcmd;
+
+       if (!rdev->wiphy.vendor_commands)
+               return -EOPNOTSUPP;
+
+       if (IS_ERR(wdev)) {
+               err = PTR_ERR(wdev);
+               if (err != -EINVAL)
+                       return err;
+               wdev = NULL;
+       } else if (wdev->wiphy != &rdev->wiphy) {
+               return -EINVAL;
+       }
+
+       if (!info->attrs[NL80211_ATTR_VENDOR_ID] ||
+           !info->attrs[NL80211_ATTR_VENDOR_SUBCMD])
+               return -EINVAL;
+
+       vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]);
+       subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]);
+       for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) {
+               const struct wiphy_vendor_command *vcmd;
+               void *data = NULL;
+               int len = 0;
+
+               vcmd = &rdev->wiphy.vendor_commands[i];
+
+               if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd)
+                       continue;
+
+               if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV |
+                                  WIPHY_VENDOR_CMD_NEED_NETDEV)) {
+                       if (!wdev)
+                               return -EINVAL;
+                       if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV &&
+                           !wdev->netdev)
+                               return -EINVAL;
+
+                       if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) {
+                               if (wdev->netdev &&
+                                   !netif_running(wdev->netdev))
+                                       return -ENETDOWN;
+                               if (!wdev->netdev && !wdev->p2p_started)
+                                       return -ENETDOWN;
+                       }
+               } else {
+                       wdev = NULL;
+               }
+
+               if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {
+                       data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);
+                       len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]);
+               }
+
+               rdev->cur_cmd_info = info;
+               err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev,
+                                                         data, len);
+               rdev->cur_cmd_info = NULL;
+               return err;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy,
+                                          enum nl80211_commands cmd,
+                                          enum nl80211_attrs attr,
+                                          int approxlen)
+{
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+       if (WARN_ON(!rdev->cur_cmd_info))
+               return NULL;
+
+       return __cfg80211_alloc_vendor_skb(rdev, approxlen,
+                                          rdev->cur_cmd_info->snd_portid,
+                                          rdev->cur_cmd_info->snd_seq,
+                                          cmd, attr, GFP_KERNEL);
+}
+EXPORT_SYMBOL(__cfg80211_alloc_reply_skb);
+
+int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
+{
+       struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
+       void *hdr = ((void **)skb->cb)[1];
+       struct nlattr *data = ((void **)skb->cb)[2];
+
+       if (WARN_ON(!rdev->cur_cmd_info)) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
+       nla_nest_end(skb, data);
+       genlmsg_end(skb, hdr);
+       return genlmsg_reply(skb, rdev->cur_cmd_info);
+}
+EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
+
+
 #define NL80211_FLAG_NEED_WIPHY                0x01
 #define NL80211_FLAG_NEED_NETDEV       0x02
 #define NL80211_FLAG_NEED_RTNL         0x04
@@ -9599,6 +9785,14 @@ static const struct genl_ops nl80211_ops[] = {
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL80211_CMD_VENDOR,
+               .doit = nl80211_vendor_cmd,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_WIPHY |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
 };
 
 /* notification functions */
index ec54e1a..7d20d84 100644 (file)
@@ -135,6 +135,33 @@ static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
        return "Unknown";
 }
 
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
+{
+       const struct ieee80211_regdomain *regd = NULL;
+       const struct ieee80211_regdomain *wiphy_regd = NULL;
+
+       regd = get_cfg80211_regdom();
+       if (!wiphy)
+               goto out;
+
+       wiphy_regd = get_wiphy_regdom(wiphy);
+       if (!wiphy_regd)
+               goto out;
+
+       if (wiphy_regd->dfs_region == regd->dfs_region)
+               goto out;
+
+       REG_DBG_PRINT("%s: device specific dfs_region "
+                     "(%s) disagrees with cfg80211's "
+                     "central dfs_region (%s)\n",
+                     dev_name(&wiphy->dev),
+                     reg_dfs_region_str(wiphy_regd->dfs_region),
+                     reg_dfs_region_str(regd->dfs_region));
+
+out:
+       return regd->dfs_region;
+}
+
 static void rcu_free_regdom(const struct ieee80211_regdomain *r)
 {
        if (!r)
index cc4c2c0..02bd8f4 100644 (file)
@@ -21,6 +21,7 @@ extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
 bool reg_is_valid_request(const char *alpha2);
 bool is_world_regdom(const char *alpha2);
 bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
 
 int regulatory_hint_user(const char *alpha2,
                         enum nl80211_user_reg_hint_type user_reg_hint_type);
index d4397eb..a32d52a 100644 (file)
@@ -161,7 +161,7 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
                dev->bss_generation++;
 }
 
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 {
        struct cfg80211_scan_request *request;
        struct wireless_dev *wdev;
@@ -210,17 +210,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
                dev_put(wdev->netdev);
 
        rdev->scan_req = NULL;
-
-       /*
-        * OK. If this is invoked with "leak" then we can't
-        * free this ... but we've cleaned it up anyway. The
-        * driver failed to call the scan_done callback, so
-        * all bets are off, it might still be trying to use
-        * the scan request or not ... if it accesses the dev
-        * in there (it shouldn't anyway) then it may crash.
-        */
-       if (!leak)
-               kfree(request);
+       kfree(request);
 }
 
 void __cfg80211_scan_done(struct work_struct *wk)
@@ -231,7 +221,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
                            scan_done_wk);
 
        rtnl_lock();
-       ___cfg80211_scan_done(rdev, false);
+       ___cfg80211_scan_done(rdev);
        rtnl_unlock();
 }