Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Tue, 3 Jan 2012 20:16:34 +0000 (15:16 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 3 Jan 2012 20:16:34 +0000 (15:16 -0500)
Conflicts:
drivers/net/wireless/b43/dma.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c

179 files changed:
drivers/bluetooth/btusb.c
drivers/net/wireless/ath/Makefile
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath6kl/Kconfig
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/bmi.c
drivers/net/wireless/ath/ath6kl/bmi.h
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/hif-ops.h
drivers/net/wireless/ath/ath6kl/hif.c
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/target.h
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/usb.c [new file with mode: 0644]
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9002_calib.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_mci.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/calib.c
drivers/net/wireless/ath/ath9k/dfs.c
drivers/net/wireless/ath/ath9k/dfs_debug.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/mci.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/wmi.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/key.c
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/Makefile
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-bus.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-led.h
drivers/net/wireless/iwlwifi/iwl-mac80211.c
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-testmode.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-ucode.c
drivers/net/wireless/iwlwifi/iwl-wifi.h [new file with mode: 0644]
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/ioctl.h
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx_platform_data.c
include/linux/nl80211.h
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/bluetooth/mgmt.h
include/net/bluetooth/smp.h
include/net/cfg80211.h
include/net/mac80211.h
net/bluetooth/Kconfig
net/bluetooth/Makefile
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/Kconfig
net/bluetooth/cmtp/Kconfig
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/hci_sysfs.c
net/bluetooth/hidp/Kconfig
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/rfcomm/Kconfig
net/bluetooth/rfcomm/core.c
net/bluetooth/sco.c
net/bluetooth/smp.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/nfc/llcp/llcp.c
net/nfc/nfc.h
net/wireless/nl80211.c

index ea5ad1cbbd3d80be1b1277b414dc2417d82bef00..fbfba802a3d77baa018ebb61b9d2b3fd3f0df9f6 100644 (file)
@@ -101,6 +101,7 @@ static struct usb_device_id btusb_table[] = {
        { USB_DEVICE(0x0c10, 0x0000) },
 
        /* Broadcom BCM20702A0 */
+       { USB_DEVICE(0x0a5c, 0x21e3) },
        { USB_DEVICE(0x413c, 0x8197) },
 
        { }     /* Terminating entry */
@@ -508,15 +509,10 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
 
        pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
 
-       urb->dev      = data->udev;
-       urb->pipe     = pipe;
-       urb->context  = hdev;
-       urb->complete = btusb_isoc_complete;
-       urb->interval = data->isoc_rx_ep->bInterval;
+       usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
+                               hdev, data->isoc_rx_ep->bInterval);
 
        urb->transfer_flags  = URB_FREE_BUFFER | URB_ISO_ASAP;
-       urb->transfer_buffer = buf;
-       urb->transfer_buffer_length = size;
 
        __fill_isoc_descriptor(urb, size,
                        le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
index d1214696a35b89411d3d62642032b496b2419415..d716b748e57440311b1912b6b99ba99930ed32f4 100644 (file)
@@ -11,3 +11,4 @@ ath-objs :=   main.o \
                key.o
 
 ath-$(CONFIG_ATH_DEBUG) += debug.o
+ccflags-y += -D__CHECK_ENDIAN__
index c1d699fd5717ad892e365ee4065e9eaa74d35183..efc01110dc344aa11c9fccfc3fe56b3c046f1bf2 100644 (file)
@@ -255,7 +255,7 @@ enum ATH_DEBUG {
 
 #define ath_dbg(common, dbg_mask, fmt, ...)                            \
 do {                                                                   \
-       if ((common)->debug_mask & dbg_mask)                            \
+       if ((common)->debug_mask & ATH_DBG_##dbg_mask)                  \
                _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__);    \
 } while (0)
 
@@ -265,10 +265,13 @@ do {                                                                      \
 #else
 
 static inline  __attribute__ ((format (printf, 3, 4)))
-void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
+void _ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
             const char *fmt, ...)
 {
 }
+#define ath_dbg(common, dbg_mask, fmt, ...)                            \
+       _ath_dbg(common, ATH_DBG_##dbg_mask, fmt, ##__VA_ARGS__)
+
 #define ATH_DBG_WARN(foo, arg...) do {} while (0)
 #define ATH_DBG_WARN_ON_ONCE(foo) ({                           \
        int __ret_warn_once = !!(foo);                          \
index 3d5f8be20eac588435498745f0ae41d2b64ae975..d755a5e7ed2036b9f7e237431413cd093fed07fc 100644 (file)
@@ -1,12 +1,29 @@
 config ATH6KL
-       tristate "Atheros ath6kl support"
+       tristate "Atheros mobile chipsets support"
+
+config ATH6KL_SDIO
+       tristate "Atheros ath6kl SDIO support"
+       depends on ATH6KL
        depends on MMC
        depends on CFG80211
        ---help---
          This module adds support for wireless adapters based on
-         Atheros AR6003 chipset running over SDIO. If you choose to
-         build it as a module, it will be called ath6kl. Pls note
-         that AR6002 and AR6001 are not supported by this driver.
+         Atheros AR6003 and AR6004 chipsets running over SDIO. If you
+         choose to build it as a module, it will be called ath6kl_sdio.
+         Please note that AR6002 and AR6001 are not supported by this
+         driver.
+
+config ATH6KL_USB
+       tristate "Atheros ath6kl USB support"
+       depends on ATH6KL
+       depends on USB
+       depends on CFG80211
+       depends on EXPERIMENTAL
+       ---help---
+         This module adds support for wireless adapters based on
+         Atheros AR6004 chipset running over USB. This is still under
+         implementation and it isn't functional. If you choose to
+         build it as a module, it will be called ath6kl_usb.
 
 config ATH6KL_DEBUG
        bool "Atheros ath6kl debugging"
index 707069303550e9eae103f533875eb72b3376d9fb..e14cef9c3c0e8d7828a78c45d2ebcd26289a15b2 100644 (file)
 # Author(s): ="Atheros"
 #------------------------------------------------------------------------------
 
-obj-$(CONFIG_ATH6KL) := ath6kl.o
-ath6kl-y += debug.o
-ath6kl-y += hif.o
-ath6kl-y += htc.o
-ath6kl-y += bmi.o
-ath6kl-y += cfg80211.o
-ath6kl-y += init.o
-ath6kl-y += main.o
-ath6kl-y += txrx.o
-ath6kl-y += wmi.o
-ath6kl-y += sdio.o
-ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
+obj-$(CONFIG_ATH6KL_SDIO) := ath6kl_sdio.o
+ath6kl_sdio-y += debug.o
+ath6kl_sdio-y += hif.o
+ath6kl_sdio-y += htc.o
+ath6kl_sdio-y += bmi.o
+ath6kl_sdio-y += cfg80211.o
+ath6kl_sdio-y += init.o
+ath6kl_sdio-y += main.o
+ath6kl_sdio-y += txrx.o
+ath6kl_sdio-y += wmi.o
+ath6kl_sdio-y += sdio.o
+ath6kl_sdio-$(CONFIG_NL80211_TESTMODE) += testmode.o
+
+obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o
+ath6kl_usb-y += debug.o
+ath6kl_usb-y += hif.o
+ath6kl_usb-y += htc.o
+ath6kl_usb-y += bmi.o
+ath6kl_usb-y += cfg80211.o
+ath6kl_usb-y += init.o
+ath6kl_usb-y += main.o
+ath6kl_usb-y += txrx.o
+ath6kl_usb-y += wmi.o
+ath6kl_usb-y += usb.o
+ath6kl_usb-$(CONFIG_NL80211_TESTMODE) += testmode.o
 
 ccflags-y += -D__CHECK_ENDIAN__
index a962fe4c6b7e43d612b8cda710df01239a55305d..aef00d5a1438ce501408e8d1055cac00df449977 100644 (file)
 #include "target.h"
 #include "debug.h"
 
-static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
-{
-       u32 addr;
-       unsigned long timeout;
-       int ret;
-
-       ar->bmi.cmd_credits = 0;
-
-       /* Read the counter register to get the command credits */
-       addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
-
-       timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
-       while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) {
-
-               /*
-                * Hit the credit counter with a 4-byte access, the first byte
-                * read will hit the counter and cause a decrement, while the
-                * remaining 3 bytes has no effect. The rationale behind this
-                * is to make all HIF accesses 4-byte aligned.
-                */
-               ret = hif_read_write_sync(ar, addr,
-                                        (u8 *)&ar->bmi.cmd_credits, 4,
-                                        HIF_RD_SYNC_BYTE_INC);
-               if (ret) {
-                       ath6kl_err("Unable to decrement the command credit count register: %d\n",
-                                  ret);
-                       return ret;
-               }
-
-               /* The counter is only 8 bits.
-                * Ignore anything in the upper 3 bytes
-                */
-               ar->bmi.cmd_credits &= 0xFF;
-       }
-
-       if (!ar->bmi.cmd_credits) {
-               ath6kl_err("bmi communication timeout\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar)
-{
-       unsigned long timeout;
-       u32 rx_word = 0;
-       int ret = 0;
-
-       timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
-       while (time_before(jiffies, timeout) && !rx_word) {
-               ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS,
-                                         (u8 *)&rx_word, sizeof(rx_word),
-                                         HIF_RD_SYNC_BYTE_INC);
-               if (ret) {
-                       ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n");
-                       return ret;
-               }
-
-                /* all we really want is one bit */
-               rx_word &= (1 << ENDPOINT1);
-       }
-
-       if (!rx_word) {
-               ath6kl_err("bmi_recv_buf FIFO empty\n");
-               return -EINVAL;
-       }
-
-       return ret;
-}
-
-static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
-{
-       int ret;
-       u32 addr;
-
-       ret = ath6kl_get_bmi_cmd_credits(ar);
-       if (ret)
-               return ret;
-
-       addr = ar->mbox_info.htc_addr;
-
-       ret = hif_read_write_sync(ar, addr, buf, len,
-                                 HIF_WR_SYNC_BYTE_INC);
-       if (ret)
-               ath6kl_err("unable to send the bmi data to the device\n");
-
-       return ret;
-}
-
-static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len)
-{
-       int ret;
-       u32 addr;
-
-       /*
-        * During normal bootup, small reads may be required.
-        * Rather than issue an HIF Read and then wait as the Target
-        * adds successive bytes to the FIFO, we wait here until
-        * we know that response data is available.
-        *
-        * This allows us to cleanly timeout on an unexpected
-        * Target failure rather than risk problems at the HIF level.
-        * In particular, this avoids SDIO timeouts and possibly garbage
-        * data on some host controllers.  And on an interconnect
-        * such as Compact Flash (as well as some SDIO masters) which
-        * does not provide any indication on data timeout, it avoids
-        * a potential hang or garbage response.
-        *
-        * Synchronization is more difficult for reads larger than the
-        * size of the MBOX FIFO (128B), because the Target is unable
-        * to push the 129th byte of data until AFTER the Host posts an
-        * HIF Read and removes some FIFO data.  So for large reads the
-        * Host proceeds to post an HIF Read BEFORE all the data is
-        * actually available to read.  Fortunately, large BMI reads do
-        * not occur in practice -- they're supported for debug/development.
-        *
-        * So Host/Target BMI synchronization is divided into these cases:
-        *  CASE 1: length < 4
-        *        Should not happen
-        *
-        *  CASE 2: 4 <= length <= 128
-        *        Wait for first 4 bytes to be in FIFO
-        *        If CONSERVATIVE_BMI_READ is enabled, also wait for
-        *        a BMI command credit, which indicates that the ENTIRE
-        *        response is available in the the FIFO
-        *
-        *  CASE 3: length > 128
-        *        Wait for the first 4 bytes to be in FIFO
-        *
-        * For most uses, a small timeout should be sufficient and we will
-        * usually see a response quickly; but there may be some unusual
-        * (debug) cases of BMI_EXECUTE where we want an larger timeout.
-        * For now, we use an unbounded busy loop while waiting for
-        * BMI_EXECUTE.
-        *
-        * If BMI_EXECUTE ever needs to support longer-latency execution,
-        * especially in production, this code needs to be enhanced to sleep
-        * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
-        * a function of Host processor speed.
-        */
-       if (len >= 4) { /* NB: Currently, always true */
-               ret = ath6kl_bmi_get_rx_lkahd(ar);
-               if (ret)
-                       return ret;
-       }
-
-       addr = ar->mbox_info.htc_addr;
-       ret = hif_read_write_sync(ar, addr, buf, len,
-                                 HIF_RD_SYNC_BYTE_INC);
-       if (ret) {
-               ath6kl_err("Unable to read the bmi data from the device: %d\n",
-                          ret);
-               return ret;
-       }
-
-       return 0;
-}
-
 int ath6kl_bmi_done(struct ath6kl *ar)
 {
        int ret;
@@ -190,7 +31,7 @@ int ath6kl_bmi_done(struct ath6kl *ar)
 
        ar->bmi.done_sent = true;
 
-       ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
+       ret = ath6kl_hif_bmi_write(ar, (u8 *)&cid, sizeof(cid));
        if (ret) {
                ath6kl_err("Unable to send bmi done: %d\n", ret);
                return ret;
@@ -210,14 +51,20 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
                return -EACCES;
        }
 
-       ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
+       ret = ath6kl_hif_bmi_write(ar, (u8 *)&cid, sizeof(cid));
        if (ret) {
                ath6kl_err("Unable to send get target info: %d\n", ret);
                return ret;
        }
 
-       ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version,
-                                 sizeof(targ_info->version));
+       if (ar->hif_type == ATH6KL_HIF_TYPE_USB) {
+               ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info,
+                                         sizeof(*targ_info));
+       } else {
+               ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version,
+                               sizeof(targ_info->version));
+       }
+
        if (ret) {
                ath6kl_err("Unable to recv target info: %d\n", ret);
                return ret;
@@ -225,7 +72,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
 
        if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) {
                /* Determine how many bytes are in the Target's targ_info */
-               ret = ath6kl_bmi_recv_buf(ar,
+               ret = ath6kl_hif_bmi_read(ar,
                                   (u8 *)&targ_info->byte_count,
                                   sizeof(targ_info->byte_count));
                if (ret) {
@@ -244,7 +91,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
                }
 
                /* Read the remainder of the targ_info */
-               ret = ath6kl_bmi_recv_buf(ar,
+               ret = ath6kl_hif_bmi_read(ar,
                                   ((u8 *)targ_info) +
                                   sizeof(targ_info->byte_count),
                                   sizeof(*targ_info) -
@@ -276,8 +123,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
                return -EACCES;
        }
 
-       size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       size = ar->bmi.max_data_size + sizeof(cid) + sizeof(addr) + sizeof(len);
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -290,8 +137,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
        len_remain = len;
 
        while (len_remain) {
-               rx_len = (len_remain < BMI_DATASZ_MAX) ?
-                                       len_remain : BMI_DATASZ_MAX;
+               rx_len = (len_remain < ar->bmi.max_data_size) ?
+                                       len_remain : ar->bmi.max_data_size;
                offset = 0;
                memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
                offset += sizeof(cid);
@@ -300,13 +147,13 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
                memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len));
                offset += sizeof(len);
 
-               ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+               ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
                if (ret) {
                        ath6kl_err("Unable to write to the device: %d\n",
                                   ret);
                        return ret;
                }
-               ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len);
+               ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, rx_len);
                if (ret) {
                        ath6kl_err("Unable to read from the device: %d\n",
                                   ret);
@@ -326,7 +173,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
        u32 offset;
        u32 len_remain, tx_len;
        const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len);
-       u8 aligned_buf[BMI_DATASZ_MAX];
+       u8 aligned_buf[400];
        u8 *src;
 
        if (ar->bmi.done_sent) {
@@ -334,12 +181,15 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
                return -EACCES;
        }
 
-       if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) {
+       if ((ar->bmi.max_data_size + header) > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
 
-       memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header);
+       if (WARN_ON(ar->bmi.max_data_size > sizeof(aligned_buf)))
+               return -E2BIG;
+
+       memset(ar->bmi.cmd_buf, 0, ar->bmi.max_data_size + header);
 
        ath6kl_dbg(ATH6KL_DBG_BMI,
                  "bmi write memory: addr: 0x%x, len: %d\n", addr, len);
@@ -348,7 +198,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
        while (len_remain) {
                src = &buf[len - len_remain];
 
-               if (len_remain < (BMI_DATASZ_MAX - header)) {
+               if (len_remain < (ar->bmi.max_data_size - header)) {
                        if (len_remain & 3) {
                                /* align it with 4 bytes */
                                len_remain = len_remain +
@@ -358,7 +208,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
                        }
                        tx_len = len_remain;
                } else {
-                       tx_len = (BMI_DATASZ_MAX - header);
+                       tx_len = (ar->bmi.max_data_size - header);
                }
 
                offset = 0;
@@ -371,7 +221,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
                memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len);
                offset += tx_len;
 
-               ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+               ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
                if (ret) {
                        ath6kl_err("Unable to write to the device: %d\n",
                                   ret);
@@ -396,7 +246,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
        }
 
        size = sizeof(cid) + sizeof(addr) + sizeof(param);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -413,13 +263,13 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
        memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param));
        offset += sizeof(*param);
 
-       ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+       ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
        if (ret) {
                ath6kl_err("Unable to write to the device: %d\n", ret);
                return ret;
        }
 
-       ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
+       ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, sizeof(*param));
        if (ret) {
                ath6kl_err("Unable to read from the device: %d\n", ret);
                return ret;
@@ -443,7 +293,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
        }
 
        size = sizeof(cid) + sizeof(addr);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -457,7 +307,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
        memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
        offset += sizeof(addr);
 
-       ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+       ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
        if (ret) {
                ath6kl_err("Unable to write to the device: %d\n", ret);
                return ret;
@@ -479,7 +329,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
        }
 
        size = sizeof(cid) + sizeof(addr);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -493,13 +343,13 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
        memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
        offset += sizeof(addr);
 
-       ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+       ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
        if (ret) {
                ath6kl_err("Unable to write to the device: %d\n", ret);
                return ret;
        }
 
-       ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
+       ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, sizeof(*param));
        if (ret) {
                ath6kl_err("Unable to read from the device: %d\n", ret);
                return ret;
@@ -522,7 +372,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
        }
 
        size = sizeof(cid) + sizeof(addr) + sizeof(param);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -540,7 +390,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
        memcpy(&(ar->bmi.cmd_buf[offset]), &param, sizeof(param));
        offset += sizeof(param);
 
-       ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+       ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
        if (ret) {
                ath6kl_err("Unable to write to the device: %d\n", ret);
                return ret;
@@ -563,8 +413,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
                return -EACCES;
        }
 
-       size = BMI_DATASZ_MAX + header;
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       size = ar->bmi.max_data_size + header;
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -575,8 +425,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
 
        len_remain = len;
        while (len_remain) {
-               tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ?
-                         len_remain : (BMI_DATASZ_MAX - header);
+               tx_len = (len_remain < (ar->bmi.max_data_size - header)) ?
+                         len_remain : (ar->bmi.max_data_size - header);
 
                offset = 0;
                memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
@@ -587,7 +437,7 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
                        tx_len);
                offset += tx_len;
 
-               ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+               ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
                if (ret) {
                        ath6kl_err("Unable to write to the device: %d\n",
                                   ret);
@@ -613,7 +463,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
        }
 
        size = sizeof(cid) + sizeof(addr);
-       if (size > MAX_BMI_CMDBUF_SZ) {
+       if (size > ar->bmi.max_cmd_size) {
                WARN_ON(1);
                return -EINVAL;
        }
@@ -629,7 +479,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
        memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
        offset += sizeof(addr);
 
-       ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
+       ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
        if (ret) {
                ath6kl_err("Unable to start LZ stream to the device: %d\n",
                           ret);
@@ -677,8 +527,13 @@ void ath6kl_bmi_reset(struct ath6kl *ar)
 
 int ath6kl_bmi_init(struct ath6kl *ar)
 {
-       ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
+       if (WARN_ON(ar->bmi.max_data_size == 0))
+               return -EINVAL;
+
+       /* cmd + addr + len + data_size */
+       ar->bmi.max_cmd_size = ar->bmi.max_data_size + (sizeof(u32) * 3);
 
+       ar->bmi.cmd_buf = kzalloc(ar->bmi.max_cmd_size, GFP_ATOMIC);
        if (!ar->bmi.cmd_buf)
                return -ENOMEM;
 
index 009e8f650ab1dc7f2f5de82c78fd9930074d846d..f1ca6812456df4d85c5bd85ef37c48c43b3c9c61 100644 (file)
  * BMI handles all required Target-side cache flushing.
  */
 
-#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
-                          (sizeof(u32) * 3 /* cmd + addr + len */))
-
-/* Maximum data size used for BMI transfers */
-#define BMI_DATASZ_MAX                      256
-
 /* BMI Commands */
 
 #define BMI_NO_COMMAND                      0
index 02526044acb925d4f360d2e6504e6326087f0c2a..6c59a217b1a133f390d1dd2f444494110660b9f7 100644 (file)
 #include "testmode.h"
 
 static unsigned int ath6kl_p2p;
-static unsigned int multi_norm_if_support;
 
 module_param(ath6kl_p2p, uint, 0644);
-module_param(multi_norm_if_support, uint, 0644);
 
 #define RATETAB_ENT(_rate, _rateid, _flags) {   \
        .bitrate    = (_rate),                  \
@@ -127,6 +125,37 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
 
 #define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
 
+/* returns true if scheduled scan was stopped */
+static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
+{
+       struct ath6kl *ar = vif->ar;
+
+       if (ar->state != ATH6KL_STATE_SCHED_SCAN)
+               return false;
+
+       del_timer_sync(&vif->sched_scan_timer);
+
+       ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                          ATH6KL_HOST_MODE_AWAKE);
+
+       ar->state = ATH6KL_STATE_ON;
+
+       return true;
+}
+
+static void ath6kl_cfg80211_sscan_disable(struct ath6kl_vif *vif)
+{
+       struct ath6kl *ar = vif->ar;
+       bool stopped;
+
+       stopped = __ath6kl_cfg80211_sscan_stop(vif);
+
+       if (!stopped)
+               return;
+
+       cfg80211_sched_scan_stopped(ar->wiphy);
+}
+
 static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
                                  enum nl80211_wpa_versions wpa_version)
 {
@@ -205,6 +234,10 @@ static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
                *ar_cipher = AES_CRYPT;
                *ar_cipher_len = 0;
                break;
+       case WLAN_CIPHER_SUITE_SMS4:
+               *ar_cipher = WAPI_CRYPT;
+               *ar_cipher_len = 0;
+               break;
        default:
                ath6kl_err("cipher 0x%x not supported\n", cipher);
                return -ENOTSUPP;
@@ -355,7 +388,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
 
        if (type == NL80211_IFTYPE_STATION ||
            type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
-               for (i = 0; i < MAX_NUM_VIF; i++) {
+               for (i = 0; i < ar->vif_max; i++) {
                        if ((ar->avail_idx_map >> i) & BIT(0)) {
                                *if_idx = i;
                                return true;
@@ -365,7 +398,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
 
        if (type == NL80211_IFTYPE_P2P_CLIENT ||
            type == NL80211_IFTYPE_P2P_GO) {
-               for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++) {
+               for (i = ar->max_norm_iface; i < ar->vif_max; i++) {
                        if ((ar->avail_idx_map >> i) & BIT(0)) {
                                *if_idx = i;
                                return true;
@@ -382,6 +415,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
        int status;
+       u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
+
+       ath6kl_cfg80211_sscan_disable(vif);
 
        vif->sme_state = SME_CONNECTING;
 
@@ -427,9 +463,12 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
        if (sme->ie && (sme->ie_len > 0)) {
                status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len);
-               if (status)
+               if (status) {
+                       up(&ar->sem);
                        return status;
-       }
+               }
+       } else
+               ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
 
        if (test_bit(CONNECTED, &vif->flags) &&
            vif->ssid_len == sme->ssid_len &&
@@ -519,6 +558,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
        vif->nw_type = vif->next_mode;
 
+       if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
+               nw_subtype = SUBTYPE_P2PCLIENT;
+
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                   "%s: connect called with authmode %d dot11 auth %d"
                   " PW crypto %d PW crypto len %d GRP crypto %d"
@@ -536,7 +578,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                                        vif->grp_crypto, vif->grp_crypto_len,
                                        vif->ssid_len, vif->ssid,
                                        vif->req_bssid, vif->ch_hint,
-                                       ar->connect_ctrl_flags);
+                                       ar->connect_ctrl_flags, nw_subtype);
 
        up(&ar->sem);
 
@@ -563,17 +605,28 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        return 0;
 }
 
-static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid,
+static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
+                                   enum network_type nw_type,
+                                   const u8 *bssid,
                                    struct ieee80211_channel *chan,
                                    const u8 *beacon_ie, size_t beacon_ie_len)
 {
        struct ath6kl *ar = vif->ar;
        struct cfg80211_bss *bss;
+       u16 cap_mask, cap_val;
        u8 *ie;
 
+       if (nw_type & ADHOC_NETWORK) {
+               cap_mask = WLAN_CAPABILITY_IBSS;
+               cap_val = WLAN_CAPABILITY_IBSS;
+       } else {
+               cap_mask = WLAN_CAPABILITY_ESS;
+               cap_val = WLAN_CAPABILITY_ESS;
+       }
+
        bss = cfg80211_get_bss(ar->wiphy, chan, bssid,
-                              vif->ssid, vif->ssid_len, WLAN_CAPABILITY_ESS,
-                              WLAN_CAPABILITY_ESS);
+                              vif->ssid, vif->ssid_len,
+                              cap_mask, cap_val);
        if (bss == NULL) {
                /*
                 * Since cfg80211 may not yet know about the BSS,
@@ -591,13 +644,12 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid,
                memcpy(ie + 2, vif->ssid, vif->ssid_len);
                memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
                bss = cfg80211_inform_bss(ar->wiphy, chan,
-                                         bssid, 0, WLAN_CAPABILITY_ESS, 100,
+                                         bssid, 0, cap_val, 100,
                                          ie, 2 + vif->ssid_len + beacon_ie_len,
                                          0, GFP_KERNEL);
                if (bss)
-                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for "
-                                  "%pM prior to indicating connect/roamed "
-                                  "event\n", bssid);
+                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
+                                  "cfg80211\n", bssid);
                kfree(ie);
        } else
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss "
@@ -660,16 +712,16 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
 
        chan = ieee80211_get_channel(ar->wiphy, (int) channel);
 
-
-       if (nw_type & ADHOC_NETWORK) {
-               cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
+       if (ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, assoc_info,
+                                    beacon_ie_len) < 0) {
+               ath6kl_err("could not add cfg80211 bss entry\n");
                return;
        }
 
-       if (ath6kl_add_bss_if_needed(vif, bssid, chan, assoc_info,
-                                    beacon_ie_len) < 0) {
-               ath6kl_err("could not add cfg80211 bss entry for "
-                          "connect/roamed notification\n");
+       if (nw_type & ADHOC_NETWORK) {
+               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
+                          nw_type & ADHOC_CREATOR ? "creator" : "joiner");
+               cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
                return;
        }
 
@@ -691,12 +743,14 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
 static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
                                      struct net_device *dev, u16 reason_code)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
+       struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
                   reason_code);
 
+       ath6kl_cfg80211_sscan_disable(vif);
+
        if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
@@ -789,7 +843,7 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
 static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                struct cfg80211_scan_request *request)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl *ar = ath6kl_priv(ndev);
        struct ath6kl_vif *vif = netdev_priv(ndev);
        s8 n_channels = 0;
        u16 *channels = NULL;
@@ -799,6 +853,8 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
        if (!ath6kl_cfg80211_ready(vif))
                return -EIO;
 
+       ath6kl_cfg80211_sscan_disable(vif);
+
        if (!ar->usr_bss_filter) {
                clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
                ret = ath6kl_wmi_bssfilter_cmd(
@@ -824,6 +880,10 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                                  request->ssids[i].ssid);
        }
 
+       /*
+        * FIXME: we should clear the IE in fw if it's not set so just
+        * remove the check altogether
+        */
        if (request->ie) {
                ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
                                               WMI_FRAME_PROBE_REQ,
@@ -860,9 +920,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
        if (test_bit(CONNECTED, &vif->flags))
                force_fg_scan = 1;
 
-       ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, WMI_LONG_SCAN,
-                                      force_fg_scan, false, 0, 0, n_channels,
-                                      channels);
+       if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+                   ar->fw_capabilities)) {
+               /*
+                * If capable of doing P2P mgmt operations using
+                * station interface, send additional information like
+                * supported rates to advertise and xmit rates for
+                * probe requests
+                */
+               ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
+                                               WMI_LONG_SCAN, force_fg_scan,
+                                               false, 0, 0, n_channels,
+                                               channels, request->no_cck,
+                                               request->rates);
+       } else {
+               ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
+                                               WMI_LONG_SCAN, force_fg_scan,
+                                               false, 0, 0, n_channels,
+                                               channels);
+       }
        if (ret)
                ath6kl_err("wmi_startscan_cmd failed\n");
        else
@@ -905,7 +981,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                                   const u8 *mac_addr,
                                   struct key_params *params)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl *ar = ath6kl_priv(ndev);
        struct ath6kl_vif *vif = netdev_priv(ndev);
        struct ath6kl_key *key = NULL;
        u8 key_usage;
@@ -937,13 +1013,19 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                key_usage = GROUP_USAGE;
 
        if (params) {
+               int seq_len = params->seq_len;
+               if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
+                   seq_len > ATH6KL_KEY_SEQ_LEN) {
+                       /* Only first half of the WPI PN is configured */
+                       seq_len = ATH6KL_KEY_SEQ_LEN;
+               }
                if (params->key_len > WLAN_MAX_KEY_LEN ||
-                   params->seq_len > sizeof(key->seq))
+                   seq_len > sizeof(key->seq))
                        return -EINVAL;
 
                key->key_len = params->key_len;
                memcpy(key->key, params->key, key->key_len);
-               key->seq_len = params->seq_len;
+               key->seq_len = seq_len;
                memcpy(key->seq, params->seq, key->seq_len);
                key->cipher = params->cipher;
        }
@@ -961,6 +1043,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
        case WLAN_CIPHER_SUITE_CCMP:
                key_type = AES_CRYPT;
                break;
+       case WLAN_CIPHER_SUITE_SMS4:
+               key_type = WAPI_CRYPT;
+               break;
 
        default:
                return -ENOTSUPP;
@@ -976,10 +1061,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                   __func__, key_index, key->key_len, key_type,
                   key_usage, key->seq_len);
 
-       vif->def_txkey_index = key_index;
-
        if (vif->nw_type == AP_NETWORK && !pairwise &&
-           (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
+           (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
+            key_type == WAPI_CRYPT) && params) {
                ar->ap_mode_bkey.valid = true;
                ar->ap_mode_bkey.key_index = key_index;
                ar->ap_mode_bkey.key_type = key_type;
@@ -1012,8 +1096,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                return 0;
        }
 
-       return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
-                                    vif->def_txkey_index,
+       return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
                                     key_type, key_usage, key->key_len,
                                     key->seq, key->seq_len, key->key,
                                     KEY_OP_INIT_VAL,
@@ -1024,7 +1107,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
                                   u8 key_index, bool pairwise,
                                   const u8 *mac_addr)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl *ar = ath6kl_priv(ndev);
        struct ath6kl_vif *vif = netdev_priv(ndev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
@@ -1090,7 +1173,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
                                           u8 key_index, bool unicast,
                                           bool multicast)
 {
-       struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
+       struct ath6kl *ar = ath6kl_priv(ndev);
        struct ath6kl_vif *vif = netdev_priv(ndev);
        struct ath6kl_key *key = NULL;
        u8 key_usage;
@@ -1181,11 +1264,12 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 */
 static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
                                       enum nl80211_tx_power_setting type,
-                                      int dbm)
+                                      int mbm)
 {
        struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
        struct ath6kl_vif *vif;
        u8 ath6kl_dbm;
+       int dbm = MBM_TO_DBM(mbm);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
                   type, dbm);
@@ -1288,7 +1372,7 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
        struct net_device *ndev;
        u8 if_idx, nw_type;
 
-       if (ar->num_vif == MAX_NUM_VIF) {
+       if (ar->num_vif == ar->vif_max) {
                ath6kl_err("Reached maximum number of supported vif\n");
                return ERR_PTR(-EINVAL);
        }
@@ -1333,9 +1417,6 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
 
-       if (!ath6kl_cfg80211_ready(vif))
-               return -EIO;
-
        switch (type) {
        case NL80211_IFTYPE_STATION:
                vif->next_mode = INFRA_NETWORK;
@@ -1426,7 +1507,7 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
                                        vif->grp_crypto, vif->grp_crypto_len,
                                        vif->ssid_len, vif->ssid,
                                        vif->req_bssid, vif->ch_hint,
-                                       ar->connect_ctrl_flags);
+                                       ar->connect_ctrl_flags, SUBTYPE_NONE);
        set_bit(CONNECT_PEND, &vif->flags);
 
        return 0;
@@ -1453,6 +1534,7 @@ static const u32 cipher_suites[] = {
        WLAN_CIPHER_SUITE_TKIP,
        WLAN_CIPHER_SUITE_CCMP,
        CCKM_KRK_CIPHER_SUITE,
+       WLAN_CIPHER_SUITE_SMS4,
 };
 
 static bool is_rate_legacy(s32 rate)
@@ -1779,7 +1861,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
        case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
 
-               ath6kl_cfg80211_stop(ar);
+               ath6kl_cfg80211_stop_all(ar);
 
                /* save the current power mode before enabling power save */
                ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
@@ -1796,7 +1878,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
        case ATH6KL_CFG_SUSPEND_CUTPOWER:
 
-               ath6kl_cfg80211_stop(ar);
+               ath6kl_cfg80211_stop_all(ar);
 
                if (ar->state == ATH6KL_STATE_OFF) {
                        ath6kl_dbg(ATH6KL_DBG_SUSPEND,
@@ -1816,6 +1898,13 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
                break;
 
+       case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
+               /*
+                * Nothing needed for schedule scan, firmware is already in
+                * wow mode and sleeping most of the time.
+                */
+               break;
+
        default:
                break;
        }
@@ -1864,6 +1953,9 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
                }
                break;
 
+       case ATH6KL_STATE_SCHED_SCAN:
+               break;
+
        default:
                break;
        }
@@ -1987,7 +2079,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        int ies_len;
        struct wmi_connect_cmd p;
        int res;
-       int i;
+       int i, ret;
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
 
@@ -2045,7 +2137,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
                return -EOPNOTSUPP; /* TODO */
 
-       vif->dot11_auth_mode = OPEN_AUTH;
+       ret = ath6kl_set_auth_type(vif, info->auth_type);
+       if (ret)
+               return ret;
 
        memset(&p, 0, sizeof(p));
 
@@ -2081,6 +2175,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
                case WLAN_CIPHER_SUITE_CCMP:
                        p.prwise_crypto_type |= AES_CRYPT;
                        break;
+               case WLAN_CIPHER_SUITE_SMS4:
+                       p.prwise_crypto_type |= WAPI_CRYPT;
+                       break;
                }
        }
        if (p.prwise_crypto_type == 0) {
@@ -2100,6 +2197,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        case WLAN_CIPHER_SUITE_CCMP:
                p.grp_crypto_type = AES_CRYPT;
                break;
+       case WLAN_CIPHER_SUITE_SMS4:
+               p.grp_crypto_type = WAPI_CRYPT;
+               break;
        default:
                p.grp_crypto_type = NONE_CRYPT;
                break;
@@ -2114,6 +2214,16 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
        p.dot11_auth_mode = vif->dot11_auth_mode;
        p.ch = cpu_to_le16(vif->next_chan);
 
+       if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
+               p.nw_subtype = SUBTYPE_P2PGO;
+       } else {
+               /*
+                * Due to firmware limitation, it is not possible to
+                * do P2P mgmt operations in AP mode
+                */
+               p.nw_subtype = SUBTYPE_NONE;
+       }
+
        res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
        if (res < 0)
                return res;
@@ -2279,9 +2389,23 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
        }
 
        *cookie = id;
-       return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
-                                         chan->center_freq, wait,
-                                         buf, len);
+
+       if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
+                   ar->fw_capabilities)) {
+               /*
+                * If capable of doing P2P mgmt operations using
+                * station interface, send additional information like
+                * supported rates to advertise and xmit rates for
+                * probe requests
+                */
+               return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
+                                               chan->center_freq, wait,
+                                               buf, len, no_cck);
+       } else {
+               return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
+                                                 chan->center_freq, wait,
+                                                 buf, len);
+       }
 }
 
 static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
@@ -2302,6 +2426,90 @@ static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
        }
 }
 
+static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
+                       struct net_device *dev,
+                       struct cfg80211_sched_scan_request *request)
+{
+       struct ath6kl *ar = ath6kl_priv(dev);
+       struct ath6kl_vif *vif = netdev_priv(dev);
+       u16 interval;
+       int ret;
+       u8 i;
+
+       if (ar->state != ATH6KL_STATE_ON)
+               return -EIO;
+
+       if (vif->sme_state != SME_DISCONNECTED)
+               return -EBUSY;
+
+       for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
+               ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
+                                         i, DISABLE_SSID_FLAG,
+                                         0, NULL);
+       }
+
+       /* fw uses seconds, also make sure that it's >0 */
+       interval = max_t(u16, 1, request->interval / 1000);
+
+       ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+                                 interval, interval,
+                                 10, 0, 0, 0, 3, 0, 0, 0);
+
+       if (request->n_ssids && request->ssids[0].ssid_len) {
+               for (i = 0; i < request->n_ssids; i++) {
+                       ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
+                                                 i, SPECIFIC_SSID_FLAG,
+                                                 request->ssids[i].ssid_len,
+                                                 request->ssids[i].ssid);
+               }
+       }
+
+       ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                         ATH6KL_WOW_MODE_ENABLE,
+                                         WOW_FILTER_SSID,
+                                         WOW_HOST_REQ_DELAY);
+       if (ret) {
+               ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
+               return ret;
+       }
+
+       /* this also clears IE in fw if it's not set */
+       ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
+                                      WMI_FRAME_PROBE_REQ,
+                                      request->ie, request->ie_len);
+       if (ret) {
+               ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
+                           ret);
+               return ret;
+       }
+
+       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                                ATH6KL_HOST_MODE_ASLEEP);
+       if (ret) {
+               ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
+                           ret);
+               return ret;
+       }
+
+       ar->state = ATH6KL_STATE_SCHED_SCAN;
+
+       return ret;
+}
+
+static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
+                                     struct net_device *dev)
+{
+       struct ath6kl_vif *vif = netdev_priv(dev);
+       bool stopped;
+
+       stopped = __ath6kl_cfg80211_sscan_stop(vif);
+
+       if (!stopped)
+               return -EIO;
+
+       return 0;
+}
+
 static const struct ieee80211_txrx_stypes
 ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
        [NL80211_IFTYPE_STATION] = {
@@ -2359,25 +2567,17 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
        .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
        .mgmt_tx = ath6kl_mgmt_tx,
        .mgmt_frame_register = ath6kl_mgmt_frame_register,
+       .sched_scan_start = ath6kl_cfg80211_sscan_start,
+       .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
 };
 
-void ath6kl_cfg80211_stop(struct ath6kl *ar)
+void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
 {
-       struct ath6kl_vif *vif;
-
-       /* FIXME: for multi vif */
-       vif = ath6kl_vif_first(ar);
-       if (!vif) {
-               /* save the current power mode before enabling power save */
-               ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
-
-               if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
-                       ath6kl_warn("ath6kl_deep_sleep_enable: "
-                                   "wmi_powermode_cmd failed\n");
-               return;
-       }
+       ath6kl_cfg80211_sscan_disable(vif);
 
        switch (vif->sme_state) {
+       case SME_DISCONNECTED:
+               break;
        case SME_CONNECTING:
                cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
                                        NULL, 0,
@@ -2385,33 +2585,50 @@ void ath6kl_cfg80211_stop(struct ath6kl *ar)
                                        GFP_KERNEL);
                break;
        case SME_CONNECTED:
-       default:
-               /*
-                * FIXME: oddly enough smeState is in DISCONNECTED during
-                * suspend, why? Need to send disconnected event in that
-                * state.
-                */
                cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
                break;
        }
 
        if (test_bit(CONNECTED, &vif->flags) ||
            test_bit(CONNECT_PEND, &vif->flags))
-               ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
+               ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
 
        vif->sme_state = SME_DISCONNECTED;
        clear_bit(CONNECTED, &vif->flags);
        clear_bit(CONNECT_PEND, &vif->flags);
 
        /* disable scanning */
-       if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,
-                                     0, 0, 0, 0, 0, 0, 0) != 0)
-               printk(KERN_WARNING "ath6kl: failed to disable scan "
-                      "during suspend\n");
+       if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
+                                     0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
+               ath6kl_warn("failed to disable scan during stop\n");
 
        ath6kl_cfg80211_scan_complete_event(vif, true);
 }
 
+void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
+{
+       struct ath6kl_vif *vif;
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif) {
+               /* save the current power mode before enabling power save */
+               ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+               if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
+                       ath6kl_warn("ath6kl_deep_sleep_enable: "
+                                   "wmi_powermode_cmd failed\n");
+               return;
+       }
+
+       /*
+        * FIXME: we should take ar->list_lock to protect changes in the
+        * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
+        * sleeps.
+        */
+       list_for_each_entry(vif, &ar->vif_list, list)
+               ath6kl_cfg80211_stop(vif);
+}
+
 struct ath6kl *ath6kl_core_alloc(struct device *dev)
 {
        struct ath6kl *ar;
@@ -2427,17 +2644,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
        }
 
        ar = wiphy_priv(wiphy);
-       if (!multi_norm_if_support)
-               ar->p2p = !!ath6kl_p2p;
+       ar->p2p = !!ath6kl_p2p;
        ar->wiphy = wiphy;
        ar->dev = dev;
 
-       if (multi_norm_if_support)
-               ar->max_norm_iface = 2;
-       else
-               ar->max_norm_iface = 1;
+       ar->vif_max = 1;
 
-       /* FIXME: Remove this once the multivif support is enabled */
        ar->max_norm_iface = 1;
 
        spin_lock_init(&ar->lock);
@@ -2459,9 +2671,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev)
        ar->tx_pwr = 0;
 
        ar->intra_bss = 1;
-       memset(&ar->sc_params, 0, sizeof(ar->sc_params));
-       ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
-       ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
        ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
 
        ar->state = ATH6KL_STATE_OFF;
@@ -2522,6 +2731,8 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
        wiphy->wowlan.pattern_min_len = 1;
        wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
 
+       wiphy->max_sched_scan_ssids = 10;
+
        ret = wiphy_register(wiphy);
        if (ret < 0) {
                ath6kl_err("couldn't register wiphy device\n");
@@ -2541,6 +2752,9 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif)
 
        setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
                    (unsigned long) vif->ndev);
+       setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer,
+                   (unsigned long) vif);
+
        set_bit(WMM_ENABLED, &vif->flags);
        spin_lock_init(&vif->if_lock);
 
index 59fa9d859def609a97d6f3ecb5760a9a25f5ee15..81f20a572315d8291d30a26711745d768eee663d 100644 (file)
@@ -20,7 +20,8 @@
 enum ath6kl_cfg_suspend_mode {
        ATH6KL_CFG_SUSPEND_DEEPSLEEP,
        ATH6KL_CFG_SUSPEND_CUTPOWER,
-       ATH6KL_CFG_SUSPEND_WOW
+       ATH6KL_CFG_SUSPEND_WOW,
+       ATH6KL_CFG_SUSPEND_SCHED_SCAN,
 };
 
 struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
@@ -52,6 +53,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
 int ath6kl_cfg80211_resume(struct ath6kl *ar);
 
-void ath6kl_cfg80211_stop(struct ath6kl *ar);
+void ath6kl_cfg80211_stop(struct ath6kl_vif *vif);
+void ath6kl_cfg80211_stop_all(struct ath6kl *ar);
 
 #endif /* ATH6KL_CFG80211_H */
index 41e465f29e6312afdde51bea46d39c84960abf2f..bfd6597763daa9dcb953aeb413cc5b62c68fcde4 100644 (file)
@@ -71,6 +71,7 @@ enum crypto_type {
        WEP_CRYPT           = 0x02,
        TKIP_CRYPT          = 0x04,
        AES_CRYPT           = 0x08,
+       WAPI_CRYPT          = 0x10,
 };
 
 struct htc_endpoint_credit_dist;
index e7e095e536a7e0bb34d81e4a63d1a87b159a2a14..c863a28f2e0c6f2a6b7477292cbc8be4fbe483e9 100644 (file)
@@ -70,10 +70,20 @@ enum ath6kl_fw_ie_type {
        ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5,
        ATH6KL_FW_IE_CAPABILITIES = 6,
        ATH6KL_FW_IE_PATCH_ADDR = 7,
+       ATH6KL_FW_IE_BOARD_ADDR = 8,
+       ATH6KL_FW_IE_VIF_MAX = 9,
 };
 
 enum ath6kl_fw_capability {
        ATH6KL_FW_CAPABILITY_HOST_P2P = 0,
+       ATH6KL_FW_CAPABILITY_SCHED_SCAN = 1,
+
+       /*
+        * Firmware is capable of supporting P2P mgmt operations on a
+        * station interface. After group formation, the station
+        * interface will become a P2P client/GO interface as the case may be
+        */
+       ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
 
        /* this needs to be last */
        ATH6KL_FW_CAPABILITY_MAX,
@@ -88,37 +98,47 @@ struct ath6kl_fw_ie {
 };
 
 /* AR6003 1.0 definitions */
-#define AR6003_REV1_VERSION                 0x300002ba
+#define AR6003_HW_1_0_VERSION                 0x300002ba
 
 /* AR6003 2.0 definitions */
-#define AR6003_REV2_VERSION                 0x30000384
-#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS  0x57e910
-#define AR6003_REV2_OTP_FILE                "ath6k/AR6003/hw2.0/otp.bin.z77"
-#define AR6003_REV2_FIRMWARE_FILE           "ath6k/AR6003/hw2.0/athwlan.bin.z77"
-#define AR6003_REV2_TCMD_FIRMWARE_FILE      "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
-#define AR6003_REV2_PATCH_FILE              "ath6k/AR6003/hw2.0/data.patch.bin"
-#define AR6003_REV2_FIRMWARE_2_FILE         "ath6k/AR6003/hw2.0/fw-2.bin"
-#define AR6003_REV2_BOARD_DATA_FILE         "ath6k/AR6003/hw2.0/bdata.bin"
-#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
+#define AR6003_HW_2_0_VERSION                 0x30000384
+#define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS  0x57e910
+#define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
+#define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
+#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
+#define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
+#define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
+#define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
+#define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \
+                       "ath6k/AR6003/hw2.0/bdata.SD31.bin"
 
 /* AR6003 3.0 definitions */
-#define AR6003_REV3_VERSION                 0x30000582
-#define AR6003_REV3_OTP_FILE                "ath6k/AR6003/hw2.1.1/otp.bin"
-#define AR6003_REV3_FIRMWARE_FILE           "ath6k/AR6003/hw2.1.1/athwlan.bin"
-#define AR6003_REV3_TCMD_FIRMWARE_FILE    "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
-#define AR6003_REV3_PATCH_FILE            "ath6k/AR6003/hw2.1.1/data.patch.bin"
-#define AR6003_REV3_FIRMWARE_2_FILE           "ath6k/AR6003/hw2.1.1/fw-2.bin"
-#define AR6003_REV3_BOARD_DATA_FILE       "ath6k/AR6003/hw2.1.1/bdata.bin"
-#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE    \
-       "ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
+#define AR6003_HW_2_1_1_VERSION                 0x30000582
+#define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
+#define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
+#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \
+                       "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
+#define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
+#define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
+#define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
+#define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE        \
+                       "ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
 
 /* AR6004 1.0 definitions */
-#define AR6004_REV1_VERSION                 0x30000623
-#define AR6004_REV1_FIRMWARE_FILE           "ath6k/AR6004/hw6.1/fw.ram.bin"
-#define AR6004_REV1_FIRMWARE_2_FILE         "ath6k/AR6004/hw6.1/fw-2.bin"
-#define AR6004_REV1_BOARD_DATA_FILE         "ath6k/AR6004/hw6.1/bdata.bin"
-#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin"
-#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin"
+#define AR6004_HW_1_0_VERSION                 0x30000623
+#define AR6004_HW_1_0_FIRMWARE_2_FILE         "ath6k/AR6004/hw1.0/fw-2.bin"
+#define AR6004_HW_1_0_FIRMWARE_FILE           "ath6k/AR6004/hw1.0/fw.ram.bin"
+#define AR6004_HW_1_0_BOARD_DATA_FILE         "ath6k/AR6004/hw1.0/bdata.bin"
+#define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \
+       "ath6k/AR6004/hw1.0/bdata.DB132.bin"
+
+/* AR6004 1.1 definitions */
+#define AR6004_HW_1_1_VERSION                 0x30000001
+#define AR6004_HW_1_1_FIRMWARE_2_FILE         "ath6k/AR6004/hw1.1/fw-2.bin"
+#define AR6004_HW_1_1_FIRMWARE_FILE           "ath6k/AR6004/hw1.1/fw.ram.bin"
+#define AR6004_HW_1_1_BOARD_DATA_FILE         "ath6k/AR6004/hw1.1/bdata.bin"
+#define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \
+       "ath6k/AR6004/hw1.1/bdata.DB132.bin"
 
 /* Per STA data, used in AP mode */
 #define STA_PS_AWAKE           BIT(0)
@@ -272,6 +292,8 @@ struct ath6kl_bmi {
        u32 cmd_credits;
        bool done_sent;
        u8 *cmd_buf;
+       u32 max_data_size;
+       u32 max_cmd_size;
 };
 
 struct target_stats {
@@ -381,7 +403,16 @@ struct ath6kl_req_key {
        u8 key_len;
 };
 
-#define MAX_NUM_VIF    1
+enum ath6kl_hif_type {
+       ATH6KL_HIF_TYPE_SDIO,
+       ATH6KL_HIF_TYPE_USB,
+};
+
+/*
+ * Driver's maximum limit, note that some firmwares support only one vif
+ * and the runtime (current) limit must be checked from ar->vif_max.
+ */
+#define ATH6KL_VIF_MAX 3
 
 /* vif flags info */
 enum ath6kl_vif_state {
@@ -424,7 +455,10 @@ struct ath6kl_vif {
        struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
        struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
        struct aggr_info *aggr_cntxt;
+
        struct timer_list disconnect_timer;
+       struct timer_list sched_scan_timer;
+
        struct cfg80211_scan_request *scan_req;
        enum sme_state sme_state;
        int reconnect_flag;
@@ -442,6 +476,8 @@ struct ath6kl_vif {
 #define WOW_LIST_ID            0
 #define WOW_HOST_REQ_DELAY     500 /* ms */
 
+#define ATH6KL_SCHED_SCAN_RESULT_DELAY 5000 /* ms */
+
 /* Flag info */
 enum ath6kl_dev_state {
        WMI_ENABLED,
@@ -460,6 +496,7 @@ enum ath6kl_state {
        ATH6KL_STATE_DEEPSLEEP,
        ATH6KL_STATE_CUTPOWER,
        ATH6KL_STATE_WOW,
+       ATH6KL_STATE_SCHED_SCAN,
 };
 
 struct ath6kl {
@@ -474,11 +511,13 @@ struct ath6kl {
        int tx_pending[ENDPOINT_MAX];
        int total_tx_data_pend;
        struct htc_target *htc_target;
+       enum ath6kl_hif_type hif_type;
        void *hif_priv;
        struct list_head vif_list;
        /* Lock to avoid race in vif_list entries among add/del/traverse */
        spinlock_t list_lock;
        u8 num_vif;
+       unsigned int vif_max;
        u8 max_norm_iface;
        u8 avail_idx_map;
        spinlock_t lock;
@@ -517,7 +556,6 @@ struct ath6kl {
        struct list_head amsdu_rx_buffer_queue;
        u8 rx_meta_ver;
        enum wlan_low_pwr_state wlan_pwr_state;
-       struct wmi_scan_params_cmd sc_params;
        u8 mac_addr[ETH_ALEN];
 #define AR_MCAST_FILTER_MAC_ADDR_SIZE  4
        struct {
@@ -525,12 +563,25 @@ struct ath6kl {
                size_t rx_report_len;
        } tm;
 
-       struct {
+       struct ath6kl_hw {
+               u32 id;
+               const char *name;
                u32 dataset_patch_addr;
                u32 app_load_addr;
                u32 app_start_override_addr;
                u32 board_ext_data_addr;
                u32 reserved_ram_size;
+               u32 board_addr;
+               u32 refclk_hz;
+               u32 uarttx_pin;
+
+               const char *fw_otp;
+               const char *fw;
+               const char *fw_tcmd;
+               const char *fw_patch;
+               const char *fw_api2;
+               const char *fw_board;
+               const char *fw_default_board;
        } hw;
 
        u16 conf_flags;
@@ -583,7 +634,7 @@ struct ath6kl {
 #endif /* CONFIG_ATH6KL_DEBUG */
 };
 
-static inline void *ath6kl_priv(struct net_device *dev)
+static inline struct ath6kl *ath6kl_priv(struct net_device *dev)
 {
        return ((struct ath6kl_vif *) netdev_priv(dev))->ar;
 }
index 9eff0d010bb161812f70712bd51e9c7700acc2f9..eb808b46f94cec1010a16e0733f9dacbf5ee4147 100644 (file)
@@ -1551,10 +1551,10 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
                                                size_t count, loff_t *ppos)
 {
        struct ath6kl *ar = file->private_data;
-       char buf[16];
+       char buf[32];
        int len;
 
-       len = snprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t,
+       len = scnprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t,
                                        ar->listen_intvl_b);
 
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
index 9853c9c125c1417c9ab87de1afc6aea8b8fe3160..e569c652e35c81ebd90810588c0181d759a825c2 100644 (file)
@@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK {
        ATH6KL_DBG_BOOT         = BIT(18),    /* driver init and fw boot */
        ATH6KL_DBG_WMI_DUMP     = BIT(19),
        ATH6KL_DBG_SUSPEND      = BIT(20),
+       ATH6KL_DBG_USB          = BIT(21),
        ATH6KL_DBG_ANY          = 0xffffffff  /* enable all logs */
 };
 
index eed22870448bd2f68b0cc2c9897ecbc50cb2fdd4..2fe1dadfc77a105d1cac911abc15fb770e8f7e32 100644 (file)
@@ -91,6 +91,36 @@ static inline int ath6kl_hif_suspend(struct ath6kl *ar,
        return ar->hif_ops->suspend(ar, wow);
 }
 
+/*
+ * Read from the ATH6KL through its diagnostic window. No cooperation from
+ * the Target is required for this.
+ */
+static inline int ath6kl_hif_diag_read32(struct ath6kl *ar, u32 address,
+                                        u32 *value)
+{
+       return ar->hif_ops->diag_read32(ar, address, value);
+}
+
+/*
+ * Write to the ATH6KL through its diagnostic window. No cooperation from
+ * the Target is required for this.
+ */
+static inline int ath6kl_hif_diag_write32(struct ath6kl *ar, u32 address,
+                                         __le32 value)
+{
+       return ar->hif_ops->diag_write32(ar, address, value);
+}
+
+static inline int ath6kl_hif_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       return ar->hif_ops->bmi_read(ar, buf, len);
+}
+
+static inline int ath6kl_hif_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       return ar->hif_ops->bmi_write(ar, buf, len);
+}
+
 static inline int ath6kl_hif_resume(struct ath6kl *ar)
 {
        ath6kl_dbg(ATH6KL_DBG_HIF, "hif resume\n");
index e57da35e59fa78d66566841765a803f2f36e1637..0772ef650174e7f2c3aebc3793e357adc5929c25 100644 (file)
@@ -689,6 +689,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
        ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
                   dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
 
+       /* usb doesn't support enabling interrupts */
+       /* FIXME: remove check once USB support is implemented */
+       if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB)
+               return 0;
+
        status = ath6kl_hif_disable_intrs(dev);
 
 fail_setup:
index f2dc3bcdae4ae6661fdf191e93181855f685b597..699a036f3a44eaad75ee9f81c4bca9e574c84d80 100644 (file)
@@ -35,6 +35,7 @@
 #define MAX_SCATTER_REQ_TRANSFER_SIZE    (32 * 1024)
 
 #define MANUFACTURER_ID_AR6003_BASE        0x300
+#define MANUFACTURER_ID_AR6004_BASE        0x400
     /* SDIO manufacturer ID and Codes */
 #define MANUFACTURER_ID_ATH6KL_BASE_MASK     0xFF00
 #define MANUFACTURER_CODE                  0x271       /* Atheros */
@@ -244,6 +245,10 @@ struct ath6kl_hif_ops {
        void (*cleanup_scatter)(struct ath6kl *ar);
        int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow);
        int (*resume)(struct ath6kl *ar);
+       int (*diag_read32)(struct ath6kl *ar, u32 address, u32 *value);
+       int (*diag_write32)(struct ath6kl *ar, u32 address, __le32 value);
+       int (*bmi_read)(struct ath6kl *ar, u8 *buf, u32 len);
+       int (*bmi_write)(struct ath6kl *ar, u8 *buf, u32 len);
        int (*power_on)(struct ath6kl *ar);
        int (*power_off)(struct ath6kl *ar);
        void (*stop)(struct ath6kl *ar);
index f3b63ca25c7e02b469feb800f8294fe1c3d195b5..b01702258faf156d9b02e304c0b28688cb5f656a 100644 (file)
@@ -2543,6 +2543,12 @@ int ath6kl_htc_wait_target(struct htc_target *target)
        struct htc_service_connect_resp resp;
        int status;
 
+       /* FIXME: remove once USB support is implemented */
+       if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) {
+               ath6kl_err("HTC doesn't support USB yet. Patience!\n");
+               return -EOPNOTSUPP;
+       }
+
        /* we should be getting 1 control message that the target is ready */
        packet = htc_wait_for_ctrl_msg(target);
 
@@ -2772,7 +2778,9 @@ void ath6kl_htc_cleanup(struct htc_target *target)
 {
        struct htc_packet *packet, *tmp_packet;
 
-       ath6kl_hif_cleanup_scatter(target->dev->ar);
+       /* FIXME: remove check once USB support is implemented */
+       if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB)
+               ath6kl_hif_cleanup_scatter(target->dev->ar);
 
        list_for_each_entry_safe(packet, tmp_packet,
                        &target->free_ctrl_txbuf, list) {
index 5acb4a4b93bf33b4870b9f2bd3055142ee3734b2..7f55be3092d1c63698bc2f9d83d88d6ce2769868 100644 (file)
@@ -33,6 +33,80 @@ module_param(debug_mask, uint, 0644);
 module_param(testmode, uint, 0644);
 module_param(suspend_cutpower, bool, 0444);
 
+static const struct ath6kl_hw hw_list[] = {
+       {
+               .id                             = AR6003_HW_2_0_VERSION,
+               .name                           = "ar6003 hw 2.0",
+               .dataset_patch_addr             = 0x57e884,
+               .app_load_addr                  = 0x543180,
+               .board_ext_data_addr            = 0x57e500,
+               .reserved_ram_size              = 6912,
+               .refclk_hz                      = 26000000,
+               .uarttx_pin                     = 8,
+
+               /* hw2.0 needs override address hardcoded */
+               .app_start_override_addr        = 0x944C00,
+
+               .fw_otp                 = AR6003_HW_2_0_OTP_FILE,
+               .fw                     = AR6003_HW_2_0_FIRMWARE_FILE,
+               .fw_tcmd                = AR6003_HW_2_0_TCMD_FIRMWARE_FILE,
+               .fw_patch               = AR6003_HW_2_0_PATCH_FILE,
+               .fw_api2                = AR6003_HW_2_0_FIRMWARE_2_FILE,
+               .fw_board               = AR6003_HW_2_0_BOARD_DATA_FILE,
+               .fw_default_board       = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE,
+       },
+       {
+               .id                             = AR6003_HW_2_1_1_VERSION,
+               .name                           = "ar6003 hw 2.1.1",
+               .dataset_patch_addr             = 0x57ff74,
+               .app_load_addr                  = 0x1234,
+               .board_ext_data_addr            = 0x542330,
+               .reserved_ram_size              = 512,
+               .refclk_hz                      = 26000000,
+               .uarttx_pin                     = 8,
+
+               .fw_otp                 = AR6003_HW_2_1_1_OTP_FILE,
+               .fw                     = AR6003_HW_2_1_1_FIRMWARE_FILE,
+               .fw_tcmd                = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE,
+               .fw_patch               = AR6003_HW_2_1_1_PATCH_FILE,
+               .fw_api2                = AR6003_HW_2_1_1_FIRMWARE_2_FILE,
+               .fw_board               = AR6003_HW_2_1_1_BOARD_DATA_FILE,
+               .fw_default_board       = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE,
+       },
+       {
+               .id                             = AR6004_HW_1_0_VERSION,
+               .name                           = "ar6004 hw 1.0",
+               .dataset_patch_addr             = 0x57e884,
+               .app_load_addr                  = 0x1234,
+               .board_ext_data_addr            = 0x437000,
+               .reserved_ram_size              = 19456,
+               .board_addr                     = 0x433900,
+               .refclk_hz                      = 26000000,
+               .uarttx_pin                     = 11,
+
+               .fw                     = AR6004_HW_1_0_FIRMWARE_FILE,
+               .fw_api2                = AR6004_HW_1_0_FIRMWARE_2_FILE,
+               .fw_board               = AR6004_HW_1_0_BOARD_DATA_FILE,
+               .fw_default_board       = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE,
+       },
+       {
+               .id                             = AR6004_HW_1_1_VERSION,
+               .name                           = "ar6004 hw 1.1",
+               .dataset_patch_addr             = 0x57e884,
+               .app_load_addr                  = 0x1234,
+               .board_ext_data_addr            = 0x437000,
+               .reserved_ram_size              = 11264,
+               .board_addr                     = 0x43d400,
+               .refclk_hz                      = 40000000,
+               .uarttx_pin                     = 11,
+
+               .fw                     = AR6004_HW_1_1_FIRMWARE_FILE,
+               .fw_api2                = AR6004_HW_1_1_FIRMWARE_2_FILE,
+               .fw_board               = AR6004_HW_1_1_BOARD_DATA_FILE,
+               .fw_default_board       = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE,
+       },
+};
+
 /*
  * Include definitions here that can be used to tune the WLAN module
  * behavior. Different customers can tune the behavior as per their needs,
@@ -58,7 +132,6 @@ module_param(suspend_cutpower, bool, 0444);
  */
 #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
 
-#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
 
 #define ATH6KL_DATA_OFFSET    64
 struct sk_buff *ath6kl_buf_alloc(int size)
@@ -348,11 +421,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
                        status = -EIO;
                }
 
-       /*
-        * FIXME: Make sure p2p configurations are not applied to
-        * non-p2p capable interfaces when multivif support is enabled.
-        */
-       if (ar->p2p) {
+       if (ar->p2p && (ar->vif_max == 1 || idx)) {
                ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
                                              P2P_FLAG_CAPABILITIES_REQ |
                                              P2P_FLAG_MACADDR_REQ |
@@ -365,11 +434,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
                }
        }
 
-       /*
-        * FIXME: Make sure p2p configurations are not applied to
-        * non-p2p capable interfaces when multivif support is enabled.
-        */
-       if (ar->p2p) {
+       if (ar->p2p && (ar->vif_max == 1 || idx)) {
                /* Enable Probe Request reporting for P2P */
                ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
                if (ret) {
@@ -385,7 +450,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
 {
        u32 param, ram_reserved_size;
        u8 fw_iftype, fw_mode = 0, fw_submode = 0;
-       int i;
+       int i, status;
 
        /*
         * Note: Even though the firmware interface type is
@@ -397,7 +462,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
         */
        fw_iftype = HI_OPTION_FW_MODE_BSS_STA;
 
-       for (i = 0; i < MAX_NUM_VIF; i++)
+       for (i = 0; i < ar->vif_max; i++)
                fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
 
        /*
@@ -411,15 +476,11 @@ int ath6kl_configure_target(struct ath6kl *ar)
                fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
                              (i * HI_OPTION_FW_SUBMODE_BITS);
 
-       for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++)
+       for (i = ar->max_norm_iface; i < ar->vif_max; i++)
                fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
                              (i * HI_OPTION_FW_SUBMODE_BITS);
 
-       /*
-        * FIXME: This needs to be removed once the multivif
-        * support is enabled.
-        */
-       if (ar->p2p)
+       if (ar->p2p && ar->vif_max == 1)
                fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
 
        param = HTC_PROTOCOL_VERSION;
@@ -442,7 +503,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
                return -EIO;
        }
 
-       param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT);
+       param |= (ar->vif_max << HI_OPTION_NUM_DEV_SHIFT);
        param |= fw_mode << HI_OPTION_FW_MODE_SHIFT;
        param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT;
 
@@ -491,6 +552,24 @@ int ath6kl_configure_target(struct ath6kl *ar)
                /* use default number of control buffers */
                return -EIO;
 
+       /* Configure GPIO AR600x UART */
+       param = ar->hw.uarttx_pin;
+       status = ath6kl_bmi_write(ar,
+                               ath6kl_get_hi_item_addr(ar,
+                               HI_ITEM(hi_dbg_uart_txpin)),
+                               (u8 *)&param, 4);
+       if (status)
+               return status;
+
+       /* Configure target refclk_hz */
+       param =  ar->hw.refclk_hz;
+       status = ath6kl_bmi_write(ar,
+                               ath6kl_get_hi_item_addr(ar,
+                               HI_ITEM(hi_refclk_hz)),
+                               (u8 *)&param, 4);
+       if (status)
+               return status;
+
        return 0;
 }
 
@@ -550,11 +629,11 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
 static const char *get_target_ver_dir(const struct ath6kl *ar)
 {
        switch (ar->version.target_ver) {
-       case AR6003_REV1_VERSION:
+       case AR6003_HW_1_0_VERSION:
                return "ath6k/AR6003/hw1.0";
-       case AR6003_REV2_VERSION:
+       case AR6003_HW_2_0_VERSION:
                return "ath6k/AR6003/hw2.0";
-       case AR6003_REV3_VERSION:
+       case AR6003_HW_2_1_1_VERSION:
                return "ath6k/AR6003/hw2.1.1";
        }
        ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
@@ -612,17 +691,10 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
        if (ar->fw_board != NULL)
                return 0;
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_BOARD_DATA_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               filename = AR6004_REV1_BOARD_DATA_FILE;
-               break;
-       default:
-               filename = AR6003_REV3_BOARD_DATA_FILE;
-               break;
-       }
+       if (WARN_ON(ar->hw.fw_board == NULL))
+               return -EINVAL;
+
+       filename = ar->hw.fw_board;
 
        ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
                            &ar->fw_board_len);
@@ -640,17 +712,7 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar)
        ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
                    filename, ret);
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
-               break;
-       default:
-               filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
-               break;
-       }
+       filename = ar->hw.fw_default_board;
 
        ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
                            &ar->fw_board_len);
@@ -674,19 +736,14 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar)
        if (ar->fw_otp != NULL)
                return 0;
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_OTP_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
+       if (ar->hw.fw_otp == NULL) {
+               ath6kl_dbg(ATH6KL_DBG_BOOT,
+                          "no OTP file configured for this hw\n");
                return 0;
-               break;
-       default:
-               filename = AR6003_REV3_OTP_FILE;
-               break;
        }
 
+       filename = ar->hw.fw_otp;
+
        ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
                            &ar->fw_otp_len);
        if (ret) {
@@ -707,38 +764,22 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar)
                return 0;
 
        if (testmode) {
-               switch (ar->version.target_ver) {
-               case AR6003_REV2_VERSION:
-                       filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
-                       break;
-               case AR6003_REV3_VERSION:
-                       filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
-                       break;
-               case AR6004_REV1_VERSION:
-                       ath6kl_warn("testmode not supported with ar6004\n");
+               if (ar->hw.fw_tcmd == NULL) {
+                       ath6kl_warn("testmode not supported\n");
                        return -EOPNOTSUPP;
-               default:
-                       ath6kl_warn("unknown target version: 0x%x\n",
-                                      ar->version.target_ver);
-                       return -EINVAL;
                }
 
+               filename = ar->hw.fw_tcmd;
+
                set_bit(TESTMODE, &ar->flag);
 
                goto get_fw;
        }
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_FIRMWARE_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               filename = AR6004_REV1_FIRMWARE_FILE;
-               break;
-       default:
-               filename = AR6003_REV3_FIRMWARE_FILE;
-               break;
-       }
+       if (WARN_ON(ar->hw.fw == NULL))
+               return -EINVAL;
+
+       filename = ar->hw.fw;
 
 get_fw:
        ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
@@ -756,27 +797,20 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar)
        const char *filename;
        int ret;
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_PATCH_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               /* FIXME: implement for AR6004 */
+       if (ar->fw_patch != NULL)
                return 0;
-               break;
-       default:
-               filename = AR6003_REV3_PATCH_FILE;
-               break;
-       }
 
-       if (ar->fw_patch == NULL) {
-               ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
-                                   &ar->fw_patch_len);
-               if (ret) {
-                       ath6kl_err("Failed to get patch file %s: %d\n",
-                                  filename, ret);
-                       return ret;
-               }
+       if (ar->hw.fw_patch == NULL)
+               return 0;
+
+       filename = ar->hw.fw_patch;
+
+       ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
+                           &ar->fw_patch_len);
+       if (ret) {
+               ath6kl_err("Failed to get patch file %s: %d\n",
+                          filename, ret);
+               return ret;
        }
 
        return 0;
@@ -811,19 +845,10 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
        int ret, ie_id, i, index, bit;
        __le32 *val;
 
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               filename = AR6003_REV2_FIRMWARE_2_FILE;
-               break;
-       case AR6003_REV3_VERSION:
-               filename = AR6003_REV3_FIRMWARE_2_FILE;
-               break;
-       case AR6004_REV1_VERSION:
-               filename = AR6004_REV1_FIRMWARE_2_FILE;
-               break;
-       default:
+       if (ar->hw.fw_api2 == NULL)
                return -EOPNOTSUPP;
-       }
+
+       filename = ar->hw.fw_api2;
 
        ret = request_firmware(&fw, filename, ar->dev);
        if (ret)
@@ -913,12 +938,15 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
                                   ar->hw.reserved_ram_size);
                        break;
                case ATH6KL_FW_IE_CAPABILITIES:
+                       if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
+                               break;
+
                        ath6kl_dbg(ATH6KL_DBG_BOOT,
                                   "found firmware capabilities ie (%zd B)\n",
                                   ie_len);
 
                        for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
-                               index = ALIGN(i, 8) / 8;
+                               index = i / 8;
                                bit = i % 8;
 
                                if (data[index] & (1 << bit))
@@ -937,9 +965,34 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
                        ar->hw.dataset_patch_addr = le32_to_cpup(val);
 
                        ath6kl_dbg(ATH6KL_DBG_BOOT,
-                                  "found patch address ie 0x%d\n",
+                                  "found patch address ie 0x%x\n",
                                   ar->hw.dataset_patch_addr);
                        break;
+               case ATH6KL_FW_IE_BOARD_ADDR:
+                       if (ie_len != sizeof(*val))
+                               break;
+
+                       val = (__le32 *) data;
+                       ar->hw.board_addr = le32_to_cpup(val);
+
+                       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                                  "found board address ie 0x%x\n",
+                                  ar->hw.board_addr);
+                       break;
+               case ATH6KL_FW_IE_VIF_MAX:
+                       if (ie_len != sizeof(*val))
+                               break;
+
+                       val = (__le32 *) data;
+                       ar->vif_max = min_t(unsigned int, le32_to_cpup(val),
+                                           ATH6KL_VIF_MAX);
+
+                       if (ar->vif_max > 1 && !ar->p2p)
+                               ar->max_norm_iface = 2;
+
+                       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                                  "found vif max ie %d\n", ar->vif_max);
+                       break;
                default:
                        ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n",
                                   le32_to_cpup(&hdr->id));
@@ -994,8 +1047,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
         * For AR6004, host determine Target RAM address for
         * writing board data.
         */
-       if (ar->target_type == TARGET_TYPE_AR6004) {
-               board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
+       if (ar->hw.board_addr != 0) {
+               board_address = ar->hw.board_addr;
                ath6kl_bmi_write(ar,
                                ath6kl_get_hi_item_addr(ar,
                                HI_ITEM(hi_board_data)),
@@ -1013,7 +1066,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
                        HI_ITEM(hi_board_ext_data)),
                        (u8 *) &board_ext_address, 4);
 
-       if (board_ext_address == 0) {
+       if (ar->target_type == TARGET_TYPE_AR6003 &&
+           board_ext_address == 0) {
                ath6kl_err("Failed to get board file target address.\n");
                return -EINVAL;
        }
@@ -1033,8 +1087,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
                break;
        }
 
-       if (ar->fw_board_len == (board_data_size +
-                                board_ext_data_size)) {
+       if (board_ext_address &&
+           ar->fw_board_len == (board_data_size + board_ext_data_size)) {
 
                /* write extended board data */
                ath6kl_dbg(ATH6KL_DBG_BOOT,
@@ -1092,8 +1146,8 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
        bool from_hw = false;
        int ret;
 
-       if (WARN_ON(ar->fw_otp == NULL))
-               return -ENOENT;
+       if (ar->fw_otp == NULL)
+               return 0;
 
        address = ar->hw.app_load_addr;
 
@@ -1142,7 +1196,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
        int ret;
 
        if (WARN_ON(ar->fw == NULL))
-               return -ENOENT;
+               return 0;
 
        address = ar->hw.app_load_addr;
 
@@ -1172,8 +1226,8 @@ static int ath6kl_upload_patch(struct ath6kl *ar)
        u32 address, param;
        int ret;
 
-       if (WARN_ON(ar->fw_patch == NULL))
-               return -ENOENT;
+       if (ar->fw_patch == NULL)
+               return 0;
 
        address = ar->hw.dataset_patch_addr;
 
@@ -1258,7 +1312,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
                return status;
 
        /* WAR to avoid SDIO CRC err */
-       if (ar->version.target_ver == AR6003_REV2_VERSION) {
+       if (ar->version.target_ver == AR6003_HW_2_0_VERSION) {
                ath6kl_err("temporary war to avoid sdio crc error\n");
 
                param = 0x20;
@@ -1315,47 +1369,29 @@ static int ath6kl_init_upload(struct ath6kl *ar)
        if (status)
                return status;
 
-       /* Configure GPIO AR6003 UART */
-       param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
-       status = ath6kl_bmi_write(ar,
-                                 ath6kl_get_hi_item_addr(ar,
-                                 HI_ITEM(hi_dbg_uart_txpin)),
-                                 (u8 *)&param, 4);
-
        return status;
 }
 
 static int ath6kl_init_hw_params(struct ath6kl *ar)
 {
-       switch (ar->version.target_ver) {
-       case AR6003_REV2_VERSION:
-               ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
-               ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
-               ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
-               ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
+       const struct ath6kl_hw *hw;
+       int i;
 
-               /* hw2.0 needs override address hardcoded */
-               ar->hw.app_start_override_addr = 0x944C00;
+       for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+               hw = &hw_list[i];
 
-               break;
-       case AR6003_REV3_VERSION:
-               ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
-               ar->hw.app_load_addr = 0x1234;
-               ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
-               ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
-               break;
-       case AR6004_REV1_VERSION:
-               ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
-               ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
-               ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
-               ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
-               break;
-       default:
+               if (hw->id == ar->version.target_ver)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(hw_list)) {
                ath6kl_err("Unsupported hardware version: 0x%x\n",
                           ar->version.target_ver);
                return -EINVAL;
        }
 
+       ar->hw = *hw;
+
        ath6kl_dbg(ATH6KL_DBG_BOOT,
                   "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n",
                   ar->version.target_ver, ar->target_type,
@@ -1364,10 +1400,25 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
                   "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x",
                   ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr,
                   ar->hw.reserved_ram_size);
+       ath6kl_dbg(ATH6KL_DBG_BOOT,
+                  "refclk_hz %d uarttx_pin %d",
+                  ar->hw.refclk_hz, ar->hw.uarttx_pin);
 
        return 0;
 }
 
+static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
+{
+       switch (type) {
+       case ATH6KL_HIF_TYPE_SDIO:
+               return "sdio";
+       case ATH6KL_HIF_TYPE_USB:
+               return "usb";
+       }
+
+       return NULL;
+}
+
 int ath6kl_init_hw_start(struct ath6kl *ar)
 {
        long timeleft;
@@ -1428,6 +1479,15 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
 
        ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n");
 
+
+       if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
+               ath6kl_info("%s %s fw %s%s\n",
+                           ar->hw.name,
+                           ath6kl_init_get_hif_name(ar->hif_type),
+                           ar->wiphy->fw_version,
+                           test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
+       }
+
        if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
                ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
                           ATH6KL_ABI_VERSION, ar->version.abi_ver);
@@ -1448,7 +1508,7 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
        if ((ath6kl_set_host_app_area(ar)) != 0)
                ath6kl_err("unable to set the host app area\n");
 
-       for (i = 0; i < MAX_NUM_VIF; i++) {
+       for (i = 0; i < ar->vif_max; i++) {
                ret = ath6kl_target_config_wlan_params(ar, i);
                if (ret)
                        goto err_htc_stop;
@@ -1558,7 +1618,7 @@ int ath6kl_core_init(struct ath6kl *ar)
                goto err_node_cleanup;
        }
 
-       for (i = 0; i < MAX_NUM_VIF; i++)
+       for (i = 0; i < ar->vif_max; i++)
                ar->avail_idx_map |= BIT(i);
 
        rtnl_lock();
@@ -1603,7 +1663,17 @@ int ath6kl_core_init(struct ath6kl *ar)
 
        ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
                            WIPHY_FLAG_HAVE_AP_SME |
-                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+                           WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+
+       if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
+               ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+
+       ar->wiphy->probe_resp_offload =
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
+               NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
 
        set_bit(FIRST_BOOT, &ar->flag);
 
index 5e5f4ca8f3f079488391bf902897991e3ba3e03d..eea3c747653ed327ddb03a14ac12cbdf4c0b34f1 100644 (file)
@@ -175,64 +175,6 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
        ar->cookie_count++;
 }
 
-/* set the window address register (using 4-byte register access ). */
-static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
-{
-       int status;
-       s32 i;
-       __le32 addr_val;
-
-       /*
-        * Write bytes 1,2,3 of the register to set the upper address bytes,
-        * the LSB is written last to initiate the access cycle
-        */
-
-       for (i = 1; i <= 3; i++) {
-               /*
-                * Fill the buffer with the address byte value we want to
-                * hit 4 times. No need to worry about endianness as the
-                * same byte is copied to all four bytes of addr_val at
-                * any time.
-                */
-               memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4);
-
-               /*
-                * Hit each byte of the register address with a 4-byte
-                * write operation to the same address, this is a harmless
-                * operation.
-                */
-               status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val,
-                                            4, HIF_WR_SYNC_BYTE_FIX);
-               if (status)
-                       break;
-       }
-
-       if (status) {
-               ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n",
-                          addr, reg_addr);
-               return status;
-       }
-
-       /*
-        * Write the address register again, this time write the whole
-        * 4-byte value. The effect here is that the LSB write causes the
-        * cycle to start, the extra 3 byte write to bytes 1,2,3 has no
-        * effect since we are writing the same values again
-        */
-       addr_val = cpu_to_le32(addr);
-       status = hif_read_write_sync(ar, reg_addr,
-                                    (u8 *)&(addr_val),
-                                    4, HIF_WR_SYNC_BYTE_INC);
-
-       if (status) {
-               ath6kl_err("failed to write 0x%x to window reg: 0x%X\n",
-                          addr, reg_addr);
-               return status;
-       }
-
-       return 0;
-}
-
 /*
  * Read from the hardware through its diagnostic window. No cooperation
  * from the firmware is required for this.
@@ -241,14 +183,7 @@ int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value)
 {
        int ret;
 
-       /* set window register to start read cycle */
-       ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address);
-       if (ret)
-               return ret;
-
-       /* read the data */
-       ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value,
-                                 sizeof(*value), HIF_RD_SYNC_BYTE_INC);
+       ret = ath6kl_hif_diag_read32(ar, address, value);
        if (ret) {
                ath6kl_warn("failed to read32 through diagnose window: %d\n",
                            ret);
@@ -266,18 +201,15 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value)
 {
        int ret;
 
-       /* set write data */
-       ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value,
-                                 sizeof(value), HIF_WR_SYNC_BYTE_INC);
+       ret = ath6kl_hif_diag_write32(ar, address, value);
+
        if (ret) {
                ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n",
                           address, value);
                return ret;
        }
 
-       /* set window register, which starts the write cycle */
-       return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS,
-                                     address);
+       return 0;
 }
 
 int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length)
@@ -465,7 +397,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
        case NONE_AUTH:
                if (vif->prwise_crypto == WEP_CRYPT)
                        ath6kl_install_static_wep_keys(vif);
-               break;
+               if (!ik->valid || ik->key_type != WAPI_CRYPT)
+                       break;
+               /* for WAPI, we need to set the delayed group key, continue: */
        case WPA_PSK_AUTH:
        case WPA2_PSK_AUTH:
        case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
@@ -534,6 +468,18 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
                                wpa_ie = pos; /* WPS IE */
                                break; /* overrides WPA/RSN IE */
                        }
+               } else if (pos[0] == 0x44 && wpa_ie == NULL) {
+                       /*
+                        * Note: WAPI Parameter Set IE re-uses Element ID that
+                        * was officially allocated for BSS AC Access Delay. As
+                        * such, we need to be a bit more careful on when
+                        * parsing the frame. However, BSS AC Access Delay
+                        * element is not supposed to be included in
+                        * (Re)Association Request frames, so this should not
+                        * cause problems.
+                        */
+                       wpa_ie = pos; /* WAPI IE */
+                       break;
                }
                pos += 2 + pos[1];
        }
@@ -581,20 +527,6 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)
 
 /* WMI Event handlers */
 
-static const char *get_hw_id_string(u32 id)
-{
-       switch (id) {
-       case AR6003_REV1_VERSION:
-               return "1.0";
-       case AR6003_REV2_VERSION:
-               return "2.0";
-       case AR6003_REV3_VERSION:
-               return "2.1.1";
-       default:
-               return "unknown";
-       }
-}
-
 void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
 {
        struct ath6kl *ar = devt;
@@ -617,13 +549,6 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
        /* indicate to the waiting thread that the ready event was received */
        set_bit(WMI_READY, &ar->flag);
        wake_up(&ar->event_wq);
-
-       if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
-               ath6kl_info("hw %s fw %s%s\n",
-                           get_hw_id_string(ar->wiphy->hw_version),
-                           ar->wiphy->fw_version,
-                           test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
-       }
 }
 
 void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
@@ -1077,21 +1002,11 @@ static int ath6kl_open(struct net_device *dev)
 
 static int ath6kl_close(struct net_device *dev)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
 
        netif_stop_queue(dev);
 
-       ath6kl_disconnect(vif);
-
-       if (test_bit(WMI_READY, &ar->flag)) {
-               if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF,
-                                             0, 0, 0, 0, 0, 0, 0, 0, 0))
-                       return -EIO;
-
-       }
-
-       ath6kl_cfg80211_scan_complete_event(vif, true);
+       ath6kl_cfg80211_stop(vif);
 
        clear_bit(WLAN_ENABLED, &vif->flags);
 
index e69ca5ee5bb193e1e1e5d1f3c5f47fe8f1ee981e..15c3f56caf4f9da4bc4e8450113feea02cb96a0d 100644 (file)
@@ -40,8 +40,12 @@ struct ath6kl_sdio {
        struct bus_request bus_req[BUS_REQUEST_MAX_NUM];
 
        struct ath6kl *ar;
+
        u8 *dma_buffer;
 
+       /* protects access to dma_buffer */
+       struct mutex dma_buffer_mutex;
+
        /* scatter request list head */
        struct list_head scat_req;
 
@@ -396,6 +400,7 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
        if (buf_needs_bounce(buf)) {
                if (!ar_sdio->dma_buffer)
                        return -ENOMEM;
+               mutex_lock(&ar_sdio->dma_buffer_mutex);
                tbuf = ar_sdio->dma_buffer;
                memcpy(tbuf, buf, len);
                bounced = true;
@@ -406,6 +411,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
        if ((request & HIF_READ) && bounced)
                memcpy(buf, tbuf, len);
 
+       if (bounced)
+               mutex_unlock(&ar_sdio->dma_buffer_mutex);
+
        return ret;
 }
 
@@ -799,7 +807,28 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
                return ret;
        }
 
-       if ((flags & MMC_PM_WAKE_SDIO_IRQ) && wow) {
+       if (!(flags & MMC_PM_WAKE_SDIO_IRQ))
+               goto deepsleep;
+
+       /* sdio irq wakes up host */
+
+       if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
+               ret =  ath6kl_cfg80211_suspend(ar,
+                                              ATH6KL_CFG_SUSPEND_SCHED_SCAN,
+                                              NULL);
+               if (ret) {
+                       ath6kl_warn("Schedule scan suspend failed: %d", ret);
+                       return ret;
+               }
+
+               ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+               if (ret)
+                       ath6kl_warn("set sdio wake irq flag failed: %d\n", ret);
+
+               return ret;
+       }
+
+       if (wow) {
                /*
                 * The host sdio controller is capable of keep power and
                 * sdio irq wake up at this point. It's fine to continue
@@ -816,6 +845,7 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
                return ret;
        }
 
+deepsleep:
        return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL);
 }
 
@@ -839,6 +869,8 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
 
        case ATH6KL_STATE_WOW:
                break;
+       case ATH6KL_STATE_SCHED_SCAN:
+               break;
        }
 
        ath6kl_cfg80211_resume(ar);
@@ -846,6 +878,264 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
        return 0;
 }
 
+/* set the window address register (using 4-byte register access ). */
+static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
+{
+       int status;
+       u8 addr_val[4];
+       s32 i;
+
+       /*
+        * Write bytes 1,2,3 of the register to set the upper address bytes,
+        * the LSB is written last to initiate the access cycle
+        */
+
+       for (i = 1; i <= 3; i++) {
+               /*
+                * Fill the buffer with the address byte value we want to
+                * hit 4 times.
+                */
+               memset(addr_val, ((u8 *)&addr)[i], 4);
+
+               /*
+                * Hit each byte of the register address with a 4-byte
+                * write operation to the same address, this is a harmless
+                * operation.
+                */
+               status = ath6kl_sdio_read_write_sync(ar, reg_addr + i, addr_val,
+                                            4, HIF_WR_SYNC_BYTE_FIX);
+               if (status)
+                       break;
+       }
+
+       if (status) {
+               ath6kl_err("%s: failed to write initial bytes of 0x%x "
+                          "to window reg: 0x%X\n", __func__,
+                          addr, reg_addr);
+               return status;
+       }
+
+       /*
+        * Write the address register again, this time write the whole
+        * 4-byte value. The effect here is that the LSB write causes the
+        * cycle to start, the extra 3 byte write to bytes 1,2,3 has no
+        * effect since we are writing the same values again
+        */
+       status = ath6kl_sdio_read_write_sync(ar, reg_addr, (u8 *)(&addr),
+                                    4, HIF_WR_SYNC_BYTE_INC);
+
+       if (status) {
+               ath6kl_err("%s: failed to write 0x%x to window reg: 0x%X\n",
+                          __func__, addr, reg_addr);
+               return status;
+       }
+
+       return 0;
+}
+
+static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
+{
+       int status;
+
+       /* set window register to start read cycle */
+       status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS,
+                                       address);
+
+       if (status)
+               return status;
+
+       /* read the data */
+       status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS,
+                               (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC);
+       if (status) {
+               ath6kl_err("%s: failed to read from window data addr\n",
+                       __func__);
+               return status;
+       }
+
+       return status;
+}
+
+static int ath6kl_sdio_diag_write32(struct ath6kl *ar, u32 address,
+                                   __le32 data)
+{
+       int status;
+       u32 val = (__force u32) data;
+
+       /* set write data */
+       status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS,
+                               (u8 *) &val, sizeof(u32), HIF_WR_SYNC_BYTE_INC);
+       if (status) {
+               ath6kl_err("%s: failed to write 0x%x to window data addr\n",
+                          __func__, data);
+               return status;
+       }
+
+       /* set window register, which starts the write cycle */
+       return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS,
+                                     address);
+}
+
+static int ath6kl_sdio_bmi_credits(struct ath6kl *ar)
+{
+       u32 addr;
+       unsigned long timeout;
+       int ret;
+
+       ar->bmi.cmd_credits = 0;
+
+       /* Read the counter register to get the command credits */
+       addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
+
+       timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
+       while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) {
+
+               /*
+                * Hit the credit counter with a 4-byte access, the first byte
+                * read will hit the counter and cause a decrement, while the
+                * remaining 3 bytes has no effect. The rationale behind this
+                * is to make all HIF accesses 4-byte aligned.
+                */
+               ret = ath6kl_sdio_read_write_sync(ar, addr,
+                                        (u8 *)&ar->bmi.cmd_credits, 4,
+                                        HIF_RD_SYNC_BYTE_INC);
+               if (ret) {
+                       ath6kl_err("Unable to decrement the command credit "
+                                               "count register: %d\n", ret);
+                       return ret;
+               }
+
+               /* The counter is only 8 bits.
+                * Ignore anything in the upper 3 bytes
+                */
+               ar->bmi.cmd_credits &= 0xFF;
+       }
+
+       if (!ar->bmi.cmd_credits) {
+               ath6kl_err("bmi communication timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar)
+{
+       unsigned long timeout;
+       u32 rx_word = 0;
+       int ret = 0;
+
+       timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
+       while ((time_before(jiffies, timeout)) && !rx_word) {
+               ret = ath6kl_sdio_read_write_sync(ar,
+                                       RX_LOOKAHEAD_VALID_ADDRESS,
+                                       (u8 *)&rx_word, sizeof(rx_word),
+                                       HIF_RD_SYNC_BYTE_INC);
+               if (ret) {
+                       ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n");
+                       return ret;
+               }
+
+                /* all we really want is one bit */
+               rx_word &= (1 << ENDPOINT1);
+       }
+
+       if (!rx_word) {
+               ath6kl_err("bmi_recv_buf FIFO empty\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       int ret;
+       u32 addr;
+
+       ret = ath6kl_sdio_bmi_credits(ar);
+       if (ret)
+               return ret;
+
+       addr = ar->mbox_info.htc_addr;
+
+       ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len,
+                                         HIF_WR_SYNC_BYTE_INC);
+       if (ret)
+               ath6kl_err("unable to send the bmi data to the device\n");
+
+       return ret;
+}
+
+static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       int ret;
+       u32 addr;
+
+       /*
+        * During normal bootup, small reads may be required.
+        * Rather than issue an HIF Read and then wait as the Target
+        * adds successive bytes to the FIFO, we wait here until
+        * we know that response data is available.
+        *
+        * This allows us to cleanly timeout on an unexpected
+        * Target failure rather than risk problems at the HIF level.
+        * In particular, this avoids SDIO timeouts and possibly garbage
+        * data on some host controllers.  And on an interconnect
+        * such as Compact Flash (as well as some SDIO masters) which
+        * does not provide any indication on data timeout, it avoids
+        * a potential hang or garbage response.
+        *
+        * Synchronization is more difficult for reads larger than the
+        * size of the MBOX FIFO (128B), because the Target is unable
+        * to push the 129th byte of data until AFTER the Host posts an
+        * HIF Read and removes some FIFO data.  So for large reads the
+        * Host proceeds to post an HIF Read BEFORE all the data is
+        * actually available to read.  Fortunately, large BMI reads do
+        * not occur in practice -- they're supported for debug/development.
+        *
+        * So Host/Target BMI synchronization is divided into these cases:
+        *  CASE 1: length < 4
+        *        Should not happen
+        *
+        *  CASE 2: 4 <= length <= 128
+        *        Wait for first 4 bytes to be in FIFO
+        *        If CONSERVATIVE_BMI_READ is enabled, also wait for
+        *        a BMI command credit, which indicates that the ENTIRE
+        *        response is available in the the FIFO
+        *
+        *  CASE 3: length > 128
+        *        Wait for the first 4 bytes to be in FIFO
+        *
+        * For most uses, a small timeout should be sufficient and we will
+        * usually see a response quickly; but there may be some unusual
+        * (debug) cases of BMI_EXECUTE where we want an larger timeout.
+        * For now, we use an unbounded busy loop while waiting for
+        * BMI_EXECUTE.
+        *
+        * If BMI_EXECUTE ever needs to support longer-latency execution,
+        * especially in production, this code needs to be enhanced to sleep
+        * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
+        * a function of Host processor speed.
+        */
+       if (len >= 4) { /* NB: Currently, always true */
+               ret = ath6kl_bmi_get_rx_lkahd(ar);
+               if (ret)
+                       return ret;
+       }
+
+       addr = ar->mbox_info.htc_addr;
+       ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len,
+                                 HIF_RD_SYNC_BYTE_INC);
+       if (ret) {
+               ath6kl_err("Unable to read the bmi data from the device: %d\n",
+                          ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static void ath6kl_sdio_stop(struct ath6kl *ar)
 {
        struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
@@ -890,6 +1180,10 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
        .cleanup_scatter = ath6kl_sdio_cleanup_scatter,
        .suspend = ath6kl_sdio_suspend,
        .resume = ath6kl_sdio_resume,
+       .diag_read32 = ath6kl_sdio_diag_read32,
+       .diag_write32 = ath6kl_sdio_diag_write32,
+       .bmi_read = ath6kl_sdio_bmi_read,
+       .bmi_write = ath6kl_sdio_bmi_write,
        .power_on = ath6kl_sdio_power_on,
        .power_off = ath6kl_sdio_power_off,
        .stop = ath6kl_sdio_stop,
@@ -958,6 +1252,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
        spin_lock_init(&ar_sdio->lock);
        spin_lock_init(&ar_sdio->scat_lock);
        spin_lock_init(&ar_sdio->wr_async_lock);
+       mutex_init(&ar_sdio->dma_buffer_mutex);
 
        INIT_LIST_HEAD(&ar_sdio->scat_req);
        INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
@@ -976,8 +1271,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
        }
 
        ar_sdio->ar = ar;
+       ar->hif_type = ATH6KL_HIF_TYPE_SDIO;
        ar->hif_priv = ar_sdio;
        ar->hif_ops = &ath6kl_sdio_ops;
+       ar->bmi.max_data_size = 256;
 
        ath6kl_sdio_set_mbox_info(ar);
 
@@ -1027,13 +1324,15 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
 static const struct sdio_device_id ath6kl_sdio_devices[] = {
        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))},
        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))},
+       {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0))},
+       {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1))},
        {},
 };
 
 MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices);
 
 static struct sdio_driver ath6kl_sdio_driver = {
-       .name = "ath6kl",
+       .name = "ath6kl_sdio",
        .id_table = ath6kl_sdio_devices,
        .probe = ath6kl_sdio_probe,
        .remove = ath6kl_sdio_remove,
@@ -1063,13 +1362,19 @@ MODULE_AUTHOR("Atheros Communications, Inc.");
 MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices");
 MODULE_LICENSE("Dual BSD/GPL");
 
-MODULE_FIRMWARE(AR6003_REV2_OTP_FILE);
-MODULE_FIRMWARE(AR6003_REV2_FIRMWARE_FILE);
-MODULE_FIRMWARE(AR6003_REV2_PATCH_FILE);
-MODULE_FIRMWARE(AR6003_REV2_BOARD_DATA_FILE);
-MODULE_FIRMWARE(AR6003_REV2_DEFAULT_BOARD_DATA_FILE);
-MODULE_FIRMWARE(AR6003_REV3_OTP_FILE);
-MODULE_FIRMWARE(AR6003_REV3_FIRMWARE_FILE);
-MODULE_FIRMWARE(AR6003_REV3_PATCH_FILE);
-MODULE_FIRMWARE(AR6003_REV3_BOARD_DATA_FILE);
-MODULE_FIRMWARE(AR6003_REV3_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_0_OTP_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_0_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_0_PATCH_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_1_1_OTP_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_1_1_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_1_1_PATCH_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
index 687e2b350e8fb20ea081ea3eb355de5dc727e040..108a723a1085ad1cb9f7d879498dae8a4eda73d3 100644 (file)
@@ -20,7 +20,7 @@
 #define AR6003_BOARD_DATA_SZ           1024
 #define AR6003_BOARD_EXT_DATA_SZ       768
 
-#define AR6004_BOARD_DATA_SZ     7168
+#define AR6004_BOARD_DATA_SZ     6144
 #define AR6004_BOARD_EXT_DATA_SZ 0
 
 #define RESET_CONTROL_ADDRESS          0x00000000
@@ -334,20 +334,6 @@ struct host_interest {
        (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \
        (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0))
 
-#define AR6003_REV2_APP_LOAD_ADDRESS            0x543180
-#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS      0x57E500
-#define AR6003_REV2_DATASET_PATCH_ADDRESS       0x57e884
-#define AR6003_REV2_RAM_RESERVE_SIZE            6912
-
-#define AR6003_REV3_APP_LOAD_ADDRESS            0x545000
-#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS      0x542330
-#define AR6003_REV3_DATASET_PATCH_ADDRESS       0x57FF74
-#define AR6003_REV3_RAM_RESERVE_SIZE            512
-
-#define AR6004_REV1_BOARD_DATA_ADDRESS          0x435400
-#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS      0x437000
-#define AR6004_REV1_RAM_RESERVE_SIZE            11264
-
 #define ATH6KL_FWLOG_PAYLOAD_SIZE              1500
 
 struct ath6kl_dbglog_buf {
index d9cff2b950b1e2248a340a3a7f4b496cf025b8e2..506a3031a8850d2b8281306df8a6f5346ea57bd4 100644 (file)
@@ -453,11 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
                set_bit(WMI_CTRL_EP_FULL, &ar->flag);
                spin_unlock_bh(&ar->lock);
                ath6kl_err("wmi ctrl ep is full\n");
-               goto stop_adhoc_netq;
+               return action;
        }
 
        if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
-               goto stop_adhoc_netq;
+               return action;
 
        /*
         * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
@@ -465,20 +465,18 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
         */
        if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
            ar->hiac_stream_active_pri &&
-           ar->cookie_count <= MAX_HI_COOKIE_NUM) {
+           ar->cookie_count <= MAX_HI_COOKIE_NUM)
                /*
                 * Give preference to the highest priority stream by
                 * dropping the packets which overflowed.
                 */
                action = HTC_SEND_FULL_DROP;
-               goto stop_adhoc_netq;
-       }
 
-stop_adhoc_netq:
        /* FIXME: Locking */
        spin_lock_bh(&ar->list_lock);
        list_for_each_entry(vif, &ar->vif_list, list) {
-               if (vif->nw_type == ADHOC_NETWORK) {
+               if (vif->nw_type == ADHOC_NETWORK ||
+                   action != HTC_SEND_FULL_DROP) {
                        spin_unlock_bh(&ar->list_lock);
 
                        spin_lock_bh(&vif->if_lock);
@@ -543,7 +541,7 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
        int status;
        enum htc_endpoint_id eid;
        bool wake_event = false;
-       bool flushing[MAX_NUM_VIF] = {false};
+       bool flushing[ATH6KL_VIF_MAX] = {false};
        u8 if_idx;
        struct ath6kl_vif *vif;
 
@@ -571,8 +569,6 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
                if (!skb || !skb->data)
                        goto fatal;
 
-               packet->buf = skb->data;
-
                __skb_queue_tail(&skb_queue, skb);
 
                if (!status && (packet->act_len != skb->len))
@@ -593,10 +589,10 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
 
                if (eid == ar->ctrl_ep) {
                        if_idx = wmi_cmd_hdr_get_if_idx(
-                               (struct wmi_cmd_hdr *) skb->data);
+                               (struct wmi_cmd_hdr *) packet->buf);
                } else {
                        if_idx = wmi_data_hdr_get_if_idx(
-                               (struct wmi_data_hdr *) skb->data);
+                               (struct wmi_data_hdr *) packet->buf);
                }
 
                vif = ath6kl_get_vif_by_index(ar, if_idx);
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
new file mode 100644 (file)
index 0000000..e3cf397
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2007-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "debug.h"
+#include "core.h"
+
+/* usb device object */
+struct ath6kl_usb {
+       struct usb_device *udev;
+       struct usb_interface *interface;
+       u8 *diag_cmd_buffer;
+       u8 *diag_resp_buffer;
+       struct ath6kl *ar;
+};
+
+/* diagnostic command defnitions */
+#define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD        1
+#define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP       2
+#define ATH6KL_USB_CONTROL_REQ_DIAG_CMD            3
+#define ATH6KL_USB_CONTROL_REQ_DIAG_RESP           4
+
+#define ATH6KL_USB_CTRL_DIAG_CC_READ               0
+#define ATH6KL_USB_CTRL_DIAG_CC_WRITE              1
+
+struct ath6kl_usb_ctrl_diag_cmd_write {
+       __le32 cmd;
+       __le32 address;
+       __le32 value;
+       __le32 _pad[1];
+} __packed;
+
+struct ath6kl_usb_ctrl_diag_cmd_read {
+       __le32 cmd;
+       __le32 address;
+} __packed;
+
+struct ath6kl_usb_ctrl_diag_resp_read {
+       __le32 value;
+} __packed;
+
+#define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write))
+#define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read))
+
+static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb)
+{
+       usb_set_intfdata(ar_usb->interface, NULL);
+
+       kfree(ar_usb->diag_cmd_buffer);
+       kfree(ar_usb->diag_resp_buffer);
+
+       kfree(ar_usb);
+}
+
+static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface)
+{
+       struct ath6kl_usb *ar_usb = NULL;
+       struct usb_device *dev = interface_to_usbdev(interface);
+       int status = 0;
+
+       ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL);
+       if (ar_usb == NULL)
+               goto fail_ath6kl_usb_create;
+
+       memset(ar_usb, 0, sizeof(struct ath6kl_usb));
+       usb_set_intfdata(interface, ar_usb);
+       ar_usb->udev = dev;
+       ar_usb->interface = interface;
+
+       ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL);
+       if (ar_usb->diag_cmd_buffer == NULL) {
+               status = -ENOMEM;
+               goto fail_ath6kl_usb_create;
+       }
+
+       ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP,
+                                          GFP_KERNEL);
+       if (ar_usb->diag_resp_buffer == NULL) {
+               status = -ENOMEM;
+               goto fail_ath6kl_usb_create;
+       }
+
+fail_ath6kl_usb_create:
+       if (status != 0) {
+               ath6kl_usb_destroy(ar_usb);
+               ar_usb = NULL;
+       }
+       return ar_usb;
+}
+
+static void ath6kl_usb_device_detached(struct usb_interface *interface)
+{
+       struct ath6kl_usb *ar_usb;
+
+       ar_usb = usb_get_intfdata(interface);
+       if (ar_usb == NULL)
+               return;
+
+       ath6kl_stop_txrx(ar_usb->ar);
+
+       ath6kl_core_cleanup(ar_usb->ar);
+
+       ath6kl_usb_destroy(ar_usb);
+}
+
+static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb,
+                                  u8 req, u16 value, u16 index, void *data,
+                                  u32 size)
+{
+       u8 *buf = NULL;
+       int ret;
+
+       if (size > 0) {
+               buf = kmalloc(size, GFP_KERNEL);
+               if (buf == NULL)
+                       return -ENOMEM;
+
+               memcpy(buf, data, size);
+       }
+
+       /* note: if successful returns number of bytes transfered */
+       ret = usb_control_msg(ar_usb->udev,
+                             usb_sndctrlpipe(ar_usb->udev, 0),
+                             req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, value, index, buf,
+                             size, 1000);
+
+       if (ret < 0) {
+               ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
+                          __func__, ret);
+       }
+
+       kfree(buf);
+
+       return 0;
+}
+
+static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb,
+                                 u8 req, u16 value, u16 index, void *data,
+                                 u32 size)
+{
+       u8 *buf = NULL;
+       int ret;
+
+       if (size > 0) {
+               buf = kmalloc(size, GFP_KERNEL);
+               if (buf == NULL)
+                       return -ENOMEM;
+       }
+
+       /* note: if successful returns number of bytes transfered */
+       ret = usb_control_msg(ar_usb->udev,
+                                usb_rcvctrlpipe(ar_usb->udev, 0),
+                                req,
+                                USB_DIR_IN | USB_TYPE_VENDOR |
+                                USB_RECIP_DEVICE, value, index, buf,
+                                size, 2 * HZ);
+
+       if (ret < 0) {
+               ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
+                          __func__, ret);
+       }
+
+       memcpy((u8 *) data, buf, size);
+
+       kfree(buf);
+
+       return 0;
+}
+
+static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb,
+                                    u8 req_val, u8 *req_buf, u32 req_len,
+                                    u8 resp_val, u8 *resp_buf, u32 *resp_len)
+{
+       int ret;
+
+       /* send command */
+       ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0,
+                                        req_buf, req_len);
+
+       if (ret != 0)
+               return ret;
+
+       if (resp_buf == NULL) {
+               /* no expected response */
+               return ret;
+       }
+
+       /* get response */
+       ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0,
+                                       resp_buf, *resp_len);
+
+       return ret;
+}
+
+static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
+{
+       struct ath6kl_usb *ar_usb = ar->hif_priv;
+       struct ath6kl_usb_ctrl_diag_resp_read *resp;
+       struct ath6kl_usb_ctrl_diag_cmd_read *cmd;
+       u32 resp_len;
+       int ret;
+
+       cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer;
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ;
+       cmd->address = cpu_to_le32(address);
+       resp_len = sizeof(*resp);
+
+       ret = ath6kl_usb_ctrl_msg_exchange(ar_usb,
+                               ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
+                               (u8 *) cmd,
+                               sizeof(struct ath6kl_usb_ctrl_diag_cmd_write),
+                               ATH6KL_USB_CONTROL_REQ_DIAG_RESP,
+                               ar_usb->diag_resp_buffer, &resp_len);
+
+       if (ret)
+               return ret;
+
+       resp = (struct ath6kl_usb_ctrl_diag_resp_read *)
+               ar_usb->diag_resp_buffer;
+
+       *data = le32_to_cpu(resp->value);
+
+       return ret;
+}
+
+static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
+{
+       struct ath6kl_usb *ar_usb = ar->hif_priv;
+       struct ath6kl_usb_ctrl_diag_cmd_write *cmd;
+
+       cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer;
+
+       memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write));
+       cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE);
+       cmd->address = cpu_to_le32(address);
+       cmd->value = data;
+
+       return ath6kl_usb_ctrl_msg_exchange(ar_usb,
+                                           ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
+                                           (u8 *) cmd,
+                                           sizeof(*cmd),
+                                           0, NULL, NULL);
+
+}
+
+static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       struct ath6kl_usb *ar_usb = ar->hif_priv;
+       int ret;
+
+       /* get response */
+       ret = ath6kl_usb_submit_ctrl_in(ar_usb,
+                                       ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP,
+                                       0, 0, buf, len);
+       if (ret != 0) {
+               ath6kl_err("Unable to read the bmi data from the device: %d\n",
+                          ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
+{
+       struct ath6kl_usb *ar_usb = ar->hif_priv;
+       int ret;
+
+       /* send command */
+       ret = ath6kl_usb_submit_ctrl_out(ar_usb,
+                                        ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD,
+                                        0, 0, buf, len);
+       if (ret != 0) {
+               ath6kl_err("unable to send the bmi data to the device: %d\n",
+                          ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ath6kl_usb_power_on(struct ath6kl *ar)
+{
+       return 0;
+}
+
+static int ath6kl_usb_power_off(struct ath6kl *ar)
+{
+       return 0;
+}
+
+static const struct ath6kl_hif_ops ath6kl_usb_ops = {
+       .diag_read32 = ath6kl_usb_diag_read32,
+       .diag_write32 = ath6kl_usb_diag_write32,
+       .bmi_read = ath6kl_usb_bmi_read,
+       .bmi_write = ath6kl_usb_bmi_write,
+       .power_on = ath6kl_usb_power_on,
+       .power_off = ath6kl_usb_power_off,
+};
+
+/* ath6kl usb driver registered functions */
+static int ath6kl_usb_probe(struct usb_interface *interface,
+                           const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(interface);
+       struct ath6kl *ar;
+       struct ath6kl_usb *ar_usb = NULL;
+       int vendor_id, product_id;
+       int ret = 0;
+
+       usb_get_dev(dev);
+
+       vendor_id = le16_to_cpu(dev->descriptor.idVendor);
+       product_id = le16_to_cpu(dev->descriptor.idProduct);
+
+       ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id);
+       ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id);
+
+       if (interface->cur_altsetting)
+               ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n",
+                          interface->cur_altsetting->desc.bInterfaceNumber);
+
+
+       if (dev->speed == USB_SPEED_HIGH)
+               ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n");
+       else
+               ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");
+
+       ar_usb = ath6kl_usb_create(interface);
+
+       if (ar_usb == NULL) {
+               ret = -ENOMEM;
+               goto err_usb_put;
+       }
+
+       ar = ath6kl_core_alloc(&ar_usb->udev->dev);
+       if (ar == NULL) {
+               ath6kl_err("Failed to alloc ath6kl core\n");
+               ret = -ENOMEM;
+               goto err_usb_destroy;
+       }
+
+       ar->hif_priv = ar_usb;
+       ar->hif_type = ATH6KL_HIF_TYPE_USB;
+       ar->hif_ops = &ath6kl_usb_ops;
+       ar->mbox_info.block_size = 16;
+       ar->bmi.max_data_size = 252;
+
+       ar_usb->ar = ar;
+
+       ret = ath6kl_core_init(ar);
+       if (ret) {
+               ath6kl_err("Failed to init ath6kl core: %d\n", ret);
+               goto err_core_free;
+       }
+
+       return ret;
+
+err_core_free:
+       ath6kl_core_free(ar);
+err_usb_destroy:
+       ath6kl_usb_destroy(ar_usb);
+err_usb_put:
+       usb_put_dev(dev);
+
+       return ret;
+}
+
+static void ath6kl_usb_remove(struct usb_interface *interface)
+{
+       usb_put_dev(interface_to_usbdev(interface));
+       ath6kl_usb_device_detached(interface);
+}
+
+/* table of devices that work with this driver */
+static struct usb_device_id ath6kl_usb_ids[] = {
+       {USB_DEVICE(0x0cf3, 0x9374)},
+       { /* Terminating entry */ },
+};
+
+MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids);
+
+static struct usb_driver ath6kl_usb_driver = {
+       .name = "ath6kl_usb",
+       .probe = ath6kl_usb_probe,
+       .disconnect = ath6kl_usb_remove,
+       .id_table = ath6kl_usb_ids,
+};
+
+static int ath6kl_usb_init(void)
+{
+       usb_register(&ath6kl_usb_driver);
+       return 0;
+}
+
+static void ath6kl_usb_exit(void)
+{
+       usb_deregister(&ath6kl_usb_driver);
+}
+
+module_init(ath6kl_usb_init);
+module_exit(ath6kl_usb_exit);
+
+MODULE_AUTHOR("Atheros Communications, Inc.");
+MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);
+MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
index 922344d3b26259b040dd8c7ec9f642d8a692f7e4..f6f2aa27fc20ee1abc34e96b4c704894249c48e0 100644 (file)
@@ -85,7 +85,7 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
 {
        struct ath6kl_vif *vif, *found = NULL;
 
-       if (WARN_ON(if_idx > (MAX_NUM_VIF - 1)))
+       if (WARN_ON(if_idx > (ar->vif_max - 1)))
                return NULL;
 
        /* FIXME: Locking */
@@ -187,7 +187,7 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
        struct wmi_data_hdr *data_hdr;
        int ret;
 
-       if (WARN_ON(skb == NULL || (if_idx > MAX_NUM_VIF - 1)))
+       if (WARN_ON(skb == NULL || (if_idx > wmi->parent_dev->vif_max - 1)))
                return -EINVAL;
 
        if (tx_meta_info) {
@@ -977,6 +977,13 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len,
        return 0;
 }
 
+void ath6kl_wmi_sscan_timer(unsigned long ptr)
+{
+       struct ath6kl_vif *vif = (struct ath6kl_vif *) ptr;
+
+       cfg80211_sched_scan_results(vif->ar->wiphy);
+}
+
 static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
                                       struct ath6kl_vif *vif)
 {
@@ -1066,6 +1073,21 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
                return -ENOMEM;
        cfg80211_put_bss(bss);
 
+       /*
+        * Firmware doesn't return any event when scheduled scan has
+        * finished, so we need to use a timer to find out when there are
+        * no more results.
+        *
+        * The timer is started from the first bss info received, otherwise
+        * the timer would not ever fire if the scan interval is short
+        * enough.
+        */
+       if (ar->state == ATH6KL_STATE_SCHED_SCAN &&
+           !timer_pending(&vif->sched_scan_timer)) {
+               mod_timer(&vif->sched_scan_timer, jiffies +
+                         msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY));
+       }
+
        return 0;
 }
 
@@ -1620,7 +1642,7 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
        int ret;
        u16 info1;
 
-       if (WARN_ON(skb == NULL || (if_idx > (MAX_NUM_VIF - 1))))
+       if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1))))
                return -EINVAL;
 
        ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
@@ -1682,7 +1704,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
                           u8 pairwise_crypto_len,
                           enum crypto_type group_crypto,
                           u8 group_crypto_len, int ssid_len, u8 *ssid,
-                          u8 *bssid, u16 channel, u32 ctrl_flags)
+                          u8 *bssid, u16 channel, u32 ctrl_flags,
+                          u8 nw_subtype)
 {
        struct sk_buff *skb;
        struct wmi_connect_cmd *cc;
@@ -1722,6 +1745,7 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
        cc->grp_crypto_len = group_crypto_len;
        cc->ch = cpu_to_le16(channel);
        cc->ctrl_flags = cpu_to_le32(ctrl_flags);
+       cc->nw_subtype = nw_subtype;
 
        if (bssid != NULL)
                memcpy(cc->bssid, bssid, ETH_ALEN);
@@ -1774,6 +1798,72 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
        return ret;
 }
 
+int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
+                            enum wmi_scan_type scan_type,
+                            u32 force_fgscan, u32 is_legacy,
+                            u32 home_dwell_time, u32 force_scan_interval,
+                            s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates)
+{
+       struct sk_buff *skb;
+       struct wmi_begin_scan_cmd *sc;
+       s8 size;
+       int i, band, ret;
+       struct ath6kl *ar = wmi->parent_dev;
+       int num_rates;
+
+       size = sizeof(struct wmi_begin_scan_cmd);
+
+       if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
+               return -EINVAL;
+
+       if (num_chan > WMI_MAX_CHANNELS)
+               return -EINVAL;
+
+       if (num_chan)
+               size += sizeof(u16) * (num_chan - 1);
+
+       skb = ath6kl_wmi_get_new_buf(size);
+       if (!skb)
+               return -ENOMEM;
+
+       sc = (struct wmi_begin_scan_cmd *) skb->data;
+       sc->scan_type = scan_type;
+       sc->force_fg_scan = cpu_to_le32(force_fgscan);
+       sc->is_legacy = cpu_to_le32(is_legacy);
+       sc->home_dwell_time = cpu_to_le32(home_dwell_time);
+       sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
+       sc->no_cck = cpu_to_le32(no_cck);
+       sc->num_ch = num_chan;
+
+       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               struct ieee80211_supported_band *sband =
+                   ar->wiphy->bands[band];
+               u32 ratemask = rates[band];
+               u8 *supp_rates = sc->supp_rates[band].rates;
+               num_rates = 0;
+
+               for (i = 0; i < sband->n_bitrates; i++) {
+                       if ((BIT(i) & ratemask) == 0)
+                               continue; /* skip rate */
+                       supp_rates[num_rates++] =
+                           (u8) (sband->bitrates[i].bitrate / 5);
+               }
+               sc->supp_rates[band].nrates = num_rates;
+       }
+
+       for (i = 0; i < num_chan; i++)
+               sc->ch_list[i] = cpu_to_le16(ch_list[i]);
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_BEGIN_SCAN_CMDID,
+                                 NO_SYNC_WMIFLAG);
+
+       return ret;
+}
+
+/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
+ * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
+ * mgmt operations using station interface.
+ */
 int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
                             enum wmi_scan_type scan_type,
                             u32 force_fgscan, u32 is_legacy,
@@ -2940,7 +3030,10 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
        p = (struct wmi_set_appie_cmd *) skb->data;
        p->mgmt_frm_type = mgmt_frm_type;
        p->ie_len = ie_len;
-       memcpy(p->ie_info, ie, ie_len);
+
+       if (ie != NULL && ie_len > 0)
+               memcpy(p->ie_info, ie, ie_len);
+
        return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID,
                                   NO_SYNC_WMIFLAG);
 }
@@ -2981,6 +3074,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
                                   NO_SYNC_WMIFLAG);
 }
 
+/* ath6kl_wmi_send_action_cmd is to be deprecated. Use
+ * ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P
+ * mgmt operations using station interface.
+ */
 int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
                               u32 wait, const u8 *data, u16 data_len)
 {
@@ -3018,14 +3115,57 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
                                   NO_SYNC_WMIFLAG);
 }
 
+int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
+                              u32 wait, const u8 *data, u16 data_len,
+                              u32 no_cck)
+{
+       struct sk_buff *skb;
+       struct wmi_send_mgmt_cmd *p;
+       u8 *buf;
+
+       if (wait)
+               return -EINVAL; /* Offload for wait not supported */
+
+       buf = kmalloc(data_len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
+       if (!skb) {
+               kfree(buf);
+               return -ENOMEM;
+       }
+
+       kfree(wmi->last_mgmt_tx_frame);
+       memcpy(buf, data, data_len);
+       wmi->last_mgmt_tx_frame = buf;
+       wmi->last_mgmt_tx_frame_len = data_len;
+
+       ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u "
+                  "len=%u\n", id, freq, wait, data_len);
+       p = (struct wmi_send_mgmt_cmd *) skb->data;
+       p->id = cpu_to_le32(id);
+       p->freq = cpu_to_le32(freq);
+       p->wait = cpu_to_le32(wait);
+       p->no_cck = cpu_to_le32(no_cck);
+       p->len = cpu_to_le16(data_len);
+       memcpy(p->data, data, data_len);
+       return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_MGMT_CMDID,
+                                  NO_SYNC_WMIFLAG);
+}
+
 int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
                                       const u8 *dst, const u8 *data,
                                       u16 data_len)
 {
        struct sk_buff *skb;
        struct wmi_p2p_probe_response_cmd *p;
+       size_t cmd_len = sizeof(*p) + data_len;
 
-       skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
+       if (data_len == 0)
+               cmd_len++; /* work around target minimum length requirement */
+
+       skb = ath6kl_wmi_get_new_buf(cmd_len);
        if (!skb)
                return -ENOMEM;
 
index 76342d5a190617ac0cd1012e4f07eddf3d1d1616..42ac311eda4e23f84cc61f29a6ac68d01e147bc0 100644 (file)
@@ -329,6 +329,10 @@ enum wmi_cmd_id {
        WMI_SYNCHRONIZE_CMDID,
        WMI_CREATE_PSTREAM_CMDID,
        WMI_DELETE_PSTREAM_CMDID,
+       /* WMI_START_SCAN_CMDID is to be deprecated. Use
+        * WMI_BEGIN_SCAN_CMDID instead. The new cmd supports P2P mgmt
+        * operations using station interface.
+        */
        WMI_START_SCAN_CMDID,
        WMI_SET_SCAN_PARAMS_CMDID,
        WMI_SET_BSS_FILTER_CMDID,
@@ -542,12 +546,61 @@ enum wmi_cmd_id {
        WMI_GTK_OFFLOAD_OP_CMDID,
        WMI_REMAIN_ON_CHNL_CMDID,
        WMI_CANCEL_REMAIN_ON_CHNL_CMDID,
+       /* WMI_SEND_ACTION_CMDID is to be deprecated. Use
+        * WMI_SEND_MGMT_CMDID instead. The new cmd supports P2P mgmt
+        * operations using station interface.
+        */
        WMI_SEND_ACTION_CMDID,
        WMI_PROBE_REQ_REPORT_CMDID,
        WMI_DISABLE_11B_RATES_CMDID,
        WMI_SEND_PROBE_RESPONSE_CMDID,
        WMI_GET_P2P_INFO_CMDID,
        WMI_AP_JOIN_BSS_CMDID,
+
+       WMI_SMPS_ENABLE_CMDID,
+       WMI_SMPS_CONFIG_CMDID,
+       WMI_SET_RATECTRL_PARM_CMDID,
+       /*  LPL specific commands*/
+       WMI_LPL_FORCE_ENABLE_CMDID,
+       WMI_LPL_SET_POLICY_CMDID,
+       WMI_LPL_GET_POLICY_CMDID,
+       WMI_LPL_GET_HWSTATE_CMDID,
+       WMI_LPL_SET_PARAMS_CMDID,
+       WMI_LPL_GET_PARAMS_CMDID,
+
+       WMI_SET_BUNDLE_PARAM_CMDID,
+
+       /*GreenTx specific commands*/
+
+       WMI_GREENTX_PARAMS_CMDID,
+
+       WMI_RTT_MEASREQ_CMDID,
+       WMI_RTT_CAPREQ_CMDID,
+       WMI_RTT_STATUSREQ_CMDID,
+
+       /* WPS Commands */
+       WMI_WPS_START_CMDID,
+       WMI_GET_WPS_STATUS_CMDID,
+
+       /* More P2P commands */
+       WMI_SET_NOA_CMDID,
+       WMI_GET_NOA_CMDID,
+       WMI_SET_OPPPS_CMDID,
+       WMI_GET_OPPPS_CMDID,
+       WMI_ADD_PORT_CMDID,
+       WMI_DEL_PORT_CMDID,
+
+       /* 802.11w cmd */
+       WMI_SET_RSN_CAP_CMDID,
+       WMI_GET_RSN_CAP_CMDID,
+       WMI_SET_IGTK_CMDID,
+
+       WMI_RX_FILTER_COALESCE_FILTER_OP_CMDID,
+       WMI_RX_FILTER_SET_FRAME_TEST_LIST_CMDID,
+
+       WMI_SEND_MGMT_CMDID,
+       WMI_BEGIN_SCAN_CMDID,
+
 };
 
 enum wmi_mgmt_frame_type {
@@ -567,6 +620,14 @@ enum network_type {
        AP_NETWORK = 0x10,
 };
 
+enum network_subtype {
+       SUBTYPE_NONE,
+       SUBTYPE_BT,
+       SUBTYPE_P2PDEV,
+       SUBTYPE_P2PCLIENT,
+       SUBTYPE_P2PGO,
+};
+
 enum dot11_auth_mode {
        OPEN_AUTH = 0x01,
        SHARED_AUTH = 0x02,
@@ -639,6 +700,7 @@ struct wmi_connect_cmd {
        __le16 ch;
        u8 bssid[ETH_ALEN];
        __le32 ctrl_flags;
+       u8 nw_subtype;
 } __packed;
 
 /* WMI_RECONNECT_CMDID */
@@ -726,7 +788,12 @@ enum wmi_scan_type {
        WMI_SHORT_SCAN = 1,
 };
 
-struct wmi_start_scan_cmd {
+struct wmi_supp_rates {
+       u8 nrates;
+       u8 rates[ATH6KL_RATE_MAXSIZE];
+};
+
+struct wmi_begin_scan_cmd {
        __le32 force_fg_scan;
 
        /* for legacy cisco AP compatibility */
@@ -738,9 +805,15 @@ struct wmi_start_scan_cmd {
        /* time interval between scans (msec) */
        __le32 force_scan_intvl;
 
+       /* no CCK rates */
+       __le32 no_cck;
+
        /* enum wmi_scan_type */
        u8 scan_type;
 
+       /* Supported rates to advertise in the probe request frames */
+       struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS];
+
        /* how many channels follow */
        u8 num_ch;
 
@@ -748,8 +821,31 @@ struct wmi_start_scan_cmd {
        __le16 ch_list[1];
 } __packed;
 
-/* WMI_SET_SCAN_PARAMS_CMDID */
-#define WMI_SHORTSCANRATIO_DEFAULT      3
+/* wmi_start_scan_cmd is to be deprecated. Use
+ * wmi_begin_scan_cmd instead. The new structure supports P2P mgmt
+ * operations using station interface.
+ */
+struct wmi_start_scan_cmd {
+       __le32 force_fg_scan;
+
+       /* for legacy cisco AP compatibility */
+       __le32 is_legacy;
+
+       /* max duration in the home channel(msec) */
+       __le32 home_dwell_time;
+
+       /* time interval between scans (msec) */
+       __le32 force_scan_intvl;
+
+       /* enum wmi_scan_type */
+       u8 scan_type;
+
+       /* how many channels follow */
+       u8 num_ch;
+
+       /* channels in Mhz */
+       __le16 ch_list[1];
+} __packed;
 
 /*
  *  Warning: scan control flag value of 0xFF is used to disable
@@ -783,13 +879,6 @@ enum wmi_scan_ctrl_flags_bits {
        ENABLE_SCAN_ABORT_EVENT = 0x40
 };
 
-#define DEFAULT_SCAN_CTRL_FLAGS                        \
-       (CONNECT_SCAN_CTRL_FLAGS |              \
-        SCAN_CONNECTED_CTRL_FLAGS |            \
-        ACTIVE_SCAN_CTRL_FLAGS |               \
-        ROAM_SCAN_CTRL_FLAGS |                 \
-        ENABLE_AUTO_CTRL_FLAGS)
-
 struct wmi_scan_params_cmd {
          /* sec */
        __le16 fg_start_period;
@@ -1818,7 +1907,7 @@ struct wmi_set_ip_cmd {
 } __packed;
 
 enum ath6kl_wow_filters {
-       WOW_FILTER_SSID                 = BIT(0),
+       WOW_FILTER_SSID                 = BIT(1),
        WOW_FILTER_OPTION_MAGIC_PACKET  = BIT(2),
        WOW_FILTER_OPTION_EAP_REQ       = BIT(3),
        WOW_FILTER_OPTION_PATTERNS      = BIT(4),
@@ -1963,7 +2052,7 @@ struct wmi_tx_complete_event {
  * !!! Warning !!!
  * -Changing the following values needs compilation of both driver and firmware
  */
-#define AP_MAX_NUM_STA          8
+#define AP_MAX_NUM_STA          10
 
 /* Spl. AID used to set DTIM flag in the beacons */
 #define MCAST_AID               0xFF
@@ -2046,6 +2135,10 @@ struct wmi_remain_on_chnl_cmd {
        __le32 duration;
 } __packed;
 
+/* wmi_send_action_cmd is to be deprecated. Use
+ * wmi_send_mgmt_cmd instead. The new structure supports P2P mgmt
+ * operations using station interface.
+ */
 struct wmi_send_action_cmd {
        __le32 id;
        __le32 freq;
@@ -2054,6 +2147,15 @@ struct wmi_send_action_cmd {
        u8 data[0];
 } __packed;
 
+struct wmi_send_mgmt_cmd {
+       __le32 id;
+       __le32 freq;
+       __le32 wait;
+       __le32 no_cck;
+       __le16 len;
+       u8 data[0];
+} __packed;
+
 struct wmi_tx_status_event {
        __le32 id;
        u8 ack_status;
@@ -2242,7 +2344,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
                           u8 pairwise_crypto_len,
                           enum crypto_type group_crypto,
                           u8 group_crypto_len, int ssid_len, u8 *ssid,
-                          u8 *bssid, u16 channel, u32 ctrl_flags);
+                          u8 *bssid, u16 channel, u32 ctrl_flags,
+                          u8 nw_subtype);
 
 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
                             u16 channel);
@@ -2252,6 +2355,14 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
                             u32 force_fgscan, u32 is_legacy,
                             u32 home_dwell_time, u32 force_scan_interval,
                             s8 num_chan, u16 *ch_list);
+
+int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
+                            enum wmi_scan_type scan_type,
+                            u32 force_fgscan, u32 is_legacy,
+                            u32 home_dwell_time, u32 force_scan_interval,
+                            s8 num_chan, u16 *ch_list, u32 no_cck,
+                            u32 *rates);
+
 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
                              u16 fg_end_sec, u16 bg_sec,
                              u16 minact_chdw_msec, u16 maxact_chdw_msec,
@@ -2346,6 +2457,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
 int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
                               u32 wait, const u8 *data, u16 data_len);
 
+int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
+                              u32 wait, const u8 *data, u16 data_len,
+                              u32 no_cck);
+
 int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
                                       const u8 *dst, const u8 *data,
                                       u16 data_len);
@@ -2359,6 +2474,8 @@ int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx);
 int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
                             const u8 *ie, u8 ie_len);
 
+void ath6kl_wmi_sscan_timer(unsigned long ptr);
+
 struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
 void *ath6kl_wmi_init(struct ath6kl *devt);
 void ath6kl_wmi_shutdown(struct wmi *wmi);
index 1b4786ae00ac14f0beb096aa210e098be98cb4ea..dc6be4afe8eb96ad1ecce4147db6ff761d1556bc 100644 (file)
@@ -81,6 +81,14 @@ config ATH9K_RATE_CONTROL
          Say Y, if you want to use the ath9k specific rate control
          module instead of minstrel_ht.
 
+config ATH9K_BTCOEX_SUPPORT
+       bool "Atheros ath9k bluetooth coexistence support"
+       depends on ATH9K
+       default y
+       ---help---
+         Say Y, if you want to use the ath9k radios together with
+         Bluetooth modules in the same system.
+
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
        depends on USB && MAC80211
index a639b94f764301792a23765333b1509f64fec39a..bc56f57b393b5ad669f2178e63f1e13d36a03d4a 100644 (file)
@@ -136,8 +136,8 @@ static void ath9k_ani_restart(struct ath_hw *ah)
                cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
        }
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "Writing ofdmbase=%u   cckbase=%u\n", ofdm_base, cck_base);
+       ath_dbg(common, ANI, "Writing ofdmbase=%u   cckbase=%u\n",
+               ofdm_base, cck_base);
 
        ENABLE_REGWRITE_BUFFER(ah);
 
@@ -268,8 +268,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
 
        aniState->noiseFloor = BEACON_RSSI(ah);
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+       ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
                aniState->ofdmNoiseImmunityLevel,
                immunityLevel, aniState->noiseFloor,
                aniState->rssiThrLow, aniState->rssiThrHigh);
@@ -336,8 +335,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
        const struct ani_cck_level_entry *entry_cck;
 
        aniState->noiseFloor = BEACON_RSSI(ah);
-       ath_dbg(common, ATH_DBG_ANI,
-               "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
+       ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
                aniState->cckNoiseImmunityLevel, immunityLevel,
                aniState->noiseFloor, aniState->rssiThrLow,
                aniState->rssiThrHigh);
@@ -481,8 +479,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
 
        if (ah->opmode != NL80211_IFTYPE_STATION
            && ah->opmode != NL80211_IFTYPE_ADHOC) {
-               ath_dbg(common, ATH_DBG_ANI,
-                       "Reset ANI state opmode %u\n", ah->opmode);
+               ath_dbg(common, ANI, "Reset ANI state opmode %u\n", ah->opmode);
                ah->stats.ast_ani_reset++;
 
                if (ah->opmode == NL80211_IFTYPE_AP) {
@@ -582,7 +579,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
                    ATH9K_ANI_OFDM_DEF_LEVEL ||
                    aniState->cckNoiseImmunityLevel !=
                    ATH9K_ANI_CCK_DEF_LEVEL) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
                                ah->opmode,
                                chan->channel,
@@ -599,7 +596,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
                /*
                 * restore historical levels for this channel
                 */
-               ath_dbg(common, ATH_DBG_ANI,
+               ath_dbg(common, ANI,
                        "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
                        ah->opmode,
                        chan->channel,
@@ -662,7 +659,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
 
        if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
                if (phyCnt1 < ofdm_base) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "phyCnt1 0x%x, resetting counter value to 0x%x\n",
                                phyCnt1, ofdm_base);
                        REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
@@ -670,7 +667,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
                                  AR_PHY_ERR_OFDM_TIMING);
                }
                if (phyCnt2 < cck_base) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "phyCnt2 0x%x, resetting counter value to 0x%x\n",
                                phyCnt2, cck_base);
                        REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
@@ -713,7 +710,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
        cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
                         aniState->listenTime;
 
-       ath_dbg(common, ATH_DBG_ANI,
+       ath_dbg(common, ANI,
                "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
                aniState->listenTime,
                aniState->ofdmNoiseImmunityLevel,
@@ -748,7 +745,7 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
 
-       ath_dbg(common, ATH_DBG_ANI, "Enable MIB counters\n");
+       ath_dbg(common, ANI, "Enable MIB counters\n");
 
        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 
@@ -770,7 +767,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
 
-       ath_dbg(common, ATH_DBG_ANI, "Disable MIB counters\n");
+       ath_dbg(common, ANI, "Disable MIB counters\n");
 
        REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -845,7 +842,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
        int i;
 
-       ath_dbg(common, ATH_DBG_ANI, "Initialize ANI\n");
+       ath_dbg(common, ANI, "Initialize ANI\n");
 
        if (use_new_ani(ah)) {
                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
index f199e9e2514950757e27dcba7da906571dad954b..f901a17f76baf6da3a2ad3e55880a8aa25df35e8 100644 (file)
@@ -158,7 +158,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
        /* pre-reverse this field */
        tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n",
+       ath_dbg(common, CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n",
                new_bias, synth_freq);
 
        /* swizzle rf_pwd_icsyndiv */
@@ -1053,8 +1053,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
-                       ath_dbg(common, ATH_DBG_ANI,
-                               "level out of range (%u > %zu)\n",
+                       ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(ah->totalSizeDesired));
                        return false;
                }
@@ -1157,8 +1156,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(firstep)) {
-                       ath_dbg(common, ATH_DBG_ANI,
-                               "level out of range (%u > %zu)\n",
+                       ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(firstep));
                        return false;
                }
@@ -1177,8 +1175,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(cycpwrThr1)) {
-                       ath_dbg(common, ATH_DBG_ANI,
-                               "level out of range (%u > %zu)\n",
+                       ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(cycpwrThr1));
                        return false;
                }
@@ -1195,23 +1192,22 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
        case ATH9K_ANI_PRESENT:
                break;
        default:
-               ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
+               ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
                return false;
        }
 
-       ath_dbg(common, ATH_DBG_ANI, "ANI parameters:\n");
-       ath_dbg(common, ATH_DBG_ANI,
+       ath_dbg(common, ANI, "ANI parameters:\n");
+       ath_dbg(common, ANI,
                "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
                aniState->noiseImmunityLevel,
                aniState->spurImmunityLevel,
                !aniState->ofdmWeakSigDetectOff);
-       ath_dbg(common, ATH_DBG_ANI,
+       ath_dbg(common, ANI,
                "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
                aniState->cckWeakSigThreshold,
                aniState->firstepLevel,
                aniState->listenTime);
-       ath_dbg(common, ATH_DBG_ANI,
-               "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+       ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
                aniState->ofdmPhyErrCount,
                aniState->cckPhyErrCount);
 
@@ -1295,7 +1291,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                                    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
 
                if (!on != aniState->ofdmWeakSigDetectOff) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: ofdm weak signal: %s=>%s\n",
                                chan->channel,
                                !aniState->ofdmWeakSigDetectOff ?
@@ -1313,7 +1309,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(firstep_table)) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(firstep_table));
                        return false;
@@ -1350,7 +1346,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                              AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
 
                if (level != aniState->firstepLevel) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->firstepLevel,
@@ -1358,7 +1354,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                                ATH9K_ANI_FIRSTEP_LVL_NEW,
                                value,
                                aniState->iniDef.firstep);
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->firstepLevel,
@@ -1378,7 +1374,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(cycpwrThr1_table));
                        return false;
@@ -1414,7 +1410,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                              AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
 
                if (level != aniState->spurImmunityLevel) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->spurImmunityLevel,
@@ -1422,7 +1418,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
                                ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
                                value,
                                aniState->iniDef.cycpwrThr1);
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->spurImmunityLevel,
@@ -1448,11 +1444,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
        case ATH9K_ANI_PRESENT:
                break;
        default:
-               ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
+               ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
                return false;
        }
 
-       ath_dbg(common, ATH_DBG_ANI,
+       ath_dbg(common, ANI,
                "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
                aniState->spurImmunityLevel,
                !aniState->ofdmWeakSigDetectOff ? "on" : "off",
@@ -1506,7 +1502,7 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
 
        iniDef = &aniState->iniDef;
 
-       ath_dbg(common, ATH_DBG_ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+       ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
                ah->hw_version.macVersion,
                ah->hw_version.macRev,
                ah->opmode,
index 157337febc2b6c9bfd0df1ab6baef4eef2b8e684..c55e5bbafc4676947d861d5203491a85230cbe38 100644 (file)
@@ -61,18 +61,16 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah,
        switch (currCal->calData->calType) {
        case IQ_MISMATCH_CAL:
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "starting IQ Mismatch Calibration\n");
                break;
        case ADC_GAIN_CAL:
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "starting ADC Gain Calibration\n");
+               ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
                break;
        case ADC_DC_CAL:
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "starting ADC DC Calibration\n");
+               ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
                break;
        }
 
@@ -129,7 +127,7 @@ static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
                ah->totalIqCorrMeas[i] +=
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
                        "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
                        ah->cal_samples, i, ah->totalPowerMeasI[i],
                        ah->totalPowerMeasQ[i],
@@ -151,7 +149,7 @@ static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
                ah->totalAdcQEvenPhase[i] +=
                        REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
                        "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
                        ah->cal_samples, i,
                        ah->totalAdcIOddPhase[i],
@@ -175,7 +173,7 @@ static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
                ah->totalAdcDcOffsetQEvenPhase[i] +=
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
 
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
                        "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
                        ah->cal_samples, i,
                        ah->totalAdcDcOffsetIOddPhase[i],
@@ -198,11 +196,11 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                powerMeasQ = ah->totalPowerMeasQ[i];
                iqCorrMeas = ah->totalIqCorrMeas[i];
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Starting IQ Cal and Correction for Chain %d\n",
                        i);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Original: Chn %d iq_corr_meas = 0x%08x\n",
                        i, ah->totalIqCorrMeas[i]);
 
@@ -213,12 +211,11 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        iqCorrNeg = 1;
                }
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-               ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-                       iqCorrNeg);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
+                       i, powerMeasI);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
+                       i, powerMeasQ);
+               ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
 
                iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
                qCoffDenom = powerMeasQ / 64;
@@ -227,13 +224,13 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                    (qCoffDenom != 0)) {
                        iCoff = iqCorrMeas / iCoffDenom;
                        qCoff = powerMeasI / qCoffDenom - 64;
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d iCoff = 0x%08x\n", i, iCoff);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d qCoff = 0x%08x\n", i, qCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
+                               i, iCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
+                               i, qCoff);
 
                        iCoff = iCoff & 0x3f;
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
                        if (iqCorrNeg == 0x0)
                                iCoff = 0x40 - iCoff;
@@ -243,7 +240,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        else if (qCoff <= -16)
                                qCoff = -16;
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
                                i, iCoff, qCoff);
 
@@ -253,7 +250,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
                                      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
                                      qCoff);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "IQ Cal and Correction done for Chain %d\n",
                                i);
                }
@@ -275,21 +272,17 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
                qOddMeasOffset = ah->totalAdcQOddPhase[i];
                qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Starting ADC Gain Cal for Chain %d\n", i);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
-                       iOddMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_even_i = 0x%08x\n", i,
-                       iEvenMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
-                       qOddMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_even_q = 0x%08x\n", i,
-                       qEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
+                       i, iOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
+                       i, iEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
+                       i, qOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
+                       i, qEvenMeasOffset);
 
                if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
                        iGainMismatch =
@@ -299,19 +292,19 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
                                ((qOddMeasOffset * 32) /
                                 qEvenMeasOffset) & 0x3f;
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d gain_mismatch_i = 0x%08x\n", i,
-                               iGainMismatch);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d gain_mismatch_q = 0x%08x\n", i,
-                               qGainMismatch);
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d gain_mismatch_i = 0x%08x\n",
+                               i, iGainMismatch);
+                       ath_dbg(common, CALIBRATE,
+                               "Chn %d gain_mismatch_q = 0x%08x\n",
+                               i, qGainMismatch);
 
                        val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
                        val &= 0xfffff000;
                        val |= (qGainMismatch) | (iGainMismatch << 6);
                        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "ADC Gain Cal done for Chain %d\n", i);
                }
        }
@@ -337,40 +330,36 @@ static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
                qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
                qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Starting ADC DC Offset Cal for Chain %d\n", i);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_odd_i = %d\n", i,
-                       iOddMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_even_i = %d\n", i,
-                       iEvenMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_odd_q = %d\n", i,
-                       qOddMeasOffset);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_even_q = %d\n", i,
-                       qEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
+                       i, iOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
+                       i, iEvenMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
+                       i, qOddMeasOffset);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
+                       i, qEvenMeasOffset);
 
                iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
                               numSamples) & 0x1ff;
                qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
                               numSamples) & 0x1ff;
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
-                       iDcMismatch);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
-                       qDcMismatch);
+               ath_dbg(common, CALIBRATE,
+                       "Chn %d dc_offset_mismatch_i = 0x%08x\n",
+                       i, iDcMismatch);
+               ath_dbg(common, CALIBRATE,
+                       "Chn %d dc_offset_mismatch_q = 0x%08x\n",
+                       i, qDcMismatch);
 
                val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
                val &= 0xc0000fff;
                val |= (qDcMismatch << 12) | (iDcMismatch << 21);
                REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "ADC DC Offset Cal done for Chain %d\n", i);
        }
 
@@ -560,7 +549,7 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
                { 0x7838, 0 },
        };
 
-       ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
+       ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
 
        /* PA CAL is not needed for high power solution */
        if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
@@ -741,7 +730,7 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
                REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
                                  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "offset calibration failed to complete in 1ms; noisy environment?\n");
                        return false;
                }
@@ -755,7 +744,7 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
        if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
                          0, AH_WAIT_TIMEOUT)) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "offset calibration failed to complete in 1ms; noisy environment?\n");
                return false;
        }
@@ -851,7 +840,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
                                   AR_PHY_AGC_CONTROL_CAL,
                                   0, AH_WAIT_TIMEOUT)) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "offset calibration failed to complete in 1ms; noisy environment?\n");
                        return false;
                }
@@ -886,22 +875,21 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
                if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
                        INIT_CAL(&ah->adcgain_caldata);
                        INSERT_CAL(ah, &ah->adcgain_caldata);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "enabling ADC Gain Calibration.\n");
+                       ath_dbg(common, CALIBRATE,
+                                       "enabling ADC Gain Calibration\n");
                }
 
                if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
                        INIT_CAL(&ah->adcdc_caldata);
                        INSERT_CAL(ah, &ah->adcdc_caldata);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "enabling ADC DC Calibration.\n");
+                       ath_dbg(common, CALIBRATE,
+                                       "enabling ADC DC Calibration\n");
                }
 
                if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
                        INIT_CAL(&ah->iq_caldata);
                        INSERT_CAL(ah, &ah->iq_caldata);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "enabling IQ Calibration.\n");
+                       ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
                }
 
                ah->cal_list_curr = ah->cal_list;
index b5920168606dea8b47226dc1e9d554f9f5fecdae..7b6417b5212eb91674fc4b57087e3b6dd3d6e768 100644 (file)
@@ -107,7 +107,7 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                }
 
                if (isr & AR_ISR_RXORN) {
-                       ath_dbg(common, ATH_DBG_INTERRUPT,
+                       ath_dbg(common, INTERRUPT,
                                "receive FIFO overrun interrupt\n");
                }
 
@@ -143,24 +143,24 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                if (fatal_int) {
                        if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
-                               ath_dbg(common, ATH_DBG_ANY,
+                               ath_dbg(common, ANY,
                                        "received PCI FATAL interrupt\n");
                        }
                        if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
-                               ath_dbg(common, ATH_DBG_ANY,
+                               ath_dbg(common, ANY,
                                        "received PCI PERR interrupt\n");
                        }
                        *masked |= ATH9K_INT_FATAL;
                }
                if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
-                       ath_dbg(common, ATH_DBG_INTERRUPT,
+                       ath_dbg(common, INTERRUPT,
                                "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
                        REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
                        REG_WRITE(ah, AR_RC, 0);
                        *masked |= ATH9K_INT_FATAL;
                }
                if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
-                       ath_dbg(common, ATH_DBG_INTERRUPT,
+                       ath_dbg(common, INTERRUPT,
                                "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
                }
 
index 23b3a6c578009051c333e70f619952bd3130b3bf..8e70f0bc073e2d12a554428701e67184f538a3c5 100644 (file)
@@ -52,7 +52,7 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
                currCal->calData->calCountMax);
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "starting IQ Mismatch Calibration\n");
 
                /* Kick-off cal */
@@ -64,7 +64,7 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
                REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
                              AR_PHY_65NM_CH0_THERM_START, 1);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "starting Temperature Compensation Calibration\n");
                break;
        }
@@ -194,7 +194,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
                                REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
                        ah->totalIqCorrMeas[i] +=
                                (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+                       ath_dbg(ath9k_hw_common(ah), CALIBRATE,
                                "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
                                ah->cal_samples, i, ah->totalPowerMeasI[i],
                                ah->totalPowerMeasQ[i],
@@ -221,11 +221,10 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                powerMeasQ = ah->totalPowerMeasQ[i];
                iqCorrMeas = ah->totalIqCorrMeas[i];
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Starting IQ Cal and Correction for Chain %d\n",
-                       i);
+               ath_dbg(common, CALIBRATE,
+                       "Starting IQ Cal and Correction for Chain %d\n", i);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Original: Chn %d iq_corr_meas = 0x%08x\n",
                        i, ah->totalIqCorrMeas[i]);
 
@@ -236,12 +235,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        iqCorrNeg = 1;
                }
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-               ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-                       iqCorrNeg);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
+                       i, powerMeasI);
+               ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
+                       i, powerMeasQ);
+               ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
 
                iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
                qCoffDenom = powerMeasQ / 64;
@@ -249,10 +247,10 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
                        iCoff = iqCorrMeas / iCoffDenom;
                        qCoff = powerMeasI / qCoffDenom - 64;
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d iCoff = 0x%08x\n", i, iCoff);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Chn %d qCoff = 0x%08x\n", i, qCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
+                               i, iCoff);
+                       ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
+                               i, qCoff);
 
                        /* Force bounds on iCoff */
                        if (iCoff >= 63)
@@ -273,10 +271,10 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        iCoff = iCoff & 0x7f;
                        qCoff = qCoff & 0x7f;
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
                                i, iCoff, qCoff);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "Register offset (0x%04x) before update = 0x%x\n",
                                offset_array[i],
                                REG_READ(ah, offset_array[i]));
@@ -287,25 +285,25 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
                        REG_RMW_FIELD(ah, offset_array[i],
                                      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
                                      qCoff);
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
                                offset_array[i],
                                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
                                REG_READ(ah, offset_array[i]));
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
                                offset_array[i],
                                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
                                REG_READ(ah, offset_array[i]));
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "IQ Cal and Correction done for Chain %d\n", i);
                }
        }
 
        REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
                    AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
-       ath_dbg(common, ATH_DBG_CALIBRATE,
+       ath_dbg(common, CALIBRATE,
                "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
                (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
                AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
@@ -349,7 +347,7 @@ static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
        f2 = (f1 * f1 + f3 * f3) / result_shift;
 
        if (!f2) {
-               ath_dbg(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
+               ath_dbg(common, CALIBRATE, "Divide by 0\n");
                return false;
        }
 
@@ -470,7 +468,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 
        if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
            (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Divide by 0:\n"
                        "a0_d0=%d\n"
                        "a0_d1=%d\n"
@@ -510,8 +508,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
        mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
 
        if ((mag1 == 0) || (mag2 == 0)) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Divide by 0: mag1=%d, mag2=%d\n",
+               ath_dbg(common, CALIBRATE, "Divide by 0: mag1=%d, mag2=%d\n",
                        mag1, mag2);
                return false;
        }
@@ -529,8 +526,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
                             mag_a0_d0, phs_a0_d0,
                             mag_a1_d0,
                             phs_a1_d0, solved_eq)) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Call to ar9003_hw_solve_iq_cal() failed.\n");
+               ath_dbg(common, CALIBRATE,
+                       "Call to ar9003_hw_solve_iq_cal() failed\n");
                return false;
        }
 
@@ -539,12 +536,12 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
        mag_rx = solved_eq[2];
        phs_rx = solved_eq[3];
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
+       ath_dbg(common, CALIBRATE,
                "chain %d: mag mismatch=%d phase mismatch=%d\n",
                chain_idx, mag_tx/res_scale, phs_tx/res_scale);
 
        if (res_scale == mag_tx) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Divide by 0: mag_tx=%d, res_scale=%d\n",
                        mag_tx, res_scale);
                return false;
@@ -557,8 +554,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
        q_q_coff = (mag_corr_tx * 128 / res_scale);
        q_i_coff = (phs_corr_tx * 256 / res_scale);
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "tx chain %d: mag corr=%d  phase corr=%d\n",
+       ath_dbg(common, CALIBRATE, "tx chain %d: mag corr=%d  phase corr=%d\n",
                chain_idx, q_q_coff, q_i_coff);
 
        if (q_i_coff < -63)
@@ -572,12 +568,11 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 
        iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "tx chain %d: iq corr coeff=%x\n",
+       ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
                chain_idx, iqc_coeff[0]);
 
        if (-mag_rx == res_scale) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Divide by 0: mag_rx=%d, res_scale=%d\n",
                        mag_rx, res_scale);
                return false;
@@ -590,8 +585,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
        q_q_coff = (mag_corr_rx * 128 / res_scale);
        q_i_coff = (phs_corr_rx * 256 / res_scale);
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "rx chain %d: mag corr=%d  phase corr=%d\n",
+       ath_dbg(common, CALIBRATE, "rx chain %d: mag corr=%d  phase corr=%d\n",
                chain_idx, q_q_coff, q_i_coff);
 
        if (q_i_coff < -63)
@@ -605,8 +599,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
 
        iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "rx chain %d: iq corr coeff=%x\n",
+       ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
                chain_idx, iqc_coeff[1]);
 
        return true;
@@ -753,8 +746,7 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
        if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
                        AR_PHY_TX_IQCAL_START_DO_CAL, 0,
                        AH_WAIT_TIMEOUT)) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Tx IQ Cal is not completed.\n");
+               ath_dbg(common, CALIBRATE, "Tx IQ Cal is not completed\n");
                return false;
        }
        return true;
@@ -792,13 +784,13 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
                        nmeasurement = MAX_MEASUREMENT;
 
                for (im = 0; im < nmeasurement; im++) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
-                               "Doing Tx IQ Cal for chain %d.\n", i);
+                       ath_dbg(common, CALIBRATE,
+                               "Doing Tx IQ Cal for chain %d\n", i);
 
                        if (REG_READ(ah, txiqcal_status[i]) &
                                        AR_PHY_TX_IQCAL_STATUS_FAILED) {
-                               ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "Tx IQ Cal failed for chain %d.\n", i);
+                               ath_dbg(common, CALIBRATE,
+                                       "Tx IQ Cal failed for chain %d\n", i);
                                goto tx_iqcal_fail;
                        }
 
@@ -824,18 +816,16 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
                                iq_res[idx + 1] = 0xffff & REG_READ(ah,
                                                chan_info_tab[i] + offset);
 
-                               ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "IQ_RES[%d]=0x%x "
-                                       "IQ_RES[%d]=0x%x\n",
+                               ath_dbg(common, CALIBRATE,
+                                       "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
                                        idx, iq_res[idx], idx + 1,
                                        iq_res[idx + 1]);
                        }
 
                        if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
                                                coeff.iqc_coeff)) {
-                               ath_dbg(common, ATH_DBG_CALIBRATE,
-                                       "Failed in calculation of \
-                                       IQ correction.\n");
+                               ath_dbg(common, CALIBRATE,
+                                       "Failed in calculation of IQ correction\n");
                                goto tx_iqcal_fail;
                        }
 
@@ -855,7 +845,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
        return;
 
 tx_iqcal_fail:
-       ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
+       ath_dbg(common, CALIBRATE, "Tx IQ Cal failed\n");
        return;
 }
 
@@ -953,7 +943,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
                if (!ar9003_hw_rtt_restore(ah, chan))
                        run_rtt_cal = true;
 
-               ath_dbg(common, ATH_DBG_CALIBRATE, "RTT restore %s\n",
+               ath_dbg(common, CALIBRATE, "RTT restore %s\n",
                        run_rtt_cal ? "failed" : "succeed");
        }
        run_agc_cal = run_rtt_cal;
@@ -1016,20 +1006,20 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
                u32 pld[4] = {0, 0, 0, 0};
 
                /* send CAL_REQ only when BT is AWAKE. */
-               ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_REQ 0x%x\n",
+               ath_dbg(common, MCI, "MCI send WLAN_CAL_REQ 0x%x\n",
                        mci_hw->wlan_cal_seq);
                MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ);
                pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++;
                ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
 
                /* Wait BT_CAL_GRANT for 50ms */
-               ath_dbg(common, ATH_DBG_MCI, "MCI wait for BT_CAL_GRANT");
+               ath_dbg(common, MCI, "MCI wait for BT_CAL_GRANT\n");
 
                if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000))
-                       ath_dbg(common, ATH_DBG_MCI, "MCI got BT_CAL_GRANT");
+                       ath_dbg(common, MCI, "MCI got BT_CAL_GRANT\n");
                else {
                        is_reusable = false;
-                       ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is not responding");
+                       ath_dbg(common, MCI, "\nMCI BT is not responding\n");
                }
        }
 
@@ -1058,7 +1048,7 @@ skip_tx_iqcal:
 
                u32 pld[4] = {0, 0, 0, 0};
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI Send WLAN_CAL_DONE 0x%x\n",
+               ath_dbg(common, MCI, "MCI Send WLAN_CAL_DONE 0x%x\n",
                        mci_hw->wlan_cal_done);
                MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE);
                pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++;
@@ -1074,9 +1064,8 @@ skip_tx_iqcal:
                if (run_rtt_cal)
                        ar9003_hw_rtt_disable(ah);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "offset calibration failed to complete in 1ms;"
-                       "noisy environment?\n");
+               ath_dbg(common, CALIBRATE,
+                       "offset calibration failed to complete in 1ms; noisy environment?\n");
                return false;
        }
 
@@ -1135,15 +1124,14 @@ skip_tx_iqcal:
        if (ah->supp_cals & IQ_MISMATCH_CAL) {
                INIT_CAL(&ah->iq_caldata);
                INSERT_CAL(ah, &ah->iq_caldata);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "enabling IQ Calibration.\n");
+               ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
        }
 
        if (ah->supp_cals & TEMP_COMP_CAL) {
                INIT_CAL(&ah->tempCompCalData);
                INSERT_CAL(ah, &ah->tempCompCalData);
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "enabling Temperature Compensation Calibration.\n");
+               ath_dbg(common, CALIBRATE,
+                       "enabling Temperature Compensation Calibration\n");
        }
 
        /* Initialize current pointer to first element in list */
index 4ba6f52943a86e3659731a7c1b81a9edb745556d..391def99314ce560bc2ddaac64d376e039142cab 100644 (file)
@@ -3043,8 +3043,7 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
        int i;
 
        if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "eeprom address not in range\n");
+               ath_dbg(common, EEPROM, "eeprom address not in range\n");
                return false;
        }
 
@@ -3075,8 +3074,8 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
        return true;
 
 error:
-       ath_dbg(common, ATH_DBG_EEPROM,
-               "unable to read eeprom region at offset %d\n", address);
+       ath_dbg(common, EEPROM, "unable to read eeprom region at offset %d\n",
+               address);
        return false;
 }
 
@@ -3160,13 +3159,13 @@ static bool ar9300_uncompress_block(struct ath_hw *ah,
                length &= 0xff;
 
                if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Restore at %d: spot=%d offset=%d length=%d\n",
                                it, spot, offset, length);
                        memcpy(&mptr[spot], &block[it+2], length);
                        spot += length;
                } else if (length > 0) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Bad restore at %d: spot=%d offset=%d length=%d\n",
                                it, spot, offset, length);
                        return false;
@@ -3188,13 +3187,13 @@ static int ar9300_compress_decision(struct ath_hw *ah,
        switch (code) {
        case _CompressNone:
                if (length != mdata_size) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "EEPROM structure size mismatch memory=%d eeprom=%d\n",
                                mdata_size, length);
                        return -1;
                }
                memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "restored eeprom %d: uncompressed, length %d\n",
                        it, length);
                break;
@@ -3203,22 +3202,21 @@ static int ar9300_compress_decision(struct ath_hw *ah,
                } else {
                        eep = ar9003_eeprom_struct_find_by_id(reference);
                        if (eep == NULL) {
-                               ath_dbg(common, ATH_DBG_EEPROM,
+                               ath_dbg(common, EEPROM,
                                        "can't find reference eeprom struct %d\n",
                                        reference);
                                return -1;
                        }
                        memcpy(mptr, eep, mdata_size);
                }
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "restore eeprom %d: block, reference %d, length %d\n",
                        it, reference, length);
                ar9300_uncompress_block(ah, mptr, mdata_size,
                                        (u8 *) (word + COMP_HDR_LEN), length);
                break;
        default:
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "unknown compression code %d\n", code);
+               ath_dbg(common, EEPROM, "unknown compression code %d\n", code);
                return -1;
        }
        return 0;
@@ -3294,34 +3292,32 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
                cptr = AR9300_BASE_ADDR_512;
        else
                cptr = AR9300_BASE_ADDR;
-       ath_dbg(common, ATH_DBG_EEPROM,
-               "Trying EEPROM access at Address 0x%04x\n", cptr);
+       ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
+               cptr);
        if (ar9300_check_eeprom_header(ah, read, cptr))
                goto found;
 
        cptr = AR9300_BASE_ADDR_512;
-       ath_dbg(common, ATH_DBG_EEPROM,
-               "Trying EEPROM access at Address 0x%04x\n", cptr);
+       ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
+               cptr);
        if (ar9300_check_eeprom_header(ah, read, cptr))
                goto found;
 
        read = ar9300_read_otp;
        cptr = AR9300_BASE_ADDR;
-       ath_dbg(common, ATH_DBG_EEPROM,
-               "Trying OTP access at Address 0x%04x\n", cptr);
+       ath_dbg(common, EEPROM, "Trying OTP access at Address 0x%04x\n", cptr);
        if (ar9300_check_eeprom_header(ah, read, cptr))
                goto found;
 
        cptr = AR9300_BASE_ADDR_512;
-       ath_dbg(common, ATH_DBG_EEPROM,
-               "Trying OTP access at Address 0x%04x\n", cptr);
+       ath_dbg(common, EEPROM, "Trying OTP access at Address 0x%04x\n", cptr);
        if (ar9300_check_eeprom_header(ah, read, cptr))
                goto found;
 
        goto fail;
 
 found:
-       ath_dbg(common, ATH_DBG_EEPROM, "Found valid EEPROM data\n");
+       ath_dbg(common, EEPROM, "Found valid EEPROM data\n");
 
        for (it = 0; it < MSTATE; it++) {
                if (!read(ah, cptr, word, COMP_HDR_LEN))
@@ -3332,13 +3328,12 @@ found:
 
                ar9300_comp_hdr_unpack(word, &code, &reference,
                                       &length, &major, &minor);
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
                        cptr, code, reference, length, major, minor);
                if ((!AR_SREV_9485(ah) && length >= 1024) ||
                    (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
-                               "Skipping bad header\n");
+                       ath_dbg(common, EEPROM, "Skipping bad header\n");
                        cptr -= COMP_HDR_LEN;
                        continue;
                }
@@ -3347,13 +3342,13 @@ found:
                read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
                checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
                mchecksum = get_unaligned_le16(&word[COMP_HDR_LEN + osize]);
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "checksum %x %x\n", checksum, mchecksum);
+               ath_dbg(common, EEPROM, "checksum %x %x\n",
+                       checksum, mchecksum);
                if (checksum == mchecksum) {
                        ar9300_compress_decision(ah, it, code, reference, mptr,
                                                 word, length, mdata_size);
                } else {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "skipping block with bad checksum\n");
                }
                cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
@@ -4424,8 +4419,8 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
                                              is2GHz) + ht40PowerIncForPdadc;
 
        for (i = 0; i < ar9300RateSize; i++) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
+               ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n",
+                       i, targetPowerValT2[i]);
        }
 }
 
@@ -4444,7 +4439,7 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
        struct ath_common *common = ath9k_hw_common(ah);
 
        if (ichain >= AR9300_MAX_CHAINS) {
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "Invalid chain index, must be less than %d\n",
                        AR9300_MAX_CHAINS);
                return -1;
@@ -4452,7 +4447,7 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
 
        if (mode) {             /* 5GHz */
                if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Invalid 5GHz cal pier index, must be less than %d\n",
                                AR9300_NUM_5G_CAL_PIERS);
                        return -1;
@@ -4462,7 +4457,7 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
                is2GHz = 0;
        } else {
                if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Invalid 2GHz cal pier index, must be less than %d\n",
                                AR9300_NUM_2G_CAL_PIERS);
                        return -1;
@@ -4624,8 +4619,7 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
 
        /* interpolate  */
        for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "ch=%d f=%d low=%d %d h=%d %d\n",
+               ath_dbg(common, EEPROM, "ch=%d f=%d low=%d %d h=%d %d\n",
                        ichain, frequency, lfrequency[ichain],
                        lcorrection[ichain], hfrequency[ichain],
                        hcorrection[ichain]);
@@ -4680,7 +4674,7 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
        ar9003_hw_power_control_override(ah, frequency, correction, voltage,
                                         temperature);
 
-       ath_dbg(common, ATH_DBG_EEPROM,
+       ath_dbg(common, EEPROM,
                "for frequency=%d, calibration correction = %d %d %d\n",
                frequency, correction[0], correction[1], correction[2]);
 
@@ -4866,7 +4860,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
                else
                        freq = centers.ctl_center;
 
-               ath_dbg(common, ATH_DBG_REGULATORY,
+               ath_dbg(common, REGULATORY,
                        "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n",
                        ctlMode, numCtlModes, isHt40CtlMode,
                        (pCtlMode[ctlMode] & EXT_ADDITIVE));
@@ -4882,7 +4876,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
 
                twiceMaxEdgePower = MAX_RATE_POWER;
                for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
-                       ath_dbg(common, ATH_DBG_REGULATORY,
+                       ath_dbg(common, REGULATORY,
                                "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n",
                                i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
                                chan->channel);
@@ -4924,7 +4918,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
 
                        minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
 
-                       ath_dbg(common, ATH_DBG_REGULATORY,
+                       ath_dbg(common, REGULATORY,
                                "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n",
                                ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
                                scaledPower, minCtlPower);
@@ -5048,7 +5042,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                                target_power_val_t2_eep[i]) >
                            paprd_scale_factor)) {
                                ah->paprd_ratemask &= ~(1 << i);
-                               ath_dbg(common, ATH_DBG_EEPROM,
+                               ath_dbg(common, EEPROM,
                                        "paprd disabled for mcs %d\n", i);
                        }
                }
@@ -5066,8 +5060,8 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                return;
 
        for (i = 0; i < ar9300RateSize; i++) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
+               ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n",
+                       i, targetPowerValT2[i]);
        }
 
        ah->txpower_limit = regulatory->max_power_level;
index 631fe4f2e495e8d2cb05fa665bccadf89ba110e5..4a315155d779fd90232a17343cf349e6ba3d64dc 100644 (file)
@@ -305,10 +305,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
 
                if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef))
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI gets 0xdeadbeef during MCI int processing"
-                               "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, "
-                               "raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
+                       ath_dbg(common, MCI,
+                               "MCI gets 0xdeadbeef during MCI int processing new raw_intr=0x%08x, new rx_msg_raw=0x%08x, raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
                                raw_intr, rx_msg_intr, mci->raw_intr,
                                mci->rx_msg_intr);
                else {
@@ -322,7 +320,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
                        REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
-                       ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n");
+                       ath_dbg(common, MCI, "AR_INTR_SYNC_MCI\n");
 
                }
        }
@@ -335,7 +333,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                }
 
                if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
-                       ath_dbg(common, ATH_DBG_INTERRUPT,
+                       ath_dbg(common, INTERRUPT,
                                "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
 
                REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
@@ -366,7 +364,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 
        if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
            (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
+               ath_dbg(ath9k_hw_common(ah), XMIT,
                        "Tx Descriptor error %x\n", ads->ds_info);
                memset(ads, 0, sizeof(*ads));
                return -EIO;
@@ -574,7 +572,7 @@ void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
        memset((void *) ah->ts_ring, 0,
                ah->ts_size * sizeof(struct ar9003_txs));
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
+       ath_dbg(ath9k_hw_common(ah), XMIT,
                "TS Start 0x%x End 0x%x Virt %p, Size %d\n",
                ah->ts_paddr_start, ah->ts_paddr_end,
                ah->ts_ring, ah->ts_size);
index 8599822dc83f1b93790ad8e86495737985b69378..709520c6835bd62444a8aa1f713fd67264be6985 100644 (file)
@@ -68,11 +68,11 @@ static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address,
        }
 
        if (time_out <= 0) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Wait for Reg 0x%08x = 0x%08x timeout.\n",
+               ath_dbg(common, MCI,
+                       "MCI Wait for Reg 0x%08x = 0x%08x timeout\n",
                        address, bit_position);
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x",
+               ath_dbg(common, MCI,
+                       "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",
                        REG_READ(ah, AR_MCI_INTERRUPT_RAW),
                        REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
                time_out = 0;
@@ -85,6 +85,9 @@ void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done)
 {
        u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
                                wait_done, false);
        udelay(5);
@@ -94,6 +97,9 @@ void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done)
 {
        u32 payload = 0x00000000;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
                                wait_done, false);
 }
@@ -107,6 +113,9 @@ static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done)
 
 void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)
 {
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,
                                NULL, 0, wait_done, false);
 }
@@ -135,7 +144,7 @@ static void ar9003_mci_send_coex_version_query(struct ath_hw *ah,
 
        if (!mci->bt_version_known &&
                        (mci->bt_state != MCI_BT_SLEEP)) {
-               ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version query\n");
+               ath_dbg(common, MCI, "MCI Send Coex version query\n");
                MCI_GPM_SET_TYPE_OPCODE(payload,
                                MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY);
                ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
@@ -150,7 +159,7 @@ static void ar9003_mci_send_coex_version_response(struct ath_hw *ah,
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        u32 payload[4] = {0, 0, 0, 0};
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version response\n");
+       ath_dbg(common, MCI, "MCI Send Coex version response\n");
        MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
                        MCI_GPM_COEX_VERSION_RESPONSE);
        *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
@@ -187,8 +196,8 @@ static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah,
 
        if (mci->bt_state != MCI_BT_SLEEP) {
 
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Send Coex BT Status Query 0x%02X\n", query_type);
+               ath_dbg(common, MCI, "MCI Send Coex BT Status Query 0x%02X\n",
+                       query_type);
 
                MCI_GPM_SET_TYPE_OPCODE(payload,
                                MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY);
@@ -203,9 +212,8 @@ static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah,
                        if (query_btinfo) {
                                mci->need_flush_btinfo = true;
 
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI send bt_status_query fail, "
-                                       "set flush flag again\n");
+                               ath_dbg(common, MCI,
+                                       "MCI send bt_status_query fail, set flush flag again\n");
                        }
                }
 
@@ -221,7 +229,10 @@ void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt,
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        u32 payload[4] = {0, 0, 0, 0};
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex %s BT GPM.\n",
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
+       ath_dbg(common, MCI, "MCI Send Coex %s BT GPM\n",
                (halt) ? "halt" : "unhalt");
 
        MCI_GPM_SET_TYPE_OPCODE(payload,
@@ -259,8 +270,8 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
                  REG_READ(ah, AR_MCI_INTERRUPT_RAW));
 
        /* Remote Reset */
-       ath_dbg(common, ATH_DBG_MCI, "MCI Reset sequence start\n");
-       ath_dbg(common, ATH_DBG_MCI, "MCI send REMOTE_RESET\n");
+       ath_dbg(common, MCI, "MCI Reset sequence start\n");
+       ath_dbg(common, MCI, "MCI send REMOTE_RESET\n");
        ar9003_mci_remote_reset(ah, true);
 
        /*
@@ -271,14 +282,13 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
        if (AR_SREV_9462_10(ah))
                udelay(252);
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI Send REQ_WAKE to remoter(BT)\n");
+       ath_dbg(common, MCI, "MCI Send REQ_WAKE to remoter(BT)\n");
        ar9003_mci_send_req_wake(ah, true);
 
        if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
                                AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) {
 
-               ath_dbg(common, ATH_DBG_MCI,
-                               "MCI SYS_WAKING from remote(BT)\n");
+               ath_dbg(common, MCI, "MCI SYS_WAKING from remote(BT)\n");
                mci->bt_state = MCI_BT_AWAKE;
 
                if (AR_SREV_9462_10(ah))
@@ -302,8 +312,7 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
 
                /* Send SYS_WAKING to BT */
 
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI send SW SYS_WAKING to remote BT\n");
+               ath_dbg(common, MCI, "MCI send SW SYS_WAKING to remote BT\n");
 
                ar9003_mci_send_sys_waking(ah, true);
                udelay(10);
@@ -332,8 +341,7 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
 
                if (AR_SREV_9462_10(ah) || mci->is_2g) {
                        /* Send LNA_TRANS */
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI send LNA_TRANS to BT\n");
+                       ath_dbg(common, MCI, "MCI send LNA_TRANS to BT\n");
                        ar9003_mci_send_lna_transfer(ah, true);
                        udelay(5);
                }
@@ -344,20 +352,17 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
                                AR_MCI_INTERRUPT_RX_MSG_RAW,
                                AR_MCI_INTERRUPT_RX_MSG_LNA_INFO,
                                mci_timeout))
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI WLAN has control over the LNA & "
-                                       "BT obeys it\n");
+                               ath_dbg(common, MCI,
+                                       "MCI WLAN has control over the LNA & BT obeys it\n");
                        else
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI BT didn't respond to"
-                                       "LNA_TRANS\n");
+                               ath_dbg(common, MCI,
+                                       "MCI BT didn't respond to LNA_TRANS\n");
                }
 
                if (AR_SREV_9462_10(ah)) {
                        /* Send another remote_reset to deassert BT clk_req. */
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI another remote_reset to "
-                               "deassert clk_req\n");
+                       ath_dbg(common, MCI,
+                               "MCI another remote_reset to deassert clk_req\n");
                        ar9003_mci_remote_reset(ah, true);
                        udelay(252);
                }
@@ -381,12 +386,17 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
 
 void ar9003_mci_disable_interrupt(struct ath_hw *ah)
 {
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
        REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
 }
 
 void ar9003_mci_enable_interrupt(struct ath_hw *ah)
 {
+       if (!ATH9K_HW_CAP_MCI)
+               return;
 
        REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
        REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
@@ -397,6 +407,9 @@ bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints)
 {
        u32 intr;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return false;
+
        intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
        return ((intr & ints) == ints);
 }
@@ -405,6 +418,10 @@ void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
                              u32 *rx_msg_intr)
 {
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        *raw_intr = mci->raw_intr;
        *rx_msg_intr = mci->rx_msg_intr;
 
@@ -418,6 +435,9 @@ void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g)
 {
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        if (!mci->update_2g5g &&
            (mci->is_2g != is_2g))
                mci->update_2g5g = true;
@@ -441,7 +461,7 @@ static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index)
        recv_type = MCI_GPM_TYPE(payload);
 
        if (recv_type == MCI_GPM_RSVD_PATTERN) {
-               ath_dbg(common, ATH_DBG_MCI, "MCI Skip RSVD GPM\n");
+               ath_dbg(common, MCI, "MCI Skip RSVD GPM\n");
                return false;
        }
 
@@ -514,11 +534,11 @@ static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done,
        *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF;
        *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF;
 
-       ath_dbg(common, ATH_DBG_MCI,
+       ath_dbg(common, MCI,
                "MCI BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n",
-               (opcode == MCI_GPM_COEX_BT_FLAGS_READ) ? "READ" :
-               ((opcode == MCI_GPM_COEX_BT_FLAGS_SET) ? "SET" : "CLEAR"),
-                                                               bt_flags);
+               opcode == MCI_GPM_COEX_BT_FLAGS_READ ? "READ" :
+               opcode == MCI_GPM_COEX_BT_FLAGS_SET ? "SET" : "CLEAR",
+               bt_flags);
 
        return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16,
                                                        wait_done, true);
@@ -531,7 +551,10 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        u32 regval, thresh;
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI full_sleep = %d, is_2g = %d\n",
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
+       ath_dbg(common, MCI, "MCI full_sleep = %d, is_2g = %d\n",
                is_full_sleep, is_2g);
 
        /*
@@ -539,14 +562,13 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
         */
 
        if (!mci->gpm_addr && !mci->sched_addr) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI GPM and schedule buffers are not allocated");
+               ath_dbg(common, MCI,
+                       "MCI GPM and schedule buffers are not allocated\n");
                return;
        }
 
        if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI it's deadbeef, quit mci_reset\n");
+               ath_dbg(common, MCI, "MCI it's deadbeef, quit mci_reset\n");
                return;
        }
 
@@ -574,8 +596,7 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
                !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) {
 
                regval |= SM(1, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
-               ath_dbg(common, ATH_DBG_MCI,
-                               "MCI sched one step look ahead\n");
+               ath_dbg(common, MCI, "MCI sched one step look ahead\n");
 
                if (!(mci->config &
                      ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
@@ -593,11 +614,9 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
                                      AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
 
                } else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI sched aggr thresh: off\n");
+                       ath_dbg(common, MCI, "MCI sched aggr thresh: off\n");
        } else
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI SCHED one step look ahead off\n");
+               ath_dbg(common, MCI, "MCI SCHED one step look ahead off\n");
 
        if (AR_SREV_9462_10(ah))
                regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
@@ -661,6 +680,9 @@ void ar9003_mci_mute_bt(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        /* disable all MCI messages */
        REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
        REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
@@ -678,12 +700,12 @@ void ar9003_mci_mute_bt(struct ath_hw *ah)
         * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
         */
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n");
+       ath_dbg(common, MCI, "MCI Send LNA take\n");
        ar9003_mci_send_lna_take(ah, true);
 
        udelay(5);
 
-       ath_dbg(common, ATH_DBG_MCI, "MCI Send sys sleeping\n");
+       ath_dbg(common, MCI, "MCI Send sys sleeping\n");
        ar9003_mci_send_sys_sleeping(ah, true);
 }
 
@@ -693,10 +715,13 @@ void ar9003_mci_sync_bt_state(struct ath_hw *ah)
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        u32 cur_bt_state;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL);
 
        if (mci->bt_state != cur_bt_state) {
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "MCI BT state mismatches. old: %d, new: %d\n",
                        mci->bt_state, cur_bt_state);
                mci->bt_state = cur_bt_state;
@@ -708,7 +733,7 @@ void ar9003_mci_sync_bt_state(struct ath_hw *ah)
                ar9003_mci_send_coex_wlan_channels(ah, true);
 
                if (mci->unhalt_bt_gpm == true) {
-                       ath_dbg(common, ATH_DBG_MCI, "MCI unhalt BT GPM");
+                       ath_dbg(common, MCI, "MCI unhalt BT GPM\n");
                        ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
                }
        }
@@ -734,7 +759,7 @@ static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done)
                        to_set = MCI_5G_FLAGS_SET_MASK;
                }
 
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "MCI BT_MCI_FLAGS: %s 0x%08x clr=0x%08x, set=0x%08x\n",
                mci->is_2g ? "2G" : "5G", new_flags, to_clear, to_set);
 
@@ -761,15 +786,15 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
        if (queue) {
 
                if (payload)
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "MCI ERROR: Send fail: %02x: %02x %02x %02x\n",
                                header,
                                *(((u8 *)payload) + 4),
                                *(((u8 *)payload) + 5),
                                *(((u8 *)payload) + 6));
                else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI ERROR: Send fail: %02x\n", header);
+                       ath_dbg(common, MCI, "MCI ERROR: Send fail: %02x\n",
+                               header);
        }
 
        /* check if the message is to be queued */
@@ -795,12 +820,12 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
                mci->update_2g5g = queue;
 
                if (queue)
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI BT_MCI_FLAGS: 2G5G status <queued> %s.\n",
+                       ath_dbg(common, MCI,
+                               "MCI BT_MCI_FLAGS: 2G5G status <queued> %s\n",
                                mci->is_2g ? "2G" : "5G");
                else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI BT_MCI_FLAGS: 2G5G status <sent> %s.\n",
+                       ath_dbg(common, MCI,
+                               "MCI BT_MCI_FLAGS: 2G5G status <sent> %s\n",
                                mci->is_2g ? "2G" : "5G");
 
                break;
@@ -809,11 +834,9 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
 
                mci->wlan_channels_update = queue;
                if (queue)
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI WLAN channel map <queued>\n");
+                       ath_dbg(common, MCI, "MCI WLAN channel map <queued>\n");
                else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI WLAN channel map <sent>\n");
+                       ath_dbg(common, MCI, "MCI WLAN channel map <sent>\n");
                break;
 
        case MCI_GPM_COEX_HALT_BT_GPM:
@@ -824,11 +847,11 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
                        mci->unhalt_bt_gpm = queue;
 
                        if (queue)
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI UNHALT BT GPM <queued>\n");
                        else {
                                mci->halted_bt_gpm = false;
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI UNHALT BT GPM <sent>\n");
                        }
                }
@@ -839,10 +862,10 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
                        mci->halted_bt_gpm = !queue;
 
                        if (queue)
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI HALT BT GPM <not sent>\n");
                        else
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI UNHALT BT GPM <sent>\n");
                }
 
@@ -857,11 +880,14 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        if (mci->update_2g5g) {
                if (mci->is_2g) {
 
                        ar9003_mci_send_2g5g_status(ah, true);
-                       ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA trans\n");
+                       ath_dbg(common, MCI, "MCI Send LNA trans\n");
                        ar9003_mci_send_lna_transfer(ah, true);
                        udelay(5);
 
@@ -878,7 +904,7 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
                                }
                        }
                } else {
-                       ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n");
+                       ath_dbg(common, MCI, "MCI Send LNA take\n");
                        ar9003_mci_send_lna_take(ah, true);
                        udelay(5);
 
@@ -908,14 +934,17 @@ bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
        u32 saved_mci_int_en;
        int i;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return false;
+
        saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
        regval = REG_READ(ah, AR_BTCOEX_CTRL);
 
        if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
 
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Not sending 0x%x. MCI is not enabled. "
-                       "full_sleep = %d\n", header,
+               ath_dbg(common, MCI,
+                       "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n",
+                       header,
                        (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0);
 
                ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
@@ -923,8 +952,9 @@ bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
 
        } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) {
 
-               ath_dbg(common, ATH_DBG_MCI,
-               "MCI Don't send message 0x%x. BT is in sleep state\n", header);
+               ath_dbg(common, MCI,
+                       "MCI Don't send message 0x%x. BT is in sleep state\n",
+                       header);
 
                ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
                return false;
@@ -973,6 +1003,9 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        mci->gpm_addr = gpm_addr;
        mci->gpm_buf = gpm_buf;
        mci->gpm_len = len;
@@ -987,9 +1020,12 @@ void ar9003_mci_cleanup(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        /* Turn off MCI and Jupiter mode. */
        REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
-       ath_dbg(common, ATH_DBG_MCI, "MCI ar9003_mci_cleanup\n");
+       ath_dbg(common, MCI, "MCI ar9003_mci_cleanup\n");
        ar9003_mci_disable_interrupt(ah);
 }
 EXPORT_SYMBOL(ar9003_mci_cleanup);
@@ -1006,40 +1042,35 @@ static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type,
 
        switch (gpm_opcode) {
        case MCI_GPM_COEX_VERSION_QUERY:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Version Query\n");
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n");
                ar9003_mci_send_coex_version_response(ah, true);
                break;
        case MCI_GPM_COEX_VERSION_RESPONSE:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Version Response\n");
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n");
                mci->bt_ver_major =
                        *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
                mci->bt_ver_minor =
                        *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
                mci->bt_version_known = true;
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI BT Coex version: %d.%d\n",
-                       mci->bt_ver_major,
-                       mci->bt_ver_minor);
+               ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n",
+                       mci->bt_ver_major, mci->bt_ver_minor);
                break;
        case MCI_GPM_COEX_STATUS_QUERY:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Status Query = 0x%02X.\n",
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX Status Query = 0x%02X\n",
                        *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
                mci->wlan_channels_update = true;
                ar9003_mci_send_coex_wlan_channels(ah, true);
                break;
        case MCI_GPM_COEX_BT_PROFILE_INFO:
                mci->query_bt = true;
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX BT_Profile_Info\n");
+               ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n");
                break;
        case MCI_GPM_COEX_BT_STATUS_UPDATE:
                mci->query_bt = true;
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX BT_Status_Update "
-                       "SEQ=%d (drop&query)\n", *(p_gpm + 3));
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n",
+                       *(p_gpm + 3));
                break;
        default:
                break;
@@ -1056,6 +1087,9 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
        u8 recv_type = 0, recv_opcode = 0;
        bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
 
+       if (!ATH9K_HW_CAP_MCI)
+               return 0;
+
        more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;
 
        while (time_out > 0) {
@@ -1090,9 +1124,8 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
                                if ((gpm_type == MCI_GPM_BT_CAL_DONE) &&
                                    !b_is_bt_cal_done) {
                                        gpm_type = MCI_GPM_BT_CAL_GRANT;
-                                       ath_dbg(common, ATH_DBG_MCI,
-                                               "MCI Recv BT_CAL_DONE"
-                                               "wait BT_CAL_GRANT\n");
+                                       ath_dbg(common, MCI,
+                                               "MCI Recv BT_CAL_DONE wait BT_CAL_GRANT\n");
                                        continue;
                                }
 
@@ -1123,7 +1156,7 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
                        u32 payload[4] = {0, 0, 0, 0};
 
                        gpm_type = MCI_GPM_BT_CAL_DONE;
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "MCI Rcv BT_CAL_REQ, send WLAN_CAL_GRANT\n");
 
                        MCI_GPM_SET_CAL_TYPE(payload,
@@ -1132,13 +1165,12 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
                        ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
                                                false, false);
 
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI now wait for BT_CAL_DONE\n");
+                       ath_dbg(common, MCI, "MCI now wait for BT_CAL_DONE\n");
 
                        continue;
                } else {
-                       ath_dbg(common, ATH_DBG_MCI, "MCI GPM subtype"
-                                       "not match 0x%x\n", *(p_gpm + 1));
+                       ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n",
+                               *(p_gpm + 1));
                        mismatch++;
                        ar9003_mci_process_gpm_extra(ah, recv_type,
                                        recv_opcode, p_gpm);
@@ -1151,16 +1183,15 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
 
        if (time_out <= 0) {
                time_out = 0;
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "MCI GPM received timeout, mismatch = %d\n", mismatch);
        } else
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Receive GPM type=0x%x, code=0x%x\n",
+               ath_dbg(common, MCI, "MCI Receive GPM type=0x%x, code=0x%x\n",
                        gpm_type, gpm_opcode);
 
        while (more_data == MCI_GPM_MORE) {
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI discard remaining GPM\n");
+               ath_dbg(common, MCI, "MCI discard remaining GPM\n");
                offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
                                          &more_data);
 
@@ -1188,6 +1219,9 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
        u32 value = 0, more_gpm = 0, gpm_ptr;
        u8 query_type;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return 0;
+
        switch (state_type) {
        case MCI_STATE_ENABLE:
                if (mci->ready) {
@@ -1201,8 +1235,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                break;
        case MCI_STATE_INIT_GPM_OFFSET:
                value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI GPM initial WRITE_PTR=%d\n", value);
+               ath_dbg(common, MCI, "MCI GPM initial WRITE_PTR=%d\n", value);
                mci->gpm_idx = value;
                break;
        case MCI_STATE_NEXT_GPM_OFFSET:
@@ -1227,8 +1260,8 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                else if (value >= mci->gpm_len) {
                        if (value != 0xFFFF) {
                                value = 0;
-                               ath_dbg(common, ATH_DBG_MCI, "MCI GPM offset"
-                                       "out of range\n");
+                               ath_dbg(common, MCI,
+                                       "MCI GPM offset out of range\n");
                        }
                } else
                        value--;
@@ -1236,8 +1269,8 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                if (value == 0xFFFF) {
                        value = MCI_GPM_INVALID;
                        more_gpm = MCI_GPM_NOMORE;
-                       ath_dbg(common, ATH_DBG_MCI, "MCI GPM ptr invalid"
-                               "@ptr=%d, offset=%d, more=GPM_NOMORE\n",
+                       ath_dbg(common, MCI,
+                               "MCI GPM ptr invalid @ptr=%d, offset=%d, more=GPM_NOMORE\n",
                                gpm_ptr, value);
                } else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) {
 
@@ -1245,9 +1278,9 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                                value = MCI_GPM_INVALID;
                                more_gpm = MCI_GPM_NOMORE;
 
-                               ath_dbg(common, ATH_DBG_MCI, "MCI GPM message"
-                                       "not available @ptr=%d, @offset=%d,"
-                                       "more=GPM_NOMORE\n", gpm_ptr, value);
+                               ath_dbg(common, MCI,
+                                       "MCI GPM message not available @ptr=%d, @offset=%d, more=GPM_NOMORE\n",
+                                       gpm_ptr, value);
                        } else {
                                for (;;) {
 
@@ -1267,9 +1300,8 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                                            mci->gpm_len)
                                                mci->gpm_idx = 0;
 
-                                       ath_dbg(common, ATH_DBG_MCI,
-                                               "MCI GPM message got ptr=%d,"
-                                               "@offset=%d, more=%d\n",
+                                       ath_dbg(common, MCI,
+                                               "MCI GPM message got ptr=%d, @offset=%d, more=%d\n",
                                                gpm_ptr, temp_index,
                                                (more_gpm == MCI_GPM_MORE));
 
@@ -1333,8 +1365,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
 
                if (mci->unhalt_bt_gpm) {
 
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI unhalt BT GPM\n");
+                       ath_dbg(common, MCI, "MCI unhalt BT GPM\n");
                        ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
                }
 
@@ -1360,8 +1391,8 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
                                      ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
                                        ATH_MCI_CONFIG_MCI_OBS_GPIO) {
 
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI reconfigure observation");
+                               ath_dbg(common, MCI,
+                                       "MCI reconfigure observation\n");
                                ar9003_mci_observation_set_up(ah);
                        }
                }
@@ -1374,16 +1405,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
        case MCI_STATE_SET_BT_COEX_VERSION:
 
                if (!p_data)
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "MCI Set BT Coex version with NULL data!!\n");
                else {
                        mci->bt_ver_major = (*p_data >> 8) & 0xff;
                        mci->bt_ver_minor = (*p_data) & 0xff;
                        mci->bt_version_known = true;
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI BT version set: %d.%d\n",
-                               mci->bt_ver_major,
-                               mci->bt_ver_minor);
+                       ath_dbg(common, MCI, "MCI BT version set: %d.%d\n",
+                               mci->bt_ver_major, mci->bt_ver_minor);
                }
                break;
 
@@ -1438,7 +1467,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
 
        case MCI_STATE_RECOVER_RX:
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI hw RECOVER_RX\n");
+               ath_dbg(common, MCI, "MCI hw RECOVER_RX\n");
                ar9003_mci_prep_interface(ah);
                mci->query_bt = true;
                mci->need_flush_btinfo = true;
index a4450cba065375509e241e7397730e9e6c4c04ad..59647a3ceb7f98ea568d34e16248c80471290f78 100644 (file)
@@ -119,8 +119,8 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
                break;
        default:
                delta = 0;
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-               "Invalid tx-chainmask: %u\n", ah->txchainmask);
+               ath_dbg(common, CALIBRATE, "Invalid tx-chainmask: %u\n",
+                       ah->txchainmask);
        }
 
        power += delta;
@@ -148,13 +148,12 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
        else
                training_power = ar9003_get_training_power_5g(ah);
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "Training power: %d, Target power: %d\n",
+       ath_dbg(common, CALIBRATE, "Training power: %d, Target power: %d\n",
                training_power, ah->paprd_target_power);
 
        if (training_power < 0) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "PAPRD target power delta out of range");
+               ath_dbg(common, CALIBRATE,
+                       "PAPRD target power delta out of range\n");
                return -ERANGE;
        }
        ah->paprd_training_power = training_power;
@@ -311,8 +310,8 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
                reg_cl_gain = AR_PHY_CL_TAB_2;
                break;
        default:
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-               "Invalid chainmask: %d\n", chain);
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
+                       "Invalid chainmask: %d\n", chain);
                break;
        }
 
@@ -850,7 +849,7 @@ bool ar9003_paprd_is_done(struct ath_hw *ah)
                agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
                                AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
 
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+               ath_dbg(ath9k_hw_common(ah), CALIBRATE,
                        "AGC2_PWR = 0x%x training done = 0x%x\n",
                        agc2_pwr, paprd_done);
        /*
index e41d26939ab8799d66d71b30b0699799aad4eca1..2589b38b689a82cdc3acbe7748ffa7bd33092906 100644 (file)
@@ -882,7 +882,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                                    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
 
                if (!on != aniState->ofdmWeakSigDetectOff) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: ofdm weak signal: %s=>%s\n",
                                chan->channel,
                                !aniState->ofdmWeakSigDetectOff ?
@@ -900,7 +900,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(firstep_table)) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(firstep_table));
                        return false;
@@ -937,7 +937,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                              AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
 
                if (level != aniState->firstepLevel) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->firstepLevel,
@@ -945,7 +945,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                                ATH9K_ANI_FIRSTEP_LVL_NEW,
                                value,
                                aniState->iniDef.firstep);
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->firstepLevel,
@@ -965,7 +965,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                u32 level = param;
 
                if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
                                level, ARRAY_SIZE(cycpwrThr1_table));
                        return false;
@@ -1001,7 +1001,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                              AR_PHY_EXT_CYCPWR_THR1, value2);
 
                if (level != aniState->spurImmunityLevel) {
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->spurImmunityLevel,
@@ -1009,7 +1009,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                                ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
                                value,
                                aniState->iniDef.cycpwrThr1);
-                       ath_dbg(common, ATH_DBG_ANI,
+                       ath_dbg(common, ANI,
                                "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
                                chan->channel,
                                aniState->spurImmunityLevel,
@@ -1036,8 +1036,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
                              AR_PHY_MRC_CCK_MUX_REG, is_on);
                if (!is_on != aniState->mrcCCKOff) {
-                       ath_dbg(common, ATH_DBG_ANI,
-                               "** ch %d: MRC CCK: %s=>%s\n",
+                       ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
                                chan->channel,
                                !aniState->mrcCCKOff ? "on" : "off",
                                is_on ? "on" : "off");
@@ -1052,11 +1051,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
        case ATH9K_ANI_PRESENT:
                break;
        default:
-               ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd);
+               ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
                return false;
        }
 
-       ath_dbg(common, ATH_DBG_ANI,
+       ath_dbg(common, ANI,
                "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
                aniState->spurImmunityLevel,
                !aniState->ofdmWeakSigDetectOff ? "on" : "off",
@@ -1125,8 +1124,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
        aniState = &ah->curchan->ani;
        iniDef = &aniState->iniDef;
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
+       ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
                ah->hw_version.macVersion,
                ah->hw_version.macRev,
                ah->opmode,
@@ -1388,7 +1386,7 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
                          ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
                            AR_PHY_WATCHDOG_IDLE_ENABLE));
 
-               ath_dbg(common, ATH_DBG_RESET, "Disabled BB Watchdog\n");
+               ath_dbg(common, RESET, "Disabled BB Watchdog\n");
                return;
        }
 
@@ -1424,8 +1422,7 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
                  AR_PHY_WATCHDOG_IDLE_MASK |
                  (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2)));
 
-       ath_dbg(common, ATH_DBG_RESET,
-               "Enabled BB Watchdog timeout (%u ms)\n",
+       ath_dbg(common, RESET, "Enabled BB Watchdog timeout (%u ms)\n",
                idle_tmo_ms);
 }
 
@@ -1454,9 +1451,9 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
                return;
 
        status = ah->bb_watchdog_last_status;
-       ath_dbg(common, ATH_DBG_RESET,
+       ath_dbg(common, RESET,
                "\n==== BB update: BB status=0x%08x ====\n", status);
-       ath_dbg(common, ATH_DBG_RESET,
+       ath_dbg(common, RESET,
                "** BB state: wd=%u det=%u rdar=%u rOFDM=%d rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
                MS(status, AR_PHY_WATCHDOG_INFO),
                MS(status, AR_PHY_WATCHDOG_DET_HANG),
@@ -1468,22 +1465,19 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
                MS(status, AR_PHY_WATCHDOG_AGC_SM),
                MS(status, AR_PHY_WATCHDOG_SRCH_SM));
 
-       ath_dbg(common, ATH_DBG_RESET,
-               "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
+       ath_dbg(common, RESET, "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
                REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
                REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
-       ath_dbg(common, ATH_DBG_RESET,
-               "** BB mode: BB_gen_controls=0x%08x **\n",
+       ath_dbg(common, RESET, "** BB mode: BB_gen_controls=0x%08x **\n",
                REG_READ(ah, AR_PHY_GEN_CTRL));
 
 #define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
        if (common->cc_survey.cycles)
-               ath_dbg(common, ATH_DBG_RESET,
+               ath_dbg(common, RESET,
                        "** BB busy times: rx_clear=%d%%, rx_frame=%d%%, tx_frame=%d%% **\n",
                        PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
 
-       ath_dbg(common, ATH_DBG_RESET,
-               "==== BB update: done ====\n\n");
+       ath_dbg(common, RESET, "==== BB update: done ====\n\n");
 }
 EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
 
index 130e5dba95557621e89ef15135ccf3d496c59c1c..95276e914c1b7c2f1448c705026762dacfdbc8c1 100644 (file)
@@ -196,6 +196,7 @@ struct ath_txq {
        u8 txq_headidx;
        u8 txq_tailidx;
        int pending_frames;
+       struct sk_buff_head complete_q;
 };
 
 struct ath_atx_ac {
index a13cabb95435873d63f8d289558d89c6dca6452e..dc5fd569690ffe15365c6c95403204d3bf29c112 100644 (file)
@@ -117,11 +117,10 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
        memset(&txctl, 0, sizeof(struct ath_tx_control));
        txctl.txq = sc->beacon.cabq;
 
-       ath_dbg(common, ATH_DBG_XMIT,
-               "transmitting CABQ packet, skb: %p\n", skb);
+       ath_dbg(common, XMIT, "transmitting CABQ packet, skb: %p\n", skb);
 
        if (ath_tx_start(hw, skb, &txctl) != 0) {
-               ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n");
+               ath_dbg(common, XMIT, "CABQ TX failed\n");
                dev_kfree_skb_any(skb);
        }
 }
@@ -204,7 +203,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 
        if (skb && cabq_depth) {
                if (sc->nvifs > 1) {
-                       ath_dbg(common, ATH_DBG_BEACON,
+                       ath_dbg(common, BEACON,
                                "Flushing previous cabq traffic\n");
                        ath_draintxq(sc, cabq, false);
                }
@@ -297,7 +296,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
                tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF;
                avp->tsf_adjust = cpu_to_le64(tsfadjust);
 
-               ath_dbg(common, ATH_DBG_BEACON,
+               ath_dbg(common, BEACON,
                        "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
                        avp->av_bslot, intval, (unsigned long long)tsfadjust);
 
@@ -371,15 +370,14 @@ void ath_beacon_tasklet(unsigned long data)
                sc->beacon.bmisscnt++;
 
                if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
-                       ath_dbg(common, ATH_DBG_BSTUCK,
+                       ath_dbg(common, BSTUCK,
                                "missed %u consecutive beacons\n",
                                sc->beacon.bmisscnt);
                        ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
                        if (sc->beacon.bmisscnt > 3)
                                ath9k_hw_bstuck_nfcal(ah);
                } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
-                       ath_dbg(common, ATH_DBG_BSTUCK,
-                               "beacon is officially stuck\n");
+                       ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
                        sc->sc_flags |= SC_OP_TSF_RESET;
                        ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
                }
@@ -406,7 +404,7 @@ void ath_beacon_tasklet(unsigned long data)
                slot = (tsftu % (intval * ATH_BCBUF)) / intval;
                vif = sc->beacon.bslot[slot];
 
-               ath_dbg(common, ATH_DBG_BEACON,
+               ath_dbg(common, BEACON,
                        "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
                        slot, tsf, tsftu / ATH_BCBUF, intval, vif);
        } else {
@@ -424,7 +422,7 @@ void ath_beacon_tasklet(unsigned long data)
                }
 
                if (sc->beacon.bmisscnt != 0) {
-                       ath_dbg(common, ATH_DBG_BSTUCK,
+                       ath_dbg(common, BSTUCK,
                                "resume beacon xmit after %u misses\n",
                                sc->beacon.bmisscnt);
                        sc->beacon.bmisscnt = 0;
@@ -541,7 +539,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
 
        /* No need to configure beacon if we are not associated */
        if (!common->curaid) {
-               ath_dbg(common, ATH_DBG_BEACON,
+               ath_dbg(common, BEACON,
                        "STA is not yet associated..skipping beacon config\n");
                return;
        }
@@ -631,8 +629,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
        /* TSF out of range threshold fixed at 1 second */
        bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-       ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-       ath_dbg(common, ATH_DBG_BEACON,
+       ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+       ath_dbg(common, BEACON,
                "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
                bs.bs_bmissthreshold, bs.bs_sleepduration,
                bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
@@ -660,8 +658,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
        tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
        nexttbtt = tsf + intval;
 
-       ath_dbg(common, ATH_DBG_BEACON,
-               "IBSS nexttbtt %u intval %u (%u)\n",
+       ath_dbg(common, BEACON, "IBSS nexttbtt %u intval %u (%u)\n",
                nexttbtt, intval, conf->beacon_interval);
 
        /*
@@ -699,9 +696,8 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
            (sc->nbcnvifs > 1) &&
            (vif->type == NL80211_IFTYPE_AP) &&
            (cur_conf->beacon_interval != bss_conf->beacon_int)) {
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Changing beacon interval of multiple \
-                       AP interfaces !\n");
+               ath_dbg(common, CONFIG,
+                       "Changing beacon interval of multiple AP interfaces !\n");
                return false;
        }
        /*
@@ -710,7 +706,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
         */
        if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
            (vif->type != NL80211_IFTYPE_AP)) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "STA vif's beacon not allowed on AP mode\n");
                return false;
        }
@@ -722,7 +718,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
            (vif->type == NL80211_IFTYPE_STATION) &&
            (sc->sc_flags & SC_OP_BEACONS) &&
            !avp->primary_sta_vif) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Beacon already configured for a station interface\n");
                return false;
        }
@@ -802,8 +798,7 @@ void ath_set_beacon(struct ath_softc *sc)
                ath_beacon_config_sta(sc, cur_conf);
                break;
        default:
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Unsupported beaconing mode\n");
+               ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
                return;
        }
 
index bbb20810ec104ed1f30892c1fb2215751d41fbc1..a6712a95d76a24da330c4d628fc15455afce5536 100644 (file)
@@ -68,6 +68,9 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
        u32 i, idx;
        bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        if (AR_SREV_9300_20_OR_LATER(ah))
                rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
 
@@ -99,6 +102,9 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        /* connect bt_active to baseband */
        REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
                    (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
@@ -121,6 +127,9 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        /* btcoex 3-wire */
        REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
                        (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
@@ -147,6 +156,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        /* Configure the desired GPIO port for TX_FRAME output */
        ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
                            AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
@@ -158,6 +170,9 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
                                     SM(wlan_weight, AR_BTCOEX_WL_WGHT);
 }
@@ -219,9 +234,9 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
 {
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
-       switch (btcoex_hw->scheme) {
+       switch (ath9k_hw_get_btcoex_scheme(ah)) {
        case ATH_BTCOEX_CFG_NONE:
-               break;
+               return;
        case ATH_BTCOEX_CFG_2WIRE:
                ath9k_hw_btcoex_enable_2wire(ah);
                break;
@@ -246,6 +261,9 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
        int i;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        btcoex_hw->enabled = false;
        if (btcoex_hw->scheme == ATH_BTCOEX_CFG_MCI) {
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
@@ -294,6 +312,9 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
 void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
                              enum ath_stomp_type stomp_type)
 {
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                ar9003_btcoex_bt_stomp(ah, stomp_type);
                return;
@@ -313,8 +334,7 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
                                AR_STOMP_NONE_WLAN_WGHT);
                break;
        default:
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-                               "Invalid Stomptype\n");
+               ath_dbg(ath9k_hw_common(ah), BTCOEX, "Invalid Stomptype\n");
                break;
        }
 }
index 99538810a3120a87ba8bdb3f94f72e6bce09e40a..172e33db7f4c49d2e9447636a380c34e5c15f3f6 100644 (file)
@@ -116,7 +116,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
                if (h[i].privNF > limit->max) {
                        high_nf_mid = true;
 
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "NFmid[%d] (%d) > MAX (%d), %s\n",
                                i, h[i].privNF, limit->max,
                                (cal->nfcal_interference ?
@@ -199,8 +199,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
                return true;
 
        if (currCal->calState != CAL_DONE) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Calibration state incorrect, %d\n",
+               ath_dbg(common, CALIBRATE, "Calibration state incorrect, %d\n",
                        currCal->calState);
                return true;
        }
@@ -208,8 +207,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
        if (!(ah->supp_cals & currCal->calData->calType))
                return true;
 
-       ath_dbg(common, ATH_DBG_CALIBRATE,
-               "Resetting Cal %d state for channel %u\n",
+       ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
                currCal->calData->calType, conf->channel->center_freq);
 
        ah->caldata->CalValid &= ~currCal->calData->calType;
@@ -302,7 +300,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
         * noisefloor until the next calibration timer.
         */
        if (j == 10000) {
-               ath_dbg(common, ATH_DBG_ANY,
+               ath_dbg(common, ANY,
                        "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
                        REG_READ(ah, AR_PHY_AGC_CONTROL));
                return;
@@ -344,17 +342,17 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
                if (!nf[i])
                        continue;
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "NF calibrated [%s] [chain %d] is %d\n",
                        (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 
                if (nf[i] > ATH9K_NF_TOO_HIGH) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
                                i, nf[i], ATH9K_NF_TOO_HIGH);
                        nf[i] = limit->max;
                } else if (nf[i] < limit->min) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
                                i, nf[i], limit->min);
                        nf[i] = limit->nominal;
@@ -373,7 +371,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
 
        chan->channelFlags &= (~CHANNEL_CW_INT);
        if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "NF did not complete in calibration window\n");
                return false;
        }
@@ -383,7 +381,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
        nf = nfarray[0];
        if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
            && nf > nfThresh) {
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "noise floor failed detected; detected %d, threshold %d\n",
                        nf, nfThresh);
                chan->channelFlags |= CHANNEL_CW_INT;
index e4e84a9e62730f3780a7eda6b4b00d535dd1d428..f4f56aff1e9d23ba5b4b444a8880a055750bae76 100644 (file)
@@ -66,7 +66,7 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
        u8 rssi;
        u16 dur;
 
-       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS,
+       ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
                "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
                are->pulse_bw_info,
                are->pulse_length_pri, are->rssi,
@@ -161,7 +161,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
 
        if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) &&
            (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
-               ath_dbg(common, ATH_DBG_DFS,
+               ath_dbg(common, DFS,
                        "Error: rs_phyer=0x%x not a radar error\n",
                        rs->rs_phyerr);
                return;
@@ -190,7 +190,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
        ard.pulse_length_ext = vdata_end[-2];
        ard.pulse_length_pri = vdata_end[-3];
 
-       ath_dbg(common, ATH_DBG_DFS,
+       ath_dbg(common, DFS,
                "bw_info=%d, length_pri=%d, length_ext=%d, "
                "rssi_pri=%d, rssi_ext=%d\n",
                ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext,
@@ -200,7 +200,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
        drp.ts = mactime;
        if (ath9k_postprocess_radar_event(sc, &ard, &drp)) {
                static u64 last_ts;
-               ath_dbg(common, ATH_DBG_DFS,
+               ath_dbg(common, DFS,
                        "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
                        "width=%d, rssi=%d, delta_ts=%llu\n",
                        drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts);
index 6e1e2a71659eae9bb9542873d85f38b1fbf0323a..4911724cb445e5ad66ef8adbcbdbceee59fef656 100644 (file)
@@ -16,8 +16,8 @@
  */
 
 
-#ifndef DFS_DEBUG_H
-#define DFS_DEBUG_H
+#ifndef ATH9K_DFS_DEBUG_H
+#define ATH9K_DFS_DEBUG_H
 
 #include "hw.h"
 
@@ -54,4 +54,4 @@ static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
 
 #endif /* CONFIG_ATH9K_DFS_DEBUGFS */
 
-#endif /* DFS_DEBUG_H */
+#endif /* ATH9K_DFS_DEBUG_H */
index e46f751ab50818d1c30d31a6f271c67409192eef..c43523233319a8d5d66af5ac221b3495d5df9632 100644 (file)
@@ -305,8 +305,7 @@ void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
                regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
                break;
        default:
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Invalid chainmask configuration\n");
+               ath_dbg(common, EEPROM, "Invalid chainmask configuration\n");
                break;
        }
 }
index 61fcab0e2d7650acc598288d8b405011f3e23f04..4322ac80c203c1dfc6762f7f8547c73fbf3af7b3 100644 (file)
@@ -38,7 +38,7 @@ static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
 
        for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
                if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Unable to read eeprom region\n");
                        return false;
                }
@@ -62,8 +62,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
 
        if (!ath9k_hw_use_flash(ah)) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Reading from EEPROM, not flash\n");
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
        }
 
        if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -204,8 +203,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
                        return false;
                }
 
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Read Magic = 0x%04X\n", magic);
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
 
                if (magic != AR5416_EEPROM_MAGIC) {
                        magic2 = swab16(magic);
@@ -227,7 +225,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
                }
        }
 
-       ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
                need_swap ? "True" : "False");
 
        if (need_swap)
@@ -249,7 +247,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
                u32 integer;
                u16 word;
 
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "EEPROM Endianness is not native.. Changing\n");
 
                word = swab16(eep->baseEepHeader.length);
@@ -435,11 +433,11 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
                                reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
                                REG_WRITE(ah, regOffset, reg32);
 
-                               ath_dbg(common, ATH_DBG_EEPROM,
+                               ath_dbg(common, EEPROM,
                                        "PDADC (%d,%4x): %4.4x %8.8x\n",
                                        i, regChainOffset, regOffset,
                                        reg32);
-                               ath_dbg(common, ATH_DBG_EEPROM,
+                               ath_dbg(common, EEPROM,
                                        "PDADC: Chain %d | "
                                        "PDADC %3d Value %3d | "
                                        "PDADC %3d Value %3d | "
@@ -1079,8 +1077,7 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 
        u16 spur_val = AR_NO_SPUR;
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "Getting spur idx:%d is2Ghz:%d val:%x\n",
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
                i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
        switch (ah->config.spurmode) {
@@ -1088,8 +1085,8 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
                break;
        case SPUR_ENABLE_IOCTL:
                spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ATH_DBG_ANI,
-                       "Getting spur val from new loc. %d\n", spur_val);
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
                break;
        case SPUR_ENABLE_EEPROM:
                spur_val = EEP_MAP4K_SPURCHAN;
index 0981c073471de9f0b1469b660c1e4993f45aeb96..f272236d8053d58201b973b6397b11362a112bb1 100644 (file)
@@ -41,7 +41,7 @@ static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
        for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
                if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
                                         eep_data)) {
-                       ath_dbg(common, ATH_DBG_EEPROM,
+                       ath_dbg(common, EEPROM,
                                "Unable to read eeprom region\n");
                        return false;
                }
@@ -66,8 +66,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
 
        if (!ath9k_hw_use_flash(ah)) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Reading from EEPROM, not flash\n");
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
        }
 
        if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -197,8 +196,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
                        return false;
                }
 
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Read Magic = 0x%04X\n", magic);
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
 
                if (magic != AR5416_EEPROM_MAGIC) {
                        magic2 = swab16(magic);
@@ -220,7 +218,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
                }
        }
 
-       ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
                need_swap ? "True" : "False");
 
        if (need_swap)
@@ -1041,8 +1039,7 @@ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
        struct ath_common *common = ath9k_hw_common(ah);
        u16 spur_val = AR_NO_SPUR;
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "Getting spur idx:%d is2Ghz:%d val:%x\n",
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
                i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
        switch (ah->config.spurmode) {
@@ -1050,8 +1047,8 @@ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
                break;
        case SPUR_ENABLE_IOCTL:
                spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ATH_DBG_ANI,
-                       "Getting spur val from new loc. %d\n", spur_val);
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
                break;
        case SPUR_ENABLE_EEPROM:
                spur_val = EEP_MAP9287_SPURCHAN;
index 9681c099d0a597ec7bd906865458673b63690748..619b95d764ff33ea0adceabd8a15cb5c93815f1e 100644 (file)
@@ -121,8 +121,7 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
 
        if (!ath9k_hw_use_flash(ah)) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Reading from EEPROM, not flash\n");
+               ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
        }
 
        if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -279,8 +278,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
        }
 
        if (!ath9k_hw_use_flash(ah)) {
-               ath_dbg(common, ATH_DBG_EEPROM,
-                       "Read Magic = 0x%04X\n", magic);
+               ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
 
                if (magic != AR5416_EEPROM_MAGIC) {
                        magic2 = swab16(magic);
@@ -303,7 +301,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
                }
        }
 
-       ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n",
+       ath_dbg(common, EEPROM, "need_swap = %s\n",
                need_swap ? "True" : "False");
 
        if (need_swap)
@@ -325,7 +323,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
                u32 integer, j;
                u16 word;
 
-               ath_dbg(common, ATH_DBG_EEPROM,
+               ath_dbg(common, EEPROM,
                        "EEPROM Endianness is not native.. Changing.\n");
 
                word = swab16(eep->baseEepHeader.length);
@@ -965,15 +963,12 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
                                reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
                                REG_WRITE(ah, regOffset, reg32);
 
-                               ath_dbg(common, ATH_DBG_EEPROM,
+                               ath_dbg(common, EEPROM,
                                        "PDADC (%d,%4x): %4.4x %8.8x\n",
                                        i, regChainOffset, regOffset,
                                        reg32);
-                               ath_dbg(common, ATH_DBG_EEPROM,
-                                       "PDADC: Chain %d | PDADC %3d "
-                                       "Value %3d | PDADC %3d Value %3d | "
-                                       "PDADC %3d Value %3d | PDADC %3d "
-                                       "Value %3d |\n",
+                               ath_dbg(common, EEPROM,
+                                       "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
                                        i, 4 * j, pdadcValues[4 * j],
                                        4 * j + 1, pdadcValues[4 * j + 1],
                                        4 * j + 2, pdadcValues[4 * j + 2],
@@ -1278,7 +1273,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
                regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
                break;
        default:
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_EEPROM,
+               ath_dbg(ath9k_hw_common(ah), EEPROM,
                        "Invalid chainmask configuration\n");
                break;
        }
@@ -1396,8 +1391,7 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 
        u16 spur_val = AR_NO_SPUR;
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "Getting spur idx:%d is2Ghz:%d val:%x\n",
+       ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
                i, is2GHz, ah->config.spurchans[i][is2GHz]);
 
        switch (ah->config.spurmode) {
@@ -1405,8 +1399,8 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
                break;
        case SPUR_ENABLE_IOCTL:
                spur_val = ah->config.spurchans[i][is2GHz];
-               ath_dbg(common, ATH_DBG_ANI,
-                       "Getting spur val from new loc. %d\n", spur_val);
+               ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+                       spur_val);
                break;
        case SPUR_ENABLE_EEPROM:
                spur_val = EEP_DEF_SPURCHAN;
index e4ae08e07719e2f4e3f1a545b6ac653cf8d29cb5..597c84e31adb3b30a69ea7beb4f91b9890a2a662 100644 (file)
@@ -130,12 +130,12 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
                sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
                /* Detect if colocated bt started scanning */
                if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
-                       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
                                "BT scan detected\n");
                        sc->sc_flags |= (SC_OP_BT_SCAN |
                                         SC_OP_BT_PRIORITY_DETECTED);
                } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
-                       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
                                "BT priority traffic detected\n");
                        sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
                }
@@ -230,8 +230,7 @@ static void ath_btcoex_no_stomp_timer(void *arg)
        struct ath_common *common = ath9k_hw_common(ah);
        bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
 
-       ath_dbg(common, ATH_DBG_BTCOEX,
-               "no stomp timer running\n");
+       ath_dbg(common, BTCOEX, "no stomp timer running\n");
 
        ath9k_ps_wakeup(sc);
        spin_lock_bh(&btcoex->btcoex_lock);
@@ -250,6 +249,9 @@ int ath_init_btcoex_timer(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
 
+       if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_NONE)
+               return 0;
+
        btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
        btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
                btcoex->btcoex_period / 100;
@@ -280,8 +282,10 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
        struct ath_btcoex *btcoex = &sc->btcoex;
        struct ath_hw *ah = sc->sc_ah;
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
-               "Starting btcoex timers\n");
+       ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
+
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
 
        /* make sure duty cycle timer is also stopped when resuming */
        if (btcoex->hw_timer_enabled)
@@ -303,6 +307,9 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
        struct ath_btcoex *btcoex = &sc->btcoex;
        struct ath_hw *ah = sc->sc_ah;
 
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        del_timer_sync(&btcoex->period_timer);
 
        if (btcoex->hw_timer_enabled)
index 57fe22b242477c03c18a6e0372d8a8fd80d12379..2eadffb7971cc82c935ab8db1530bb27944b0659 100644 (file)
@@ -167,9 +167,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
        /* TSF out of range threshold fixed at 1 second */
        bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-       ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
+       ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
                intval, tsf, tsftu);
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
                bs.bs_bmissthreshold, bs.bs_sleepduration,
                bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
@@ -224,9 +224,8 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
        if (priv->op_flags & OP_ENABLE_BEACON)
                imask |= ATH9K_INT_SWBA;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d "
-               "imask: 0x%x\n",
+       ath_dbg(common, CONFIG,
+               "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d imask: 0x%x\n",
                bss_conf->beacon_interval, nexttbtt,
                priv->ah->config.sw_beacon_response_time, imask);
 
@@ -273,9 +272,8 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
        if (priv->op_flags & OP_ENABLE_BEACON)
                imask |= ATH9K_INT_SWBA;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "IBSS Beacon config, intval: %d, nexttbtt: %u, "
-               "resp_time: %d, imask: 0x%x\n",
+       ath_dbg(common, CONFIG,
+               "IBSS Beacon config, intval: %d, nexttbtt: %u, resp_time: %d, imask: 0x%x\n",
                bss_conf->beacon_interval, nexttbtt,
                priv->ah->config.sw_beacon_response_time, imask);
 
@@ -323,7 +321,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
 
                tx_slot = ath9k_htc_tx_get_slot(priv);
                if (tx_slot < 0) {
-                       ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n");
+                       ath_dbg(common, XMIT, "No free CAB slot\n");
                        dev_kfree_skb_any(skb);
                        goto next;
                }
@@ -333,8 +331,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
                        ath9k_htc_tx_clear_slot(priv, tx_slot);
                        dev_kfree_skb_any(skb);
 
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "Failed to send CAB frame\n");
+                       ath_dbg(common, XMIT, "Failed to send CAB frame\n");
                } else {
                        spin_lock_bh(&priv->tx.tx_lock);
                        priv->tx.queued_cnt++;
@@ -409,7 +406,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
        ret = htc_send(priv->htc, beacon);
        if (ret != 0) {
                if (ret == -ENOMEM) {
-                       ath_dbg(common, ATH_DBG_BSTUCK,
+                       ath_dbg(common, BSTUCK,
                                "Failed to send beacon, no free TX buffer\n");
                }
                dev_kfree_skb_any(beacon);
@@ -434,7 +431,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
        slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval;
        slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1;
 
-       ath_dbg(common, ATH_DBG_BEACON,
+       ath_dbg(common, BEACON,
                "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n",
                slot, tsf, tsftu, intval);
 
@@ -450,8 +447,7 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv,
        if (swba->beacon_pending != 0) {
                priv->cur_beacon_conf.bmiss_cnt++;
                if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) {
-                       ath_dbg(common, ATH_DBG_BSTUCK,
-                               "Beacon stuck, HW reset\n");
+                       ath_dbg(common, BSTUCK, "Beacon stuck, HW reset\n");
                        ieee80211_queue_work(priv->hw,
                                             &priv->fatal_work);
                }
@@ -459,7 +455,7 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv,
        }
 
        if (priv->cur_beacon_conf.bmiss_cnt) {
-               ath_dbg(common, ATH_DBG_BSTUCK,
+               ath_dbg(common, BSTUCK,
                        "Resuming beacon xmit after %u misses\n",
                        priv->cur_beacon_conf.bmiss_cnt);
                priv->cur_beacon_conf.bmiss_cnt = 0;
@@ -495,8 +491,8 @@ void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
        priv->cur_beacon_conf.bslot[avp->bslot] = vif;
        spin_unlock_bh(&priv->beacon_lock);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Added interface at beacon slot: %d\n", avp->bslot);
+       ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
+               avp->bslot);
 }
 
 void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
@@ -509,8 +505,8 @@ void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
        priv->cur_beacon_conf.bslot[avp->bslot] = NULL;
        spin_unlock_bh(&priv->beacon_lock);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Removed interface at beacon slot: %d\n", avp->bslot);
+       ath_dbg(common, CONFIG, "Removed interface at beacon slot: %d\n",
+               avp->bslot);
 }
 
 /*
@@ -536,8 +532,7 @@ void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
        tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF;
        avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "tsfadjust is: %llu for bslot: %d\n",
+       ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
                (unsigned long long)tsfadjust, avp->bslot);
 }
 
@@ -568,7 +563,7 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
            (priv->num_ap_vif > 1) &&
            (vif->type == NL80211_IFTYPE_AP) &&
            (cur_conf->beacon_interval != bss_conf->beacon_int)) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Changing beacon interval of multiple AP interfaces !\n");
                return false;
        }
@@ -579,7 +574,7 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
         */
        if (priv->num_ap_vif &&
            (vif->type != NL80211_IFTYPE_AP)) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "HW in AP mode, cannot set STA beacon parameters\n");
                return false;
        }
@@ -597,7 +592,7 @@ static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
                                                           &beacon_configured);
 
                if (beacon_configured) {
-                       ath_dbg(common, ATH_DBG_CONFIG,
+                       ath_dbg(common, CONFIG,
                                "Beacon already configured for a station interface\n");
                        return false;
                }
@@ -637,8 +632,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
                ath9k_htc_beacon_config_ap(priv, cur_conf);
                break;
        default:
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Unsupported beaconing mode\n");
+               ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
                return;
        }
 }
@@ -659,8 +653,7 @@ void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
                ath9k_htc_beacon_config_ap(priv, cur_conf);
                break;
        default:
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Unsupported beaconing mode\n");
+               ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
                return;
        }
 }
index ce606b618e0b7c4813235b221c2bf9fa096887c6..6506e1fd503649ad42246b84c49c618b5b818ad9 100644 (file)
@@ -36,12 +36,12 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
                priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
                /* Detect if colocated bt started scanning */
                if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
-                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+                       ath_dbg(ath9k_hw_common(ah), BTCOEX,
                                "BT scan detected\n");
                        priv->op_flags |= (OP_BT_SCAN |
                                         OP_BT_PRIORITY_DETECTED);
                } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
-                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+                       ath_dbg(ath9k_hw_common(ah), BTCOEX,
                                "BT priority traffic detected\n");
                        priv->op_flags |= OP_BT_PRIORITY_DETECTED;
                }
@@ -102,8 +102,7 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
        struct ath_common *common = ath9k_hw_common(ah);
        bool is_btscan = priv->op_flags & OP_BT_SCAN;
 
-       ath_dbg(common, ATH_DBG_BTCOEX,
-               "time slice work for bt and wlan\n");
+       ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
 
        if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
                ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
@@ -116,6 +115,9 @@ void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
 {
        struct ath_btcoex *btcoex = &priv->btcoex;
 
+       if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
        btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
                btcoex->btcoex_period / 100;
@@ -134,7 +136,10 @@ void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
        struct ath_btcoex *btcoex = &priv->btcoex;
        struct ath_hw *ah = priv->ah;
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n");
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
+       ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex work\n");
 
        btcoex->bt_priority_cnt = 0;
        btcoex->bt_priority_time = jiffies;
@@ -148,6 +153,9 @@ void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
  */
 void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
 {
+       if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
+               return;
+
        cancel_delayed_work_sync(&priv->coex_period_work);
        cancel_delayed_work_sync(&priv->duty_cycle_work);
 }
index 966661c9e58697f2040f2ba1e94e20817dd9a166..9be10a2da1c29cc48f6a96656a596c8cf6e6c5c4 100644 (file)
@@ -299,8 +299,7 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
                          (u8 *) &val, sizeof(val),
                          100);
        if (unlikely(r)) {
-               ath_dbg(common, ATH_DBG_WMI,
-                       "REGISTER READ FAILED: (0x%04x, %d)\n",
+               ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
                        reg_offset, r);
                return -EIO;
        }
@@ -327,7 +326,7 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
                           (u8 *)tmpval, sizeof(u32) * count,
                           100);
        if (unlikely(ret)) {
-               ath_dbg(common, ATH_DBG_WMI,
+               ath_dbg(common, WMI,
                        "Multiple REGISTER READ FAILED (count: %d)\n", count);
        }
 
@@ -352,8 +351,7 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
                          (u8 *) &val, sizeof(val),
                          100);
        if (unlikely(r)) {
-               ath_dbg(common, ATH_DBG_WMI,
-                       "REGISTER WRITE FAILED:(0x%04x, %d)\n",
+               ath_dbg(common, WMI, "REGISTER WRITE FAILED:(0x%04x, %d)\n",
                        reg_offset, r);
        }
 }
@@ -384,7 +382,7 @@ static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
                          (u8 *) &rsp_status, sizeof(rsp_status),
                          100);
                if (unlikely(r)) {
-                       ath_dbg(common, ATH_DBG_WMI,
+                       ath_dbg(common, WMI,
                                "REGISTER WRITE FAILED, multi len: %d\n",
                                priv->wmi->multi_write_idx);
                }
@@ -434,7 +432,7 @@ static void ath9k_regwrite_flush(void *hw_priv)
                          (u8 *) &rsp_status, sizeof(rsp_status),
                          100);
                if (unlikely(r)) {
-                       ath_dbg(common, ATH_DBG_WMI,
+                       ath_dbg(common, WMI,
                                "REGISTER WRITE FAILED, multi len: %d\n",
                                priv->wmi->multi_write_idx);
                }
@@ -512,8 +510,7 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
        tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
        rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "TX streams %d, RX streams: %d\n",
+       ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
                tx_streams, rx_streams);
 
        if (tx_streams != rx_streams) {
@@ -610,7 +607,7 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
 {
        int qnum;
 
-       switch (priv->ah->btcoex_hw.scheme) {
+       switch (ath9k_hw_get_btcoex_scheme(priv->ah)) {
        case ATH_BTCOEX_CFG_NONE:
                break;
        case ATH_BTCOEX_CFG_3WIRE:
@@ -704,7 +701,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 
        if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
                ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
-               ath9k_init_btcoex(priv);
+               if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
+                       ath9k_init_btcoex(priv);
        }
 
        return 0;
@@ -876,9 +874,8 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
                goto err_world;
        }
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
-               "BE:%d, BK:%d, VI:%d, VO:%d\n",
+       ath_dbg(common, CONFIG,
+               "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, BE:%d, BK:%d, VI:%d, VO:%d\n",
                priv->wmi_cmd_ep,
                priv->beacon_ep,
                priv->cab_ep,
index f8ce4ea6f65cae43efd304e030bd088bd83e39a1..ef4c6066129022d90bda90416a65bdab93d59c27 100644 (file)
@@ -266,7 +266,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 
        ath9k_wmi_event_drain(priv);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
                priv->ah->curchan->channel,
                channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
@@ -415,7 +415,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
        priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
        priv->ah->is_monitoring = true;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Attached a monitor interface at idx: %d, sta idx: %d\n",
                priv->mon_vif_idx, sta_idx);
 
@@ -427,7 +427,7 @@ err_sta:
         */
        __ath9k_htc_remove_monitor_interface(priv);
 err_vif:
-       ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n");
+       ath_dbg(common, FATAL, "Unable to attach a monitor interface\n");
 
        return ret;
 }
@@ -452,7 +452,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
        priv->nstations--;
        priv->ah->is_monitoring = false;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Removed a monitor interface at idx: %d, sta idx: %d\n",
                priv->mon_vif_idx, sta_idx);
 
@@ -512,11 +512,11 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
        }
 
        if (sta) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Added a station entry for: %pM (idx: %d)\n",
                        sta->addr, tsta.sta_index);
        } else {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Added a station entry for VIF %d (idx: %d)\n",
                        avp->index, tsta.sta_index);
        }
@@ -556,11 +556,11 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
        }
 
        if (sta) {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Removed a station entry for: %pM (idx: %d)\n",
                        sta->addr, sta_idx);
        } else {
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Removed a station entry for VIF %d (idx: %d)\n",
                        avp->index, sta_idx);
        }
@@ -665,7 +665,7 @@ static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
        ath9k_htc_setup_rate(priv, sta, &trate);
        ret = ath9k_htc_send_rate_cmd(priv, &trate);
        if (!ret)
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Updated target sta: %pM, rate caps: 0x%X\n",
                        sta->addr, be32_to_cpu(trate.capflags));
 }
@@ -692,7 +692,7 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
 
        ret = ath9k_htc_send_rate_cmd(priv, &trate);
        if (!ret)
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Updated target sta: %pM, rate caps: 0x%X\n",
                        bss_conf->bssid, be32_to_cpu(trate.capflags));
 }
@@ -721,11 +721,11 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
 
        WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
        if (ret)
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Unable to %s TX aggregation for (%pM, %d)\n",
                        (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid);
        else
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "%s TX aggregation for (%pM, %d)\n",
                        (aggr.aggr_enable) ? "Starting" : "Stopping",
                        sta->addr, tid);
@@ -784,7 +784,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
        /* Long calibration runs independently of short calibration. */
        if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
                longcal = true;
-               ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+               ath_dbg(common, ANI, "longcal @%lu\n", jiffies);
                common->ani.longcal_timer = timestamp;
        }
 
@@ -793,8 +793,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
                if ((timestamp - common->ani.shortcal_timer) >=
                    short_cal_interval) {
                        shortcal = true;
-                       ath_dbg(common, ATH_DBG_ANI,
-                               "shortcal @%lu\n", jiffies);
+                       ath_dbg(common, ANI, "shortcal @%lu\n", jiffies);
                        common->ani.shortcal_timer = timestamp;
                        common->ani.resetcal_timer = timestamp;
                }
@@ -866,7 +865,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        padsize = padpos & 3;
        if (padsize && skb->len > padpos) {
                if (skb_headroom(skb) < padsize) {
-                       ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n");
+                       ath_dbg(common, XMIT, "No room for padding\n");
                        goto fail_tx;
                }
                skb_push(skb, padsize);
@@ -875,13 +874,13 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        slot = ath9k_htc_tx_get_slot(priv);
        if (slot < 0) {
-               ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n");
+               ath_dbg(common, XMIT, "No free TX slot\n");
                goto fail_tx;
        }
 
        ret = ath9k_htc_tx_start(priv, skb, slot, false);
        if (ret != 0) {
-               ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n");
+               ath_dbg(common, XMIT, "Tx failed\n");
                goto clear_slot;
        }
 
@@ -909,7 +908,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 
        mutex_lock(&priv->mutex);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Starting driver with initial channel: %d MHz\n",
                curchan->center_freq);
 
@@ -943,7 +942,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 
        ret = ath9k_htc_update_cap_target(priv, 0);
        if (ret)
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Failed to update capability in target\n");
 
        priv->op_flags &= ~OP_INVALID;
@@ -958,7 +957,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
        mod_timer(&priv->tx.cleanup_timer,
                  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
 
-       if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) {
                ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
                                           AR_STOMP_LOW_WLAN_WGHT);
                ath9k_hw_btcoex_enable(ah);
@@ -980,7 +979,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
        mutex_lock(&priv->mutex);
 
        if (priv->op_flags & OP_INVALID) {
-               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+               ath_dbg(common, ANY, "Device not present\n");
                mutex_unlock(&priv->mutex);
                return;
        }
@@ -1010,7 +1009,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 
        mutex_lock(&priv->mutex);
 
-       if (ah->btcoex_hw.enabled) {
+       if (ah->btcoex_hw.enabled &&
+           ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
                ath9k_hw_btcoex_disable(ah);
                if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
                        ath_htc_cancel_btcoex_work(priv);
@@ -1027,7 +1027,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 
        priv->op_flags |= OP_INVALID;
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
+       ath_dbg(common, CONFIG, "Driver halt\n");
        mutex_unlock(&priv->mutex);
 }
 
@@ -1120,8 +1120,8 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                ath9k_htc_start_ani(priv);
        }
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
+       ath_dbg(common, CONFIG, "Attach a VIF of type: %d at idx: %d\n",
+               vif->type, avp->index);
 
 out:
        ath9k_htc_ps_restore(priv);
@@ -1177,7 +1177,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
                        ath9k_htc_stop_ani(priv);
        }
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index);
+       ath_dbg(common, CONFIG, "Detach Interface at idx: %d\n", avp->index);
 
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
@@ -1202,8 +1202,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
                mutex_unlock(&priv->htc_pm_lock);
 
                if (enable_radio) {
-                       ath_dbg(common, ATH_DBG_CONFIG,
-                               "not-idle: enabling radio\n");
+                       ath_dbg(common, CONFIG, "not-idle: enabling radio\n");
                        ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
                        ath9k_htc_radio_enable(hw);
                }
@@ -1225,7 +1224,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
                struct ieee80211_channel *curchan = hw->conf.channel;
                int pos = curchan->hw_value;
 
-               ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+               ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
                        curchan->center_freq);
 
                ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
@@ -1265,8 +1264,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
                }
                mutex_unlock(&priv->htc_pm_lock);
 
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "idle: disabling radio\n");
+               ath_dbg(common, CONFIG, "idle: disabling radio\n");
                ath9k_htc_radio_disable(hw);
        }
 
@@ -1298,7 +1296,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
        *total_flags &= SUPPORTED_FILTERS;
 
        if (priv->op_flags & OP_INVALID) {
-               ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY,
+               ath_dbg(ath9k_hw_common(priv->ah), ANY,
                        "Unable to configure filter on invalid state\n");
                mutex_unlock(&priv->mutex);
                return;
@@ -1309,8 +1307,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
        rfilt = ath9k_htc_calcrxfilter(priv);
        ath9k_hw_setrxfilter(priv->ah, rfilt);
 
-       ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
-               "Set HW RX filter: 0x%x\n", rfilt);
+       ath_dbg(ath9k_hw_common(priv->ah), CONFIG, "Set HW RX filter: 0x%x\n",
+               rfilt);
 
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
@@ -1377,7 +1375,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
 
        qnum = get_hw_qnum(queue, priv->hwq_map);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Configure tx [queue/hwq] [%d/%d],  aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
                queue, qnum, params->aifs, params->cw_min,
                params->cw_max, params->txop);
@@ -1412,7 +1410,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
                return -ENOSPC;
 
        mutex_lock(&priv->mutex);
-       ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n");
+       ath_dbg(common, CONFIG, "Set HW Key\n");
        ath9k_htc_ps_wakeup(priv);
 
        switch (cmd) {
@@ -1448,8 +1446,7 @@ static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv)
        struct ath_common *common = ath9k_hw_common(priv->ah);
 
        ath9k_hw_write_associd(priv->ah);
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "BSSID: %pM aid: 0x%x\n",
+       ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
                common->curbssid, common->curaid);
 }
 
@@ -1487,7 +1484,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
        ath9k_htc_ps_wakeup(priv);
 
        if (changed & BSS_CHANGED_ASSOC) {
-               ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+               ath_dbg(common, CONFIG, "BSS Changed ASSOC %d\n",
                        bss_conf->assoc);
 
                bss_conf->assoc ?
@@ -1512,8 +1509,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Beacon enabled for BSS: %pM\n", bss_conf->bssid);
+               ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
+                       bss_conf->bssid);
                ath9k_htc_set_tsfadjust(priv, vif);
                priv->op_flags |= OP_ENABLE_BEACON;
                ath9k_htc_beacon_config(priv, vif);
@@ -1525,7 +1522,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
                 * AP/IBSS interfaces.
                 */
                if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) {
-                       ath_dbg(common, ATH_DBG_CONFIG,
+                       ath_dbg(common, CONFIG,
                                "Beacon disabled for BSS: %pM\n",
                                bss_conf->bssid);
                        priv->op_flags &= ~OP_ENABLE_BEACON;
@@ -1543,7 +1540,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
                    (vif->type == NL80211_IFTYPE_AP)) {
                        priv->op_flags |= OP_TSF_RESET;
                }
-               ath_dbg(common, ATH_DBG_CONFIG,
+               ath_dbg(common, CONFIG,
                        "Beacon interval changed for BSS: %pM\n",
                        bss_conf->bssid);
                ath9k_htc_beacon_config(priv, vif);
@@ -1733,8 +1730,7 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Set bitrate masks: 0x%x, 0x%x\n",
+       ath_dbg(common, CONFIG, "Set bitrate masks: 0x%x, 0x%x\n",
                mask->control[IEEE80211_BAND_2GHZ].legacy,
                mask->control[IEEE80211_BAND_5GHZ].legacy);
 out:
index 2d81c700e201cd4fa3b87cb1414a0b820785c7fc..3e40a6461512b7748200617317484219f5f9f0d1 100644 (file)
@@ -355,7 +355,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
                vif_idx = avp->index;
        } else {
                if (!priv->ah->is_monitoring) {
-                       ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+                       ath_dbg(ath9k_hw_common(priv->ah), XMIT,
                                "VIF is null, but no monitor interface !\n");
                        return -EINVAL;
                }
@@ -620,8 +620,7 @@ static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv,
        }
        spin_unlock_irqrestore(&epid_queue->lock, flags);
 
-       ath_dbg(common, ATH_DBG_XMIT,
-               "No matching packet for cookie: %d, epid: %d\n",
+       ath_dbg(common, XMIT, "No matching packet for cookie: %d, epid: %d\n",
                txs->cookie, epid);
 
        return NULL;
@@ -705,8 +704,7 @@ static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb
        if (time_after(jiffies,
                       tx_ctl->timestamp +
                       msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) {
-               ath_dbg(common, ATH_DBG_XMIT,
-                       "Dropping a packet due to TX timeout\n");
+               ath_dbg(common, XMIT, "Dropping a packet due to TX timeout\n");
                return true;
        }
 
@@ -753,7 +751,7 @@ void ath9k_htc_tx_cleanup_timer(unsigned long data)
 
                skb = ath9k_htc_tx_get_packet(priv, &event->txs);
                if (skb) {
-                       ath_dbg(common, ATH_DBG_XMIT,
+                       ath_dbg(common, XMIT,
                                "Found packet for cookie: %d, epid: %d\n",
                                event->txs.cookie,
                                MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID));
@@ -1167,8 +1165,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
        spin_unlock(&priv->rx.rxbuflock);
 
        if (rxbuf == NULL) {
-               ath_dbg(common, ATH_DBG_ANY,
-                       "No free RX buffer\n");
+               ath_dbg(common, ANY, "No free RX buffer\n");
                goto err;
        }
 
index 8cda9a1513a7838a09e1e9af6e1c13b6497999c9..ee77595750503db51e83ef90644f7884a5c529a5 100644 (file)
@@ -133,7 +133,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
                udelay(AH_TIME_QUANTUM);
        }
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_ANY,
+       ath_dbg(ath9k_hw_common(ah), ANY,
                "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
                timeout, reg, REG_READ(ah, reg), mask, val);
 
@@ -491,8 +491,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
        if (ecode != 0)
                return ecode;
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_CONFIG,
-               "Eeprom VER: %d, REV: %d\n",
+       ath_dbg(ath9k_hw_common(ah), CONFIG, "Eeprom VER: %d, REV: %d\n",
                ah->eep_ops->get_eeprom_ver(ah),
                ah->eep_ops->get_eeprom_rev(ah));
 
@@ -567,7 +566,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
                }
        }
 
-       ath_dbg(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
+       ath_dbg(common, RESET, "serialize_regmode is %d\n",
                ah->config.serialize_regmode);
 
        if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
@@ -958,8 +957,8 @@ static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
 static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
 {
        if (tu > 0xFFFF) {
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT,
-                       "bad global tx timeout %u\n", tu);
+               ath_dbg(ath9k_hw_common(ah), XMIT, "bad global tx timeout %u\n",
+                       tu);
                ah->globaltxtimeout = (u32) -1;
                return false;
        } else {
@@ -980,7 +979,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        int rx_lat = 0, tx_lat = 0, eifs = 0;
        u32 reg;
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
+       ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n",
                ah->misc_mode);
 
        if (!chan)
@@ -1275,7 +1274,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
                    (npend || type == ATH9K_RESET_COLD)) {
                        int reset_err = 0;
 
-                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+                       ath_dbg(ath9k_hw_common(ah), RESET,
                                "reset MAC via external reset\n");
 
                        reset_err = ah->external_reset();
@@ -1298,8 +1297,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 
        REG_WRITE(ah, AR_RTC_RC, 0);
        if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
-                       "RTC stuck in MAC reset\n");
+               ath_dbg(ath9k_hw_common(ah), RESET, "RTC stuck in MAC reset\n");
                return false;
        }
 
@@ -1344,8 +1342,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
                           AR_RTC_STATUS_M,
                           AR_RTC_STATUS_ON,
                           AH_WAIT_TIMEOUT)) {
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
-                       "RTC not waking up\n");
+               ath_dbg(ath9k_hw_common(ah), RESET, "RTC not waking up\n");
                return false;
        }
 
@@ -1418,7 +1415,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
                if (ath9k_hw_numtxpending(ah, qnum)) {
-                       ath_dbg(common, ATH_DBG_QUEUE,
+                       ath_dbg(common, QUEUE,
                                "Transmit frames pending on queue %d\n", qnum);
                        return false;
                }
@@ -1536,7 +1533,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                if (mci_hw->bt_state == MCI_BT_CAL_START) {
                        u32 payload[4] = {0, 0, 0, 0};
 
-                       ath_dbg(common, ATH_DBG_MCI, "MCI stop rx for BT CAL");
+                       ath_dbg(common, MCI, "MCI stop rx for BT CAL\n");
 
                        mci_hw->bt_state = MCI_BT_CAL;
 
@@ -1548,23 +1545,22 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
                        ar9003_mci_disable_interrupt(ah);
 
-                       ath_dbg(common, ATH_DBG_MCI, "send WLAN_CAL_GRANT");
+                       ath_dbg(common, MCI, "send WLAN_CAL_GRANT\n");
                        MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
                        ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
                                                16, true, false);
 
-                       ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is calibrating");
+                       ath_dbg(common, MCI, "\nMCI BT is calibrating\n");
 
                        /* Wait BT calibration to be completed for 25ms */
 
                        if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
                                                                  0, 25000))
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI got BT_CAL_DONE\n");
                        else
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI ### BT cal takes to long, force"
-                                       "bt_state to be bt_awake\n");
+                               ath_dbg(common, MCI,
+                                       "MCI ### BT cal takes to long, force bt_state to be bt_awake\n");
                        mci_hw->bt_state = MCI_BT_AWAKE;
                        /* MCI FIX: enable mci interrupt here */
                        ar9003_mci_enable_interrupt(ah);
@@ -1825,14 +1821,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                                 * message exchanges again and recal.
                                 */
 
-                               ath_dbg(common, ATH_DBG_MCI, "MCI BT wakes up"
-                                       "during WLAN calibration\n");
+                               ath_dbg(common, MCI,
+                                       "MCI BT wakes up during WLAN calibration\n");
 
                                REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
                                          AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
                                          AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE);
-                               ath_dbg(common, ATH_DBG_MCI, "MCI send"
-                                       "REMOTE_RESET\n");
+                               ath_dbg(common, MCI, "MCI send REMOTE_RESET\n");
                                ar9003_mci_remote_reset(ah, true);
                                ar9003_mci_send_sys_waking(ah, true);
                                udelay(1);
@@ -1841,7 +1836,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
                                mci_hw->bt_state = MCI_BT_AWAKE;
 
-                               ath_dbg(common, ATH_DBG_MCI, "MCI re-cal\n");
+                               ath_dbg(common, MCI, "MCI re-cal\n");
 
                                if (caldata) {
                                        caldata->done_txiqcal_once = false;
@@ -1871,14 +1866,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                u32 mask;
                mask = REG_READ(ah, AR_CFG);
                if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
-                       ath_dbg(common, ATH_DBG_RESET,
-                               "CFG Byte Swap Set 0x%x\n", mask);
+                       ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
+                               mask);
                } else {
                        mask =
                                INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
                        REG_WRITE(ah, AR_CFG, mask);
-                       ath_dbg(common, ATH_DBG_RESET,
-                               "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
+                       ath_dbg(common, RESET, "Setting CFG 0x%x\n",
+                               REG_READ(ah, AR_CFG));
                }
        } else {
                if (common->bus_ops->ath_bus_type == ATH_USB) {
@@ -1896,7 +1891,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 #endif
        }
 
-       if (ah->btcoex_hw.enabled)
+       if (ah->btcoex_hw.enabled &&
+           ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
                ath9k_hw_btcoex_enable(ah);
 
        if (mci && mci_hw->ready) {
@@ -2090,7 +2086,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
        if (ah->power_mode == mode)
                return status;
 
-       ath_dbg(common, ATH_DBG_RESET, "%s -> %s\n",
+       ath_dbg(common, RESET, "%s -> %s\n",
                modes[ah->power_mode], modes[mode]);
 
        switch (mode) {
@@ -2107,8 +2103,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
                        if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) &&
                                (mci->bt_state != MCI_BT_SLEEP) &&
                                !mci->halted_bt_gpm) {
-                               ath_dbg(common, ATH_DBG_MCI, "MCI halt BT GPM"
-                                               "(full_sleep)");
+                               ath_dbg(common, MCI,
+                                       "MCI halt BT GPM (full_sleep)\n");
                                ar9003_mci_send_coex_halt_bt_gpm(ah,
                                                                 true, true);
                        }
@@ -2174,9 +2170,8 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
                        AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
                break;
        default:
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON,
-                       "%s: unsupported opmode: %d\n",
-                       __func__, ah->opmode);
+               ath_dbg(ath9k_hw_common(ah), BEACON,
+                       "%s: unsupported opmode: %d\n", __func__, ah->opmode);
                return;
                break;
        }
@@ -2227,10 +2222,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        else
                nextTbtt = bs->bs_nexttbtt;
 
-       ath_dbg(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
-       ath_dbg(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
-       ath_dbg(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
-       ath_dbg(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
+       ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim);
+       ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt);
+       ath_dbg(common, BEACON, "beacon period %d\n", beaconintval);
+       ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod);
 
        ENABLE_REGWRITE_BUFFER(ah);
 
@@ -2322,8 +2317,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                        regulatory->current_rd += 5;
                else if (regulatory->current_rd == 0x41)
                        regulatory->current_rd = 0x43;
-               ath_dbg(common, ATH_DBG_REGULATORY,
-                       "regdomain mapped to 0x%x\n", regulatory->current_rd);
+               ath_dbg(common, REGULATORY, "regdomain mapped to 0x%x\n",
+                       regulatory->current_rd);
        }
 
        eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
@@ -2848,7 +2843,7 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah)
 {
        if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0,
                           AH_TSF_WRITE_TIMEOUT))
-               ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+               ath_dbg(ath9k_hw_common(ah), RESET,
                        "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
 
        REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
@@ -2973,7 +2968,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
 
        timer_next = tsf + trig_timeout;
 
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER,
+       ath_dbg(ath9k_hw_common(ah), HWTIMER,
                "current tsf %x period %x timer_next %x\n",
                tsf, timer_period, timer_next);
 
@@ -3062,8 +3057,8 @@ void ath_gen_timer_isr(struct ath_hw *ah)
                index = rightmost_index(timer_table, &thresh_mask);
                timer = timer_table->timers[index];
                BUG_ON(!timer);
-               ath_dbg(common, ATH_DBG_HWTIMER,
-                       "TSF overflow for Gen timer %d\n", index);
+               ath_dbg(common, HWTIMER, "TSF overflow for Gen timer %d\n",
+                       index);
                timer->overflow(timer->arg);
        }
 
@@ -3071,7 +3066,7 @@ void ath_gen_timer_isr(struct ath_hw *ah)
                index = rightmost_index(timer_table, &trigger_mask);
                timer = timer_table->timers[index];
                BUG_ON(!timer);
-               ath_dbg(common, ATH_DBG_HWTIMER,
+               ath_dbg(common, HWTIMER,
                        "Gen timer[%d] trigger\n", index);
                timer->trigger(timer->arg);
        }
index 615cc839f0de5b4077bcb1711536067c01af5a0d..48205c2960b56b185775306c55c3fb449d3f6a2c 100644 (file)
@@ -209,7 +209,11 @@ enum ath9k_hw_caps {
        ATH9K_HW_CAP_5GHZ                       = BIT(12),
        ATH9K_HW_CAP_APM                        = BIT(13),
        ATH9K_HW_CAP_RTT                        = BIT(14),
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
        ATH9K_HW_CAP_MCI                        = BIT(15),
+#else
+       ATH9K_HW_CAP_MCI                        = 0,
+#endif
        ATH9K_HW_CAP_DFS                        = BIT(16),
 };
 
@@ -1228,6 +1232,16 @@ void ar9003_mci_sync_bt_state(struct ath_hw *ah);
 void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
                              u32 *rx_msg_intr);
 
+#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+static inline enum ath_btcoex_scheme
+ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
+{
+       return ah->btcoex_hw.scheme;
+}
+#else
+#define ath9k_hw_get_btcoex_scheme(...) ATH_BTCOEX_CFG_NONE
+#endif
+
 #define ATH9K_CLOCK_RATE_CCK           22
 #define ATH9K_CLOCK_RATE_5GHZ_OFDM     40
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM     44
index c5df98139c4df7592d00d41958825d33b64220a0..abf943557deeca279a82ca434cb4eb5032d6805b 100644 (file)
@@ -276,8 +276,7 @@ static void setup_ht_cap(struct ath_softc *sc,
        tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
        rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "TX streams %d, RX streams: %d\n",
+       ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
                tx_streams, rx_streams);
 
        if (tx_streams != rx_streams) {
@@ -329,7 +328,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
        struct ath_buf *bf;
        int i, bsize, error, desc_len;
 
-       ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+       ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n",
                name, nbuf, ndesc);
 
        INIT_LIST_HEAD(head);
@@ -375,7 +374,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
                goto fail;
        }
        ds = (u8 *) dd->dd_desc;
-       ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+       ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
                name, ds, (u32) dd->dd_desc_len,
                ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
 
@@ -426,7 +425,7 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
        struct ath_hw *ah = sc->sc_ah;
        int r;
 
-       switch (sc->sc_ah->btcoex_hw.scheme) {
+       switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) {
        case ATH_BTCOEX_CFG_NONE:
                break;
        case ATH_BTCOEX_CFG_2WIRE:
@@ -881,10 +880,10 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
                kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
 
         if ((sc->btcoex.no_stomp_timer) &&
-           sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+           ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
                ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
 
-       if (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI)
+       if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_MCI)
                ath_mci_cleanup(sc);
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
index 0e4fbb3bea3310156eed28de8a6ac88466a2f744..fd3f19c2e550e4e9991c4adc9b430a91799c9bd4 100644 (file)
@@ -21,7 +21,7 @@
 static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
                                        struct ath9k_tx_queue_info *qi)
 {
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT,
+       ath_dbg(ath9k_hw_common(ah), INTERRUPT,
                "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
                ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
                ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
@@ -57,8 +57,7 @@ EXPORT_SYMBOL(ath9k_hw_puttxbuf);
 
 void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
 {
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE,
-               "Enable TXE on queue: %u\n", q);
+       ath_dbg(ath9k_hw_common(ah), QUEUE, "Enable TXE on queue: %u\n", q);
        REG_WRITE(ah, AR_Q_TXE, 1 << q);
 }
 EXPORT_SYMBOL(ath9k_hw_txstart);
@@ -202,12 +201,12 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
 
        qi = &ah->txq[q];
        if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-               ath_dbg(common, ATH_DBG_QUEUE,
+               ath_dbg(common, QUEUE,
                        "Set TXQ properties, inactive queue: %u\n", q);
                return false;
        }
 
-       ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
+       ath_dbg(common, QUEUE, "Set queue properties for: %u\n", q);
 
        qi->tqi_ver = qinfo->tqi_ver;
        qi->tqi_subtype = qinfo->tqi_subtype;
@@ -266,7 +265,7 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
 
        qi = &ah->txq[q];
        if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-               ath_dbg(common, ATH_DBG_QUEUE,
+               ath_dbg(common, QUEUE,
                        "Get TXQ properties, inactive queue: %u\n", q);
                return false;
        }
@@ -325,7 +324,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
                return -1;
        }
 
-       ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
+       ath_dbg(common, QUEUE, "Setup TX queue: %u\n", q);
 
        qi = &ah->txq[q];
        if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
@@ -348,12 +347,11 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
 
        qi = &ah->txq[q];
        if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-               ath_dbg(common, ATH_DBG_QUEUE,
-                       "Release TXQ, inactive queue: %u\n", q);
+               ath_dbg(common, QUEUE, "Release TXQ, inactive queue: %u\n", q);
                return false;
        }
 
-       ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
+       ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
 
        qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
        ah->txok_interrupt_mask &= ~(1 << q);
@@ -376,12 +374,11 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
 
        qi = &ah->txq[q];
        if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-               ath_dbg(common, ATH_DBG_QUEUE,
-                       "Reset TXQ, inactive queue: %u\n", q);
+               ath_dbg(common, QUEUE, "Reset TXQ, inactive queue: %u\n", q);
                return true;
        }
 
-       ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
+       ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q);
 
        if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
                if (chan && IS_CHAN_B(chan))
@@ -784,7 +781,7 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
        else
                atomic_dec(&ah->intr_ref_cnt);
 
-       ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
+       ath_dbg(common, INTERRUPT, "disable IER\n");
        REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
        (void) REG_READ(ah, AR_IER);
        if (!AR_SREV_9100(ah)) {
@@ -807,8 +804,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
                return;
 
        if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
-               ath_dbg(common, ATH_DBG_INTERRUPT,
-                       "Do not enable IER ref count %d\n",
+               ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
                        atomic_read(&ah->intr_ref_cnt));
                return;
        }
@@ -821,7 +817,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
        if (ah->imask & ATH9K_INT_MCI)
                async_mask |= AR_INTR_ASYNC_MASK_MCI;
 
-       ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n");
+       ath_dbg(common, INTERRUPT, "enable IER\n");
        REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
        if (!AR_SREV_9100(ah)) {
                REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, async_mask);
@@ -830,7 +826,7 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
                REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
                REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default);
        }
-       ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+       ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
                REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
 }
 EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
@@ -845,7 +841,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
        if (!(ints & ATH9K_INT_GLOBAL))
                ath9k_hw_disable_interrupts(ah);
 
-       ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
+       ath_dbg(common, INTERRUPT, "New interrupt mask 0x%x\n", ints);
 
        mask = ints & ATH9K_INT_COMMON;
        mask2 = 0;
@@ -908,7 +904,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
                        mask2 |= AR_IMR_S2_CST;
        }
 
-       ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
+       ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask);
        REG_WRITE(ah, AR_IMR, mask);
        ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
                           AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
index 7fbc4bdd4efeb6c5a8e7ea392f227fef777d0d8f..6e3d8384e081effb2422e4410ea1db1eb192c7d4 100644 (file)
@@ -339,8 +339,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
        if (!ath_prepare_reset(sc, retry_tx, flush))
                fastcc = false;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Reset to %u MHz, HT40: %d fastcc: %d\n",
+       ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
                hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
                                                          CHANNEL_HT40PLUS)),
                fastcc);
@@ -429,7 +428,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
        txctl.paprd = BIT(chain);
 
        if (ath_tx_start(hw, skb, &txctl) != 0) {
-               ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
+               ath_dbg(common, CALIBRATE, "PAPRD TX failed\n");
                dev_kfree_skb_any(skb);
                return false;
        }
@@ -438,7 +437,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
                        msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
 
        if (!time_left)
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Timeout waiting for paprd training on TX chain %d\n",
                        chain);
 
@@ -487,27 +486,27 @@ void ath_paprd_calibrate(struct work_struct *work)
 
                chain_ok = 0;
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
-                       "Sending PAPRD frame for thermal measurement "
-                       "on chain %d\n", chain);
+               ath_dbg(common, CALIBRATE,
+                       "Sending PAPRD frame for thermal measurement on chain %d\n",
+                       chain);
                if (!ath_paprd_send_frame(sc, skb, chain))
                        goto fail_paprd;
 
                ar9003_paprd_setup_gain_table(ah, chain);
 
-               ath_dbg(common, ATH_DBG_CALIBRATE,
+               ath_dbg(common, CALIBRATE,
                        "Sending PAPRD training frame on chain %d\n", chain);
                if (!ath_paprd_send_frame(sc, skb, chain))
                        goto fail_paprd;
 
                if (!ar9003_paprd_is_done(ah)) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "PAPRD not yet done on chain %d\n", chain);
                        break;
                }
 
                if (ar9003_paprd_create_curve(ah, caldata, chain)) {
-                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                       ath_dbg(common, CALIBRATE,
                                "PAPRD create curve failed on chain %d\n",
                                                                   chain);
                        break;
@@ -604,8 +603,9 @@ void ath_ani_calibrate(unsigned long data)
                                                ah->rxchainmask, longcal);
        }
 
-       ath_dbg(common, ATH_DBG_ANI,
-               "Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies,
+       ath_dbg(common, ANI,
+               "Calibration @%lu finished: %s %s %s, caldone: %s\n",
+               jiffies,
                longcal ? "long" : "", shortcal ? "short" : "",
                aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
 
@@ -715,8 +715,7 @@ void ath9k_tasklet(unsigned long data)
                 * TSF sync does not look correct; remain awake to sync with
                 * the next Beacon.
                 */
-               ath_dbg(common, ATH_DBG_PS,
-                       "TSFOOR - Sync with next Beacon\n");
+               ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n");
                sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
        }
 
@@ -742,11 +741,11 @@ void ath9k_tasklet(unsigned long data)
                        ath_tx_tasklet(sc);
        }
 
-       if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+       if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
                if (status & ATH9K_INT_GENTIMER)
                        ath_gen_timer_isr(sc->sc_ah);
 
-       if (status & ATH9K_INT_MCI)
+       if ((status & ATH9K_INT_MCI) && ATH9K_HW_CAP_MCI)
                ath_mci_intr(sc);
 
 out:
@@ -936,8 +935,8 @@ void ath_hw_check(struct work_struct *work)
        busy = ath_update_survey_stats(sc);
        spin_unlock_irqrestore(&common->cc_lock, flags);
 
-       ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
-               "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+       ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n",
+               busy, sc->hw_busy_count + 1);
        if (busy >= 99) {
                if (++sc->hw_busy_count >= 3) {
                        RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
@@ -960,8 +959,7 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
                count++;
                if (count == 3) {
                        /* Rx is hung for more than 500ms. Reset it */
-                       ath_dbg(common, ATH_DBG_RESET,
-                               "Possible RX hang, resetting");
+                       ath_dbg(common, RESET, "Possible RX hang, resetting\n");
                        RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
                        ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
                        count = 0;
@@ -1001,7 +999,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
        struct ath9k_channel *init_channel;
        int r;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Starting driver with initial channel: %d MHz\n",
                curchan->center_freq);
 
@@ -1083,14 +1081,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
        spin_unlock_bh(&sc->sc_pcu_lock);
 
-       if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
+       if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
            !ah->btcoex_hw.enabled) {
                if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
                        ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
                                                   AR_STOMP_LOW_WLAN_WGHT);
                ath9k_hw_btcoex_enable(ah);
 
-               if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+               if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
                        ath9k_btcoex_timer_resume(sc);
        }
 
@@ -1120,7 +1118,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
                if (ieee80211_is_data(hdr->frame_control) &&
                    !ieee80211_is_nullfunc(hdr->frame_control) &&
                    !ieee80211_has_pm(hdr->frame_control)) {
-                       ath_dbg(common, ATH_DBG_PS,
+                       ath_dbg(common, PS,
                                "Add PM=1 for a TX frame while in PS mode\n");
                        hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
                }
@@ -1143,12 +1141,11 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
                if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        ath9k_hw_setrxabort(sc->sc_ah, 0);
                if (ieee80211_is_pspoll(hdr->frame_control)) {
-                       ath_dbg(common, ATH_DBG_PS,
+                       ath_dbg(common, PS,
                                "Sending PS-Poll to pick a buffered frame\n");
                        sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA;
                } else {
-                       ath_dbg(common, ATH_DBG_PS,
-                               "Wake up to complete TX\n");
+                       ath_dbg(common, PS, "Wake up to complete TX\n");
                        sc->ps_flags |= PS_WAIT_FOR_TX_ACK;
                }
                /*
@@ -1162,10 +1159,10 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        memset(&txctl, 0, sizeof(struct ath_tx_control));
        txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
 
-       ath_dbg(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
+       ath_dbg(common, XMIT, "transmitting packet, skb: %p\n", skb);
 
        if (ath_tx_start(hw, skb, &txctl) != 0) {
-               ath_dbg(common, ATH_DBG_XMIT, "TX failed\n");
+               ath_dbg(common, XMIT, "TX failed\n");
                goto exit;
        }
 
@@ -1186,7 +1183,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
        ath_cancel_work(sc);
 
        if (sc->sc_flags & SC_OP_INVALID) {
-               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+               ath_dbg(common, ANY, "Device not present\n");
                mutex_unlock(&sc->mutex);
                return;
        }
@@ -1194,9 +1191,10 @@ static void ath9k_stop(struct ieee80211_hw *hw)
        /* Ensure HW is awake when we try to shut it down. */
        ath9k_ps_wakeup(sc);
 
-       if (ah->btcoex_hw.enabled) {
+       if (ah->btcoex_hw.enabled &&
+           ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
                ath9k_hw_btcoex_disable(ah);
-               if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+               if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
                        ath9k_btcoex_timer_pause(sc);
                ath_mci_flush_profile(&sc->btcoex.mci);
        }
@@ -1252,7 +1250,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        mutex_unlock(&sc->mutex);
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
+       ath_dbg(common, CONFIG, "Driver halt\n");
 }
 
 bool ath9k_uses_beacons(int type)
@@ -1467,8 +1465,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "Attach a VIF of type: %d\n", vif->type);
+       ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
 
        sc->nvifs++;
 
@@ -1488,7 +1485,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int ret = 0;
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
+       ath_dbg(common, CONFIG, "Change Interface\n");
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
 
@@ -1531,7 +1528,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-       ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
+       ath_dbg(common, CONFIG, "Detach Interface\n");
 
        ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
@@ -1622,12 +1619,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 
        if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
                if (conf->flags & IEEE80211_CONF_MONITOR) {
-                       ath_dbg(common, ATH_DBG_CONFIG,
-                               "Monitor mode is enabled\n");
+                       ath_dbg(common, CONFIG, "Monitor mode is enabled\n");
                        sc->sc_ah->is_monitoring = true;
                } else {
-                       ath_dbg(common, ATH_DBG_CONFIG,
-                               "Monitor mode is disabled\n");
+                       ath_dbg(common, CONFIG, "Monitor mode is disabled\n");
                        sc->sc_ah->is_monitoring = false;
                }
        }
@@ -1647,8 +1642,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
                else
                        sc->sc_flags &= ~SC_OP_OFFCHANNEL;
 
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Set channel: %d MHz type: %d\n",
+               ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
                        curchan->center_freq, conf->channel_type);
 
                /* update survey stats for the old channel before switching */
@@ -1705,8 +1699,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
        }
 
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Set power: %d\n", conf->power_level);
+               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
@@ -1746,8 +1739,8 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
        ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
        ath9k_ps_restore(sc);
 
-       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-               "Set HW RX filter: 0x%x\n", rfilt);
+       ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, "Set HW RX filter: 0x%x\n",
+               rfilt);
 }
 
 static int ath9k_sta_add(struct ieee80211_hw *hw,
@@ -1841,7 +1834,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
        qi.tqi_cwmax = params->cw_max;
        qi.tqi_burstTime = params->txop;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
+       ath_dbg(common, CONFIG,
                "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
                queue, txq->axq_qnum, params->aifs, params->cw_min,
                params->cw_max, params->txop);
@@ -1890,7 +1883,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
-       ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n");
+       ath_dbg(common, CONFIG, "Set HW Key\n");
 
        switch (cmd) {
        case SET_KEY:
@@ -1942,9 +1935,8 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
                memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
                common->curaid = bss_conf->aid;
                ath9k_hw_write_associd(sc->sc_ah);
-               ath_dbg(common, ATH_DBG_CONFIG,
-                               "Bss Info ASSOC %d, bssid: %pM\n",
-                               bss_conf->aid, common->curbssid);
+               ath_dbg(common, CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
+                       bss_conf->aid, common->curbssid);
                ath_beacon_config(sc, vif);
                /*
                 * Request a re-configuration of Beacon related timers
@@ -1975,8 +1967,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
 
        /* Reconfigure bss info */
        if (avp->primary_sta_vif && !bss_conf->assoc) {
-               ath_dbg(common, ATH_DBG_CONFIG,
-                       "Bss Info DISASSOC %d, bssid %pM\n",
+               ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n",
                        common->curaid, common->curbssid);
                sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
                avp->primary_sta_vif = false;
@@ -2018,7 +2009,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        if (changed & BSS_CHANGED_BSSID) {
                ath9k_config_bss(sc, vif);
 
-               ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n",
+               ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
                        common->curbssid, common->curaid);
        }
 
@@ -2096,7 +2087,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
+               ath_dbg(common, CONFIG, "BSS Changed PREAMBLE %d\n",
                        bss_conf->use_short_preamble);
                if (bss_conf->use_short_preamble)
                        sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
@@ -2105,7 +2096,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-               ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
+               ath_dbg(common, CONFIG, "BSS Changed CTS PROT %d\n",
                        bss_conf->use_cts_prot);
                if (bss_conf->use_cts_prot &&
                    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
@@ -2271,13 +2262,13 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
        cancel_delayed_work_sync(&sc->tx_complete_work);
 
        if (ah->ah_flags & AH_UNPLUGGED) {
-               ath_dbg(common, ATH_DBG_ANY, "Device has been unplugged!\n");
+               ath_dbg(common, ANY, "Device has been unplugged!\n");
                mutex_unlock(&sc->mutex);
                return;
        }
 
        if (sc->sc_flags & SC_OP_INVALID) {
-               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+               ath_dbg(common, ANY, "Device not present\n");
                mutex_unlock(&sc->mutex);
                return;
        }
index 691bf47906e2d004ccd7e05b4ffa1129d0501015..fee8c6f0b2512049a7d45de36b1001678684b460 100644 (file)
@@ -43,14 +43,14 @@ static bool ath_mci_add_profile(struct ath_common *common,
 
        if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
            (info->type == MCI_GPM_COEX_PROFILE_VOICE)) {
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "Too many SCO profile, failed to add new profile\n");
                return false;
        }
 
        if (((NUM_PROF(mci) - mci->num_sco) == ATH_MCI_MAX_ACL_PROFILE) &&
            (info->type != MCI_GPM_COEX_PROFILE_VOICE)) {
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "Too many ACL profile, failed to add new profile\n");
                return false;
        }
@@ -80,8 +80,7 @@ static void ath_mci_del_profile(struct ath_common *common,
        entry = ath_mci_find_profile(mci, info);
 
        if (!entry) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "Profile to be deleted not found\n");
+               ath_dbg(common, MCI, "Profile to be deleted not found\n");
                return;
        }
        DEC_PROF(mci, entry);
@@ -132,30 +131,30 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
                                        list);
                if (mci->num_sco && info->T == 12) {
                        mci->aggr_limit = 8;
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "Single SCO, aggregation limit 2 ms\n");
                } else if ((info->type == MCI_GPM_COEX_PROFILE_BNEP) &&
                           !info->master) {
                        btcoex->btcoex_period = 60;
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "Single slave PAN/FTP, bt period 60 ms\n");
                } else if ((info->type == MCI_GPM_COEX_PROFILE_HID) &&
                         (info->T > 0 && info->T < 50) &&
                         (info->A > 1 || info->W > 1)) {
                        btcoex->duty_cycle = 30;
                        mci->aggr_limit = 8;
-                       ath_dbg(common, ATH_DBG_MCI,
+                       ath_dbg(common, MCI,
                                "Multiple attempt/timeout single HID "
                                "aggregation limit 2 ms dutycycle 30%%\n");
                }
        } else if ((num_profile == 2) && (mci->num_hid == 2)) {
                btcoex->duty_cycle = 30;
                mci->aggr_limit = 8;
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "Two HIDs aggregation limit 2 ms dutycycle 30%%\n");
        } else if (num_profile > 3) {
                mci->aggr_limit = 6;
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "Three or more profiles aggregation limit 1.5 ms\n");
        }
 
@@ -194,42 +193,41 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
        switch (opcode) {
        case MCI_GPM_BT_CAL_REQ:
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_REQ\n");
+               ath_dbg(common, MCI, "MCI received BT_CAL_REQ\n");
 
                if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) {
                        ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL);
                        ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
                } else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI State mismatches: %d\n",
+                       ath_dbg(common, MCI, "MCI State mismatches: %d\n",
                                ar9003_mci_state(ah, MCI_STATE_BT, NULL));
 
                break;
 
        case MCI_GPM_BT_CAL_DONE:
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_DONE\n");
+               ath_dbg(common, MCI, "MCI received BT_CAL_DONE\n");
 
                if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_CAL)
-                       ath_dbg(common, ATH_DBG_MCI, "MCI error illegal!\n");
+                       ath_dbg(common, MCI, "MCI error illegal!\n");
                else
-                       ath_dbg(common, ATH_DBG_MCI, "MCI BT not in CAL state\n");
+                       ath_dbg(common, MCI, "MCI BT not in CAL state\n");
 
                break;
 
        case MCI_GPM_BT_CAL_GRANT:
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_GRANT\n");
+               ath_dbg(common, MCI, "MCI received BT_CAL_GRANT\n");
 
                /* Send WLAN_CAL_DONE for now */
-               ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_DONE\n");
+               ath_dbg(common, MCI, "MCI send WLAN_CAL_DONE\n");
                MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
                ar9003_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload,
                                        16, false, true);
                break;
 
        default:
-               ath_dbg(common, ATH_DBG_MCI, "MCI Unknown GPM CAL message\n");
+               ath_dbg(common, MCI, "MCI Unknown GPM CAL message\n");
                break;
        }
 }
@@ -272,8 +270,7 @@ static void ath_mci_process_status(struct ath_softc *sc,
 
        /* Link status type are not handled */
        if (status->is_link) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "Skip link type status update\n");
+               ath_dbg(common, MCI, "Skip link type status update\n");
                return;
        }
 
@@ -281,14 +278,13 @@ static void ath_mci_process_status(struct ath_softc *sc,
 
        info.conn_handle = status->conn_handle;
        if (ath_mci_find_profile(mci, &info)) {
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "Skip non link state update for existing profile %d\n",
                        status->conn_handle);
                return;
        }
        if (status->conn_handle >= ATH_MCI_MAX_PROFILE) {
-               ath_dbg(common, ATH_DBG_MCI,
-                       "Ignore too many non-link update\n");
+               ath_dbg(common, MCI, "Ignore too many non-link update\n");
                return;
        }
        if (status->is_critical)
@@ -320,35 +316,32 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
        switch (opcode) {
 
        case MCI_GPM_COEX_VERSION_QUERY:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Version Query.\n");
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n");
                version = ar9003_mci_state(ah,
                                MCI_STATE_SEND_WLAN_COEX_VERSION, NULL);
                break;
 
        case MCI_GPM_COEX_VERSION_RESPONSE:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Version Response.\n");
+               ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n");
                major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
                minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI BT Coex version: %d.%d\n", major, minor);
+               ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n",
+                       major, minor);
                version = (major << 8) + minor;
                version = ar9003_mci_state(ah,
                          MCI_STATE_SET_BT_COEX_VERSION, &version);
                break;
 
        case MCI_GPM_COEX_STATUS_QUERY:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX Status Query = 0x%02x.\n",
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX Status Query = 0x%02x\n",
                        *(rx_payload + MCI_GPM_COEX_B_WLAN_BITMAP));
                ar9003_mci_state(ah,
                MCI_STATE_SEND_WLAN_CHANNELS, NULL);
                break;
 
        case MCI_GPM_COEX_BT_PROFILE_INFO:
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM Coex BT profile info\n");
+               ath_dbg(common, MCI, "MCI Recv GPM Coex BT profile info\n");
                memcpy(&profile_info,
                       (rx_payload + MCI_GPM_COEX_B_PROFILE_TYPE), 10);
 
@@ -356,9 +349,9 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
                    || (profile_info.type >=
                                            MCI_GPM_COEX_PROFILE_MAX)) {
 
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "illegal profile type = %d,"
-                               "state = %d\n", profile_info.type,
+                       ath_dbg(common, MCI,
+                               "illegal profile type = %d, state = %d\n",
+                               profile_info.type,
                                profile_info.start);
                        break;
                }
@@ -375,9 +368,8 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
                                               MCI_GPM_COEX_B_STATUS_STATE);
 
                seq_num = *((u32 *)(rx_payload + 12));
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI Recv GPM COEX BT_Status_Update: "
-                       "is_link=%d, linkId=%d, state=%d, SEQ=%d\n",
+               ath_dbg(common, MCI,
+                       "MCI Recv GPM COEX BT_Status_Update: is_link=%d, linkId=%d, state=%d, SEQ=%d\n",
                        profile_status.is_link, profile_status.conn_handle,
                        profile_status.is_critical, seq_num);
 
@@ -385,8 +377,8 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
                break;
 
        default:
-               ath_dbg(common, ATH_DBG_MCI,
-               "MCI Unknown GPM COEX message = 0x%02x\n", opcode);
+               ath_dbg(common, MCI, "MCI Unknown GPM COEX message = 0x%02x\n",
+                       opcode);
                break;
        }
 }
@@ -425,10 +417,13 @@ int ath_mci_setup(struct ath_softc *sc)
        struct ath_mci_coex *mci = &sc->mci_coex;
        int error = 0;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return 0;
+
        mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE;
 
        if (ath_mci_buf_alloc(sc, &mci->sched_buf)) {
-               ath_dbg(common, ATH_DBG_FATAL, "MCI buffer alloc failed\n");
+               ath_dbg(common, FATAL, "MCI buffer alloc failed\n");
                error = -ENOMEM;
                goto fail;
        }
@@ -458,6 +453,9 @@ void ath_mci_cleanup(struct ath_softc *sc)
        struct ath_hw *ah = sc->sc_ah;
        struct ath_mci_coex *mci = &sc->mci_coex;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        /*
         * both schedule and gpm buffers will be released
         */
@@ -476,15 +474,17 @@ void ath_mci_intr(struct ath_softc *sc)
        u32 more_data = MCI_GPM_MORE;
        bool skip_gpm = false;
 
+       if (!ATH9K_HW_CAP_MCI)
+               return;
+
        ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
 
        if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
 
                ar9003_mci_state(sc->sc_ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI interrupt but MCI disabled\n");
+               ath_dbg(common, MCI, "MCI interrupt but MCI disabled\n");
 
-               ath_dbg(common, ATH_DBG_MCI,
+               ath_dbg(common, MCI,
                        "MCI interrupt: intr = 0x%x, intr_rxmsg = 0x%x\n",
                        mci_int, mci_int_rxmsg);
                return;
@@ -499,11 +499,11 @@ void ath_mci_intr(struct ath_softc *sc)
                 * only when BT wake up. Now they are always sent, as a
                 * recovery method to reset BT MCI's RX alignment.
                 */
-               ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send REMOTE_RESET\n");
+               ath_dbg(common, MCI, "MCI interrupt send REMOTE_RESET\n");
 
                ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0,
                                        payload, 16, true, false);
-               ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send SYS_WAKING\n");
+               ath_dbg(common, MCI, "MCI interrupt send SYS_WAKING\n");
                ar9003_mci_send_message(ah, MCI_SYS_WAKING, 0,
                                        NULL, 0, true, false);
 
@@ -513,7 +513,7 @@ void ath_mci_intr(struct ath_softc *sc)
                /*
                 * always do this for recovery and 2G/5G toggling and LNA_TRANS
                 */
-               ath_dbg(common, ATH_DBG_MCI, "MCI Set BT state to AWAKE.\n");
+               ath_dbg(common, MCI, "MCI Set BT state to AWAKE\n");
                ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL);
        }
 
@@ -525,17 +525,16 @@ void ath_mci_intr(struct ath_softc *sc)
 
                        if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL)
                                        == MCI_BT_SLEEP)
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI BT stays in sleep mode\n");
                        else {
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI Set BT state to AWAKE.\n");
+                               ath_dbg(common, MCI,
+                                       "MCI Set BT state to AWAKE\n");
                                ar9003_mci_state(ah,
                                                 MCI_STATE_SET_BT_AWAKE, NULL);
                        }
                } else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI BT stays in AWAKE mode.\n");
+                       ath_dbg(common, MCI, "MCI BT stays in AWAKE mode\n");
        }
 
        if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
@@ -546,23 +545,22 @@ void ath_mci_intr(struct ath_softc *sc)
 
                        if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL)
                                        == MCI_BT_AWAKE)
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI BT stays in AWAKE mode.\n");
+                               ath_dbg(common, MCI,
+                                       "MCI BT stays in AWAKE mode\n");
                        else {
-                               ath_dbg(common, ATH_DBG_MCI,
+                               ath_dbg(common, MCI,
                                        "MCI SetBT state to SLEEP\n");
                                ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP,
                                                 NULL);
                        }
                } else
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI BT stays in SLEEP mode\n");
+                       ath_dbg(common, MCI, "MCI BT stays in SLEEP mode\n");
        }
 
        if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
            (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
 
-               ath_dbg(common, ATH_DBG_MCI, "MCI RX broken, skip GPM msgs\n");
+               ath_dbg(common, MCI, "MCI RX broken, skip GPM msgs\n");
                ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL);
                skip_gpm = true;
        }
@@ -624,7 +622,7 @@ void ath_mci_intr(struct ath_softc *sc)
 
                if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_INFO) {
                        mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO;
-                       ath_dbg(common, ATH_DBG_MCI, "MCI LNA_INFO\n");
+                       ath_dbg(common, MCI, "MCI LNA_INFO\n");
                }
 
                if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
@@ -635,16 +633,14 @@ void ath_mci_intr(struct ath_softc *sc)
                        mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO;
 
                        if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL))
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI CONT_INFO: "
-                                       "(tx) pri = %d, pwr = %d dBm\n",
+                               ath_dbg(common, MCI,
+                                       "MCI CONT_INFO: (tx) pri = %d, pwr = %d dBm\n",
                                        ar9003_mci_state(ah,
                                                MCI_STATE_CONT_PRIORITY, NULL),
                                        value_dbm);
                        else
-                               ath_dbg(common, ATH_DBG_MCI,
-                                       "MCI CONT_INFO:"
-                                       "(rx) pri = %d,pwr = %d dBm\n",
+                               ath_dbg(common, MCI,
+                                       "MCI CONT_INFO: (rx) pri = %d,pwr = %d dBm\n",
                                        ar9003_mci_state(ah,
                                                MCI_STATE_CONT_PRIORITY, NULL),
                                        value_dbm);
@@ -652,12 +648,12 @@ void ath_mci_intr(struct ath_softc *sc)
 
                if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK) {
                        mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_NACK;
-                       ath_dbg(common, ATH_DBG_MCI, "MCI CONT_NACK\n");
+                       ath_dbg(common, MCI, "MCI CONT_NACK\n");
                }
 
                if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_RST) {
                        mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_RST;
-                       ath_dbg(common, ATH_DBG_MCI, "MCI CONT_RST\n");
+                       ath_dbg(common, MCI, "MCI CONT_RST\n");
                }
        }
 
@@ -667,7 +663,6 @@ void ath_mci_intr(struct ath_softc *sc)
                             AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT);
 
        if (mci_int_rxmsg & 0xfffffffe)
-               ath_dbg(common, ATH_DBG_MCI,
-                       "MCI not processed mci_int_rxmsg = 0x%x\n",
+               ath_dbg(common, MCI, "MCI not processed mci_int_rxmsg = 0x%x\n",
                        mci_int_rxmsg);
 }
index a439edc5dc06de032575ede2faa1504f04b6afad..77dc327def8dec509f50bfe4f490f1a29351f905 100644 (file)
@@ -121,7 +121,7 @@ static void ath_pci_aspm_init(struct ath_common *common)
        if (!parent)
                return;
 
-       if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {
+       if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
                /* Bluetooth coexistance requires disabling ASPM. */
                pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
                aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
index 528d5f3e868c712a7b2372dc8616e1581205bddc..b3c3798fe5130eaf4e4ea7e528a3e8c646f8711b 100644 (file)
@@ -1199,7 +1199,7 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
                        return &ar5416_11na_ratetable;
                return &ar5416_11a_ratetable;
        default:
-               ath_dbg(common, ATH_DBG_CONFIG, "Invalid band\n");
+               ath_dbg(common, CONFIG, "Invalid band\n");
                return NULL;
        }
 }
@@ -1276,8 +1276,7 @@ static void ath_rc_init(struct ath_softc *sc,
                                        ath_rc_priv->valid_rate_index[k-1];
        ath_rc_priv->rate_table = rate_table;
 
-       ath_dbg(common, ATH_DBG_CONFIG,
-               "RC Initialized with capabilities: 0x%x\n",
+       ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n",
                ath_rc_priv->ht_cap);
 }
 
@@ -1474,7 +1473,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
                                                   oper_cw40, oper_sgi);
                        ath_rc_init(sc, priv_sta, sband, sta, rate_table);
 
-                       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+                       ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
                                "Operating HT Bandwidth changed to: %d\n",
                                sc->hw->conf.channel_type);
                }
index ad5176de07dc93dc65dc83f52487e8c448de36f3..0e666fbe084279fd91921de34efccc20b814894e 100644 (file)
@@ -172,7 +172,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
        u32 nbuf = 0;
 
        if (list_empty(&sc->rx.rxbuf)) {
-               ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n");
+               ath_dbg(common, QUEUE, "No free rx buf available\n");
                return;
        }
 
@@ -337,7 +337,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
                return ath_rx_edma_init(sc, nbufs);
        } else {
-               ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
+               ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
                        common->cachelsz, common->rx_bufsize);
 
                /* Initialize rx descriptors */
@@ -591,7 +591,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
 
        if (sc->ps_flags & PS_BEACON_SYNC) {
                sc->ps_flags &= ~PS_BEACON_SYNC;
-               ath_dbg(common, ATH_DBG_PS,
+               ath_dbg(common, PS,
                        "Reconfigure Beacon timers based on timestamp from the AP\n");
                ath_set_beacon(sc);
        }
@@ -604,7 +604,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
                 * a backup trigger for returning into NETWORK SLEEP state,
                 * so we are waiting for it as well.
                 */
-               ath_dbg(common, ATH_DBG_PS,
+               ath_dbg(common, PS,
                        "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n");
                sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON;
                return;
@@ -617,8 +617,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
                 * been delivered.
                 */
                sc->ps_flags &= ~PS_WAIT_FOR_CAB;
-               ath_dbg(common, ATH_DBG_PS,
-                       "PS wait for CAB frames timed out\n");
+               ath_dbg(common, PS, "PS wait for CAB frames timed out\n");
        }
 }
 
@@ -643,13 +642,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
                 * point.
                 */
                sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
-               ath_dbg(common, ATH_DBG_PS,
+               ath_dbg(common, PS,
                        "All PS CAB frames received, back to sleep\n");
        } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
                   !is_multicast_ether_addr(hdr->addr1) &&
                   !ieee80211_has_morefrags(hdr->frame_control)) {
                sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA;
-               ath_dbg(common, ATH_DBG_PS,
+               ath_dbg(common, PS,
                        "Going back to sleep after having received PS-Poll data (0x%lx)\n",
                        sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                        PS_WAIT_FOR_CAB |
@@ -932,7 +931,7 @@ static int ath9k_process_rate(struct ath_common *common,
         * No valid hardware bitrate found -- we should not get here
         * because hardware has already validated this frame as OK.
         */
-       ath_dbg(common, ATH_DBG_ANY,
+       ath_dbg(common, ANY,
                "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
                rx_stats->rs_rate);
 
index 35422fc1f2ce1a566ce11cb0a0d740880531badd..65c8894c5f81040361fbdd5da9aa7823e6d38900 100644 (file)
@@ -187,7 +187,7 @@ void ath9k_fatal_work(struct work_struct *work)
                                                   fatal_work);
        struct ath_common *common = ath9k_hw_common(priv->ah);
 
-       ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n");
+       ath_dbg(common, FATAL, "FATAL Event received, resetting device\n");
        ath9k_htc_reset(priv);
 }
 
@@ -330,8 +330,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
 
        time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
        if (!time_left) {
-               ath_dbg(common, ATH_DBG_WMI,
-                       "Timeout waiting for WMI command: %s\n",
+               ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n",
                        wmi_cmd_to_name(cmd_id));
                mutex_unlock(&wmi->op_mutex);
                return -ETIMEDOUT;
@@ -342,8 +341,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
        return 0;
 
 out:
-       ath_dbg(common, ATH_DBG_WMI,
-               "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
+       ath_dbg(common, WMI, "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id));
        mutex_unlock(&wmi->op_mutex);
        kfree_skb(skb);
 
index 2622fcee8c96fab2ee199c55c007ecdbe4745871..9aa01997b1ead43231bc04c4ce59801495dafc09 100644 (file)
@@ -104,6 +104,29 @@ static int ath_max_4ms_framelen[4][32] = {
 /* Aggregation logic */
 /*********************/
 
+static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
+{
+       spin_lock_bh(&txq->axq_lock);
+}
+
+static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
+{
+       spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
+{
+       struct sk_buff_head q;
+       struct sk_buff *skb;
+
+       __skb_queue_head_init(&q);
+       skb_queue_splice_init(&txq->complete_q, &q);
+       spin_unlock_bh(&txq->axq_lock);
+
+       while ((skb = __skb_dequeue(&q)))
+               ieee80211_tx_status(sc->hw, skb);
+}
+
 static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
 {
        struct ath_atx_ac *ac = tid->ac;
@@ -130,7 +153,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 
        WARN_ON(!tid->paused);
 
-       spin_lock_bh(&txq->axq_lock);
+       ath_txq_lock(sc, txq);
        tid->paused = false;
 
        if (skb_queue_empty(&tid->buf_q))
@@ -139,7 +162,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
        ath_tx_queue_tid(txq, tid);
        ath_txq_schedule(sc, txq);
 unlock:
-       spin_unlock_bh(&txq->axq_lock);
+       ath_txq_unlock_complete(sc, txq);
 }
 
 static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
@@ -189,8 +212,11 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
                tid->state &= ~AGGR_CLEANUP;
        }
 
-       if (sendbar)
+       if (sendbar) {
+               ath_txq_unlock(sc, txq);
                ath_send_bar(tid, tid->seq_start);
+               ath_txq_lock(sc, txq);
+       }
 }
 
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -554,13 +580,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                bf = bf_next;
        }
 
-       if (bar_index >= 0) {
-               u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
-               ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
-               if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
-                       tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
-       }
-
        /* prepend un-acked frames to the beginning of the pending frame queue */
        if (!skb_queue_empty(&bf_pending)) {
                if (an->sleeping)
@@ -575,6 +594,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                }
        }
 
+       if (bar_index >= 0) {
+               u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
+
+               if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
+                       tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
+
+               ath_txq_unlock(sc, txq);
+               ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
+               ath_txq_lock(sc, txq);
+       }
+
        if (tid->state & AGGR_CLEANUP)
                ath_tx_flush_tid(sc, tid);
 
@@ -1172,7 +1202,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
                return;
        }
 
-       spin_lock_bh(&txq->axq_lock);
+       ath_txq_lock(sc, txq);
        txtid->paused = true;
 
        /*
@@ -1187,7 +1217,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
                txtid->state &= ~AGGR_ADDBA_COMPLETE;
 
        ath_tx_flush_tid(sc, txtid);
-       spin_unlock_bh(&txq->axq_lock);
+       ath_txq_unlock_complete(sc, txq);
 }
 
 void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@@ -1208,7 +1238,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
                ac = tid->ac;
                txq = ac->txq;
 
-               spin_lock_bh(&txq->axq_lock);
+               ath_txq_lock(sc, txq);
 
                buffered = !skb_queue_empty(&tid->buf_q);
 
@@ -1220,7 +1250,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
                        list_del(&ac->list);
                }
 
-               spin_unlock_bh(&txq->axq_lock);
+               ath_txq_unlock(sc, txq);
 
                ieee80211_sta_set_buffered(sta, tidno, buffered);
        }
@@ -1239,7 +1269,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
                ac = tid->ac;
                txq = ac->txq;
 
-               spin_lock_bh(&txq->axq_lock);
+               ath_txq_lock(sc, txq);
                ac->clear_ps_filter = true;
 
                if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
@@ -1247,7 +1277,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
                        ath_txq_schedule(sc, txq);
                }
 
-               spin_unlock_bh(&txq->axq_lock);
+               ath_txq_unlock_complete(sc, txq);
        }
 }
 
@@ -1347,6 +1377,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
                txq->axq_qnum = axq_qnum;
                txq->mac80211_qnum = -1;
                txq->axq_link = NULL;
+               __skb_queue_head_init(&txq->complete_q);
                INIT_LIST_HEAD(&txq->axq_q);
                INIT_LIST_HEAD(&txq->axq_acq);
                spin_lock_init(&txq->axq_lock);
@@ -1471,7 +1502,8 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
  */
 void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
 {
-       spin_lock_bh(&txq->axq_lock);
+       ath_txq_lock(sc, txq);
+
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
                int idx = txq->txq_tailidx;
 
@@ -1492,7 +1524,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
                ath_txq_drain_pending_buffers(sc, txq);
 
-       spin_unlock_bh(&txq->axq_lock);
+       ath_txq_unlock_complete(sc, txq);
 }
 
 bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1626,8 +1658,8 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
        bf = list_first_entry(head, struct ath_buf, list);
        bf_last = list_entry(head->prev, struct ath_buf, list);
 
-       ath_dbg(common, ATH_DBG_QUEUE,
-               "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+       ath_dbg(common, QUEUE, "qnum: %d, txq depth: %d\n",
+               txq->axq_qnum, txq->axq_depth);
 
        if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
                list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
@@ -1638,8 +1670,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 
                if (txq->axq_link) {
                        ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "link[%u] (%p)=%llx (%p)\n",
+                       ath_dbg(common, XMIT, "link[%u] (%p)=%llx (%p)\n",
                                txq->axq_qnum, txq->axq_link,
                                ito64(bf->bf_daddr), bf->bf_desc);
                } else if (!edma)
@@ -1651,7 +1682,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
        if (puttxbuf) {
                TX_STAT_INC(txq->axq_qnum, puttxbuf);
                ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-               ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+               ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n",
                        txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
        }
 
@@ -1793,7 +1824,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
 
        bf = ath_tx_get_buffer(sc);
        if (!bf) {
-               ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
+               ath_dbg(common, XMIT, "TX buffers are full\n");
                goto error;
        }
 
@@ -1925,7 +1956,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
         */
 
        q = skb_get_queue_mapping(skb);
-       spin_lock_bh(&txq->axq_lock);
+
+       ath_txq_lock(sc, txq);
        if (txq == sc->tx.txq_map[q] &&
            ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
                ieee80211_stop_queue(sc->hw, q);
@@ -1934,7 +1966,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        ath_tx_start_dma(sc, skb, txctl);
 
-       spin_unlock_bh(&txq->axq_lock);
+       ath_txq_unlock(sc, txq);
 
        return 0;
 }
@@ -1946,13 +1978,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                            int tx_flags, struct ath_txq *txq)
 {
-       struct ieee80211_hw *hw = sc->hw;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
        int q, padpos, padsize;
 
-       ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+       ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
 
        if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
@@ -1971,7 +2002,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
        if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
                sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
-               ath_dbg(common, ATH_DBG_PS,
+               ath_dbg(common, PS,
                        "Going back to sleep after having received TX status (0x%lx)\n",
                        sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                        PS_WAIT_FOR_CAB |
@@ -1990,7 +2021,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                }
        }
 
-       ieee80211_tx_status(hw, skb);
+       __skb_queue_tail(&txq->complete_q, skb);
 }
 
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
@@ -2122,11 +2153,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
        struct ath_tx_status ts;
        int status;
 
-       ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
+       ath_dbg(common, QUEUE, "tx queue %d (%x), link %p\n",
                txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
                txq->axq_link);
 
-       spin_lock_bh(&txq->axq_lock);
+       ath_txq_lock(sc, txq);
        for (;;) {
                if (work_pending(&sc->hw_reset_work))
                        break;
@@ -2185,7 +2216,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 
                ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
        }
-       spin_unlock_bh(&txq->axq_lock);
+       ath_txq_unlock_complete(sc, txq);
 }
 
 static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2202,21 +2233,21 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
                if (ATH_TXQ_SETUP(sc, i)) {
                        txq = &sc->tx.txq[i];
-                       spin_lock_bh(&txq->axq_lock);
+                       ath_txq_lock(sc, txq);
                        if (txq->axq_depth) {
                                if (txq->axq_tx_inprogress) {
                                        needreset = true;
-                                       spin_unlock_bh(&txq->axq_lock);
+                                       ath_txq_unlock(sc, txq);
                                        break;
                                } else {
                                        txq->axq_tx_inprogress = true;
                                }
                        }
-                       spin_unlock_bh(&txq->axq_lock);
+                       ath_txq_unlock_complete(sc, txq);
                }
 
        if (needreset) {
-               ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+               ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
                        "tx hung, resetting the chip\n");
                RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
                ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
@@ -2259,8 +2290,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
                if (status == -EINPROGRESS)
                        break;
                if (status == -EIO) {
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "Error processing tx status\n");
+                       ath_dbg(common, XMIT, "Error processing tx status\n");
                        break;
                }
 
@@ -2270,10 +2300,10 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 
                txq = &sc->tx.txq[ts.qid];
 
-               spin_lock_bh(&txq->axq_lock);
+               ath_txq_lock(sc, txq);
 
                if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
-                       spin_unlock_bh(&txq->axq_lock);
+                       ath_txq_unlock(sc, txq);
                        return;
                }
 
@@ -2299,7 +2329,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
                }
 
                ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
-               spin_unlock_bh(&txq->axq_lock);
+               ath_txq_unlock_complete(sc, txq);
        }
 }
 
@@ -2437,7 +2467,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
                ac = tid->ac;
                txq = ac->txq;
 
-               spin_lock_bh(&txq->axq_lock);
+               ath_txq_lock(sc, txq);
 
                if (tid->sched) {
                        list_del(&tid->list);
@@ -2453,6 +2483,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
                tid->state &= ~AGGR_ADDBA_COMPLETE;
                tid->state &= ~AGGR_CLEANUP;
 
-               spin_unlock_bh(&txq->axq_lock);
+               ath_txq_unlock(sc, txq);
        }
 }
index 4cf7c5eb4813420c4908539f99ba8373c915d10c..0e81904956cf1c04fa37ad01e65282b55e2bf8f9 100644 (file)
@@ -143,7 +143,7 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
                break;
        case ATH_CIPHER_AES_CCM:
                if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
-                       ath_dbg(common, ATH_DBG_ANY,
+                       ath_dbg(common, ANY,
                                "AES-CCM not supported by this mac rev\n");
                        return false;
                }
@@ -152,15 +152,15 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
        case ATH_CIPHER_TKIP:
                keyType = AR_KEYTABLE_TYPE_TKIP;
                if (entry + 64 >= common->keymax) {
-                       ath_dbg(common, ATH_DBG_ANY,
+                       ath_dbg(common, ANY,
                                "entry %u inappropriate for TKIP\n", entry);
                        return false;
                }
                break;
        case ATH_CIPHER_WEP:
                if (k->kv_len < WLAN_KEY_LEN_WEP40) {
-                       ath_dbg(common, ATH_DBG_ANY,
-                               "WEP key length %u too small\n", k->kv_len);
+                       ath_dbg(common, ANY, "WEP key length %u too small\n",
+                               k->kv_len);
                        return false;
                }
                if (k->kv_len <= WLAN_KEY_LEN_WEP40)
index 37110dfd2c9627ff436379c8305151c0d6ff2e24..f19605e8eb4ca0b43903e479e669d694d49f9bdf 100644 (file)
@@ -667,6 +667,7 @@ struct b43_key {
 };
 
 /* SHM offsets to the QOS data structures for the 4 different queues. */
+#define B43_QOS_QUEUE_NUM      4
 #define B43_QOS_PARAMS(queue)  (B43_SHM_SH_EDCFQ + \
                                 (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
 #define B43_QOS_BACKGROUND     B43_QOS_PARAMS(0)
@@ -904,7 +905,7 @@ struct b43_wl {
        struct work_struct beacon_update_trigger;
 
        /* The current QOS parameters for the 4 queues. */
-       struct b43_qos_params qos_params[4];
+       struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM];
 
        /* Work for adjustment of the transmission power.
         * This is scheduled when we determine that the actual TX output
@@ -913,8 +914,12 @@ struct b43_wl {
 
        /* Packet transmit work */
        struct work_struct tx_work;
+
        /* Queue of packets to be transmitted. */
-       struct sk_buff_head tx_queue;
+       struct sk_buff_head tx_queue[B43_QOS_QUEUE_NUM];
+
+       /* Flag that implement the queues stopping. */
+       bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
 
        /* The device LEDs. */
        struct b43_leds leds;
index af23968520b61806435c71b59ec8ce7726535b35..b5f1b91002bbe609cf2a1d97e127d52f7baf32e4 100644 (file)
@@ -1465,7 +1465,9 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
        if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
            should_inject_overflow(ring)) {
                /* This TX ring is full. */
-               ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+               unsigned int skb_mapping = skb_get_queue_mapping(skb);
+               ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+               dev->wl->tx_queue_stopped[skb_mapping] = 1;
                ring->stopped = true;
                if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
                        b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1584,12 +1586,21 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        }
        if (ring->stopped) {
                B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
-               ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
                ring->stopped = false;
+       }
+
+       if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+               dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+       } else {
+               /* If the driver queue is running wake the corresponding
+                * mac80211 queue. */
+               ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
                if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
                        b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
                }
        }
+       /* Add work to the queue. */
+       ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
 }
 
 static void dma_rx(struct b43_dmaring *ring, int *slot)
index c74f36f6e34894d105a1a97bc8cb86fbc8e01aab..1c6f19393efa72037b7369993bf7af463a7bb51a 100644 (file)
@@ -3378,6 +3378,7 @@ static void b43_tx_work(struct work_struct *work)
        struct b43_wl *wl = container_of(work, struct b43_wl, tx_work);
        struct b43_wldev *dev;
        struct sk_buff *skb;
+       int queue_num;
        int err = 0;
 
        mutex_lock(&wl->mutex);
@@ -3387,15 +3388,26 @@ static void b43_tx_work(struct work_struct *work)
                return;
        }
 
-       while (skb_queue_len(&wl->tx_queue)) {
-               skb = skb_dequeue(&wl->tx_queue);
+       for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+               while (skb_queue_len(&wl->tx_queue[queue_num])) {
+                       skb = skb_dequeue(&wl->tx_queue[queue_num]);
+                       if (b43_using_pio_transfers(dev))
+                               err = b43_pio_tx(dev, skb);
+                       else
+                               err = b43_dma_tx(dev, skb);
+                       if (err == -ENOSPC) {
+                               wl->tx_queue_stopped[queue_num] = 1;
+                               ieee80211_stop_queue(wl->hw, queue_num);
+                               skb_queue_head(&wl->tx_queue[queue_num], skb);
+                               break;
+                       }
+                       if (unlikely(err))
+                               dev_kfree_skb(skb); /* Drop it */
+                       err = 0;
+               }
 
-               if (b43_using_pio_transfers(dev))
-                       err = b43_pio_tx(dev, skb);
-               else
-                       err = b43_dma_tx(dev, skb);
-               if (unlikely(err))
-                       dev_kfree_skb(skb); /* Drop it */
+               if (!err)
+                       wl->tx_queue_stopped[queue_num] = 0;
        }
 
 #if B43_DEBUG
@@ -3416,8 +3428,12 @@ static void b43_op_tx(struct ieee80211_hw *hw,
        }
        B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
-       skb_queue_tail(&wl->tx_queue, skb);
-       ieee80211_queue_work(wl->hw, &wl->tx_work);
+       skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+       if (!wl->tx_queue_stopped[skb->queue_mapping]) {
+               ieee80211_queue_work(wl->hw, &wl->tx_work);
+       } else {
+               ieee80211_stop_queue(wl->hw, skb->queue_mapping);
+       }
 }
 
 static void b43_qos_params_upload(struct b43_wldev *dev,
@@ -4147,6 +4163,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
        struct b43_wl *wl;
        struct b43_wldev *orig_dev;
        u32 mask;
+       int queue_num;
 
        if (!dev)
                return NULL;
@@ -4199,9 +4216,11 @@ redo:
        mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
        B43_WARN_ON(mask != 0xFFFFFFFF && mask);
 
-       /* Drain the TX queue */
-       while (skb_queue_len(&wl->tx_queue))
-               dev_kfree_skb(skb_dequeue(&wl->tx_queue));
+       /* Drain all TX queues. */
+       for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+               while (skb_queue_len(&wl->tx_queue[queue_num]))
+                       dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
+       }
 
        b43_mac_suspend(dev);
        b43_leds_exit(dev);
@@ -5245,6 +5264,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
        struct ieee80211_hw *hw;
        struct b43_wl *wl;
        char chip_name[6];
+       int queue_num;
 
        hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
        if (!hw) {
@@ -5264,7 +5284,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
                BIT(NL80211_IFTYPE_WDS) |
                BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->queues = modparam_qos ? 4 : 1;
+       hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;
        wl->mac80211_initially_registered_queues = hw->queues;
        hw->max_rates = 2;
        SET_IEEE80211_DEV(hw, dev->dev);
@@ -5281,7 +5301,12 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
        INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
        INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
        INIT_WORK(&wl->tx_work, b43_tx_work);
-       skb_queue_head_init(&wl->tx_queue);
+
+       /* Initialize queues and flags. */
+       for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+               skb_queue_head_init(&wl->tx_queue[queue_num]);
+               wl->tx_queue_stopped[queue_num] = 0;
+       }
 
        snprintf(chip_name, ARRAY_SIZE(chip_name),
                 (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id);
index f1a7e5890adca07cb06f6177798b09009887b9d4..0d25fe4069bf3aa48432678df9b97b0d84633d25 100644 (file)
@@ -78,19 +78,6 @@ enum b43_nphy_rssi_type {
        B43_NPHY_RSSI_TBD,
 };
 
-/* TODO: reorder functions */
-static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
-                                               bool enable);
-static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
-                                       u8 *events, u8 *delays, u8 length);
-static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
-                                      enum b43_nphy_rf_sequence seq);
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
-                                               u16 value, u8 core, bool off);
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
-                                               u16 value, u8 core);
-static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev);
-
 static inline bool b43_nphy_ipa(struct b43_wldev *dev)
 {
        enum ieee80211_band band = b43_current_band(dev->wl);
@@ -98,638 +85,573 @@ static inline bool b43_nphy_ipa(struct b43_wldev *dev)
                (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
 }
 
-void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
-{//TODO
-}
-
-static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
-{//TODO
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
+{
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               if (dev->phy.rev >= 6) {
+                       if (dev->dev->chip_id == 47162)
+                               return txpwrctrl_tx_gain_ipa_rev5;
+                       return txpwrctrl_tx_gain_ipa_rev6;
+               } else if (dev->phy.rev >= 5) {
+                       return txpwrctrl_tx_gain_ipa_rev5;
+               } else {
+                       return txpwrctrl_tx_gain_ipa;
+               }
+       } else {
+               return txpwrctrl_tx_gain_ipa_5g;
+       }
 }
 
-static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
-                                                       bool ignore_tssi)
-{//TODO
-       return B43_TXPWR_RES_DONE;
-}
+/**************************************************
+ * RF (just without b43_nphy_rf_control_intc_override)
+ **************************************************/
 
-static void b43_chantab_radio_upload(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry_rev2 *e)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
+static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
+                                      enum b43_nphy_rf_sequence seq)
 {
-       b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
-       b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
-       b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
-       b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+       static const u16 trigger[] = {
+               [B43_RFSEQ_RX2TX]               = B43_NPHY_RFSEQTR_RX2TX,
+               [B43_RFSEQ_TX2RX]               = B43_NPHY_RFSEQTR_TX2RX,
+               [B43_RFSEQ_RESET2RX]            = B43_NPHY_RFSEQTR_RST2RX,
+               [B43_RFSEQ_UPDATE_GAINH]        = B43_NPHY_RFSEQTR_UPGH,
+               [B43_RFSEQ_UPDATE_GAINL]        = B43_NPHY_RFSEQTR_UPGL,
+               [B43_RFSEQ_UPDATE_GAINU]        = B43_NPHY_RFSEQTR_UPGU,
+       };
+       int i;
+       u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
 
-       b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
-       b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
-       b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
-       b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+       B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
 
-       b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
-       b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
-       b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
-       b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+       b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+                   B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
+       b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
+       for (i = 0; i < 200; i++) {
+               if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
+                       goto ok;
+               msleep(1);
+       }
+       b43err(dev->wl, "RF sequence status timeout\n");
+ok:
+       b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
+}
 
-       b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
-       b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
-       b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
-       b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
+static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
+                                               u16 value, u8 core, bool off)
+{
+       int i;
+       u8 index = fls(field);
+       u8 addr, en_addr, val_addr;
+       /* we expect only one bit set */
+       B43_WARN_ON(field & (~(1 << (index - 1))));
 
-       b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
-       b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
-       b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
-       b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+       if (dev->phy.rev >= 3) {
+               const struct nphy_rf_control_override_rev3 *rf_ctrl;
+               for (i = 0; i < 2; i++) {
+                       if (index == 0 || index == 16) {
+                               b43err(dev->wl,
+                                       "Unsupported RF Ctrl Override call\n");
+                               return;
+                       }
 
-       b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
-       b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
-}
+                       rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
+                       en_addr = B43_PHY_N((i == 0) ?
+                               rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
+                       val_addr = B43_PHY_N((i == 0) ?
+                               rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
 
-static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry_rev3 *e)
-{
-       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
-       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
-       b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
-       b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
-       b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
-       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
-                                       e->radio_syn_pll_loopfilter1);
-       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
-                                       e->radio_syn_pll_loopfilter2);
-       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
-                                       e->radio_syn_pll_loopfilter3);
-       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
-                                       e->radio_syn_pll_loopfilter4);
-       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
-                                       e->radio_syn_pll_loopfilter5);
-       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
-                                       e->radio_syn_reserved_addr27);
-       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
-                                       e->radio_syn_reserved_addr28);
-       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
-                                       e->radio_syn_reserved_addr29);
-       b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
-                                       e->radio_syn_logen_vcobuf1);
-       b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
-       b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
-       b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+                       if (off) {
+                               b43_phy_mask(dev, en_addr, ~(field));
+                               b43_phy_mask(dev, val_addr,
+                                               ~(rf_ctrl->val_mask));
+                       } else {
+                               if (core == 0 || ((1 << core) & i) != 0) {
+                                       b43_phy_set(dev, en_addr, field);
+                                       b43_phy_maskset(dev, val_addr,
+                                               ~(rf_ctrl->val_mask),
+                                               (value << rf_ctrl->val_shift));
+                               }
+                       }
+               }
+       } else {
+               const struct nphy_rf_control_override_rev2 *rf_ctrl;
+               if (off) {
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
+                       value = 0;
+               } else {
+                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
+               }
 
-       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
-                                       e->radio_rx0_lnaa_tune);
-       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
-                                       e->radio_rx0_lnag_tune);
+               for (i = 0; i < 2; i++) {
+                       if (index <= 1 || index == 16) {
+                               b43err(dev->wl,
+                                       "Unsupported RF Ctrl Override call\n");
+                               return;
+                       }
 
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
-                                       e->radio_tx0_intpaa_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
-                                       e->radio_tx0_intpag_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
-                                       e->radio_tx0_pada_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
-                                       e->radio_tx0_padg_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
-                                       e->radio_tx0_pgaa_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
-                                       e->radio_tx0_pgag_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
-                                       e->radio_tx0_mixa_boost_tune);
-       b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
-                                       e->radio_tx0_mixg_boost_tune);
+                       if (index == 2 || index == 10 ||
+                           (index >= 13 && index <= 15)) {
+                               core = 1;
+                       }
 
-       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
-                                       e->radio_rx1_lnaa_tune);
-       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
-                                       e->radio_rx1_lnag_tune);
+                       rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
+                       addr = B43_PHY_N((i == 0) ?
+                               rf_ctrl->addr0 : rf_ctrl->addr1);
 
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
-                                       e->radio_tx1_intpaa_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
-                                       e->radio_tx1_intpag_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
-                                       e->radio_tx1_pada_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
-                                       e->radio_tx1_padg_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
-                                       e->radio_tx1_pgaa_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
-                                       e->radio_tx1_pgag_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
-                                       e->radio_tx1_mixa_boost_tune);
-       b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
-                                       e->radio_tx1_mixg_boost_tune);
+                       if ((core & (1 << i)) != 0)
+                               b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
+                                               (value << rf_ctrl->shift));
+
+                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
+                       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                                       B43_NPHY_RFCTL_CMD_START);
+                       udelay(1);
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
+               }
+       }
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
-static void b43_radio_2056_setup(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry_rev3 *e)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
+static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
+                                               u16 value, u8 core)
 {
-       struct ssb_sprom *sprom = dev->dev->bus_sprom;
-       enum ieee80211_band band = b43_current_band(dev->wl);
-       u16 offset;
-       u8 i;
-       u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
+       u8 i, j;
+       u16 reg, tmp, val;
 
        B43_WARN_ON(dev->phy.rev < 3);
+       B43_WARN_ON(field > 4);
 
-       b43_chantab_radio_2056_upload(dev, e);
-       b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
+       for (i = 0; i < 2; i++) {
+               if ((core == 1 && i == 1) || (core == 2 && !i))
+                       continue;
 
-       if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
-           b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
-               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
-               if (dev->dev->chip_id == 0x4716) {
-                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
-                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
-               } else {
-                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
-                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
-               }
-       }
-       if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
-           b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
-               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
-               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
-               b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
-       }
-
-       if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
-               for (i = 0; i < 2; i++) {
-                       offset = i ? B2056_TX1 : B2056_TX0;
-                       if (dev->phy.rev >= 5) {
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_PADG_IDAC, 0xcc);
+               reg = (i == 0) ?
+                       B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
+               b43_phy_mask(dev, reg, 0xFBFF);
 
-                               if (dev->dev->chip_id == 0x4716) {
-                                       bias = 0x40;
-                                       cbias = 0x45;
-                                       pag_boost = 0x5;
-                                       pgag_boost = 0x33;
-                                       mixg_boost = 0x55;
-                               } else {
-                                       bias = 0x25;
-                                       cbias = 0x20;
-                                       pag_boost = 0x4;
-                                       pgag_boost = 0x03;
-                                       mixg_boost = 0x65;
+               switch (field) {
+               case 0:
+                       b43_phy_write(dev, reg, 0);
+                       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+                       break;
+               case 1:
+                       if (!i) {
+                               b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
+                                               0xFC3F, (value << 6));
+                               b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
+                                               0xFFFE, 1);
+                               b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                                               B43_NPHY_RFCTL_CMD_START);
+                               for (j = 0; j < 100; j++) {
+                                       if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
+                                               j = 0;
+                                               break;
+                                       }
+                                       udelay(10);
                                }
-                               padg_boost = 0x77;
-
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
-                                       bias);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_IAUX_STAT,
-                                       bias);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_CASCBIAS,
-                                       cbias);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_BOOST_TUNE,
-                                       pag_boost);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_PGAG_BOOST_TUNE,
-                                       pgag_boost);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_PADG_BOOST_TUNE,
-                                       padg_boost);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_MIXG_BOOST_TUNE,
-                                       mixg_boost);
+                               if (j)
+                                       b43err(dev->wl,
+                                               "intc override timeout\n");
+                               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
+                                               0xFFFE);
                        } else {
-                               bias = dev->phy.is_40mhz ? 0x40 : 0x20;
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
-                                       bias);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_IAUX_STAT,
-                                       bias);
-                               b43_radio_write(dev,
-                                       offset | B2056_TX_INTPAG_CASCBIAS,
-                                       0x30);
+                               b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
+                                               0xFC3F, (value << 6));
+                               b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
+                                               0xFFFE, 1);
+                               b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                                               B43_NPHY_RFCTL_CMD_RXTX);
+                               for (j = 0; j < 100; j++) {
+                                       if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
+                                               j = 0;
+                                               break;
+                                       }
+                                       udelay(10);
+                               }
+                               if (j)
+                                       b43err(dev->wl,
+                                               "intc override timeout\n");
+                               b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
+                                               0xFFFE);
                        }
-                       b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
+                       break;
+               case 2:
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+                               tmp = 0x0020;
+                               val = value << 5;
+                       } else {
+                               tmp = 0x0010;
+                               val = value << 4;
+                       }
+                       b43_phy_maskset(dev, reg, ~tmp, val);
+                       break;
+               case 3:
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+                               tmp = 0x0001;
+                               val = value;
+                       } else {
+                               tmp = 0x0004;
+                               val = value << 2;
+                       }
+                       b43_phy_maskset(dev, reg, ~tmp, val);
+                       break;
+               case 4:
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+                               tmp = 0x0002;
+                               val = value << 1;
+                       } else {
+                               tmp = 0x0008;
+                               val = value << 3;
+                       }
+                       b43_phy_maskset(dev, reg, ~tmp, val);
+                       break;
                }
-       } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
-               /* TODO */
        }
+}
 
-       udelay(50);
-       /* VCO calibration */
-       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
-       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
-       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
-       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
-       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
-       udelay(300);
+/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
+static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
+                                         const u16 *clip_st)
+{
+       b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
+       b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
 }
 
-static void b43_chantab_phy_upload(struct b43_wldev *dev,
-                                  const struct b43_phy_n_sfo_cfg *e)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
+static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
 {
-       b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
-       b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
-       b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
-       b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
-       b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
-       b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
+       clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
+       clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
-static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
+static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
-       u8 i;
-       u16 bmask, val, tmp;
-       enum ieee80211_band band = b43_current_band(dev->wl);
+       u16 tmp;
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
+       if (dev->dev->core_rev == 16)
+               b43_mac_suspend(dev);
 
-       nphy->txpwrctrl = enable;
-       if (!enable) {
-               if (dev->phy.rev >= 3 &&
-                   (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
-                    (B43_NPHY_TXPCTL_CMD_COEFF |
-                     B43_NPHY_TXPCTL_CMD_HWPCTLEN |
-                     B43_NPHY_TXPCTL_CMD_PCTLEN))) {
-                       /* We disable enabled TX pwr ctl, save it's state */
-                       nphy->tx_pwr_idx[0] = b43_phy_read(dev,
-                                               B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
-                       nphy->tx_pwr_idx[1] = b43_phy_read(dev,
-                                               B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
-               }
+       tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
+       tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
+               B43_NPHY_CLASSCTL_WAITEDEN);
+       tmp &= ~mask;
+       tmp |= (val & mask);
+       b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
 
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
-               for (i = 0; i < 84; i++)
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+       if (dev->dev->core_rev == 16)
+               b43_mac_enable(dev);
 
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
-               for (i = 0; i < 84; i++)
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+       return tmp;
+}
 
-               tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
-               if (dev->phy.rev >= 3)
-                       tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
-               b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
+static void b43_nphy_reset_cca(struct b43_wldev *dev)
+{
+       u16 bbcfg;
 
-               if (dev->phy.rev >= 3) {
-                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
-                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
-               } else {
-                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
-               }
+       b43_phy_force_clock(dev, 1);
+       bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
+       b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
+       udelay(1);
+       b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
+       b43_phy_force_clock(dev, 0);
+       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+}
 
-               if (dev->phy.rev == 2)
-                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
-                               ~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
-               else if (dev->phy.rev < 2)
-                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
-                               ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
+static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
+{
+       struct b43_phy *phy = &dev->phy;
+       struct b43_phy_n *nphy = phy->n;
 
-               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
-                       b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
+       if (enable) {
+               static const u16 clip[] = { 0xFFFF, 0xFFFF };
+               if (nphy->deaf_count++ == 0) {
+                       nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
+                       b43_nphy_classifier(dev, 0x7, 0);
+                       b43_nphy_read_clip_detection(dev, nphy->clip_state);
+                       b43_nphy_write_clip_detection(dev, clip);
+               }
+               b43_nphy_reset_cca(dev);
        } else {
-               b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
-                                   nphy->adj_pwr_tbl);
-               b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
-                                   nphy->adj_pwr_tbl);
-
-               bmask = B43_NPHY_TXPCTL_CMD_COEFF |
-                       B43_NPHY_TXPCTL_CMD_HWPCTLEN;
-               /* wl does useless check for "enable" param here */
-               val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
-               if (dev->phy.rev >= 3) {
-                       bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
-                       if (val)
-                               val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
-               }
-               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
-
-               if (band == IEEE80211_BAND_5GHZ) {
-                       b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
-                                       ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
-                       if (dev->phy.rev > 1)
-                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
-                                               ~B43_NPHY_TXPCTL_INIT_PIDXI1,
-                                               0x64);
-               }
-
-               if (dev->phy.rev >= 3) {
-                       if (nphy->tx_pwr_idx[0] != 128 &&
-                           nphy->tx_pwr_idx[1] != 128) {
-                               /* Recover TX pwr ctl state */
-                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
-                                               ~B43_NPHY_TXPCTL_CMD_INIT,
-                                               nphy->tx_pwr_idx[0]);
-                               if (dev->phy.rev > 1)
-                                       b43_phy_maskset(dev,
-                                               B43_NPHY_TXPCTL_INIT,
-                                               ~0xff, nphy->tx_pwr_idx[1]);
-                       }
-               }
-
-               if (dev->phy.rev >= 3) {
-                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
-                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
-               } else {
-                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
-               }
-
-               if (dev->phy.rev == 2)
-                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
-               else if (dev->phy.rev < 2)
-                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
-
-               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
-                       b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
-
-               if (b43_nphy_ipa(dev)) {
-                       b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
-                       b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
+               if (--nphy->deaf_count == 0) {
+                       b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
+                       b43_nphy_write_clip_detection(dev, nphy->clip_state);
                }
        }
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
-static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
+static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-       struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
-       u8 txpi[2], bbmult, i;
-       u16 tmp, radio_gain, dac_gain;
-       u16 freq = dev->phy.channel_freq;
-       u32 txgain;
-       /* u32 gaintbl; rev3+ */
+       u8 i;
+       s16 tmp;
+       u16 data[4];
+       s16 gain[2];
+       u16 minmax[2];
+       static const u16 lna_gain[4] = { -2, 10, 19, 25 };
 
        if (nphy->hang_avoid)
                b43_nphy_stay_in_carrier_search(dev, 1);
 
-       if (dev->phy.rev >= 7) {
-               txpi[0] = txpi[1] = 30;
-       } else if (dev->phy.rev >= 3) {
-               txpi[0] = 40;
-               txpi[1] = 40;
-       } else if (sprom->revision < 4) {
-               txpi[0] = 72;
-               txpi[1] = 72;
-       } else {
+       if (nphy->gain_boost) {
                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-                       txpi[0] = sprom->txpid2g[0];
-                       txpi[1] = sprom->txpid2g[1];
-               } else if (freq >= 4900 && freq < 5100) {
-                       txpi[0] = sprom->txpid5gl[0];
-                       txpi[1] = sprom->txpid5gl[1];
-               } else if (freq >= 5100 && freq < 5500) {
-                       txpi[0] = sprom->txpid5g[0];
-                       txpi[1] = sprom->txpid5g[1];
-               } else if (freq >= 5500) {
-                       txpi[0] = sprom->txpid5gh[0];
-                       txpi[1] = sprom->txpid5gh[1];
+                       gain[0] = 6;
+                       gain[1] = 6;
                } else {
-                       txpi[0] = 91;
-                       txpi[1] = 91;
+                       tmp = 40370 - 315 * dev->phy.channel;
+                       gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
+                       tmp = 23242 - 224 * dev->phy.channel;
+                       gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
                }
+       } else {
+               gain[0] = 0;
+               gain[1] = 0;
        }
-       if (dev->phy.rev < 7 &&
-           (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10))
-               txpi[0] = txpi[1] = 91;
-
-       /*
-       for (i = 0; i < 2; i++) {
-               nphy->txpwrindex[i].index_internal = txpi[i];
-               nphy->txpwrindex[i].index_internal_save = txpi[i];
-       }
-       */
 
        for (i = 0; i < 2; i++) {
-               if (dev->phy.rev >= 3) {
-                       if (b43_nphy_ipa(dev)) {
-                               txgain = *(b43_nphy_get_ipa_gain_table(dev) +
-                                               txpi[i]);
-                       } else if (b43_current_band(dev->wl) ==
-                                  IEEE80211_BAND_5GHZ) {
-                               /* FIXME: use 5GHz tables */
-                               txgain =
-                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
-                       } else {
-                               if (dev->phy.rev >= 5 &&
-                                   sprom->fem.ghz5.extpa_gain == 3)
-                                       ; /* FIXME: 5GHz_txgain_HiPwrEPA */
-                               txgain =
-                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
-                       }
-                       radio_gain = (txgain >> 16) & 0x1FFFF;
-               } else {
-                       txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
-                       radio_gain = (txgain >> 16) & 0x1FFF;
-               }
-
-               if (dev->phy.rev >= 7)
-                       dac_gain = (txgain >> 8) & 0x7;
-               else
-                       dac_gain = (txgain >> 8) & 0x3F;
-               bbmult = txgain & 0xFF;
-
-               if (dev->phy.rev >= 3) {
-                       if (i == 0)
-                               b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
-                       else
-                               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+               if (nphy->elna_gain_config) {
+                       data[0] = 19 + gain[i];
+                       data[1] = 25 + gain[i];
+                       data[2] = 25 + gain[i];
+                       data[3] = 25 + gain[i];
                } else {
-                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+                       data[0] = lna_gain[0] + gain[i];
+                       data[1] = lna_gain[1] + gain[i];
+                       data[2] = lna_gain[2] + gain[i];
+                       data[3] = lna_gain[3] + gain[i];
                }
+               b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
 
-               if (i == 0)
-                       b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
-               else
-                       b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
-
-               b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
-
-               tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
-               if (i == 0)
-                       tmp = (tmp & 0x00FF) | (bbmult << 8);
-               else
-                       tmp = (tmp & 0xFF00) | bbmult;
-               b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
-
-               if (b43_nphy_ipa(dev)) {
-                       u32 tmp32;
-                       u16 reg = (i == 0) ?
-                               B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
-                       tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
-                                                             576 + txpi[i]));
-                       b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
-                       b43_phy_set(dev, reg, 0x4);
-               }
+               minmax[i] = 23 + gain[i];
        }
 
-       b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
+       b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
+                               minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
+       b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
+                               minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
 
        if (nphy->hang_avoid)
                b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
+static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
+                                       u8 *events, u8 *delays, u8 length)
 {
-       struct b43_phy *phy = &dev->phy;
-
-       const u32 *table = NULL;
-#if 0
-       TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
-       u32 rfpwr_offset;
-       u8 pga_gain;
-       int i;
-#endif
+       struct b43_phy_n *nphy = dev->phy.n;
+       u8 i;
+       u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
+       u16 offset1 = cmd << 4;
+       u16 offset2 = offset1 + 0x80;
 
-       if (phy->rev >= 3) {
-               if (b43_nphy_ipa(dev)) {
-                       table = b43_nphy_get_ipa_gain_table(dev);
-               } else {
-                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-                               if (phy->rev == 3)
-                                       table = b43_ntab_tx_gain_rev3_5ghz;
-                               if (phy->rev == 4)
-                                       table = b43_ntab_tx_gain_rev4_5ghz;
-                               else
-                                       table = b43_ntab_tx_gain_rev5plus_5ghz;
-                       } else {
-                               table = b43_ntab_tx_gain_rev3plus_2ghz;
-                       }
-               }
-       } else {
-               table = b43_ntab_tx_gain_rev0_1_2;
-       }
-       b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
-       b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, true);
 
-       if (phy->rev >= 3) {
-#if 0
-               nphy->gmval = (table[0] >> 16) & 0x7000;
+       b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
+       b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
 
-               for (i = 0; i < 128; i++) {
-                       pga_gain = (table[i] >> 24) & 0xF;
-                       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
-                       else
-                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
-                       b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
-                                      rfpwr_offset);
-                       b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
-                                      rfpwr_offset);
-               }
-#endif
+       for (i = length; i < 16; i++) {
+               b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
+               b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
        }
+
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, false);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
-static void b43_radio_2055_setup(struct b43_wldev *dev,
-                               const struct b43_nphy_channeltab_entry_rev2 *e)
-{
-       B43_WARN_ON(dev->phy.rev >= 3);
-
-       b43_chantab_radio_upload(dev, e);
-       udelay(50);
-       b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
-       b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
-       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
-       b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
-       udelay(300);
-}
+/**************************************************
+ * Radio 0x2056
+ **************************************************/
 
-static void b43_radio_init2055_pre(struct b43_wldev *dev)
+static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
+                               const struct b43_nphy_channeltab_entry_rev3 *e)
 {
-       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
-                    ~B43_NPHY_RFCTL_CMD_PORFORCE);
-       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                   B43_NPHY_RFCTL_CMD_CHIP0PU |
-                   B43_NPHY_RFCTL_CMD_OEPORFORCE);
-       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                   B43_NPHY_RFCTL_CMD_PORFORCE);
+       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
+       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
+       b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
+       b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
+       b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
+       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
+                                       e->radio_syn_pll_loopfilter1);
+       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
+                                       e->radio_syn_pll_loopfilter2);
+       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
+                                       e->radio_syn_pll_loopfilter3);
+       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
+                                       e->radio_syn_pll_loopfilter4);
+       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
+                                       e->radio_syn_pll_loopfilter5);
+       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
+                                       e->radio_syn_reserved_addr27);
+       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
+                                       e->radio_syn_reserved_addr28);
+       b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
+                                       e->radio_syn_reserved_addr29);
+       b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
+                                       e->radio_syn_logen_vcobuf1);
+       b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
+       b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
+       b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
+                                       e->radio_rx0_lnaa_tune);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
+                                       e->radio_rx0_lnag_tune);
+
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
+                                       e->radio_tx0_intpaa_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
+                                       e->radio_tx0_intpag_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
+                                       e->radio_tx0_pada_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
+                                       e->radio_tx0_padg_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
+                                       e->radio_tx0_pgaa_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
+                                       e->radio_tx0_pgag_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
+                                       e->radio_tx0_mixa_boost_tune);
+       b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
+                                       e->radio_tx0_mixg_boost_tune);
+
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
+                                       e->radio_rx1_lnaa_tune);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
+                                       e->radio_rx1_lnag_tune);
+
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
+                                       e->radio_tx1_intpaa_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
+                                       e->radio_tx1_intpag_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
+                                       e->radio_tx1_pada_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
+                                       e->radio_tx1_padg_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
+                                       e->radio_tx1_pgaa_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
+                                       e->radio_tx1_pgag_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
+                                       e->radio_tx1_mixa_boost_tune);
+       b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
+                                       e->radio_tx1_mixg_boost_tune);
 }
 
-static void b43_radio_init2055_post(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
+static void b43_radio_2056_setup(struct b43_wldev *dev,
+                               const struct b43_nphy_channeltab_entry_rev3 *e)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
        struct ssb_sprom *sprom = dev->dev->bus_sprom;
-       int i;
-       u16 val;
-       bool workaround = false;
+       enum ieee80211_band band = b43_current_band(dev->wl);
+       u16 offset;
+       u8 i;
+       u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
 
-       if (sprom->revision < 4)
-               workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
-                             && dev->dev->board_type == 0x46D
-                             && dev->dev->board_rev >= 0x41);
-       else
-               workaround =
-                       !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
+       B43_WARN_ON(dev->phy.rev < 3);
 
-       b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
-       if (workaround) {
-               b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
-               b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
-       }
-       b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
-       b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
-       b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
-       b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
-       b43_radio_set(dev, B2055_CAL_MISC, 0x1);
-       msleep(1);
-       b43_radio_set(dev, B2055_CAL_MISC, 0x40);
-       for (i = 0; i < 200; i++) {
-               val = b43_radio_read(dev, B2055_CAL_COUT2);
-               if (val & 0x80) {
-                       i = 0;
-                       break;
+       b43_chantab_radio_2056_upload(dev, e);
+       b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
+
+       if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+           b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+               if (dev->dev->chip_id == 0x4716) {
+                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
+                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
+               } else {
+                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
+                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
                }
-               udelay(10);
        }
-       if (i)
-               b43err(dev->wl, "radio post init timeout\n");
-       b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
-       b43_switch_channel(dev, dev->phy.channel);
-       b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
-       b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
-       b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
-       b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
-       b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
-       b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
-       if (!nphy->gain_boost) {
-               b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
-               b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
-       } else {
-               b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
-               b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
+       if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+           b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
+               b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
        }
-       udelay(2);
-}
 
-/*
- * Initialize a Broadcom 2055 N-radio
- * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
- */
-static void b43_radio_init2055(struct b43_wldev *dev)
-{
-       b43_radio_init2055_pre(dev);
-       if (b43_status(dev) < B43_STAT_INITIALIZED) {
-               /* Follow wl, not specs. Do not force uploading all regs */
-               b2055_upload_inittab(dev, 0, 0);
-       } else {
-               bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
-               b2055_upload_inittab(dev, ghz5, 0);
+       if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
+               for (i = 0; i < 2; i++) {
+                       offset = i ? B2056_TX1 : B2056_TX0;
+                       if (dev->phy.rev >= 5) {
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PADG_IDAC, 0xcc);
+
+                               if (dev->dev->chip_id == 0x4716) {
+                                       bias = 0x40;
+                                       cbias = 0x45;
+                                       pag_boost = 0x5;
+                                       pgag_boost = 0x33;
+                                       mixg_boost = 0x55;
+                               } else {
+                                       bias = 0x25;
+                                       cbias = 0x20;
+                                       pag_boost = 0x4;
+                                       pgag_boost = 0x03;
+                                       mixg_boost = 0x65;
+                               }
+                               padg_boost = 0x77;
+
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IAUX_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_CASCBIAS,
+                                       cbias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_BOOST_TUNE,
+                                       pag_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PGAG_BOOST_TUNE,
+                                       pgag_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PADG_BOOST_TUNE,
+                                       padg_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_MIXG_BOOST_TUNE,
+                                       mixg_boost);
+                       } else {
+                               bias = dev->phy.is_40mhz ? 0x40 : 0x20;
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IAUX_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_CASCBIAS,
+                                       0x30);
+                       }
+                       b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
+               }
+       } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
+               /* TODO */
        }
-       b43_radio_init2055_post(dev);
+
+       udelay(50);
+       /* VCO calibration */
+       b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
+       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
+       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+       b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
+       udelay(300);
 }
 
 static void b43_radio_init2056_pre(struct b43_wldev *dev)
@@ -771,830 +693,1013 @@ static void b43_radio_init2056(struct b43_wldev *dev)
        b43_radio_init2056_post(dev);
 }
 
-/*
- * Upload the N-PHY tables.
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
- */
-static void b43_nphy_tables_init(struct b43_wldev *dev)
+/**************************************************
+ * Radio 0x2055
+ **************************************************/
+
+static void b43_chantab_radio_upload(struct b43_wldev *dev,
+                               const struct b43_nphy_channeltab_entry_rev2 *e)
 {
-       if (dev->phy.rev < 3)
-               b43_nphy_rev0_1_2_tables_init(dev);
-       else
-               b43_nphy_rev3plus_tables_init(dev);
-}
+       b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
+       b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
+       b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
+       b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
-static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
-{
-       struct b43_phy_n *nphy = dev->phy.n;
-       enum ieee80211_band band;
-       u16 tmp;
+       b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
+       b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
+       b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
+       b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 
-       if (!enable) {
-               nphy->rfctrl_intc1_save = b43_phy_read(dev,
-                                                      B43_NPHY_RFCTL_INTC1);
-               nphy->rfctrl_intc2_save = b43_phy_read(dev,
-                                                      B43_NPHY_RFCTL_INTC2);
-               band = b43_current_band(dev->wl);
-               if (dev->phy.rev >= 3) {
-                       if (band == IEEE80211_BAND_5GHZ)
-                               tmp = 0x600;
-                       else
-                               tmp = 0x480;
-               } else {
-                       if (band == IEEE80211_BAND_5GHZ)
-                               tmp = 0x180;
-                       else
-                               tmp = 0x120;
-               }
-               b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
-               b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
-       } else {
-               b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
-                               nphy->rfctrl_intc1_save);
-               b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
-                               nphy->rfctrl_intc2_save);
-       }
-}
+       b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
+       b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
+       b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
+       b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
-static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
-{
-       u16 tmp;
+       b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
+       b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
+       b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
+       b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 
-       if (dev->phy.rev >= 3) {
-               if (b43_nphy_ipa(dev)) {
-                       tmp = 4;
-                       b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
-                             (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
-               }
+       b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
+       b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
+       b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
+       b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 
-               tmp = 1;
-               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
-                             (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
-       }
+       b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
+       b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
-static void b43_nphy_reset_cca(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
+static void b43_radio_2055_setup(struct b43_wldev *dev,
+                               const struct b43_nphy_channeltab_entry_rev2 *e)
 {
-       u16 bbcfg;
+       B43_WARN_ON(dev->phy.rev >= 3);
 
-       b43_phy_force_clock(dev, 1);
-       bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
-       b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
-       udelay(1);
-       b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
-       b43_phy_force_clock(dev, 0);
-       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+       b43_chantab_radio_upload(dev, e);
+       udelay(50);
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
+       b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+       b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
+       udelay(300);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
-static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
+static void b43_radio_init2055_pre(struct b43_wldev *dev)
 {
-       u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
-
-       mimocfg |= B43_NPHY_MIMOCFG_AUTO;
-       if (preamble == 1)
-               mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
-       else
-               mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
-
-       b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
+       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+                    ~B43_NPHY_RFCTL_CMD_PORFORCE);
+       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                   B43_NPHY_RFCTL_CMD_CHIP0PU |
+                   B43_NPHY_RFCTL_CMD_OEPORFORCE);
+       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                   B43_NPHY_RFCTL_CMD_PORFORCE);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
-static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
+static void b43_radio_init2055_post(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-
-       bool override = false;
-       u16 chain = 0x33;
-
-       if (nphy->txrx_chain == 0) {
-               chain = 0x11;
-               override = true;
-       } else if (nphy->txrx_chain == 1) {
-               chain = 0x22;
-               override = true;
-       }
-
-       b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
-                       ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
-                       chain);
-
-       if (override)
-               b43_phy_set(dev, B43_NPHY_RFSEQMODE,
-                               B43_NPHY_RFSEQMODE_CAOVER);
-       else
-               b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
-                               ~B43_NPHY_RFSEQMODE_CAOVER);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
-static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
-                               u16 samps, u8 time, bool wait)
-{
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
        int i;
-       u16 tmp;
+       u16 val;
+       bool workaround = false;
 
-       b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
-       b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
-       if (wait)
-               b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
+       if (sprom->revision < 4)
+               workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+                             && dev->dev->board_type == 0x46D
+                             && dev->dev->board_rev >= 0x41);
        else
-               b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
-
-       b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
-
-       for (i = 1000; i; i--) {
-               tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
-               if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
-                       est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
-                       est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
-                       est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
+               workaround =
+                       !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
 
-                       est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
-                       est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
-                       est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
-                                       b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
-                       return;
+       b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
+       if (workaround) {
+               b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
+               b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
+       }
+       b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
+       b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
+       b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
+       b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
+       b43_radio_set(dev, B2055_CAL_MISC, 0x1);
+       msleep(1);
+       b43_radio_set(dev, B2055_CAL_MISC, 0x40);
+       for (i = 0; i < 200; i++) {
+               val = b43_radio_read(dev, B2055_CAL_COUT2);
+               if (val & 0x80) {
+                       i = 0;
+                       break;
                }
                udelay(10);
        }
-       memset(est, 0, sizeof(*est));
+       if (i)
+               b43err(dev->wl, "radio post init timeout\n");
+       b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
+       b43_switch_channel(dev, dev->phy.channel);
+       b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
+       b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
+       b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
+       b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
+       b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
+       b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
+       if (!nphy->gain_boost) {
+               b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
+               b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
+       } else {
+               b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
+               b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
+       }
+       udelay(2);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
-static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
-                                       struct b43_phy_n_iq_comp *pcomp)
+/*
+ * Initialize a Broadcom 2055 N-radio
+ * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
+ */
+static void b43_radio_init2055(struct b43_wldev *dev)
 {
-       if (write) {
-               b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
-               b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
-               b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
-               b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
+       b43_radio_init2055_pre(dev);
+       if (b43_status(dev) < B43_STAT_INITIALIZED) {
+               /* Follow wl, not specs. Do not force uploading all regs */
+               b2055_upload_inittab(dev, 0, 0);
        } else {
-               pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
-               pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
-               pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
-               pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
+               bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
+               b2055_upload_inittab(dev, ghz5, 0);
        }
+       b43_radio_init2055_post(dev);
 }
 
-#if 0
-/* Ready but not used anywhere */
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
-static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
-{
-       u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+/**************************************************
+ * Samples
+ **************************************************/
 
-       b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
-       if (core == 0) {
-               b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
-       } else {
-               b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
-       }
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
-       b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
-       b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
-       b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
-       b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
-       b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
-       b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
+static int b43_nphy_load_samples(struct b43_wldev *dev,
+                                       struct b43_c32 *samples, u16 len) {
+       struct b43_phy_n *nphy = dev->phy.n;
+       u16 i;
+       u32 *data;
+
+       data = kzalloc(len * sizeof(u32), GFP_KERNEL);
+       if (!data) {
+               b43err(dev->wl, "allocation for samples loading failed\n");
+               return -ENOMEM;
+       }
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 1);
+
+       for (i = 0; i < len; i++) {
+               data[i] = (samples[i].i & 0x3FF << 10);
+               data[i] |= samples[i].q & 0x3FF;
+       }
+       b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
+
+       kfree(data);
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 0);
+       return 0;
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
-static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
+static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
+                                       bool test)
 {
-       u8 rxval, txval;
-       u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+       int i;
+       u16 bw, len, rot, angle;
+       struct b43_c32 *samples;
 
-       regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
-       if (core == 0) {
-               regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
-               regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
-       } else {
-               regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
-               regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
-       }
-       regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
-       regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
-       regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
-       regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
-       regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
-       regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
-       regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
-       regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
 
-       b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
-       b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
+       bw = (dev->phy.is_40mhz) ? 40 : 20;
+       len = bw << 3;
 
-       b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
-                       ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
-                       ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
-       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
-                       ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
-       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
-                       (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
-       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
-                       (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
+       if (test) {
+               if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
+                       bw = 82;
+               else
+                       bw = 80;
 
-       if (core == 0) {
-               b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
-               b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
-       } else {
-               b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
-               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
+               if (dev->phy.is_40mhz)
+                       bw <<= 1;
+
+               len = bw << 1;
        }
 
-       b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
-       b43_nphy_rf_control_override(dev, 8, 0, 3, false);
-       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+       samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
+       if (!samples) {
+               b43err(dev->wl, "allocation for samples generation failed\n");
+               return 0;
+       }
+       rot = (((freq * 36) / bw) << 16) / 100;
+       angle = 0;
 
-       if (core == 0) {
-               rxval = 1;
-               txval = 8;
-       } else {
-               rxval = 4;
-               txval = 2;
+       for (i = 0; i < len; i++) {
+               samples[i] = b43_cordic(angle);
+               angle += rot;
+               samples[i].q = CORDIC_CONVERT(samples[i].q * max);
+               samples[i].i = CORDIC_CONVERT(samples[i].i * max);
        }
-       b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
-       b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
+
+       i = b43_nphy_load_samples(dev, samples, len);
+       kfree(samples);
+       return (i < 0) ? 0 : len;
 }
-#endif
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
-static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
+static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
+                                       u16 wait, bool iqmode, bool dac_test)
 {
+       struct b43_phy_n *nphy = dev->phy.n;
        int i;
-       s32 iq;
-       u32 ii;
-       u32 qq;
-       int iq_nbits, qq_nbits;
-       int arsh, brsh;
-       u16 tmp, a, b;
+       u16 seq_mode;
+       u32 tmp;
 
-       struct nphy_iq_est est;
-       struct b43_phy_n_iq_comp old;
-       struct b43_phy_n_iq_comp new = { };
-       bool error = false;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, true);
 
-       if (mask == 0)
-               return;
+       if ((nphy->bb_mult_save & 0x80000000) == 0) {
+               tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
+               nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
+       }
 
-       b43_nphy_rx_iq_coeffs(dev, false, &old);
-       b43_nphy_rx_iq_coeffs(dev, true, &new);
-       b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
-       new = old;
+       if (!dev->phy.is_40mhz)
+               tmp = 0x6464;
+       else
+               tmp = 0x4747;
+       b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
 
-       for (i = 0; i < 2; i++) {
-               if (i == 0 && (mask & 1)) {
-                       iq = est.iq0_prod;
-                       ii = est.i0_pwr;
-                       qq = est.q0_pwr;
-               } else if (i == 1 && (mask & 2)) {
-                       iq = est.iq1_prod;
-                       ii = est.i1_pwr;
-                       qq = est.q1_pwr;
-               } else {
-                       continue;
-               }
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, false);
 
-               if (ii + qq < 2) {
-                       error = true;
-                       break;
-               }
+       b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
 
-               iq_nbits = fls(abs(iq));
-               qq_nbits = fls(qq);
+       if (loops != 0xFFFF)
+               b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
+       else
+               b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
 
-               arsh = iq_nbits - 20;
-               if (arsh >= 0) {
-                       a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
-                       tmp = ii >> arsh;
-               } else {
-                       a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
-                       tmp = ii << -arsh;
-               }
-               if (tmp == 0) {
-                       error = true;
-                       break;
-               }
-               a /= tmp;
+       b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
 
-               brsh = qq_nbits - 11;
-               if (brsh >= 0) {
-                       b = (qq << (31 - qq_nbits));
-                       tmp = ii >> brsh;
-               } else {
-                       b = (qq << (31 - qq_nbits));
-                       tmp = ii << -brsh;
-               }
-               if (tmp == 0) {
-                       error = true;
-                       break;
-               }
-               b = int_sqrt(b / tmp - a * a) - (1 << 10);
+       seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
 
-               if (i == 0 && (mask & 0x1)) {
-                       if (dev->phy.rev >= 3) {
-                               new.a0 = a & 0x3FF;
-                               new.b0 = b & 0x3FF;
-                       } else {
-                               new.a0 = b & 0x3FF;
-                               new.b0 = a & 0x3FF;
-                       }
-               } else if (i == 1 && (mask & 0x2)) {
-                       if (dev->phy.rev >= 3) {
-                               new.a1 = a & 0x3FF;
-                               new.b1 = b & 0x3FF;
-                       } else {
-                               new.a1 = b & 0x3FF;
-                               new.b1 = a & 0x3FF;
-                       }
+       b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
+       if (iqmode) {
+               b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
+               b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
+       } else {
+               if (dac_test)
+                       b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
+               else
+                       b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
+       }
+       for (i = 0; i < 100; i++) {
+               if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
+                       i = 0;
+                       break;
                }
+               udelay(10);
        }
+       if (i)
+               b43err(dev->wl, "run samples timeout\n");
 
-       if (error)
-               new = old;
-
-       b43_nphy_rx_iq_coeffs(dev, true, &new);
+       b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
-static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
+/**************************************************
+ * RSSI
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
+static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
+                                       s8 offset, u8 core, u8 rail,
+                                       enum b43_nphy_rssi_type type)
 {
-       u16 array[4];
-       b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
+       u16 tmp;
+       bool core1or5 = (core == 1) || (core == 5);
+       bool core2or5 = (core == 2) || (core == 5);
 
-       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
-       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
-       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
-       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
-}
+       offset = clamp_val(offset, -32, 31);
+       tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
-static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
-                                         const u16 *clip_st)
-{
-       b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
-       b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
-}
+       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
+       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
+       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
+       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
-static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
-{
-       clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
-       clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
-}
+       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
+       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
+       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
+       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
-static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
-{
-       if (dev->phy.rev >= 3) {
-               if (!init)
-                       return;
-               if (0 /* FIXME */) {
-                       b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
-                       b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
-                       b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
-                       b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
-               }
-       } else {
-               b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
-               b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
+       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
+       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
+       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
+       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
 
-               switch (dev->dev->bus_type) {
-#ifdef CONFIG_B43_BCMA
-               case B43_BUS_BCMA:
-                       bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
-                                                0xFC00, 0xFC00);
-                       break;
-#endif
-#ifdef CONFIG_B43_SSB
-               case B43_BUS_SSB:
-                       ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
-                                               0xFC00, 0xFC00);
-                       break;
-#endif
-               }
+       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
+       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
+       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
+       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
 
-               b43_write32(dev, B43_MMIO_MACCTL,
-                       b43_read32(dev, B43_MMIO_MACCTL) &
-                       ~B43_MACCTL_GPOUTSMSK);
-               b43_write16(dev, B43_MMIO_GPIO_MASK,
-                       b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
-               b43_write16(dev, B43_MMIO_GPIO_CONTROL,
-                       b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
+       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
+       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
+       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
+       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
 
-               if (init) {
-                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
-                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
-                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
-                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
-               }
-       }
+       if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
+       if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
+
+       if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
+       if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
+               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
-static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
+static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
 {
-       u16 tmp;
+       u8 i;
+       u16 reg, val;
 
-       if (dev->dev->core_rev == 16)
-               b43_mac_suspend(dev);
+       if (code == 0) {
+               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
+               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
+               b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
+               b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
+               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
+               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
+               b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
+               b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
+       } else {
+               for (i = 0; i < 2; i++) {
+                       if ((code == 1 && i == 1) || (code == 2 && !i))
+                               continue;
 
-       tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
-       tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
-               B43_NPHY_CLASSCTL_WAITEDEN);
-       tmp &= ~mask;
-       tmp |= (val & mask);
-       b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
+                       reg = (i == 0) ?
+                               B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
+                       b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
 
-       if (dev->dev->core_rev == 16)
-               b43_mac_enable(dev);
+                       if (type < 3) {
+                               reg = (i == 0) ?
+                                       B43_NPHY_AFECTL_C1 :
+                                       B43_NPHY_AFECTL_C2;
+                               b43_phy_maskset(dev, reg, 0xFCFF, 0);
 
-       return tmp;
-}
+                               reg = (i == 0) ?
+                                       B43_NPHY_RFCTL_LUT_TRSW_UP1 :
+                                       B43_NPHY_RFCTL_LUT_TRSW_UP2;
+                               b43_phy_maskset(dev, reg, 0xFFC3, 0);
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
-static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
-{
-       struct b43_phy *phy = &dev->phy;
-       struct b43_phy_n *nphy = phy->n;
+                               if (type == 0)
+                                       val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
+                               else if (type == 1)
+                                       val = 16;
+                               else
+                                       val = 32;
+                               b43_phy_set(dev, reg, val);
 
-       if (enable) {
-               static const u16 clip[] = { 0xFFFF, 0xFFFF };
-               if (nphy->deaf_count++ == 0) {
-                       nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
-                       b43_nphy_classifier(dev, 0x7, 0);
-                       b43_nphy_read_clip_detection(dev, nphy->clip_state);
-                       b43_nphy_write_clip_detection(dev, clip);
-               }
-               b43_nphy_reset_cca(dev);
-       } else {
-               if (--nphy->deaf_count == 0) {
-                       b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
-                       b43_nphy_write_clip_detection(dev, nphy->clip_state);
-               }
-       }
-}
+                               reg = (i == 0) ?
+                                       B43_NPHY_TXF_40CO_B1S0 :
+                                       B43_NPHY_TXF_40CO_B32S1;
+                               b43_phy_set(dev, reg, 0x0020);
+                       } else {
+                               if (type == 6)
+                                       val = 0x0100;
+                               else if (type == 3)
+                                       val = 0x0200;
+                               else
+                                       val = 0x0300;
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
-static void b43_nphy_stop_playback(struct b43_wldev *dev)
-{
-       struct b43_phy_n *nphy = dev->phy.n;
-       u16 tmp;
+                               reg = (i == 0) ?
+                                       B43_NPHY_AFECTL_C1 :
+                                       B43_NPHY_AFECTL_C2;
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
+                               b43_phy_maskset(dev, reg, 0xFCFF, val);
+                               b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
 
-       tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
-       if (tmp & 0x1)
-               b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
-       else if (tmp & 0x2)
-               b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
+                               if (type != 3 && type != 6) {
+                                       enum ieee80211_band band =
+                                               b43_current_band(dev->wl);
 
-       b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
+                                       if (b43_nphy_ipa(dev))
+                                               val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
+                                       else
+                                               val = 0x11;
+                                       reg = (i == 0) ? 0x2000 : 0x3000;
+                                       reg |= B2055_PADDRV;
+                                       b43_radio_write16(dev, reg, val);
 
-       if (nphy->bb_mult_save & 0x80000000) {
-               tmp = nphy->bb_mult_save & 0xFFFF;
-               b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
-               nphy->bb_mult_save = 0;
+                                       reg = (i == 0) ?
+                                               B43_NPHY_AFECTL_OVER1 :
+                                               B43_NPHY_AFECTL_OVER;
+                                       b43_phy_set(dev, reg, 0x0200);
+                               }
+                       }
+               }
        }
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
-static void b43_nphy_spur_workaround(struct b43_wldev *dev)
+static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
-
-       u8 channel = dev->phy.channel;
-       int tone[2] = { 57, 58 };
-       u32 noise[2] = { 0x3FF, 0x3FF };
+       u16 val;
 
-       B43_WARN_ON(dev->phy.rev < 3);
+       if (type < 3)
+               val = 0;
+       else if (type == 6)
+               val = 1;
+       else if (type == 3)
+               val = 2;
+       else
+               val = 3;
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
+       val = (val << 12) | (val << 14);
+       b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
+       b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
 
-       if (nphy->gband_spurwar_en) {
-               /* TODO: N PHY Adjust Analog Pfbw (7) */
-               if (channel == 11 && dev->phy.is_40mhz)
-                       ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
-               else
-                       ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
-               /* TODO: N PHY Adjust CRS Min Power (0x1E) */
+       if (type < 3) {
+               b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
+                               (type + 1) << 4);
+               b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
+                               (type + 1) << 4);
        }
 
-       if (nphy->aband_spurwar_en) {
-               if (channel == 54) {
-                       tone[0] = 0x20;
-                       noise[0] = 0x25F;
-               } else if (channel == 38 || channel == 102 || channel == 118) {
-                       if (0 /* FIXME */) {
-                               tone[0] = 0x20;
-                               noise[0] = 0x21F;
-                       } else {
-                               tone[0] = 0;
-                               noise[0] = 0;
-                       }
-               } else if (channel == 134) {
-                       tone[0] = 0x20;
-                       noise[0] = 0x21F;
-               } else if (channel == 151) {
-                       tone[0] = 0x10;
-                       noise[0] = 0x23F;
-               } else if (channel == 153 || channel == 161) {
-                       tone[0] = 0x30;
-                       noise[0] = 0x23F;
-               } else {
-                       tone[0] = 0;
-                       noise[0] = 0;
+       if (code == 0) {
+               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
+               if (type < 3) {
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+                               ~(B43_NPHY_RFCTL_CMD_RXEN |
+                                 B43_NPHY_RFCTL_CMD_CORESEL));
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
+                               ~(0x1 << 12 |
+                                 0x1 << 5 |
+                                 0x1 << 1 |
+                                 0x1));
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+                               ~B43_NPHY_RFCTL_CMD_START);
+                       udelay(20);
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
+               }
+       } else {
+               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
+               if (type < 3) {
+                       b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
+                               ~(B43_NPHY_RFCTL_CMD_RXEN |
+                                 B43_NPHY_RFCTL_CMD_CORESEL),
+                               (B43_NPHY_RFCTL_CMD_RXEN |
+                                code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
+                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
+                               (0x1 << 12 |
+                                 0x1 << 5 |
+                                 0x1 << 1 |
+                                 0x1));
+                       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+                               B43_NPHY_RFCTL_CMD_START);
+                       udelay(20);
+                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
                }
-
-               if (!tone[0] && !noise[0])
-                       ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
-               else
-                       ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
        }
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
-static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
+static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
-
-       u8 i;
-       s16 tmp;
-       u16 data[4];
-       s16 gain[2];
-       u16 minmax[2];
-       static const u16 lna_gain[4] = { -2, 10, 19, 25 };
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
-
-       if (nphy->gain_boost) {
-               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-                       gain[0] = 6;
-                       gain[1] = 6;
-               } else {
-                       tmp = 40370 - 315 * dev->phy.channel;
-                       gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
-                       tmp = 23242 - 224 * dev->phy.channel;
-                       gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
-               }
-       } else {
-               gain[0] = 0;
-               gain[1] = 0;
-       }
+       if (dev->phy.rev >= 3)
+               b43_nphy_rev3_rssi_select(dev, code, type);
+       else
+               b43_nphy_rev2_rssi_select(dev, code, type);
+}
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
+static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
+{
+       int i;
        for (i = 0; i < 2; i++) {
-               if (nphy->elna_gain_config) {
-                       data[0] = 19 + gain[i];
-                       data[1] = 25 + gain[i];
-                       data[2] = 25 + gain[i];
-                       data[3] = 25 + gain[i];
+               if (type == 2) {
+                       if (i == 0) {
+                               b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
+                                                 0xFC, buf[0]);
+                               b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
+                                                 0xFC, buf[1]);
+                       } else {
+                               b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
+                                                 0xFC, buf[2 * i]);
+                               b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
+                                                 0xFC, buf[2 * i + 1]);
+                       }
                } else {
-                       data[0] = lna_gain[0] + gain[i];
-                       data[1] = lna_gain[1] + gain[i];
-                       data[2] = lna_gain[2] + gain[i];
-                       data[3] = lna_gain[3] + gain[i];
+                       if (i == 0)
+                               b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
+                                                 0xF3, buf[0] << 2);
+                       else
+                               b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
+                                                 0xF3, buf[2 * i + 1] << 2);
                }
-               b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
-
-               minmax[i] = 23 + gain[i];
        }
-
-       b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
-                               minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
-       b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
-                               minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
-static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
+static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
+                               u8 nsamp)
 {
-       struct b43_phy_n *nphy = dev->phy.n;
-       struct ssb_sprom *sprom = dev->dev->bus_sprom;
-
-       /* PHY rev 0, 1, 2 */
-       u8 i, j;
-       u8 code;
-       u16 tmp;
-       u8 rfseq_events[3] = { 6, 8, 7 };
-       u8 rfseq_delays[3] = { 10, 30, 1 };
-
-       /* PHY rev >= 3 */
-       bool ghz5;
-       bool ext_lna;
-       u16 rssi_gain;
-       struct nphy_gain_ctl_workaround_entry *e;
-       u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
-       u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
+       int i;
+       int out;
+       u16 save_regs_phy[9];
+       u16 s[2];
 
        if (dev->phy.rev >= 3) {
-               /* Prepare values */
-               ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
-                       & B43_NPHY_BANDCTL_5GHZ;
-               ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA;
-               e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
-               if (ghz5 && dev->phy.rev >= 5)
-                       rssi_gain = 0x90;
-               else
-                       rssi_gain = 0x50;
-
-               b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
-
-               /* Set Clip 2 detect */
-               b43_phy_set(dev, B43_NPHY_C1_CGAINI,
-                               B43_NPHY_C1_CGAINI_CL2DETECT);
-               b43_phy_set(dev, B43_NPHY_C2_CGAINI,
-                               B43_NPHY_C2_CGAINI_CL2DETECT);
-
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
-                               0x17);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
-                               0x17);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
-                               rssi_gain);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
-                               rssi_gain);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
-                               0x17);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
-                               0x17);
-               b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
-               b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
-
-               b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
-               b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
-               b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
-               b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
-               b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
-               b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
-
-               b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
-               b43_phy_write(dev, 0x2A7, e->init_gain);
-               b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
-                                       e->rfseq_init);
-               b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
-
-               /* TODO: check defines. Do not match variables names */
-               b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
-               b43_phy_write(dev, 0x2A9, e->cliphi_gain);
-               b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
-               b43_phy_write(dev, 0x2AB, e->clipmd_gain);
-               b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
-               b43_phy_write(dev, 0x2AD, e->cliplo_gain);
-
-               b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
-               b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
-               b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
-               b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
-               b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
-               b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
-                               ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
-               b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
-                               ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
-               b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+               save_regs_phy[0] = b43_phy_read(dev,
+                                               B43_NPHY_RFCTL_LUT_TRSW_UP1);
+               save_regs_phy[1] = b43_phy_read(dev,
+                                               B43_NPHY_RFCTL_LUT_TRSW_UP2);
+               save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+               save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+               save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
+               save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+               save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
+               save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
+               save_regs_phy[8] = 0;
        } else {
-               /* Set Clip 2 detect */
-               b43_phy_set(dev, B43_NPHY_C1_CGAINI,
-                               B43_NPHY_C1_CGAINI_CL2DETECT);
-               b43_phy_set(dev, B43_NPHY_C2_CGAINI,
-                               B43_NPHY_C2_CGAINI_CL2DETECT);
-
-               /* Set narrowband clip threshold */
-               b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
-               b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
-
-               if (!dev->phy.is_40mhz) {
-                       /* Set dwell lengths */
-                       b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
-                       b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
-                       b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
-                       b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
-               }
+               save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+               save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+               save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+               save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
+               save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
+               save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
+               save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
+               save_regs_phy[7] = 0;
+               save_regs_phy[8] = 0;
+       }
 
-               /* Set wideband clip 2 threshold */
-               b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
-                               ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
-                               21);
-               b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
-                               ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
-                               21);
-
-               if (!dev->phy.is_40mhz) {
-                       b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
-                               ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
-                       b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
-                               ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
-                       b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
-                               ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
-                       b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
-                               ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
-               }
+       b43_nphy_rssi_select(dev, 5, type);
 
-               b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+       if (dev->phy.rev < 2) {
+               save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
+               b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
+       }
 
-               if (nphy->gain_boost) {
-                       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
-                           dev->phy.is_40mhz)
-                               code = 4;
-                       else
-                               code = 5;
+       for (i = 0; i < 4; i++)
+               buf[i] = 0;
+
+       for (i = 0; i < nsamp; i++) {
+               if (dev->phy.rev < 2) {
+                       s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
+                       s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
                } else {
-                       code = dev->phy.is_40mhz ? 6 : 7;
+                       s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
+                       s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
                }
 
-               /* Set HPVGA2 index */
-               b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
-                               ~B43_NPHY_C1_INITGAIN_HPVGA2,
-                               code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
-               b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
-                               ~B43_NPHY_C2_INITGAIN_HPVGA2,
-                               code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
+               buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
+               buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
+               buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
+               buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
+       }
+       out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
+               (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
 
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
-               /* specs say about 2 loops, but wl does 4 */
-               for (i = 0; i < 4; i++)
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-                                                       (code << 8 | 0x7C));
+       if (dev->phy.rev < 2)
+               b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
 
-               b43_nphy_adjust_lna_gain_table(dev);
+       if (dev->phy.rev >= 3) {
+               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
+                               save_regs_phy[0]);
+               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
+                               save_regs_phy[1]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
+       } else {
+               b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
+               b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
+               b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
+               b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
+               b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
+       }
 
-               if (nphy->elna_gain_config) {
-                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-
-                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
-
-                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
-                       /* specs say about 2 loops, but wl does 4 */
-                       for (i = 0; i < 4; i++)
-                               b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-                                                       (code << 8 | 0x74));
-               }
+       return out;
+}
 
-               if (dev->phy.rev == 2) {
-                       for (i = 0; i < 4; i++) {
-                               b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
-                                               (0x0400 * i) + 0x0020);
-                               for (j = 0; j < 21; j++) {
-                                       tmp = j * (i < 2 ? 3 : 1);
-                                       b43_phy_write(dev,
-                                               B43_NPHY_TABLE_DATALO, tmp);
-                               }
-                       }
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
+static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
+{
+       int i, j;
+       u8 state[4];
+       u8 code, val;
+       u16 class, override;
+       u8 regs_save_radio[2];
+       u16 regs_save_phy[2];
+
+       s8 offset[4];
+       u8 core;
+       u8 rail;
+
+       u16 clip_state[2];
+       u16 clip_off[2] = { 0xFFFF, 0xFFFF };
+       s32 results_min[4] = { };
+       u8 vcm_final[4] = { };
+       s32 results[4][4] = { };
+       s32 miniq[4][2] = { };
+
+       if (type == 2) {
+               code = 0;
+               val = 6;
+       } else if (type < 2) {
+               code = 25;
+               val = 4;
+       } else {
+               B43_WARN_ON(1);
+               return;
+       }
+
+       class = b43_nphy_classifier(dev, 0, 0);
+       b43_nphy_classifier(dev, 7, 4);
+       b43_nphy_read_clip_detection(dev, clip_state);
+       b43_nphy_write_clip_detection(dev, clip_off);
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+               override = 0x140;
+       else
+               override = 0x110;
+
+       regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+       regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
+       b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
+
+       regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+       regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
+       b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
+
+       state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
+       state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
+       b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
+       b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
+       state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
+       state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
+
+       b43_nphy_rssi_select(dev, 5, type);
+       b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
+       b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
+
+       for (i = 0; i < 4; i++) {
+               u8 tmp[4];
+               for (j = 0; j < 4; j++)
+                       tmp[j] = i;
+               if (type != 1)
+                       b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
+               b43_nphy_poll_rssi(dev, type, results[i], 8);
+               if (type < 2)
+                       for (j = 0; j < 2; j++)
+                               miniq[i][j] = min(results[i][2 * j],
+                                               results[i][2 * j + 1]);
+       }
+
+       for (i = 0; i < 4; i++) {
+               s32 mind = 40;
+               u8 minvcm = 0;
+               s32 minpoll = 249;
+               s32 curr;
+               for (j = 0; j < 4; j++) {
+                       if (type == 2)
+                               curr = abs(results[j][i]);
+                       else
+                               curr = abs(miniq[j][i / 2] - code * 8);
+
+                       if (curr < mind) {
+                               mind = curr;
+                               minvcm = j;
+                       }
+
+                       if (results[j][i] < minpoll)
+                               minpoll = results[j][i];
                }
+               results_min[i] = minpoll;
+               vcm_final[i] = minvcm;
+       }
 
-               b43_nphy_set_rf_sequence(dev, 5,
-                               rfseq_events, rfseq_delays, 3);
-               b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
-                       ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
-                       0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
+       if (type != 1)
+               b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
 
-               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-                       b43_phy_maskset(dev, B43_PHY_N(0xC5D),
-                                       0xFF80, 4);
+       for (i = 0; i < 4; i++) {
+               offset[i] = (code * 8) - results[vcm_final[i]][i];
+
+               if (offset[i] < 0)
+                       offset[i] = -((abs(offset[i]) + 4) / 8);
+               else
+                       offset[i] = (offset[i] + 4) / 8;
+
+               if (results_min[i] == 248)
+                       offset[i] = code - 32;
+
+               core = (i / 2) ? 2 : 1;
+               rail = (i % 2) ? 1 : 0;
+
+               b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
+                                               type);
+       }
+
+       b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
+       b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
+
+       switch (state[2]) {
+       case 1:
+               b43_nphy_rssi_select(dev, 1, 2);
+               break;
+       case 4:
+               b43_nphy_rssi_select(dev, 1, 0);
+               break;
+       case 2:
+               b43_nphy_rssi_select(dev, 1, 1);
+               break;
+       default:
+               b43_nphy_rssi_select(dev, 1, 1);
+               break;
+       }
+
+       switch (state[3]) {
+       case 1:
+               b43_nphy_rssi_select(dev, 2, 2);
+               break;
+       case 4:
+               b43_nphy_rssi_select(dev, 2, 0);
+               break;
+       default:
+               b43_nphy_rssi_select(dev, 2, 1);
+               break;
+       }
+
+       b43_nphy_rssi_select(dev, 0, type);
+
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
+       b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
+       b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
+
+       b43_nphy_classifier(dev, 7, class);
+       b43_nphy_write_clip_detection(dev, clip_state);
+       /* Specs don't say about reset here, but it makes wl and b43 dumps
+          identical, it really seems wl performs this */
+       b43_nphy_reset_cca(dev);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
+static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
+{
+       /* TODO */
+}
+
+/*
+ * RSSI Calibration
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
+ */
+static void b43_nphy_rssi_cal(struct b43_wldev *dev)
+{
+       if (dev->phy.rev >= 3) {
+               b43_nphy_rev3_rssi_cal(dev);
+       } else {
+               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
+               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
+               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
+       }
+}
+
+/**************************************************
+ * Workarounds
+ **************************************************/
+
+static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
+{
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+       bool ghz5;
+       bool ext_lna;
+       u16 rssi_gain;
+       struct nphy_gain_ctl_workaround_entry *e;
+       u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
+       u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
+
+       /* Prepare values */
+       ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
+               & B43_NPHY_BANDCTL_5GHZ;
+       ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA;
+       e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
+       if (ghz5 && dev->phy.rev >= 5)
+               rssi_gain = 0x90;
+       else
+               rssi_gain = 0x50;
+
+       b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
+
+       /* Set Clip 2 detect */
+       b43_phy_set(dev, B43_NPHY_C1_CGAINI,
+                       B43_NPHY_C1_CGAINI_CL2DETECT);
+       b43_phy_set(dev, B43_NPHY_C2_CGAINI,
+                       B43_NPHY_C2_CGAINI_CL2DETECT);
+
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+                       0x17);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+                       0x17);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
+                       rssi_gain);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
+                       rssi_gain);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+                       0x17);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+                       0x17);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
+
+       b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
+       b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
+       b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
+       b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
+       b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
+       b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
+
+       b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+       b43_phy_write(dev, 0x2A7, e->init_gain);
+       b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
+                               e->rfseq_init);
+       b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+
+       /* TODO: check defines. Do not match variables names */
+       b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
+       b43_phy_write(dev, 0x2A9, e->cliphi_gain);
+       b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
+       b43_phy_write(dev, 0x2AB, e->clipmd_gain);
+       b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
+       b43_phy_write(dev, 0x2AD, e->cliplo_gain);
+
+       b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
+       b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
+       b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
+       b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
+       b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
+       b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+                       ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
+       b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+                       ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
+       b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
+
+       u8 i, j;
+       u8 code;
+       u16 tmp;
+       u8 rfseq_events[3] = { 6, 8, 7 };
+       u8 rfseq_delays[3] = { 10, 30, 1 };
+
+       /* Set Clip 2 detect */
+       b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
+       b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
+
+       /* Set narrowband clip threshold */
+       b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
+       b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
+
+       if (!dev->phy.is_40mhz) {
+               /* Set dwell lengths */
+               b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
+               b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
+               b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
+               b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
+       }
+
+       /* Set wideband clip 2 threshold */
+       b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+                       ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
+       b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+                       ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
+
+       if (!dev->phy.is_40mhz) {
+               b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
+                       ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
+               b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
+                       ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
+               b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
+                       ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
+               b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
+                       ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
+       }
+
+       b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+
+       if (nphy->gain_boost) {
+               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
+                       dev->phy.is_40mhz)
+                       code = 4;
+               else
+                       code = 5;
+       } else {
+               code = dev->phy.is_40mhz ? 6 : 7;
+       }
+
+       /* Set HPVGA2 index */
+       b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
+                       code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
+       b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
+                       code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
+
+       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
+       /* specs say about 2 loops, but wl does 4 */
+       for (i = 0; i < 4; i++)
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
+
+       b43_nphy_adjust_lna_gain_table(dev);
+
+       if (nphy->elna_gain_config) {
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+               b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
+               /* specs say about 2 loops, but wl does 4 */
+               for (i = 0; i < 4; i++)
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+                                               (code << 8 | 0x74));
+       }
+
+       if (dev->phy.rev == 2) {
+               for (i = 0; i < 4; i++) {
+                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+                                       (0x0400 * i) + 0x0020);
+                       for (j = 0; j < 21; j++) {
+                               tmp = j * (i < 2 ? 3 : 1);
+                               b43_phy_write(dev,
+                                       B43_NPHY_TABLE_DATALO, tmp);
+                       }
+               }
        }
+
+       b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
+       b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
+               ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
+               0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+               b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
+static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
+{
+       if (dev->phy.rev >= 3)
+               b43_nphy_gain_ctl_workarounds_rev3plus(dev);
+       else
+               b43_nphy_gain_ctl_workarounds_rev1_2(dev);
 }
 
 static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
@@ -1660,7 +1765,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
        b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
        b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
 
-       b43_nphy_gain_ctrl_workarounds(dev);
+       b43_nphy_gain_ctl_workarounds(dev);
 
        b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
        b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
@@ -1763,7 +1868,7 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
        b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
        b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
 
-       b43_nphy_gain_ctrl_workarounds(dev);
+       b43_nphy_gain_ctl_workarounds(dev);
 
        if (dev->phy.rev < 2) {
                if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
@@ -1823,984 +1928,811 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
                b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
-static int b43_nphy_load_samples(struct b43_wldev *dev,
-                                       struct b43_c32 *samples, u16 len) {
-       struct b43_phy_n *nphy = dev->phy.n;
-       u16 i;
-       u32 *data;
-
-       data = kzalloc(len * sizeof(u32), GFP_KERNEL);
-       if (!data) {
-               b43err(dev->wl, "allocation for samples loading failed\n");
-               return -ENOMEM;
-       }
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 1);
+/**************************************************
+ * Tx and Rx
+ **************************************************/
 
-       for (i = 0; i < len; i++) {
-               data[i] = (samples[i].i & 0x3FF << 10);
-               data[i] |= samples[i].q & 0x3FF;
-       }
-       b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
-
-       kfree(data);
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, 0);
-       return 0;
+void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
+{//TODO
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
-static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
-                                       bool test)
-{
-       int i;
-       u16 bw, len, rot, angle;
-       struct b43_c32 *samples;
-
+static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
+{//TODO
+}
 
-       bw = (dev->phy.is_40mhz) ? 40 : 20;
-       len = bw << 3;
+static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
+                                                       bool ignore_tssi)
+{//TODO
+       return B43_TXPWR_RES_DONE;
+}
 
-       if (test) {
-               if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
-                       bw = 82;
-               else
-                       bw = 80;
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
+static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
+       u8 i;
+       u16 bmask, val, tmp;
+       enum ieee80211_band band = b43_current_band(dev->wl);
 
-               if (dev->phy.is_40mhz)
-                       bw <<= 1;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 1);
 
-               len = bw << 1;
-       }
+       nphy->txpwrctrl = enable;
+       if (!enable) {
+               if (dev->phy.rev >= 3 &&
+                   (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
+                    (B43_NPHY_TXPCTL_CMD_COEFF |
+                     B43_NPHY_TXPCTL_CMD_HWPCTLEN |
+                     B43_NPHY_TXPCTL_CMD_PCTLEN))) {
+                       /* We disable enabled TX pwr ctl, save it's state */
+                       nphy->tx_pwr_idx[0] = b43_phy_read(dev,
+                                               B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
+                       nphy->tx_pwr_idx[1] = b43_phy_read(dev,
+                                               B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
+               }
 
-       samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
-       if (!samples) {
-               b43err(dev->wl, "allocation for samples generation failed\n");
-               return 0;
-       }
-       rot = (((freq * 36) / bw) << 16) / 100;
-       angle = 0;
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
+               for (i = 0; i < 84; i++)
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
 
-       for (i = 0; i < len; i++) {
-               samples[i] = b43_cordic(angle);
-               angle += rot;
-               samples[i].q = CORDIC_CONVERT(samples[i].q * max);
-               samples[i].i = CORDIC_CONVERT(samples[i].i * max);
-       }
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
+               for (i = 0; i < 84; i++)
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
 
-       i = b43_nphy_load_samples(dev, samples, len);
-       kfree(samples);
-       return (i < 0) ? 0 : len;
-}
+               tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+               if (dev->phy.rev >= 3)
+                       tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+               b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
-static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
-                                       u16 wait, bool iqmode, bool dac_test)
-{
-       struct b43_phy_n *nphy = dev->phy.n;
-       int i;
-       u16 seq_mode;
-       u32 tmp;
+               if (dev->phy.rev >= 3) {
+                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+               } else {
+                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+               }
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, true);
+               if (dev->phy.rev == 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+                               ~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
+               else if (dev->phy.rev < 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+                               ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
 
-       if ((nphy->bb_mult_save & 0x80000000) == 0) {
-               tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
-               nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
-       }
+               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+                       b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
+       } else {
+               b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
+                                   nphy->adj_pwr_tbl);
+               b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
+                                   nphy->adj_pwr_tbl);
 
-       if (!dev->phy.is_40mhz)
-               tmp = 0x6464;
-       else
-               tmp = 0x4747;
-       b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+               bmask = B43_NPHY_TXPCTL_CMD_COEFF |
+                       B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+               /* wl does useless check for "enable" param here */
+               val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+               if (dev->phy.rev >= 3) {
+                       bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+                       if (val)
+                               val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+               }
+               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
 
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, false);
+               if (band == IEEE80211_BAND_5GHZ) {
+                       b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+                                       ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
+                       if (dev->phy.rev > 1)
+                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+                                               ~B43_NPHY_TXPCTL_INIT_PIDXI1,
+                                               0x64);
+               }
 
-       b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
+               if (dev->phy.rev >= 3) {
+                       if (nphy->tx_pwr_idx[0] != 128 &&
+                           nphy->tx_pwr_idx[1] != 128) {
+                               /* Recover TX pwr ctl state */
+                               b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+                                               ~B43_NPHY_TXPCTL_CMD_INIT,
+                                               nphy->tx_pwr_idx[0]);
+                               if (dev->phy.rev > 1)
+                                       b43_phy_maskset(dev,
+                                               B43_NPHY_TXPCTL_INIT,
+                                               ~0xff, nphy->tx_pwr_idx[1]);
+                       }
+               }
 
-       if (loops != 0xFFFF)
-               b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
-       else
-               b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
+               if (dev->phy.rev >= 3) {
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
+               } else {
+                       b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
+               }
 
-       b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
+               if (dev->phy.rev == 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
+               else if (dev->phy.rev < 2)
+                       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
 
-       seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
+               if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+                       b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
 
-       b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
-       if (iqmode) {
-               b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
-               b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
-       } else {
-               if (dac_test)
-                       b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
-               else
-                       b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
-       }
-       for (i = 0; i < 100; i++) {
-               if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
-                       i = 0;
-                       break;
+               if (b43_nphy_ipa(dev)) {
+                       b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
+                       b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
                }
-               udelay(10);
        }
-       if (i)
-               b43err(dev->wl, "run samples timeout\n");
-
-       b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
-}
 
-/*
- * Transmits a known value for LO calibration
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
- */
-static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
-                               bool iqmode, bool dac_test)
-{
-       u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
-       if (samp == 0)
-               return -1;
-       b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
-       return 0;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 0);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
-static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
+static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-       int i, j;
-       u32 tmp;
-       u32 cur_real, cur_imag, real_part, imag_part;
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
-       u16 buffer[7];
+       u8 txpi[2], bbmult, i;
+       u16 tmp, radio_gain, dac_gain;
+       u16 freq = dev->phy.channel_freq;
+       u32 txgain;
+       /* u32 gaintbl; rev3+ */
 
        if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, true);
-
-       b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
-
-       for (i = 0; i < 2; i++) {
-               tmp = ((buffer[i * 2] & 0x3FF) << 10) |
-                       (buffer[i * 2 + 1] & 0x3FF);
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
-                               (((i + 26) << 10) | 320));
-               for (j = 0; j < 128; j++) {
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
-                                       ((tmp >> 16) & 0xFFFF));
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-                                       (tmp & 0xFFFF));
-               }
-       }
-
-       for (i = 0; i < 2; i++) {
-               tmp = buffer[5 + i];
-               real_part = (tmp >> 8) & 0xFF;
-               imag_part = (tmp & 0xFF);
-               b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
-                               (((i + 26) << 10) | 448));
+               b43_nphy_stay_in_carrier_search(dev, 1);
 
-               if (dev->phy.rev >= 3) {
-                       cur_real = real_part;
-                       cur_imag = imag_part;
-                       tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
-               }
-
-               for (j = 0; j < 128; j++) {
-                       if (dev->phy.rev < 3) {
-                               cur_real = (real_part * loscale[j] + 128) >> 8;
-                               cur_imag = (imag_part * loscale[j] + 128) >> 8;
-                               tmp = ((cur_real & 0xFF) << 8) |
-                                       (cur_imag & 0xFF);
-                       }
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
-                                       ((tmp >> 16) & 0xFFFF));
-                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
-                                       (tmp & 0xFFFF));
+       if (dev->phy.rev >= 7) {
+               txpi[0] = txpi[1] = 30;
+       } else if (dev->phy.rev >= 3) {
+               txpi[0] = 40;
+               txpi[1] = 40;
+       } else if (sprom->revision < 4) {
+               txpi[0] = 72;
+               txpi[1] = 72;
+       } else {
+               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+                       txpi[0] = sprom->txpid2g[0];
+                       txpi[1] = sprom->txpid2g[1];
+               } else if (freq >= 4900 && freq < 5100) {
+                       txpi[0] = sprom->txpid5gl[0];
+                       txpi[1] = sprom->txpid5gl[1];
+               } else if (freq >= 5100 && freq < 5500) {
+                       txpi[0] = sprom->txpid5g[0];
+                       txpi[1] = sprom->txpid5g[1];
+               } else if (freq >= 5500) {
+                       txpi[0] = sprom->txpid5gh[0];
+                       txpi[1] = sprom->txpid5gh[1];
+               } else {
+                       txpi[0] = 91;
+                       txpi[1] = 91;
                }
        }
+       if (dev->phy.rev < 7 &&
+           (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10))
+               txpi[0] = txpi[1] = 91;
 
-       if (dev->phy.rev >= 3) {
-               b43_shm_write16(dev, B43_SHM_SHARED,
-                               B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
-               b43_shm_write16(dev, B43_SHM_SHARED,
-                               B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
-       }
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, false);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
-static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
-                                       u8 *events, u8 *delays, u8 length)
-{
-       struct b43_phy_n *nphy = dev->phy.n;
-       u8 i;
-       u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
-       u16 offset1 = cmd << 4;
-       u16 offset2 = offset1 + 0x80;
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, true);
-
-       b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
-       b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
-
-       for (i = length; i < 16; i++) {
-               b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
-               b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
-       }
-
-       if (nphy->hang_avoid)
-               b43_nphy_stay_in_carrier_search(dev, false);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
-static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
-                                      enum b43_nphy_rf_sequence seq)
-{
-       static const u16 trigger[] = {
-               [B43_RFSEQ_RX2TX]               = B43_NPHY_RFSEQTR_RX2TX,
-               [B43_RFSEQ_TX2RX]               = B43_NPHY_RFSEQTR_TX2RX,
-               [B43_RFSEQ_RESET2RX]            = B43_NPHY_RFSEQTR_RST2RX,
-               [B43_RFSEQ_UPDATE_GAINH]        = B43_NPHY_RFSEQTR_UPGH,
-               [B43_RFSEQ_UPDATE_GAINL]        = B43_NPHY_RFSEQTR_UPGL,
-               [B43_RFSEQ_UPDATE_GAINU]        = B43_NPHY_RFSEQTR_UPGU,
-       };
-       int i;
-       u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
-
-       B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
-
-       b43_phy_set(dev, B43_NPHY_RFSEQMODE,
-                   B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
-       b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
-       for (i = 0; i < 200; i++) {
-               if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
-                       goto ok;
-               msleep(1);
+       /*
+       for (i = 0; i < 2; i++) {
+               nphy->txpwrindex[i].index_internal = txpi[i];
+               nphy->txpwrindex[i].index_internal_save = txpi[i];
        }
-       b43err(dev->wl, "RF sequence status timeout\n");
-ok:
-       b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
-                                               u16 value, u8 core, bool off)
-{
-       int i;
-       u8 index = fls(field);
-       u8 addr, en_addr, val_addr;
-       /* we expect only one bit set */
-       B43_WARN_ON(field & (~(1 << (index - 1))));
-
-       if (dev->phy.rev >= 3) {
-               const struct nphy_rf_control_override_rev3 *rf_ctrl;
-               for (i = 0; i < 2; i++) {
-                       if (index == 0 || index == 16) {
-                               b43err(dev->wl,
-                                       "Unsupported RF Ctrl Override call\n");
-                               return;
-                       }
-
-                       rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
-                       en_addr = B43_PHY_N((i == 0) ?
-                               rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
-                       val_addr = B43_PHY_N((i == 0) ?
-                               rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
+       */
 
-                       if (off) {
-                               b43_phy_mask(dev, en_addr, ~(field));
-                               b43_phy_mask(dev, val_addr,
-                                               ~(rf_ctrl->val_mask));
+       for (i = 0; i < 2; i++) {
+               if (dev->phy.rev >= 3) {
+                       if (b43_nphy_ipa(dev)) {
+                               txgain = *(b43_nphy_get_ipa_gain_table(dev) +
+                                               txpi[i]);
+                       } else if (b43_current_band(dev->wl) ==
+                                  IEEE80211_BAND_5GHZ) {
+                               /* FIXME: use 5GHz tables */
+                               txgain =
+                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
                        } else {
-                               if (core == 0 || ((1 << core) & i) != 0) {
-                                       b43_phy_set(dev, en_addr, field);
-                                       b43_phy_maskset(dev, val_addr,
-                                               ~(rf_ctrl->val_mask),
-                                               (value << rf_ctrl->val_shift));
-                               }
+                               if (dev->phy.rev >= 5 &&
+                                   sprom->fem.ghz5.extpa_gain == 3)
+                                       ; /* FIXME: 5GHz_txgain_HiPwrEPA */
+                               txgain =
+                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
                        }
-               }
-       } else {
-               const struct nphy_rf_control_override_rev2 *rf_ctrl;
-               if (off) {
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
-                       value = 0;
+                       radio_gain = (txgain >> 16) & 0x1FFFF;
                } else {
-                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
+                       txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
+                       radio_gain = (txgain >> 16) & 0x1FFF;
                }
 
-               for (i = 0; i < 2; i++) {
-                       if (index <= 1 || index == 16) {
-                               b43err(dev->wl,
-                                       "Unsupported RF Ctrl Override call\n");
-                               return;
-                       }
+               if (dev->phy.rev >= 7)
+                       dac_gain = (txgain >> 8) & 0x7;
+               else
+                       dac_gain = (txgain >> 8) & 0x3F;
+               bbmult = txgain & 0xFF;
 
-                       if (index == 2 || index == 10 ||
-                           (index >= 13 && index <= 15)) {
-                               core = 1;
-                       }
+               if (dev->phy.rev >= 3) {
+                       if (i == 0)
+                               b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+                       else
+                               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+               } else {
+                       b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+               }
 
-                       rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
-                       addr = B43_PHY_N((i == 0) ?
-                               rf_ctrl->addr0 : rf_ctrl->addr1);
+               if (i == 0)
+                       b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
+               else
+                       b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
 
-                       if ((core & (1 << i)) != 0)
-                               b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
-                                               (value << rf_ctrl->shift));
+               b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
 
-                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
-                       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                                       B43_NPHY_RFCTL_CMD_START);
-                       udelay(1);
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
+               tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
+               if (i == 0)
+                       tmp = (tmp & 0x00FF) | (bbmult << 8);
+               else
+                       tmp = (tmp & 0xFF00) | bbmult;
+               b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
+
+               if (b43_nphy_ipa(dev)) {
+                       u32 tmp32;
+                       u16 reg = (i == 0) ?
+                               B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
+                       tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
+                                                             576 + txpi[i]));
+                       b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
+                       b43_phy_set(dev, reg, 0x4);
                }
        }
-}
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
-                                               u16 value, u8 core)
-{
-       u8 i, j;
-       u16 reg, tmp, val;
-
-       B43_WARN_ON(dev->phy.rev < 3);
-       B43_WARN_ON(field > 4);
+       b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
 
-       for (i = 0; i < 2; i++) {
-               if ((core == 1 && i == 1) || (core == 2 && !i))
-                       continue;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 0);
+}
 
-               reg = (i == 0) ?
-                       B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
-               b43_phy_mask(dev, reg, 0xFBFF);
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+{
+       struct b43_phy *phy = &dev->phy;
 
-               switch (field) {
-               case 0:
-                       b43_phy_write(dev, reg, 0);
-                       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
-                       break;
-               case 1:
-                       if (!i) {
-                               b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
-                                               0xFC3F, (value << 6));
-                               b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
-                                               0xFFFE, 1);
-                               b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                                               B43_NPHY_RFCTL_CMD_START);
-                               for (j = 0; j < 100; j++) {
-                                       if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
-                                               j = 0;
-                                               break;
-                                       }
-                                       udelay(10);
-                               }
-                               if (j)
-                                       b43err(dev->wl,
-                                               "intc override timeout\n");
-                               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
-                                               0xFFFE);
-                       } else {
-                               b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
-                                               0xFC3F, (value << 6));
-                               b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
-                                               0xFFFE, 1);
-                               b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                                               B43_NPHY_RFCTL_CMD_RXTX);
-                               for (j = 0; j < 100; j++) {
-                                       if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
-                                               j = 0;
-                                               break;
-                                       }
-                                       udelay(10);
-                               }
-                               if (j)
-                                       b43err(dev->wl,
-                                               "intc override timeout\n");
-                               b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
-                                               0xFFFE);
-                       }
-                       break;
-               case 2:
-                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-                               tmp = 0x0020;
-                               val = value << 5;
-                       } else {
-                               tmp = 0x0010;
-                               val = value << 4;
-                       }
-                       b43_phy_maskset(dev, reg, ~tmp, val);
-                       break;
-               case 3:
-                       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-                               tmp = 0x0001;
-                               val = value;
-                       } else {
-                               tmp = 0x0004;
-                               val = value << 2;
-                       }
-                       b43_phy_maskset(dev, reg, ~tmp, val);
-                       break;
-               case 4:
+       const u32 *table = NULL;
+#if 0
+       TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
+       u32 rfpwr_offset;
+       u8 pga_gain;
+       int i;
+#endif
+
+       if (phy->rev >= 3) {
+               if (b43_nphy_ipa(dev)) {
+                       table = b43_nphy_get_ipa_gain_table(dev);
+               } else {
                        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
-                               tmp = 0x0002;
-                               val = value << 1;
+                               if (phy->rev == 3)
+                                       table = b43_ntab_tx_gain_rev3_5ghz;
+                               if (phy->rev == 4)
+                                       table = b43_ntab_tx_gain_rev4_5ghz;
+                               else
+                                       table = b43_ntab_tx_gain_rev5plus_5ghz;
                        } else {
-                               tmp = 0x0008;
-                               val = value << 3;
+                               table = b43_ntab_tx_gain_rev3plus_2ghz;
                        }
-                       b43_phy_maskset(dev, reg, ~tmp, val);
-                       break;
                }
+       } else {
+               table = b43_ntab_tx_gain_rev0_1_2;
+       }
+       b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
+       b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+
+       if (phy->rev >= 3) {
+#if 0
+               nphy->gmval = (table[0] >> 16) & 0x7000;
+
+               for (i = 0; i < 128; i++) {
+                       pga_gain = (table[i] >> 24) & 0xF;
+                       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+                       else
+                               rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
+                       b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
+                                      rfpwr_offset);
+                       b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
+                                      rfpwr_offset);
+               }
+#endif
        }
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
-static void b43_nphy_bphy_init(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
+static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
 {
-       unsigned int i;
-       u16 val;
+       struct b43_phy_n *nphy = dev->phy.n;
+       enum ieee80211_band band;
+       u16 tmp;
 
-       val = 0x1E1F;
-       for (i = 0; i < 16; i++) {
-               b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
-               val -= 0x202;
-       }
-       val = 0x3E3F;
-       for (i = 0; i < 16; i++) {
-               b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
-               val -= 0x202;
+       if (!enable) {
+               nphy->rfctrl_intc1_save = b43_phy_read(dev,
+                                                      B43_NPHY_RFCTL_INTC1);
+               nphy->rfctrl_intc2_save = b43_phy_read(dev,
+                                                      B43_NPHY_RFCTL_INTC2);
+               band = b43_current_band(dev->wl);
+               if (dev->phy.rev >= 3) {
+                       if (band == IEEE80211_BAND_5GHZ)
+                               tmp = 0x600;
+                       else
+                               tmp = 0x480;
+               } else {
+                       if (band == IEEE80211_BAND_5GHZ)
+                               tmp = 0x180;
+                       else
+                               tmp = 0x120;
+               }
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
+       } else {
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
+                               nphy->rfctrl_intc1_save);
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
+                               nphy->rfctrl_intc2_save);
        }
-       b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
-static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
-                                       s8 offset, u8 core, u8 rail,
-                                       enum b43_nphy_rssi_type type)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
+static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
 {
        u16 tmp;
-       bool core1or5 = (core == 1) || (core == 5);
-       bool core2or5 = (core == 2) || (core == 5);
-
-       offset = clamp_val(offset, -32, 31);
-       tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
 
-       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
-       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
-       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
-       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
+       if (dev->phy.rev >= 3) {
+               if (b43_nphy_ipa(dev)) {
+                       tmp = 4;
+                       b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
+                             (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
+               }
 
-       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
-       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
-       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
-       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
+               tmp = 1;
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
+                             (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
+       }
+}
 
-       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
-       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
-       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
-       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
+static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
 
-       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
-       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
-       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
-       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
+       bool override = false;
+       u16 chain = 0x33;
 
-       if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
-       if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
-       if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
-       if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
+       if (nphy->txrx_chain == 0) {
+               chain = 0x11;
+               override = true;
+       } else if (nphy->txrx_chain == 1) {
+               chain = 0x22;
+               override = true;
+       }
 
-       if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
-       if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
+       b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+                       ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
+                       chain);
 
-       if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
-       if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
-               b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+       if (override)
+               b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+                               B43_NPHY_RFSEQMODE_CAOVER);
+       else
+               b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+                               ~B43_NPHY_RFSEQMODE_CAOVER);
 }
 
-static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
+static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
+                               u16 samps, u8 time, bool wait)
 {
-       u16 val;
+       int i;
+       u16 tmp;
 
-       if (type < 3)
-               val = 0;
-       else if (type == 6)
-               val = 1;
-       else if (type == 3)
-               val = 2;
+       b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
+       b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
+       if (wait)
+               b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
        else
-               val = 3;
+               b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
 
-       val = (val << 12) | (val << 14);
-       b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
-       b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
+       b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
 
-       if (type < 3) {
-               b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
-                               (type + 1) << 4);
-               b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
-                               (type + 1) << 4);
-       }
+       for (i = 1000; i; i--) {
+               tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
+               if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
+                       est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
+                       est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
+                       est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
 
-       if (code == 0) {
-               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
-               if (type < 3) {
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
-                               ~(B43_NPHY_RFCTL_CMD_RXEN |
-                                 B43_NPHY_RFCTL_CMD_CORESEL));
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
-                               ~(0x1 << 12 |
-                                 0x1 << 5 |
-                                 0x1 << 1 |
-                                 0x1));
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
-                               ~B43_NPHY_RFCTL_CMD_START);
-                       udelay(20);
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
-               }
-       } else {
-               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
-               if (type < 3) {
-                       b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
-                               ~(B43_NPHY_RFCTL_CMD_RXEN |
-                                 B43_NPHY_RFCTL_CMD_CORESEL),
-                               (B43_NPHY_RFCTL_CMD_RXEN |
-                                code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
-                       b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
-                               (0x1 << 12 |
-                                 0x1 << 5 |
-                                 0x1 << 1 |
-                                 0x1));
-                       b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
-                               B43_NPHY_RFCTL_CMD_START);
-                       udelay(20);
-                       b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
+                       est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
+                       est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
+                       est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
+                                       b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
+                       return;
                }
+               udelay(10);
        }
+       memset(est, 0, sizeof(*est));
 }
 
-static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
+static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
+                                       struct b43_phy_n_iq_comp *pcomp)
 {
-       u8 i;
-       u16 reg, val;
-
-       if (code == 0) {
-               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
-               b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
-               b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
-               b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
-               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
-               b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
-               b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
-               b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
+       if (write) {
+               b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
+               b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
+               b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
+               b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
        } else {
-               for (i = 0; i < 2; i++) {
-                       if ((code == 1 && i == 1) || (code == 2 && !i))
-                               continue;
-
-                       reg = (i == 0) ?
-                               B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
-                       b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
+               pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
+               pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
+               pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
+               pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
+       }
+}
 
-                       if (type < 3) {
-                               reg = (i == 0) ?
-                                       B43_NPHY_AFECTL_C1 :
-                                       B43_NPHY_AFECTL_C2;
-                               b43_phy_maskset(dev, reg, 0xFCFF, 0);
+#if 0
+/* Ready but not used anywhere */
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
+static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
+{
+       u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
 
-                               reg = (i == 0) ?
-                                       B43_NPHY_RFCTL_LUT_TRSW_UP1 :
-                                       B43_NPHY_RFCTL_LUT_TRSW_UP2;
-                               b43_phy_maskset(dev, reg, 0xFFC3, 0);
+       b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
+       if (core == 0) {
+               b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
+       } else {
+               b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
+       }
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
+       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
+       b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
+       b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
+       b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
+       b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
+       b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
+       b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
+}
 
-                               if (type == 0)
-                                       val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
-                               else if (type == 1)
-                                       val = 16;
-                               else
-                                       val = 32;
-                               b43_phy_set(dev, reg, val);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
+static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
+{
+       u8 rxval, txval;
+       u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
 
-                               reg = (i == 0) ?
-                                       B43_NPHY_TXF_40CO_B1S0 :
-                                       B43_NPHY_TXF_40CO_B32S1;
-                               b43_phy_set(dev, reg, 0x0020);
-                       } else {
-                               if (type == 6)
-                                       val = 0x0100;
-                               else if (type == 3)
-                                       val = 0x0200;
-                               else
-                                       val = 0x0300;
+       regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
+       if (core == 0) {
+               regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+               regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
+       } else {
+               regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+               regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+       }
+       regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+       regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+       regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
+       regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
+       regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
+       regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
+       regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
+       regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
 
-                               reg = (i == 0) ?
-                                       B43_NPHY_AFECTL_C1 :
-                                       B43_NPHY_AFECTL_C2;
+       b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
+       b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
 
-                               b43_phy_maskset(dev, reg, 0xFCFF, val);
-                               b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
+       b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+                       ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
+                       ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
+       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
+                       ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
+       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
+                       (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
+       b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
+                       (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
 
-                               if (type != 3 && type != 6) {
-                                       enum ieee80211_band band =
-                                               b43_current_band(dev->wl);
+       if (core == 0) {
+               b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
+               b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
+       } else {
+               b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
+               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
+       }
 
-                                       if (b43_nphy_ipa(dev))
-                                               val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
-                                       else
-                                               val = 0x11;
-                                       reg = (i == 0) ? 0x2000 : 0x3000;
-                                       reg |= B2055_PADDRV;
-                                       b43_radio_write16(dev, reg, val);
+       b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
+       b43_nphy_rf_control_override(dev, 8, 0, 3, false);
+       b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
 
-                                       reg = (i == 0) ?
-                                               B43_NPHY_AFECTL_OVER1 :
-                                               B43_NPHY_AFECTL_OVER;
-                                       b43_phy_set(dev, reg, 0x0200);
-                               }
-                       }
-               }
+       if (core == 0) {
+               rxval = 1;
+               txval = 8;
+       } else {
+               rxval = 4;
+               txval = 2;
        }
+       b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
+       b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
 }
+#endif
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
-static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
-       if (dev->phy.rev >= 3)
-               b43_nphy_rev3_rssi_select(dev, code, type);
-       else
-               b43_nphy_rev2_rssi_select(dev, code, type);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
-static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
+static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
 {
        int i;
+       s32 iq;
+       u32 ii;
+       u32 qq;
+       int iq_nbits, qq_nbits;
+       int arsh, brsh;
+       u16 tmp, a, b;
+
+       struct nphy_iq_est est;
+       struct b43_phy_n_iq_comp old;
+       struct b43_phy_n_iq_comp new = { };
+       bool error = false;
+
+       if (mask == 0)
+               return;
+
+       b43_nphy_rx_iq_coeffs(dev, false, &old);
+       b43_nphy_rx_iq_coeffs(dev, true, &new);
+       b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
+       new = old;
+
        for (i = 0; i < 2; i++) {
-               if (type == 2) {
-                       if (i == 0) {
-                               b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
-                                                 0xFC, buf[0]);
-                               b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
-                                                 0xFC, buf[1]);
-                       } else {
-                               b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
-                                                 0xFC, buf[2 * i]);
-                               b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
-                                                 0xFC, buf[2 * i + 1]);
-                       }
+               if (i == 0 && (mask & 1)) {
+                       iq = est.iq0_prod;
+                       ii = est.i0_pwr;
+                       qq = est.q0_pwr;
+               } else if (i == 1 && (mask & 2)) {
+                       iq = est.iq1_prod;
+                       ii = est.i1_pwr;
+                       qq = est.q1_pwr;
                } else {
-                       if (i == 0)
-                               b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
-                                                 0xF3, buf[0] << 2);
-                       else
-                               b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
-                                                 0xF3, buf[2 * i + 1] << 2);
+                       continue;
                }
-       }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
-static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
-                               u8 nsamp)
-{
-       int i;
-       int out;
-       u16 save_regs_phy[9];
-       u16 s[2];
-
-       if (dev->phy.rev >= 3) {
-               save_regs_phy[0] = b43_phy_read(dev,
-                                               B43_NPHY_RFCTL_LUT_TRSW_UP1);
-               save_regs_phy[1] = b43_phy_read(dev,
-                                               B43_NPHY_RFCTL_LUT_TRSW_UP2);
-               save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
-               save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
-               save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
-               save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
-               save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
-               save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
-               save_regs_phy[8] = 0;
-       } else {
-               save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
-               save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
-               save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
-               save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
-               save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
-               save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
-               save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
-               save_regs_phy[7] = 0;
-               save_regs_phy[8] = 0;
-       }
 
-       b43_nphy_rssi_select(dev, 5, type);
+               if (ii + qq < 2) {
+                       error = true;
+                       break;
+               }
 
-       if (dev->phy.rev < 2) {
-               save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
-               b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
-       }
+               iq_nbits = fls(abs(iq));
+               qq_nbits = fls(qq);
 
-       for (i = 0; i < 4; i++)
-               buf[i] = 0;
+               arsh = iq_nbits - 20;
+               if (arsh >= 0) {
+                       a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+                       tmp = ii >> arsh;
+               } else {
+                       a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+                       tmp = ii << -arsh;
+               }
+               if (tmp == 0) {
+                       error = true;
+                       break;
+               }
+               a /= tmp;
 
-       for (i = 0; i < nsamp; i++) {
-               if (dev->phy.rev < 2) {
-                       s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
-                       s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
+               brsh = qq_nbits - 11;
+               if (brsh >= 0) {
+                       b = (qq << (31 - qq_nbits));
+                       tmp = ii >> brsh;
                } else {
-                       s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
-                       s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
+                       b = (qq << (31 - qq_nbits));
+                       tmp = ii << -brsh;
+               }
+               if (tmp == 0) {
+                       error = true;
+                       break;
                }
+               b = int_sqrt(b / tmp - a * a) - (1 << 10);
 
-               buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
-               buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
-               buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
-               buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
+               if (i == 0 && (mask & 0x1)) {
+                       if (dev->phy.rev >= 3) {
+                               new.a0 = a & 0x3FF;
+                               new.b0 = b & 0x3FF;
+                       } else {
+                               new.a0 = b & 0x3FF;
+                               new.b0 = a & 0x3FF;
+                       }
+               } else if (i == 1 && (mask & 0x2)) {
+                       if (dev->phy.rev >= 3) {
+                               new.a1 = a & 0x3FF;
+                               new.b1 = b & 0x3FF;
+                       } else {
+                               new.a1 = b & 0x3FF;
+                               new.b1 = a & 0x3FF;
+                       }
+               }
        }
-       out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
-               (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
 
-       if (dev->phy.rev < 2)
-               b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
+       if (error)
+               new = old;
 
-       if (dev->phy.rev >= 3) {
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
-                               save_regs_phy[0]);
-               b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
-                               save_regs_phy[1]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
-               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
-               b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
-       } else {
-               b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
-               b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
-               b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
-               b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
-               b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
-       }
+       b43_nphy_rx_iq_coeffs(dev, true, &new);
+}
 
-       return out;
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
+static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
+{
+       u16 array[4];
+       b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
+
+       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
+       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
+       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
+       b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
-static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
+static void b43_nphy_stop_playback(struct b43_wldev *dev)
 {
-       int i, j;
-       u8 state[4];
-       u8 code, val;
-       u16 class, override;
-       u8 regs_save_radio[2];
-       u16 regs_save_phy[2];
+       struct b43_phy_n *nphy = dev->phy.n;
+       u16 tmp;
 
-       s8 offset[4];
-       u8 core;
-       u8 rail;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 1);
 
-       u16 clip_state[2];
-       u16 clip_off[2] = { 0xFFFF, 0xFFFF };
-       s32 results_min[4] = { };
-       u8 vcm_final[4] = { };
-       s32 results[4][4] = { };
-       s32 miniq[4][2] = { };
+       tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
+       if (tmp & 0x1)
+               b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
+       else if (tmp & 0x2)
+               b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
 
-       if (type == 2) {
-               code = 0;
-               val = 6;
-       } else if (type < 2) {
-               code = 25;
-               val = 4;
-       } else {
-               B43_WARN_ON(1);
-               return;
-       }
+       b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
 
-       class = b43_nphy_classifier(dev, 0, 0);
-       b43_nphy_classifier(dev, 7, 4);
-       b43_nphy_read_clip_detection(dev, clip_state);
-       b43_nphy_write_clip_detection(dev, clip_off);
+       if (nphy->bb_mult_save & 0x80000000) {
+               tmp = nphy->bb_mult_save & 0xFFFF;
+               b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+               nphy->bb_mult_save = 0;
+       }
 
-       if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
-               override = 0x140;
-       else
-               override = 0x110;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 0);
+}
 
-       regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
-       regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
-       b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
+static void b43_nphy_spur_workaround(struct b43_wldev *dev)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
 
-       regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
-       regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
-       b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
+       u8 channel = dev->phy.channel;
+       int tone[2] = { 57, 58 };
+       u32 noise[2] = { 0x3FF, 0x3FF };
 
-       state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
-       state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
-       b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
-       b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
-       state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
-       state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
+       B43_WARN_ON(dev->phy.rev < 3);
 
-       b43_nphy_rssi_select(dev, 5, type);
-       b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
-       b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 1);
 
-       for (i = 0; i < 4; i++) {
-               u8 tmp[4];
-               for (j = 0; j < 4; j++)
-                       tmp[j] = i;
-               if (type != 1)
-                       b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
-               b43_nphy_poll_rssi(dev, type, results[i], 8);
-               if (type < 2)
-                       for (j = 0; j < 2; j++)
-                               miniq[i][j] = min(results[i][2 * j],
-                                               results[i][2 * j + 1]);
+       if (nphy->gband_spurwar_en) {
+               /* TODO: N PHY Adjust Analog Pfbw (7) */
+               if (channel == 11 && dev->phy.is_40mhz)
+                       ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
+               else
+                       ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
+               /* TODO: N PHY Adjust CRS Min Power (0x1E) */
        }
 
-       for (i = 0; i < 4; i++) {
-               s32 mind = 40;
-               u8 minvcm = 0;
-               s32 minpoll = 249;
-               s32 curr;
-               for (j = 0; j < 4; j++) {
-                       if (type == 2)
-                               curr = abs(results[j][i]);
-                       else
-                               curr = abs(miniq[j][i / 2] - code * 8);
-
-                       if (curr < mind) {
-                               mind = curr;
-                               minvcm = j;
+       if (nphy->aband_spurwar_en) {
+               if (channel == 54) {
+                       tone[0] = 0x20;
+                       noise[0] = 0x25F;
+               } else if (channel == 38 || channel == 102 || channel == 118) {
+                       if (0 /* FIXME */) {
+                               tone[0] = 0x20;
+                               noise[0] = 0x21F;
+                       } else {
+                               tone[0] = 0;
+                               noise[0] = 0;
                        }
-
-                       if (results[j][i] < minpoll)
-                               minpoll = results[j][i];
+               } else if (channel == 134) {
+                       tone[0] = 0x20;
+                       noise[0] = 0x21F;
+               } else if (channel == 151) {
+                       tone[0] = 0x10;
+                       noise[0] = 0x23F;
+               } else if (channel == 153 || channel == 161) {
+                       tone[0] = 0x30;
+                       noise[0] = 0x23F;
+               } else {
+                       tone[0] = 0;
+                       noise[0] = 0;
                }
-               results_min[i] = minpoll;
-               vcm_final[i] = minvcm;
-       }
-
-       if (type != 1)
-               b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
 
-       for (i = 0; i < 4; i++) {
-               offset[i] = (code * 8) - results[vcm_final[i]][i];
-
-               if (offset[i] < 0)
-                       offset[i] = -((abs(offset[i]) + 4) / 8);
+               if (!tone[0] && !noise[0])
+                       ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
                else
-                       offset[i] = (offset[i] + 4) / 8;
+                       ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
+       }
 
-               if (results_min[i] == 248)
-                       offset[i] = code - 32;
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, 0);
+}
 
-               core = (i / 2) ? 2 : 1;
-               rail = (i % 2) ? 1 : 0;
+/*
+ * Transmits a known value for LO calibration
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
+ */
+static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
+                               bool iqmode, bool dac_test)
+{
+       u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
+       if (samp == 0)
+               return -1;
+       b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
+       return 0;
+}
 
-               b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
-                                               type);
-       }
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
+static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
+       int i, j;
+       u32 tmp;
+       u32 cur_real, cur_imag, real_part, imag_part;
 
-       b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
-       b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
+       u16 buffer[7];
 
-       switch (state[2]) {
-       case 1:
-               b43_nphy_rssi_select(dev, 1, 2);
-               break;
-       case 4:
-               b43_nphy_rssi_select(dev, 1, 0);
-               break;
-       case 2:
-               b43_nphy_rssi_select(dev, 1, 1);
-               break;
-       default:
-               b43_nphy_rssi_select(dev, 1, 1);
-               break;
-       }
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, true);
 
-       switch (state[3]) {
-       case 1:
-               b43_nphy_rssi_select(dev, 2, 2);
-               break;
-       case 4:
-               b43_nphy_rssi_select(dev, 2, 0);
-               break;
-       default:
-               b43_nphy_rssi_select(dev, 2, 1);
-               break;
-       }
+       b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
 
-       b43_nphy_rssi_select(dev, 0, type);
+       for (i = 0; i < 2; i++) {
+               tmp = ((buffer[i * 2] & 0x3FF) << 10) |
+                       (buffer[i * 2 + 1] & 0x3FF);
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+                               (((i + 26) << 10) | 320));
+               for (j = 0; j < 128; j++) {
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
+                                       ((tmp >> 16) & 0xFFFF));
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+                                       (tmp & 0xFFFF));
+               }
+       }
 
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
-       b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
-       b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
+       for (i = 0; i < 2; i++) {
+               tmp = buffer[5 + i];
+               real_part = (tmp >> 8) & 0xFF;
+               imag_part = (tmp & 0xFF);
+               b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+                               (((i + 26) << 10) | 448));
 
-       b43_nphy_classifier(dev, 7, class);
-       b43_nphy_write_clip_detection(dev, clip_state);
-       /* Specs don't say about reset here, but it makes wl and b43 dumps
-          identical, it really seems wl performs this */
-       b43_nphy_reset_cca(dev);
-}
+               if (dev->phy.rev >= 3) {
+                       cur_real = real_part;
+                       cur_imag = imag_part;
+                       tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
+               }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
-static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
-{
-       /* TODO */
-}
+               for (j = 0; j < 128; j++) {
+                       if (dev->phy.rev < 3) {
+                               cur_real = (real_part * loscale[j] + 128) >> 8;
+                               cur_imag = (imag_part * loscale[j] + 128) >> 8;
+                               tmp = ((cur_real & 0xFF) << 8) |
+                                       (cur_imag & 0xFF);
+                       }
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
+                                       ((tmp >> 16) & 0xFFFF));
+                       b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+                                       (tmp & 0xFFFF));
+               }
+       }
 
-/*
- * RSSI Calibration
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
- */
-static void b43_nphy_rssi_cal(struct b43_wldev *dev)
-{
        if (dev->phy.rev >= 3) {
-               b43_nphy_rev3_rssi_cal(dev);
-       } else {
-               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
-               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
-               b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
+               b43_shm_write16(dev, B43_SHM_SHARED,
+                               B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
+               b43_shm_write16(dev, B43_SHM_SHARED,
+                               B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
        }
+
+       if (nphy->hang_avoid)
+               b43_nphy_stay_in_carrier_search(dev, false);
 }
 
 /*
@@ -2846,24 +2778,6 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
        b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
 }
 
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
-static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
-{
-       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
-               if (dev->phy.rev >= 6) {
-                       if (dev->dev->chip_id == 47162)
-                               return txpwrctrl_tx_gain_ipa_rev5;
-                       return txpwrctrl_tx_gain_ipa_rev6;
-               } else if (dev->phy.rev >= 5) {
-                       return txpwrctrl_tx_gain_ipa_rev5;
-               } else {
-                       return txpwrctrl_tx_gain_ipa;
-               }
-       } else {
-               return txpwrctrl_tx_gain_ipa_5g;
-       }
-}
-
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
 static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
 {
@@ -3847,10 +3761,104 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
        b43_mac_enable(dev);
 }
 
+/**************************************************
+ * N-PHY init
+ **************************************************/
+
 /*
- * Init N-PHY
- * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
+ * Upload the N-PHY tables.
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
  */
+static void b43_nphy_tables_init(struct b43_wldev *dev)
+{
+       if (dev->phy.rev < 3)
+               b43_nphy_rev0_1_2_tables_init(dev);
+       else
+               b43_nphy_rev3plus_tables_init(dev);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
+static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
+{
+       u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
+
+       mimocfg |= B43_NPHY_MIMOCFG_AUTO;
+       if (preamble == 1)
+               mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
+       else
+               mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
+
+       b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
+static void b43_nphy_bphy_init(struct b43_wldev *dev)
+{
+       unsigned int i;
+       u16 val;
+
+       val = 0x1E1F;
+       for (i = 0; i < 16; i++) {
+               b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+               val -= 0x202;
+       }
+       val = 0x3E3F;
+       for (i = 0; i < 16; i++) {
+               b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
+               val -= 0x202;
+       }
+       b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
+static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
+{
+       if (dev->phy.rev >= 3) {
+               if (!init)
+                       return;
+               if (0 /* FIXME */) {
+                       b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
+                       b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
+                       b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
+                       b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
+               }
+       } else {
+               b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
+               b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
+
+               switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+               case B43_BUS_BCMA:
+                       bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
+                                                0xFC00, 0xFC00);
+                       break;
+#endif
+#ifdef CONFIG_B43_SSB
+               case B43_BUS_SSB:
+                       ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
+                                               0xFC00, 0xFC00);
+                       break;
+#endif
+               }
+
+               b43_write32(dev, B43_MMIO_MACCTL,
+                       b43_read32(dev, B43_MMIO_MACCTL) &
+                       ~B43_MACCTL_GPOUTSMSK);
+               b43_write16(dev, B43_MMIO_GPIO_MASK,
+                       b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
+               b43_write16(dev, B43_MMIO_GPIO_CONTROL,
+                       b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
+
+               if (init) {
+                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+                       b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+               }
+       }
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
 int b43_phy_initn(struct b43_wldev *dev)
 {
        struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -4045,11 +4053,26 @@ int b43_phy_initn(struct b43_wldev *dev)
        return 0;
 }
 
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_chantab_phy_upload(struct b43_wldev *dev,
+                                  const struct b43_phy_n_sfo_cfg *e)
+{
+       b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
+       b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
+       b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
+       b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
+       b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
+       b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
 static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
 {
-       struct bcma_drv_cc *cc;
-       u32 pmu_ctl;
+       struct bcma_drv_cc __maybe_unused *cc;
+       u32 __maybe_unused pmu_ctl;
 
        switch (dev->dev->bus_type) {
 #ifdef CONFIG_B43_BCMA
@@ -4260,6 +4283,10 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
        return 0;
 }
 
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
 static int b43_nphy_op_allocate(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy;
index 8f54c2eb68249ae5041773eb746c5d5d3805dd1c..cd6375de2a606a2662ba2c5a63e5906c88b4656c 100644 (file)
@@ -17,16 +17,26 @@ config BRCMSMAC
 
 config BRCMFMAC
        tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
-       depends on MMC
        depends on CFG80211
        select BRCMUTIL
-       select FW_LOADER
        ---help---
          This module adds support for embedded wireless adapters based on
-         Broadcom IEEE802.11n FullMAC chipsets.  This driver uses the kernel's
-         wireless extensions subsystem.  If you choose to build a module,
+         Broadcom IEEE802.11n FullMAC chipsets. It has to work with at least
+         one of the bus interface support. If you choose to build a module,
          it'll be called brcmfmac.ko.
 
+config BRCMFMAC_SDIO
+       bool "SDIO bus interface support for FullMAC"
+       depends on MMC
+       depends on BRCMFMAC
+       select FW_LOADER
+       default y
+       ---help---
+         This option enables the SDIO bus interface support for Broadcom
+         FullMAC WLAN driver.
+         Say Y if you want to use brcmfmac for a compatible SDIO interface
+         wireless card.
+
 config BRCMDBG
        bool "Broadcom driver debug functions"
        depends on BRCMSMAC || BRCMFMAC
index d58aa1b0a932de0ed1b095d29c5ece1589492995..9ca9ea1135ea3c311938bf9d86d6b98a557deeba 100644 (file)
@@ -19,16 +19,16 @@ ccflags-y += \
        -Idrivers/net/wireless/brcm80211/brcmfmac       \
        -Idrivers/net/wireless/brcm80211/include
 
-DHDOFILES = \
-       wl_cfg80211.o \
-       dhd_cdc.o \
-       dhd_common.o \
-       dhd_sdio.o      \
-       dhd_linux.o \
-       bcmsdh.o \
-       bcmsdh_sdmmc.o \
-       sdio_chip.o
-
 obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
-brcmfmac-objs += $(DHDOFILES)
+brcmfmac-objs += \
+               wl_cfg80211.o \
+               dhd_cdc.o \
+               dhd_common.o \
+               dhd_linux.o
+brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
+               dhd_sdio.o \
+               bcmsdh.o \
+               bcmsdh_sdmmc.o \
+               sdio_chip.o
+
 ccflags-y += -D__CHECK_ENDIAN__
index 6c85d668c9d7caf74848193a94501ab3c6a99bd3..4bc8d251acf8ed79d446b0dce22c938ca9bcb709 100644 (file)
@@ -31,7 +31,6 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 #include <soc.h>
-#include "dhd.h"
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
 #include "sdio_host.h"
@@ -51,12 +50,18 @@ static void brcmf_sdioh_irqhandler(struct sdio_func *func)
        sdio_claim_host(func);
 }
 
+/* dummy handler for SDIO function 2 interrupt */
+static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func)
+{
+}
+
 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
 {
        brcmf_dbg(TRACE, "Entering\n");
 
        sdio_claim_host(sdiodev->func[1]);
        sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
+       sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler);
        sdio_release_host(sdiodev->func[1]);
 
        return 0;
@@ -67,6 +72,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
        brcmf_dbg(TRACE, "Entering\n");
 
        sdio_claim_host(sdiodev->func[1]);
+       sdio_release_irq(sdiodev->func[2]);
        sdio_release_irq(sdiodev->func[1]);
        sdio_release_host(sdiodev->func[1]);
 
index b895f198a950c1a8577ef675909b4b427bed92a6..9b8c0ed833d40f523ffbb9ea9f3388ad610daa71 100644 (file)
@@ -31,9 +31,8 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 #include "sdio_host.h"
-#include "dhd.h"
 #include "dhd_dbg.h"
-#include "wl_cfg80211.h"
+#include "dhd_bus.h"
 
 #define SDIO_VENDOR_ID_BROADCOM                0x02d0
 
@@ -488,6 +487,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
                sdiodev->bus_if = bus_if;
                bus_if->bus_priv = sdiodev;
                bus_if->type = SDIO_BUS;
+               bus_if->align = BRCMF_SDALIGN;
                dev_set_drvdata(&func->card->dev, sdiodev);
 
                atomic_set(&sdiodev->suspend, false);
index ed60f4d6962785a598cdb71cc2832e42da28fd16..e58ea40a75b0679645a983a715fbfa1e71fb0fe3 100644 (file)
@@ -156,18 +156,6 @@ struct brcmf_event {
        struct brcmf_event_msg msg;
 } __packed;
 
-struct dngl_stats {
-       unsigned long rx_packets;       /* total packets received */
-       unsigned long tx_packets;       /* total packets transmitted */
-       unsigned long rx_bytes; /* total bytes received */
-       unsigned long tx_bytes; /* total bytes transmitted */
-       unsigned long rx_errors;        /* bad packets received */
-       unsigned long tx_errors;        /* packet transmit problems */
-       unsigned long rx_dropped;       /* packets dropped by dongle */
-       unsigned long tx_dropped;       /* packets dropped by dongle */
-       unsigned long multicast;        /* multicast packets received */
-};
-
 /* event codes sent by the dongle to this driver */
 #define BRCMF_E_SET_SSID                       0
 #define BRCMF_E_JOIN                           1
@@ -317,13 +305,6 @@ struct dngl_stats {
 #define BRCMF_E_LINK_ASSOC_REC                 3
 #define BRCMF_E_LINK_BSSCFG_DIS                        4
 
-/* The level of bus communication with the dongle */
-enum brcmf_bus_state {
-       BRCMF_BUS_DOWN,         /* Not ready for frame transfers */
-       BRCMF_BUS_LOAD,         /* Download access only (CPU reset) */
-       BRCMF_BUS_DATA          /* Ready for frame transfers */
-};
-
 /* Pattern matching filter. Specifies an offset within received packets to
  * start matching, the pattern to match, the size of the pattern, and a bitmask
  * that indicates which bits within the pattern should be matched.
@@ -571,33 +552,20 @@ struct brcmf_dcmd {
        uint needed;            /* bytes needed (optional) */
 };
 
-struct brcmf_bus {
-       u8 type;                /* bus type */
-       void *bus_priv;         /* pointer to bus private structure */
-       enum brcmf_bus_state state;
-};
-
 /* Forward decls for struct brcmf_pub (see below) */
-struct brcmf_sdio;             /* device bus info */
 struct brcmf_proto;    /* device communication protocol info */
-struct brcmf_info;     /* device driver info */
 struct brcmf_cfg80211_dev; /* cfg80211 device info */
 
 /* Common structure for module and instance linkage */
 struct brcmf_pub {
        /* Linkage ponters */
-       struct brcmf_sdio *bus;
        struct brcmf_bus *bus_if;
        struct brcmf_proto *prot;
-       struct brcmf_info *info;
        struct brcmf_cfg80211_dev *config;
        struct device *dev;             /* fullmac dongle device pointer */
 
        /* Internal brcmf items */
-       bool up;                /* Driver up/down (to OS) */
-       bool txoff;             /* Transmit flow-controlled */
        uint hdrlen;            /* Total BRCMF header length (proto + bus) */
-       uint maxctl;            /* Max size rxctl request from proto to bus */
        uint rxsz;              /* Rx buffer size bus module should use */
        u8 wme_dp;              /* wme discard priority */
 
@@ -605,48 +573,21 @@ struct brcmf_pub {
        bool iswl;              /* Dongle-resident driver is wl */
        unsigned long drv_version;      /* Version of dongle-resident driver */
        u8 mac[ETH_ALEN];               /* MAC address obtained from dongle */
-       struct dngl_stats dstats;       /* Stats for dongle-based data */
 
        /* Additional stats for the bus level */
 
-       /* Data packets sent to dongle */
-       unsigned long tx_packets;
        /* Multicast data packets sent to dongle */
        unsigned long tx_multicast;
-       /* Errors in sending data to dongle */
-       unsigned long tx_errors;
-       /* Control packets sent to dongle */
-       unsigned long tx_ctlpkts;
-       /* Errors sending control frames to dongle */
-       unsigned long tx_ctlerrs;
-       /* Packets sent up the network interface */
-       unsigned long rx_packets;
-       /* Multicast packets sent up the network interface */
-       unsigned long rx_multicast;
-       /* Errors processing rx data packets */
-       unsigned long rx_errors;
-       /* Control frames processed from dongle */
-       unsigned long rx_ctlpkts;
-
-       /* Errors in processing rx control frames */
-       unsigned long rx_ctlerrs;
-       /* Packets dropped locally (no memory) */
-       unsigned long rx_dropped;
        /* Packets flushed due to unscheduled sendup thread */
        unsigned long rx_flushed;
        /* Number of times dpc scheduled by watchdog timer */
        unsigned long wd_dpc_sched;
 
-       /* Number of packets where header read-ahead was used. */
-       unsigned long rx_readahead_cnt;
-       /* Number of tx packets we had to realloc for headroom */
-       unsigned long tx_realloc;
        /* Number of flow control pkts recvd */
        unsigned long fc_packets;
 
        /* Last error return */
        int bcmerror;
-       uint tickcnt;
 
        /* Last error from dongle */
        int dongle_error;
@@ -663,6 +604,15 @@ struct brcmf_pub {
 
        u8 country_code[BRCM_CNTRY_BUF_SZ];
        char eventmask[BRCMF_EVENTING_MASK_LEN];
+
+       struct brcmf_if *iflist[BRCMF_MAX_IFS];
+
+       struct mutex proto_block;
+
+       struct work_struct setmacaddr_work;
+       struct work_struct multicast_work;
+       u8 macvalue[ETH_ALEN];
+       atomic_t pend_8021x_cnt;
 };
 
 struct brcmf_if_event {
@@ -682,73 +632,33 @@ extern const struct bcmevent_name bcmevent_names[];
 extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
                          char *buf, uint len);
 
-/* Indication from bus module regarding presence/insertion of dongle.
- * Return struct brcmf_pub pointer, used as handle to OS module in later calls.
- * Returned structure should have bus and prot pointers filled in.
- * bus_hdrlen specifies required headroom for bus module header.
- */
-extern struct brcmf_pub *brcmf_attach(struct brcmf_sdio *bus,
-                                     uint bus_hdrlen, struct device *dev);
 extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
 extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
 
 extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
 
-/* Indication from bus module regarding removal/absence of dongle */
-extern void brcmf_detach(struct brcmf_pub *drvr);
-
-/* Indication from bus module to change flow-control state */
-extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on);
-
-extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
-                        struct sk_buff *pkt, int prec);
-
-/* Receive frame for delivery to OS.  Callee disposes of rxp. */
-extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
-                          struct sk_buff_head *rxlist);
-static inline void brcmf_rx_packet(struct brcmf_pub *drvr, int ifidx,
-                                  struct sk_buff *pkt)
-{
-       struct sk_buff_head q;
-
-       skb_queue_head_init(&q);
-       skb_queue_tail(&q, pkt);
-       brcmf_rx_frame(drvr, ifidx, &q);
-}
-
 /* Return pointer to interface name */
 extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
 
-/* Notify tx completion */
-extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
-                            bool success);
-
 /* Query dongle */
 extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
                                       uint cmd, void *buf, uint len);
 
-/* OS independent layer functions */
-extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
-extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
 #ifdef BCMDBG
 extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
 #endif                         /* BCMDBG */
 
-extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
-extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
+extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
+extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
                              void *pktdata, struct brcmf_event_msg *,
                              void **data_ptr);
 
-extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
-                       char *name, u8 *mac_addr);
-extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
+extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
 
 /* Send packet to dongle via data channel */
 extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
                         struct sk_buff *pkt);
 
-extern int brcmf_bus_start(struct brcmf_pub *drvr);
-
 extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
 extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
                                             int enable, int master_mode);
@@ -757,25 +667,4 @@ extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
 #define BRCMF_DCMD_MEDLEN      1536    /* "med" cmd buffer required */
 #define        BRCMF_DCMD_MAXLEN       8192    /* max length cmd buffer required */
 
-/* message levels */
-#define BRCMF_ERROR_VAL        0x0001
-#define BRCMF_TRACE_VAL        0x0002
-#define BRCMF_INFO_VAL 0x0004
-#define BRCMF_DATA_VAL 0x0008
-#define BRCMF_CTL_VAL  0x0010
-#define BRCMF_TIMER_VAL        0x0020
-#define BRCMF_HDRS_VAL 0x0040
-#define BRCMF_BYTES_VAL        0x0080
-#define BRCMF_INTR_VAL 0x0100
-#define BRCMF_GLOM_VAL 0x0400
-#define BRCMF_EVENT_VAL        0x0800
-#define BRCMF_BTA_VAL  0x1000
-#define BRCMF_ISCAN_VAL 0x2000
-
-/* Enter idle immediately (no timeout) */
-#define BRCMF_IDLE_IMMEDIATE   (-1)
-#define BRCMF_IDLE_ACTIVE      0       /* Do not request any SD clock change
-                                when idle */
-#define BRCMF_IDLE_INTERVAL    1
-
 #endif                         /* _BRCMF_H_ */
index 1841f996110b0c36f54e57fb4970d086936675fe..ad9be2410b59337158879fe301673433d68d6320 100644 (file)
 #ifndef _BRCMF_BUS_H_
 #define _BRCMF_BUS_H_
 
-/* Packet alignment for most efficient SDIO (can change based on platform) */
-#define BRCMF_SDALIGN  (1 << 6)
+/* The level of bus communication with the dongle */
+enum brcmf_bus_state {
+       BRCMF_BUS_DOWN,         /* Not ready for frame transfers */
+       BRCMF_BUS_LOAD,         /* Download access only (CPU reset) */
+       BRCMF_BUS_DATA          /* Ready for frame transfers */
+};
 
-/* watchdog polling interval in ms */
-#define BRCMF_WD_POLL_MS       10
+struct dngl_stats {
+       unsigned long rx_packets;       /* total packets received */
+       unsigned long tx_packets;       /* total packets transmitted */
+       unsigned long rx_bytes; /* total bytes received */
+       unsigned long tx_bytes; /* total bytes transmitted */
+       unsigned long rx_errors;        /* bad packets received */
+       unsigned long tx_errors;        /* packet transmit problems */
+       unsigned long rx_dropped;       /* packets dropped by dongle */
+       unsigned long tx_dropped;       /* packets dropped by dongle */
+       unsigned long multicast;        /* multicast packets received */
+};
+
+/* interface structure between common and bus layer */
+struct brcmf_bus {
+       u8 type;                /* bus type */
+       void *bus_priv;         /* pointer to bus private structure */
+       void *drvr;             /* pointer to driver pub structure brcmf_pub */
+       enum brcmf_bus_state state;
+       uint maxctl;            /* Max size rxctl request from proto to bus */
+       bool drvr_up;           /* Status flag of driver up/down */
+       unsigned long tx_realloc;       /* Tx packets realloced for headroom */
+       struct dngl_stats dstats;       /* Stats for dongle-based data */
+       u8 align;               /* bus alignment requirement */
+
+       /* interface functions pointers */
+       /* Stop bus module: clear pending frames, disable data flow */
+       void (*brcmf_bus_stop)(struct device *);
+       /* Initialize bus module: prepare for communication w/dongle */
+       int (*brcmf_bus_init)(struct device *);
+       /* Send a data frame to the dongle.  Callee disposes of txp. */
+       int (*brcmf_bus_txdata)(struct device *, struct sk_buff *);
+       /* Send/receive a control message to/from the dongle.
+        * Expects caller to enforce a single outstanding transaction.
+        */
+       int (*brcmf_bus_txctl)(struct device *, unsigned char *, uint);
+       int (*brcmf_bus_rxctl)(struct device *, unsigned char *, uint);
+};
 
 /*
- * Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
+ * interface functions from common layer
  */
 
-/* Stop bus module: clear pending frames, disable data flow */
-extern void brcmf_sdbrcm_bus_stop(struct device *dev);
+/* Remove any protocol-specific data header. */
+extern int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
+                              struct sk_buff *rxp);
 
-/* Initialize bus module: prepare for communication w/dongle */
-extern int brcmf_sdbrcm_bus_init(struct device *dev);
+extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
+                        struct sk_buff *pkt, int prec);
 
-/* Send a data frame to the dongle.  Callee disposes of txp. */
-extern int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *txp);
+/* Receive frame for delivery to OS.  Callee disposes of rxp. */
+extern void brcmf_rx_frame(struct device *dev, int ifidx,
+                          struct sk_buff_head *rxlist);
+static inline void brcmf_rx_packet(struct device *dev, int ifidx,
+                                  struct sk_buff *pkt)
+{
+       struct sk_buff_head q;
 
-/* Send/receive a control message to/from the dongle.
- * Expects caller to enforce a single outstanding transaction.
- */
-extern int
-brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen);
+       skb_queue_head_init(&q);
+       skb_queue_tail(&q, pkt);
+       brcmf_rx_frame(dev, ifidx, &q);
+}
+
+/* Indication from bus module regarding presence/insertion of dongle. */
+extern int brcmf_attach(uint bus_hdrlen, struct device *dev);
+/* Indication from bus module regarding removal/absence of dongle */
+extern void brcmf_detach(struct device *dev);
+
+/* Indication from bus module to change flow-control state */
+extern void brcmf_txflowcontrol(struct device *dev, int ifidx, bool on);
 
-extern int
-brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen);
+/* Notify tx completion */
+extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
+                            bool success);
 
-extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
+extern int brcmf_bus_start(struct device *dev);
 
+extern int brcmf_add_if(struct device *dev, int ifidx,
+                       char *name, u8 *mac_addr);
 #endif                         /* _BRCMF_BUS_H_ */
index ebd53aa7202bcff86ad480a00ca7a6bbea395ae8..ac8d1f4378886c53d2678c5ab763a9bfd6b87951 100644 (file)
@@ -82,13 +82,14 @@ struct brcmf_proto_bdc_header {
 
 
 #define RETRIES 2 /* # of retries to retrieve matching dcmd response */
-#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
+#define BUS_HEADER_LEN (16+64)         /* Must be atleast SDPCM_RESERVE
                                         * (amount of header tha might be added)
                                         * plus any space that might be needed
-                                        * for alignment padding.
+                                        * for bus alignment padding.
                                         */
-#define ROUND_UP_MARGIN        2048    /* Biggest SDIO block size possible for
+#define ROUND_UP_MARGIN        2048    /* Biggest bus block size possible for
                                 * round off at the end of buffer
+                                * Currently is SDIO
                                 */
 
 struct brcmf_proto {
@@ -116,8 +117,9 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
                len = CDC_MAX_MSG_SIZE;
 
        /* Send request */
-       return brcmf_sdbrcm_bus_txctl(drvr->dev, (unsigned char *)&prot->msg,
-                                     len);
+       return drvr->bus_if->brcmf_bus_txctl(drvr->dev,
+                                            (unsigned char *)&prot->msg,
+                                            len);
 }
 
 static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
@@ -128,7 +130,7 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
        brcmf_dbg(TRACE, "Enter\n");
 
        do {
-               ret = brcmf_sdbrcm_bus_rxctl(drvr->dev,
+               ret = drvr->bus_if->brcmf_bus_rxctl(drvr->dev,
                                (unsigned char *)&prot->msg,
                                len + sizeof(struct brcmf_proto_cdc_dcmd));
                if (ret < 0)
@@ -284,7 +286,7 @@ brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
                brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
                return ret;
        }
-       brcmf_os_proto_block(drvr);
+       mutex_lock(&drvr->proto_block);
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -338,7 +340,7 @@ brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd,
        prot->pending = false;
 
 done:
-       brcmf_os_proto_unblock(drvr);
+       mutex_unlock(&drvr->proto_block);
 
        return ret;
 }
@@ -376,10 +378,12 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
        BDC_SET_IF_IDX(h, ifidx);
 }
 
-int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
+int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
                        struct sk_buff *pktbuf)
 {
        struct brcmf_proto_bdc_header *h;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -435,7 +439,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
 
        drvr->prot = cdc;
        drvr->hdrlen += BDC_HEADER_LEN;
-       drvr->maxctl = BRCMF_DCMD_MAXLEN +
+       drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
                        sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
        return 0;
 
@@ -451,18 +455,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)
        drvr->prot = NULL;
 }
 
-void brcmf_proto_dstats(struct brcmf_pub *drvr)
-{
-       /* No stats from dongle added yet, copy bus stats */
-       drvr->dstats.tx_packets = drvr->tx_packets;
-       drvr->dstats.tx_errors = drvr->tx_errors;
-       drvr->dstats.rx_packets = drvr->rx_packets;
-       drvr->dstats.rx_errors = drvr->rx_errors;
-       drvr->dstats.rx_dropped = drvr->rx_dropped;
-       drvr->dstats.multicast = drvr->rx_multicast;
-       return;
-}
-
 int brcmf_proto_init(struct brcmf_pub *drvr)
 {
        int ret = 0;
@@ -470,19 +462,19 @@ int brcmf_proto_init(struct brcmf_pub *drvr)
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       brcmf_os_proto_block(drvr);
+       mutex_lock(&drvr->proto_block);
 
        /* Get the device MAC address */
        strcpy(buf, "cur_etheraddr");
        ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
                                          buf, sizeof(buf));
        if (ret < 0) {
-               brcmf_os_proto_unblock(drvr);
+               mutex_unlock(&drvr->proto_block);
                return ret;
        }
        memcpy(drvr->mac, buf, ETH_ALEN);
 
-       brcmf_os_proto_unblock(drvr);
+       mutex_unlock(&drvr->proto_block);
 
        ret = brcmf_c_preinit_dcmds(drvr);
 
index 69f335aeb255aa8a4a626db621120e7525014ed3..a51d8f5d36fcf843bf311e5e257d560bb134e134 100644 (file)
@@ -83,12 +83,14 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
        return len;
 }
 
-bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
+bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
                      struct sk_buff *pkt, int prec)
 {
        struct sk_buff *p;
        int eprec = -1;         /* precedence to evict from */
        bool discard_oldest;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        /* Fast case, precedence queue is not full and we are also not
         * exceeding total queue length
@@ -431,7 +433,7 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
 #endif                         /* BCMDBG */
 
 int
-brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
+brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
                   struct brcmf_event_msg *event, void **data_ptr)
 {
        /* check whether packet is a BRCM event pkt */
@@ -473,18 +475,18 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
 
                if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
                        if (ifevent->action == BRCMF_E_IF_ADD)
-                               brcmf_add_if(drvr_priv, ifevent->ifidx,
+                               brcmf_add_if(drvr->dev, ifevent->ifidx,
                                             event->ifname,
                                             pvt_data->eth.h_dest);
                        else
-                               brcmf_del_if(drvr_priv, ifevent->ifidx);
+                               brcmf_del_if(drvr, ifevent->ifidx);
                } else {
                        brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
                                  ifevent->ifidx, event->ifname);
                }
 
                /* send up the if event: btamp user needs it */
-               *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
+               *ifidx = brcmf_ifname2idx(drvr, event->ifname);
                break;
 
                /* These are what external supplicant/authenticator wants */
@@ -496,7 +498,7 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
        default:
                /* Fall through: this should get _everything_  */
 
-               *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
+               *ifidx = brcmf_ifname2idx(drvr, event->ifname);
                brcmf_dbg(TRACE, "MAC event %d, flags %x, status %x\n",
                          type, flags, status);
 
@@ -796,7 +798,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
                                 "event_msgs" + '\0' + bitvec  */
        uint up = 0;
        char buf[128], *ptr;
-       u32 dongle_align = BRCMF_SDALIGN;
+       u32 dongle_align = drvr->bus_if->align;
        u32 glom = 0;
        u32 roaming = 1;
        uint bcn_timeout = 3;
@@ -804,7 +806,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
        int scan_unassoc_time = 40;
        int i;
 
-       brcmf_os_proto_block(drvr);
+       mutex_lock(&drvr->proto_block);
 
        /* Set Country code */
        if (drvr->country_code[0] != 0) {
@@ -873,7 +875,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
                                                 0, true);
        }
 
-       brcmf_os_proto_unblock(drvr);
+       mutex_unlock(&drvr->proto_block);
 
        return 0;
 }
index 7467922f0536fd6b1ded500b3f85ba511894ab47..bb26ee36bc6894e3223f35b2838e391892a947c4 100644 (file)
 #ifndef _BRCMF_DBG_H_
 #define _BRCMF_DBG_H_
 
+/* message levels */
+#define BRCMF_ERROR_VAL        0x0001
+#define BRCMF_TRACE_VAL        0x0002
+#define BRCMF_INFO_VAL 0x0004
+#define BRCMF_DATA_VAL 0x0008
+#define BRCMF_CTL_VAL  0x0010
+#define BRCMF_TIMER_VAL        0x0020
+#define BRCMF_HDRS_VAL 0x0040
+#define BRCMF_BYTES_VAL        0x0080
+#define BRCMF_INTR_VAL 0x0100
+#define BRCMF_GLOM_VAL 0x0400
+#define BRCMF_EVENT_VAL        0x0800
+#define BRCMF_BTA_VAL  0x1000
+#define BRCMF_ISCAN_VAL 0x2000
+
 #if defined(BCMDBG)
 
 #define brcmf_dbg(level, fmt, ...)                                     \
index 2c3a99d6c9a6d40981e2fb369ad54f2f336dd411..eb9eb766ac270d5e3011b98568343eeba12c5833 100644 (file)
@@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 /* Interface control information */
 struct brcmf_if {
-       struct brcmf_info *info;        /* back pointer to brcmf_info */
+       struct brcmf_pub *drvr; /* back pointer to brcmf_pub */
        /* OS/stack specifics */
        struct net_device *ndev;
        struct net_device_stats stats;
@@ -60,26 +60,11 @@ struct brcmf_if {
        u8 mac_addr[ETH_ALEN];  /* assigned MAC address */
 };
 
-/* Local private structure (extension of pub) */
-struct brcmf_info {
-       struct brcmf_pub pub;
-
-       /* OS/stack specifics */
-       struct brcmf_if *iflist[BRCMF_MAX_IFS];
-
-       struct mutex proto_block;
-
-       struct work_struct setmacaddr_work;
-       struct work_struct multicast_work;
-       u8 macvalue[ETH_ALEN];
-       atomic_t pend_8021x_cnt;
-};
-
 /* Error bits */
 int brcmf_msg_level = BRCMF_ERROR_VAL;
 module_param(brcmf_msg_level, int, 0);
 
-int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
+int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name)
 {
        int i = BRCMF_MAX_IFS;
        struct brcmf_if *ifp;
@@ -88,7 +73,7 @@ int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
                return 0;
 
        while (--i > 0) {
-               ifp = drvr_priv->iflist[i];
+               ifp = drvr->iflist[i];
                if (ifp && !strncmp(ifp->ndev->name, name, IFNAMSIZ))
                        break;
        }
@@ -100,20 +85,18 @@ int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
 
 char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
 {
-       struct brcmf_info *drvr_priv = drvr->info;
-
        if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
                brcmf_dbg(ERROR, "ifidx %d out of range\n", ifidx);
                return "<if_bad>";
        }
 
-       if (drvr_priv->iflist[ifidx] == NULL) {
+       if (drvr->iflist[ifidx] == NULL) {
                brcmf_dbg(ERROR, "null i/f %d\n", ifidx);
                return "<if_null>";
        }
 
-       if (drvr_priv->iflist[ifidx]->ndev)
-               return drvr_priv->iflist[ifidx]->ndev->name;
+       if (drvr->iflist[ifidx]->ndev)
+               return drvr->iflist[ifidx]->ndev->name;
 
        return "<if_none>";
 }
@@ -131,10 +114,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
        uint buflen;
        int ret;
 
-       struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+       struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
                                                    multicast_work);
 
-       ndev = drvr_priv->iflist[0]->ndev;
+       ndev = drvr->iflist[0]->ndev;
        cnt = netdev_mc_count(ndev);
 
        /* Determine initial value of allmulti flag */
@@ -168,10 +151,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
        dcmd.len = buflen;
        dcmd.set = true;
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
        if (ret < 0) {
                brcmf_dbg(ERROR, "%s: set mcast_list failed, cnt %d\n",
-                         brcmf_ifname(&drvr_priv->pub, 0), cnt);
+                         brcmf_ifname(drvr, 0), cnt);
                dcmd_value = cnt ? true : dcmd_value;
        }
 
@@ -193,7 +176,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
            ("allmulti", (void *)&dcmd_le_value,
            sizeof(dcmd_le_value), buf, buflen)) {
                brcmf_dbg(ERROR, "%s: mkiovar failed for allmulti, datalen %d buflen %u\n",
-                         brcmf_ifname(&drvr_priv->pub, 0),
+                         brcmf_ifname(drvr, 0),
                          (int)sizeof(dcmd_value), buflen);
                kfree(buf);
                return;
@@ -205,10 +188,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
        dcmd.len = buflen;
        dcmd.set = true;
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
        if (ret < 0) {
                brcmf_dbg(ERROR, "%s: set allmulti %d failed\n",
-                         brcmf_ifname(&drvr_priv->pub, 0),
+                         brcmf_ifname(drvr, 0),
                          le32_to_cpu(dcmd_le_value));
        }
 
@@ -226,10 +209,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
        dcmd.len = sizeof(dcmd_le_value);
        dcmd.set = true;
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
        if (ret < 0) {
                brcmf_dbg(ERROR, "%s: set promisc %d failed\n",
-                         brcmf_ifname(&drvr_priv->pub, 0),
+                         brcmf_ifname(drvr, 0),
                          le32_to_cpu(dcmd_le_value));
        }
 }
@@ -241,14 +224,14 @@ _brcmf_set_mac_address(struct work_struct *work)
        struct brcmf_dcmd dcmd;
        int ret;
 
-       struct brcmf_info *drvr_priv = container_of(work, struct brcmf_info,
+       struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
                                                    setmacaddr_work);
 
        brcmf_dbg(TRACE, "enter\n");
-       if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr_priv->macvalue,
+       if (!brcmf_c_mkiovar("cur_etheraddr", (char *)drvr->macvalue,
                           ETH_ALEN, buf, 32)) {
                brcmf_dbg(ERROR, "%s: mkiovar failed for cur_etheraddr\n",
-                         brcmf_ifname(&drvr_priv->pub, 0));
+                         brcmf_ifname(drvr, 0));
                return;
        }
        memset(&dcmd, 0, sizeof(dcmd));
@@ -257,13 +240,13 @@ _brcmf_set_mac_address(struct work_struct *work)
        dcmd.len = 32;
        dcmd.set = true;
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, 0, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, 0, &dcmd, dcmd.len);
        if (ret < 0)
                brcmf_dbg(ERROR, "%s: set cur_etheraddr failed\n",
-                         brcmf_ifname(&drvr_priv->pub, 0));
+                         brcmf_ifname(drvr, 0));
        else
-               memcpy(drvr_priv->iflist[0]->ndev->dev_addr,
-                      drvr_priv->macvalue, ETH_ALEN);
+               memcpy(drvr->iflist[0]->ndev->dev_addr,
+                      drvr->macvalue, ETH_ALEN);
 
        return;
 }
@@ -271,28 +254,26 @@ _brcmf_set_mac_address(struct work_struct *work)
 static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
        struct sockaddr *sa = (struct sockaddr *)addr;
 
-       memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
-       schedule_work(&drvr_priv->setmacaddr_work);
+       memcpy(&drvr->macvalue, sa->sa_data, ETH_ALEN);
+       schedule_work(&drvr->setmacaddr_work);
        return 0;
 }
 
 static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
 
-       schedule_work(&drvr_priv->multicast_work);
+       schedule_work(&drvr->multicast_work);
 }
 
 int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
 {
-       struct brcmf_info *drvr_priv = drvr->info;
-
        /* Reject if down */
-       if (!drvr->up || (drvr->bus_if->state == BRCMF_BUS_DOWN))
+       if (!drvr->bus_if->drvr_up || (drvr->bus_if->state == BRCMF_BUS_DOWN))
                return -ENODEV;
 
        /* Update multicast statistic */
@@ -303,112 +284,113 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
                if (is_multicast_ether_addr(eh->h_dest))
                        drvr->tx_multicast++;
                if (ntohs(eh->h_proto) == ETH_P_PAE)
-                       atomic_inc(&drvr_priv->pend_8021x_cnt);
+                       atomic_inc(&drvr->pend_8021x_cnt);
        }
 
        /* If the protocol uses a data header, apply it */
        brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
 
        /* Use bus module to send data frame */
-       return brcmf_sdbrcm_bus_txdata(drvr->dev, pktbuf);
+       return drvr->bus_if->brcmf_bus_txdata(drvr->dev, pktbuf);
 }
 
 static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        int ret;
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
        /* Reject if down */
-       if (!drvr_priv->pub.up ||
-           (drvr_priv->pub.bus_if->state == BRCMF_BUS_DOWN)) {
-               brcmf_dbg(ERROR, "xmit rejected pub.up=%d state=%d\n",
-                         drvr_priv->pub.up,
-                         drvr_priv->pub.bus_if->state);
+       if (!drvr->bus_if->drvr_up ||
+           (drvr->bus_if->state == BRCMF_BUS_DOWN)) {
+               brcmf_dbg(ERROR, "xmit rejected drvup=%d state=%d\n",
+                         drvr->bus_if->drvr_up,
+                         drvr->bus_if->state);
                netif_stop_queue(ndev);
                return -ENODEV;
        }
 
-       if (!drvr_priv->iflist[ifp->idx]) {
+       if (!drvr->iflist[ifp->idx]) {
                brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
                netif_stop_queue(ndev);
                return -ENODEV;
        }
 
        /* Make sure there's enough room for any header */
-       if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
+       if (skb_headroom(skb) < drvr->hdrlen) {
                struct sk_buff *skb2;
 
                brcmf_dbg(INFO, "%s: insufficient headroom\n",
-                         brcmf_ifname(&drvr_priv->pub, ifp->idx));
-               drvr_priv->pub.tx_realloc++;
-               skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
+                         brcmf_ifname(drvr, ifp->idx));
+               drvr->bus_if->tx_realloc++;
+               skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
                dev_kfree_skb(skb);
                skb = skb2;
                if (skb == NULL) {
                        brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
-                                 brcmf_ifname(&drvr_priv->pub, ifp->idx));
+                                 brcmf_ifname(drvr, ifp->idx));
                        ret = -ENOMEM;
                        goto done;
                }
        }
 
-       ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
+       ret = brcmf_sendpkt(drvr, ifp->idx, skb);
 
 done:
        if (ret)
-               drvr_priv->pub.dstats.tx_dropped++;
+               drvr->bus_if->dstats.tx_dropped++;
        else
-               drvr_priv->pub.tx_packets++;
+               drvr->bus_if->dstats.tx_packets++;
 
        /* Return ok: we always eat the packet */
        return 0;
 }
 
-void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
+void brcmf_txflowcontrol(struct device *dev, int ifidx, bool state)
 {
        struct net_device *ndev;
-       struct brcmf_info *drvr_priv = drvr->info;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       drvr->txoff = state;
-       ndev = drvr_priv->iflist[ifidx]->ndev;
+       ndev = drvr->iflist[ifidx]->ndev;
        if (state == ON)
                netif_stop_queue(ndev);
        else
                netif_wake_queue(ndev);
 }
 
-static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
+static int brcmf_host_event(struct brcmf_pub *drvr, int *ifidx,
                            void *pktdata, struct brcmf_event_msg *event,
                            void **data)
 {
        int bcmerror = 0;
 
-       bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
+       bcmerror = brcmf_c_host_event(drvr, ifidx, pktdata, event, data);
        if (bcmerror != 0)
                return bcmerror;
 
-       if (drvr_priv->iflist[*ifidx]->ndev)
-               brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->ndev,
+       if (drvr->iflist[*ifidx]->ndev)
+               brcmf_cfg80211_event(drvr->iflist[*ifidx]->ndev,
                                     event, *data);
 
        return bcmerror;
 }
 
-void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
+void brcmf_rx_frame(struct device *dev, int ifidx,
                    struct sk_buff_head *skb_list)
 {
-       struct brcmf_info *drvr_priv = drvr->info;
        unsigned char *eth;
        uint len;
        void *data;
        struct sk_buff *skb, *pnext;
        struct brcmf_if *ifp;
        struct brcmf_event_msg event;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -430,9 +412,9 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
                eth = skb->data;
                len = skb->len;
 
-               ifp = drvr_priv->iflist[ifidx];
+               ifp = drvr->iflist[ifidx];
                if (ifp == NULL)
-                       ifp = drvr_priv->iflist[0];
+                       ifp = drvr->iflist[0];
 
                if (!ifp || !ifp->ndev ||
                    ifp->ndev->reg_state != NETREG_REGISTERED) {
@@ -444,7 +426,7 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
                skb->protocol = eth_type_trans(skb, skb->dev);
 
                if (skb->pkt_type == PACKET_MULTICAST)
-                       drvr_priv->pub.rx_multicast++;
+                       bus_if->dstats.multicast++;
 
                skb->data = eth;
                skb->len = len;
@@ -454,17 +436,17 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
 
                /* Process special event packets and then discard them */
                if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
-                       brcmf_host_event(drvr_priv, &ifidx,
+                       brcmf_host_event(drvr, &ifidx,
                                          skb_mac_header(skb),
                                          &event, &data);
 
-               if (drvr_priv->iflist[ifidx]) {
-                       ifp = drvr_priv->iflist[ifidx];
+               if (drvr->iflist[ifidx]) {
+                       ifp = drvr->iflist[ifidx];
                        ifp->ndev->last_rx = jiffies;
                }
 
-               drvr->dstats.rx_bytes += skb->len;
-               drvr->rx_packets++;     /* Local count */
+               bus_if->dstats.rx_bytes += skb->len;
+               bus_if->dstats.rx_packets++;    /* Local count */
 
                if (in_interrupt())
                        netif_rx(skb);
@@ -479,51 +461,48 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
        }
 }
 
-void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
+void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
 {
        uint ifidx;
-       struct brcmf_info *drvr_priv = drvr->info;
        struct ethhdr *eh;
        u16 type;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
-       brcmf_proto_hdrpull(drvr, &ifidx, txp);
+       brcmf_proto_hdrpull(dev, &ifidx, txp);
 
        eh = (struct ethhdr *)(txp->data);
        type = ntohs(eh->h_proto);
 
        if (type == ETH_P_PAE)
-               atomic_dec(&drvr_priv->pend_8021x_cnt);
+               atomic_dec(&drvr->pend_8021x_cnt);
 
 }
 
 static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_bus *bus_if = ifp->drvr->bus_if;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       if (drvr_priv->pub.up)
-               /* Use the protocol to get dongle stats */
-               brcmf_proto_dstats(&drvr_priv->pub);
-
        /* Copy dongle stats to net device stats */
-       ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
-       ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets;
-       ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes;
-       ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes;
-       ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors;
-       ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors;
-       ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped;
-       ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped;
-       ifp->stats.multicast = drvr_priv->pub.dstats.multicast;
+       ifp->stats.rx_packets = bus_if->dstats.rx_packets;
+       ifp->stats.tx_packets = bus_if->dstats.tx_packets;
+       ifp->stats.rx_bytes = bus_if->dstats.rx_bytes;
+       ifp->stats.tx_bytes = bus_if->dstats.tx_bytes;
+       ifp->stats.rx_errors = bus_if->dstats.rx_errors;
+       ifp->stats.tx_errors = bus_if->dstats.tx_errors;
+       ifp->stats.rx_dropped = bus_if->dstats.rx_dropped;
+       ifp->stats.tx_dropped = bus_if->dstats.tx_dropped;
+       ifp->stats.multicast = bus_if->dstats.multicast;
 
        return &ifp->stats;
 }
 
 /* Retrieve current toe component enables, which are kept
         as a bitmap in toe_ol iovar */
-static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
+static int brcmf_toe_get(struct brcmf_pub *drvr, int ifidx, u32 *toe_ol)
 {
        struct brcmf_dcmd dcmd;
        __le32 toe_le;
@@ -538,17 +517,17 @@ static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
        dcmd.set = false;
 
        strcpy(buf, "toe_ol");
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
        if (ret < 0) {
                /* Check for older dongle image that doesn't support toe_ol */
                if (ret == -EIO) {
                        brcmf_dbg(ERROR, "%s: toe not supported by device\n",
-                                 brcmf_ifname(&drvr_priv->pub, ifidx));
+                                 brcmf_ifname(drvr, ifidx));
                        return -EOPNOTSUPP;
                }
 
                brcmf_dbg(INFO, "%s: could not get toe_ol: ret=%d\n",
-                         brcmf_ifname(&drvr_priv->pub, ifidx), ret);
+                         brcmf_ifname(drvr, ifidx), ret);
                return ret;
        }
 
@@ -559,7 +538,7 @@ static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
 
 /* Set current toe component enables in toe_ol iovar,
         and set toe global enable iovar */
-static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
+static int brcmf_toe_set(struct brcmf_pub *drvr, int ifidx, u32 toe_ol)
 {
        struct brcmf_dcmd dcmd;
        char buf[32];
@@ -577,10 +556,10 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
        strcpy(buf, "toe_ol");
        memcpy(&buf[sizeof("toe_ol")], &toe_le, sizeof(u32));
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
        if (ret < 0) {
                brcmf_dbg(ERROR, "%s: could not set toe_ol: ret=%d\n",
-                         brcmf_ifname(&drvr_priv->pub, ifidx), ret);
+                         brcmf_ifname(drvr, ifidx), ret);
                return ret;
        }
 
@@ -590,10 +569,10 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
        strcpy(buf, "toe");
        memcpy(&buf[sizeof("toe")], &toe_le, sizeof(u32));
 
-       ret = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, dcmd.len);
+       ret = brcmf_proto_dcmd(drvr, ifidx, &dcmd, dcmd.len);
        if (ret < 0) {
                brcmf_dbg(ERROR, "%s: could not set toe: ret=%d\n",
-                         brcmf_ifname(&drvr_priv->pub, ifidx), ret);
+                         brcmf_ifname(drvr, ifidx), ret);
                return ret;
        }
 
@@ -604,18 +583,18 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
                                    struct ethtool_drvinfo *info)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
 
        sprintf(info->driver, KBUILD_MODNAME);
-       sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
-       sprintf(info->bus_info, "%s", dev_name(drvr_priv->pub.dev));
+       sprintf(info->version, "%lu", drvr->drv_version);
+       sprintf(info->bus_info, "%s", dev_name(drvr->dev));
 }
 
 static struct ethtool_ops brcmf_ethtool_ops = {
        .get_drvinfo = brcmf_ethtool_get_drvinfo
 };
 
-static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
+static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
 {
        struct ethtool_drvinfo info;
        char drvname[sizeof(info.driver)];
@@ -649,18 +628,18 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
                }
 
                /* otherwise, require dongle to be up */
-               else if (!drvr_priv->pub.up) {
+               else if (!drvr->bus_if->drvr_up) {
                        brcmf_dbg(ERROR, "dongle is not up\n");
                        return -ENODEV;
                }
 
                /* finally, report dongle driver type */
-               else if (drvr_priv->pub.iswl)
+               else if (drvr->iswl)
                        sprintf(info.driver, "wl");
                else
                        sprintf(info.driver, "xx");
 
-               sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
+               sprintf(info.version, "%lu", drvr->drv_version);
                if (copy_to_user(uaddr, &info, sizeof(info)))
                        return -EFAULT;
                brcmf_dbg(CTL, "given %*s, returning %s\n",
@@ -670,7 +649,7 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
                /* Get toe offload components from dongle */
        case ETHTOOL_GRXCSUM:
        case ETHTOOL_GTXCSUM:
-               ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
+               ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
                if (ret < 0)
                        return ret;
 
@@ -691,7 +670,7 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
                        return -EFAULT;
 
                /* Read the current settings, update and write back */
-               ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
+               ret = brcmf_toe_get(drvr, 0, &toe_cmpnt);
                if (ret < 0)
                        return ret;
 
@@ -703,17 +682,17 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
                else
                        toe_cmpnt &= ~csum_dir;
 
-               ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt);
+               ret = brcmf_toe_set(drvr, 0, toe_cmpnt);
                if (ret < 0)
                        return ret;
 
                /* If setting TX checksum mode, tell Linux the new mode */
                if (cmd == ETHTOOL_STXCSUM) {
                        if (edata.data)
-                               drvr_priv->iflist[0]->ndev->features |=
+                               drvr->iflist[0]->ndev->features |=
                                    NETIF_F_IP_CSUM;
                        else
-                               drvr_priv->iflist[0]->ndev->features &=
+                               drvr->iflist[0]->ndev->features &=
                                    ~NETIF_F_IP_CSUM;
                }
 
@@ -730,15 +709,15 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
                                    int cmd)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
 
        brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
 
-       if (!drvr_priv->iflist[ifp->idx])
+       if (!drvr->iflist[ifp->idx])
                return -1;
 
        if (cmd == SIOCETHTOOL)
-               return brcmf_ethtool(drvr_priv, ifr->ifr_data);
+               return brcmf_ethtool(drvr, ifr->ifr_data);
 
        return -EOPNOTSUPP;
 }
@@ -751,7 +730,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        int buflen = 0;
        bool is_set_key_cmd;
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
 
        memset(&dcmd, 0, sizeof(dcmd));
        dcmd.cmd = cmd;
@@ -762,13 +741,13 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
                buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
 
        /* send to dongle (must be up, and wl) */
-       if ((drvr_priv->pub.bus_if->state != BRCMF_BUS_DATA)) {
+       if ((drvr->bus_if->state != BRCMF_BUS_DATA)) {
                brcmf_dbg(ERROR, "DONGLE_DOWN\n");
                err = -EIO;
                goto done;
        }
 
-       if (!drvr_priv->pub.iswl) {
+       if (!drvr->iswl) {
                err = -EIO;
                goto done;
        }
@@ -785,7 +764,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        if (is_set_key_cmd)
                brcmf_netdev_wait_pend8021x(ndev);
 
-       err = brcmf_proto_dcmd(&drvr_priv->pub, ifp->idx, &dcmd, buflen);
+       err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen);
 
 done:
        if (err > 0)
@@ -797,15 +776,15 @@ done:
 static int brcmf_netdev_stop(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_pub *drvr = &ifp->info->pub;
+       struct brcmf_pub *drvr = ifp->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
        brcmf_cfg80211_down(drvr->config);
-       if (drvr->up == 0)
+       if (drvr->bus_if->drvr_up == 0)
                return 0;
 
        /* Set state and stop OS transmissions */
-       drvr->up = false;
+       drvr->bus_if->drvr_up = false;
        netif_stop_queue(ndev);
 
        return 0;
@@ -814,7 +793,7 @@ static int brcmf_netdev_stop(struct net_device *ndev)
 static int brcmf_netdev_open(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
        u32 toe_ol;
        s32 ret = 0;
 
@@ -822,28 +801,28 @@ static int brcmf_netdev_open(struct net_device *ndev)
 
        if (ifp->idx == 0) {    /* do it only for primary eth0 */
                /* try to bring up bus */
-               ret = brcmf_bus_start(&drvr_priv->pub);
+               ret = brcmf_bus_start(drvr->dev);
                if (ret != 0) {
                        brcmf_dbg(ERROR, "failed with code %d\n", ret);
                        return -1;
                }
-               atomic_set(&drvr_priv->pend_8021x_cnt, 0);
+               atomic_set(&drvr->pend_8021x_cnt, 0);
 
-               memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
+               memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
 
                /* Get current TOE mode from dongle */
-               if (brcmf_toe_get(drvr_priv, ifp->idx, &toe_ol) >= 0
+               if (brcmf_toe_get(drvr, ifp->idx, &toe_ol) >= 0
                    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-                       drvr_priv->iflist[ifp->idx]->ndev->features |=
+                       drvr->iflist[ifp->idx]->ndev->features |=
                                NETIF_F_IP_CSUM;
                else
-                       drvr_priv->iflist[ifp->idx]->ndev->features &=
+                       drvr->iflist[ifp->idx]->ndev->features &=
                                ~NETIF_F_IP_CSUM;
        }
        /* Allow transmit calls */
        netif_start_queue(ndev);
-       drvr_priv->pub.up = true;
-       if (brcmf_cfg80211_up(drvr_priv->pub.config)) {
+       drvr->bus_if->drvr_up = true;
+       if (brcmf_cfg80211_up(drvr->config)) {
                brcmf_dbg(ERROR, "failed to bring up cfg80211\n");
                return -1;
        }
@@ -862,14 +841,16 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
 };
 
 int
-brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
+brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
 {
        struct brcmf_if *ifp;
        struct net_device *ndev;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "idx %d\n", ifidx);
 
-       ifp = drvr_priv->iflist[ifidx];
+       ifp = drvr->iflist[ifidx];
        /*
         * Delete the existing interface before overwriting it
         * in case we missed the BRCMF_E_IF_DEL event.
@@ -880,7 +861,7 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
                netif_stop_queue(ifp->ndev);
                unregister_netdev(ifp->ndev);
                free_netdev(ifp->ndev);
-               drvr_priv->iflist[ifidx] = NULL;
+               drvr->iflist[ifidx] = NULL;
        }
 
        /* Allocate netdev, including space for private structure */
@@ -892,16 +873,16 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
 
        ifp = netdev_priv(ndev);
        ifp->ndev = ndev;
-       ifp->info = drvr_priv;
-       drvr_priv->iflist[ifidx] = ifp;
+       ifp->drvr = drvr;
+       drvr->iflist[ifidx] = ifp;
        ifp->idx = ifidx;
        if (mac_addr != NULL)
                memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
 
-       if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
+       if (brcmf_net_attach(drvr, ifp->idx)) {
                brcmf_dbg(ERROR, "brcmf_net_attach failed");
                free_netdev(ifp->ndev);
-               drvr_priv->iflist[ifidx] = NULL;
+               drvr->iflist[ifidx] = NULL;
                return -EOPNOTSUPP;
        }
 
@@ -911,13 +892,13 @@ brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
        return 0;
 }
 
-void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
+void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
 {
        struct brcmf_if *ifp;
 
        brcmf_dbg(TRACE, "idx %d\n", ifidx);
 
-       ifp = drvr_priv->iflist[ifidx];
+       ifp = drvr->iflist[ifidx];
        if (!ifp) {
                brcmf_dbg(ERROR, "Null interface\n");
                return;
@@ -934,72 +915,70 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
                }
 
                unregister_netdev(ifp->ndev);
-               drvr_priv->iflist[ifidx] = NULL;
+               drvr->iflist[ifidx] = NULL;
                if (ifidx == 0)
-                       brcmf_cfg80211_detach(drvr_priv->pub.config);
+                       brcmf_cfg80211_detach(drvr->config);
                free_netdev(ifp->ndev);
        }
 }
 
-struct brcmf_pub *brcmf_attach(struct brcmf_sdio *bus, uint bus_hdrlen,
-                              struct device *dev)
+int brcmf_attach(uint bus_hdrlen, struct device *dev)
 {
-       struct brcmf_info *drvr_priv = NULL;
+       struct brcmf_pub *drvr = NULL;
+       int ret = 0;
 
        brcmf_dbg(TRACE, "Enter\n");
 
        /* Allocate primary brcmf_info */
-       drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
-       if (!drvr_priv)
-               goto fail;
-
-       mutex_init(&drvr_priv->proto_block);
+       drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
+       if (!drvr)
+               return -ENOMEM;
 
-       /* Link to info module */
-       drvr_priv->pub.info = drvr_priv;
+       mutex_init(&drvr->proto_block);
 
        /* Link to bus module */
-       drvr_priv->pub.bus = bus;
-       drvr_priv->pub.hdrlen = bus_hdrlen;
-       drvr_priv->pub.bus_if = dev_get_drvdata(dev);
-       drvr_priv->pub.dev = dev;
+       drvr->hdrlen = bus_hdrlen;
+       drvr->bus_if = dev_get_drvdata(dev);
+       drvr->bus_if->drvr = drvr;
+       drvr->dev = dev;
 
        /* Attach and link in the protocol */
-       if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
+       ret = brcmf_proto_attach(drvr);
+       if (ret != 0) {
                brcmf_dbg(ERROR, "brcmf_prot_attach failed\n");
                goto fail;
        }
 
-       INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
-       INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
+       INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
+       INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
 
-       return &drvr_priv->pub;
+       return ret;
 
 fail:
-       if (drvr_priv)
-               brcmf_detach(&drvr_priv->pub);
+       brcmf_detach(dev);
 
-       return NULL;
+       return ret;
 }
 
-int brcmf_bus_start(struct brcmf_pub *drvr)
+int brcmf_bus_start(struct device *dev)
 {
        int ret = -1;
-       struct brcmf_info *drvr_priv = drvr->info;
        /* Room for "event_msgs" + '\0' + bitvec */
        char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "\n");
 
        /* Bring up the bus */
-       ret = brcmf_sdbrcm_bus_init(drvr_priv->pub.dev);
+       ret = bus_if->brcmf_bus_init(dev);
        if (ret != 0) {
                brcmf_dbg(ERROR, "brcmf_sdbrcm_bus_init failed %d\n", ret);
                return ret;
        }
 
        /* If bus is not ready, can't come up */
-       if (drvr_priv->pub.bus_if->state != BRCMF_BUS_DATA) {
+       if (bus_if->state != BRCMF_BUS_DATA) {
                brcmf_dbg(ERROR, "failed bus is not ready\n");
                return -ENODEV;
        }
@@ -1036,7 +1015,7 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
        drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
 
        /* Bus is ready, do any protocol initialization */
-       ret = brcmf_proto_init(&drvr_priv->pub);
+       ret = brcmf_proto_init(drvr);
        if (ret < 0)
                return ret;
 
@@ -1045,14 +1024,13 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
 
 int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 {
-       struct brcmf_info *drvr_priv = drvr->info;
        struct net_device *ndev;
        u8 temp_addr[ETH_ALEN] = {
                0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
 
        brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
 
-       ndev = drvr_priv->iflist[ifidx]->ndev;
+       ndev = drvr->iflist[ifidx]->ndev;
        ndev->netdev_ops = &brcmf_netdev_ops_pri;
 
        /*
@@ -1060,7 +1038,7 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
         */
        if (ifidx != 0) {
                /* for virtual interfaces use the primary MAC  */
-               memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
+               memcpy(temp_addr, drvr->mac, ETH_ALEN);
 
        }
 
@@ -1071,11 +1049,11 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
                         - Locally Administered address  */
 
        }
-       ndev->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
+       ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
        ndev->ethtool_ops = &brcmf_ethtool_ops;
 
-       drvr_priv->pub.rxsz = ndev->mtu + ndev->hard_header_len +
-                             drvr_priv->pub.hdrlen;
+       drvr->rxsz = ndev->mtu + ndev->hard_header_len +
+                             drvr->hdrlen;
 
        memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
 
@@ -1104,77 +1082,46 @@ fail:
 
 static void brcmf_bus_detach(struct brcmf_pub *drvr)
 {
-       struct brcmf_info *drvr_priv;
-
        brcmf_dbg(TRACE, "Enter\n");
 
        if (drvr) {
-               drvr_priv = drvr->info;
-               if (drvr_priv) {
-                       /* Stop the protocol module */
-                       brcmf_proto_stop(&drvr_priv->pub);
+               /* Stop the protocol module */
+               brcmf_proto_stop(drvr);
 
-                       /* Stop the bus module */
-                       brcmf_sdbrcm_bus_stop(drvr_priv->pub.dev);
-               }
+               /* Stop the bus module */
+               drvr->bus_if->brcmf_bus_stop(drvr->dev);
        }
 }
 
-void brcmf_detach(struct brcmf_pub *drvr)
+void brcmf_detach(struct device *dev)
 {
-       struct brcmf_info *drvr_priv;
+       int i;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       if (drvr) {
-               drvr_priv = drvr->info;
-               if (drvr_priv) {
-                       int i;
 
-                       /* make sure primary interface removed last */
-                       for (i = BRCMF_MAX_IFS-1; i > -1; i--)
-                               if (drvr_priv->iflist[i])
-                                       brcmf_del_if(drvr_priv, i);
+       /* make sure primary interface removed last */
+       for (i = BRCMF_MAX_IFS-1; i > -1; i--)
+               if (drvr->iflist[i])
+                       brcmf_del_if(drvr, i);
 
-                       cancel_work_sync(&drvr_priv->setmacaddr_work);
-                       cancel_work_sync(&drvr_priv->multicast_work);
+       cancel_work_sync(&drvr->setmacaddr_work);
+       cancel_work_sync(&drvr->multicast_work);
 
-                       brcmf_bus_detach(drvr);
+       brcmf_bus_detach(drvr);
 
-                       if (drvr->prot)
-                               brcmf_proto_detach(drvr);
+       if (drvr->prot)
+               brcmf_proto_detach(drvr);
 
-                       kfree(drvr_priv);
-               }
-       }
-}
-
-int brcmf_os_proto_block(struct brcmf_pub *drvr)
-{
-       struct brcmf_info *drvr_priv = drvr->info;
-
-       if (drvr_priv) {
-               mutex_lock(&drvr_priv->proto_block);
-               return 1;
-       }
-       return 0;
-}
-
-int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
-{
-       struct brcmf_info *drvr_priv = drvr->info;
-
-       if (drvr_priv) {
-               mutex_unlock(&drvr_priv->proto_block);
-               return 1;
-       }
-
-       return 0;
+       bus_if->drvr = NULL;
+       kfree(drvr);
 }
 
-static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
+static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
 {
-       return atomic_read(&drvr_priv->pend_8021x_cnt);
+       return atomic_read(&drvr->pend_8021x_cnt);
 }
 
 #define MAX_WAIT_FOR_8021X_TX  10
@@ -1182,10 +1129,10 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
 int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_info *drvr_priv = ifp->info;
+       struct brcmf_pub *drvr = ifp->drvr;
        int timeout = 10 * HZ / 1000;
        int ntimes = MAX_WAIT_FOR_8021X_TX;
-       int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
+       int pend = brcmf_get_pend_8021x_cnt(drvr);
 
        while (ntimes && pend) {
                if (pend) {
@@ -1194,7 +1141,7 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
                        set_current_state(TASK_RUNNING);
                        ntimes--;
                }
-               pend = brcmf_get_pend_8021x_cnt(drvr_priv);
+               pend = brcmf_get_pend_8021x_cnt(drvr);
        }
        return pend;
 }
index 4ee1ea846f6d7f82718a4be0e9549e5a5ef7ad65..6bc4425a8b0f7ed40b3dbf43d513bcb0629802e6 100644 (file)
@@ -41,17 +41,10 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
 extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
                                struct sk_buff *txp);
 
-/* Remove any protocol-specific data header. */
-extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
-                              struct sk_buff *rxp);
-
 /* Use protocol to issue command to dongle */
 extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
                                struct brcmf_dcmd *dcmd, int len);
 
-/* Update local copy of dongle statistics */
-extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
-
 extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
 
 extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
index 43ba0dd48354ad922261c74120e857ff0da3974a..5a002a21f108aa23895ee59139c8fcb6ac37e643 100644 (file)
@@ -87,9 +87,7 @@ struct rte_console {
 #endif                         /* BCMDBG */
 #include <chipcommon.h>
 
-#include "dhd.h"
 #include "dhd_bus.h"
-#include "dhd_proto.h"
 #include "dhd_dbg.h"
 
 #define TXQLEN         2048    /* bulk tx queue length */
@@ -314,6 +312,12 @@ struct rte_console {
 MODULE_FIRMWARE(BRCMFMAC_FW_NAME);
 MODULE_FIRMWARE(BRCMFMAC_NV_NAME);
 
+#define BRCMF_IDLE_IMMEDIATE   (-1)    /* Enter idle immediately */
+#define BRCMF_IDLE_ACTIVE      0       /* Do not request any SD clock change
+                                        * when idle
+                                        */
+#define BRCMF_IDLE_INTERVAL    1
+
 /*
  * Conversion of 802.1D priority to precedence level
  */
@@ -450,8 +454,6 @@ struct sdpcm_shared_le {
 /* misc chip info needed by some of the routines */
 /* Private data for SDIO bus interaction */
 struct brcmf_sdio {
-       struct brcmf_pub *drvr;
-
        struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
        struct chip_info *ci;   /* Chip info struct */
        char *vars;             /* Variables (from CIS and/or other) */
@@ -546,6 +548,13 @@ struct brcmf_sdio {
        uint f2rxdata;          /* Number of frame data reads */
        uint f2txdata;          /* Number of f2 frame writes */
        uint f1regdata;         /* Number of f1 register accesses */
+       uint tickcnt;           /* Number of watchdog been schedule */
+       unsigned long tx_ctlerrs;       /* Err of sending ctrl frames */
+       unsigned long tx_ctlpkts;       /* Ctrl frames sent to dongle */
+       unsigned long rx_ctlerrs;       /* Err of processing rx ctrl frames */
+       unsigned long rx_ctlpkts;       /* Ctrl frames processed from dongle */
+       unsigned long rx_readahead_cnt; /* Number of packets where header
+                                        * read-ahead was used. */
 
        u8 *ctrl_frame_buf;
        u32 ctrl_frame_len;
@@ -568,6 +577,8 @@ struct brcmf_sdio {
 
        const struct firmware *firmware;
        u32 fw_ptr;
+
+       bool txoff;             /* Transmit flow-controlled */
 };
 
 /* clkstate */
@@ -1068,7 +1079,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
 
        /* If we can't reach the device, signal failure */
        if (err || brcmf_sdcard_regfail(bus->sdiodev))
-               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+               bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
 }
 
 /* copy a buffer into a pkt buffer chain */
@@ -1256,7 +1267,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                if (errcode < 0) {
                        brcmf_dbg(ERROR, "glom read of %d bytes failed: %d\n",
                                  dlen, errcode);
-                       bus->drvr->rx_errors++;
+                       bus->sdiodev->bus_if->dstats.rx_errors++;
 
                        if (bus->glomerr++ < 3) {
                                brcmf_sdbrcm_rxfail(bus, true, true);
@@ -1437,10 +1448,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                                skb_unlink(pfirst, &bus->glom);
                                brcmu_pkt_buf_free_skb(pfirst);
                                continue;
-                       } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
-                                                      pfirst) != 0) {
+                       } else if (brcmf_proto_hdrpull(bus->sdiodev->dev,
+                                                      &ifidx, pfirst) != 0) {
                                brcmf_dbg(ERROR, "rx protocol error\n");
-                               bus->drvr->rx_errors++;
+                               bus->sdiodev->bus_if->dstats.rx_errors++;
                                skb_unlink(pfirst, &bus->glom);
                                brcmu_pkt_buf_free_skb(pfirst);
                                continue;
@@ -1461,7 +1472,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                /* sent any remaining packets up */
                if (bus->glom.qlen) {
                        up(&bus->sdsem);
-                       brcmf_rx_frame(bus->drvr, ifidx, &bus->glom);
+                       brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
                        down(&bus->sdsem);
                }
 
@@ -1527,7 +1538,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
        if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
                pad = bus->blocksize - (rdlen % bus->blocksize);
                if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
-                   ((len + pad) < bus->drvr->maxctl))
+                   ((len + pad) < bus->sdiodev->bus_if->maxctl))
                        rdlen += pad;
        } else if (rdlen % BRCMF_SDALIGN) {
                rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
@@ -1538,18 +1549,18 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
                rdlen = roundup(rdlen, ALIGNMENT);
 
        /* Drop if the read is too big or it exceeds our maximum */
-       if ((rdlen + BRCMF_FIRSTREAD) > bus->drvr->maxctl) {
+       if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
                brcmf_dbg(ERROR, "%d-byte control read exceeds %d-byte buffer\n",
-                         rdlen, bus->drvr->maxctl);
-               bus->drvr->rx_errors++;
+                         rdlen, bus->sdiodev->bus_if->maxctl);
+               bus->sdiodev->bus_if->dstats.rx_errors++;
                brcmf_sdbrcm_rxfail(bus, false, false);
                goto done;
        }
 
-       if ((len - doff) > bus->drvr->maxctl) {
+       if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
                brcmf_dbg(ERROR, "%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
-                         len, len - doff, bus->drvr->maxctl);
-               bus->drvr->rx_errors++;
+                         len, len - doff, bus->sdiodev->bus_if->maxctl);
+               bus->sdiodev->bus_if->dstats.rx_errors++;
                bus->rx_toolong++;
                brcmf_sdbrcm_rxfail(bus, false, false);
                goto done;
@@ -1623,7 +1634,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen,
                brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n",
                          rdlen, sdret);
                brcmu_pkt_buf_free_skb(*pkt);
-               bus->drvr->rx_errors++;
+               bus->sdiodev->bus_if->dstats.rx_errors++;
                /* Force retry w/normal header read.
                 * Don't attempt NAK for
                 * gSPI
@@ -1715,7 +1726,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
 
        for (rxseq = bus->rx_seq, rxleft = maxframes;
             !bus->rxskip && rxleft &&
-            bus->drvr->bus_if->state != BRCMF_BUS_DOWN;
+            bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN;
             rxseq++, rxleft--) {
 
                /* Handle glomming separately */
@@ -1774,7 +1785,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
                                bus->nextlen = 0;
                        }
 
-                       bus->drvr->rx_readahead_cnt++;
+                       bus->rx_readahead_cnt++;
 
                        /* Handle Flow Control */
                        fcbits = SDPCM_FCMASK_VALUE(
@@ -1972,7 +1983,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
                        /* Too long -- skip this frame */
                        brcmf_dbg(ERROR, "too long: len %d rdlen %d\n",
                                  len, rdlen);
-                       bus->drvr->rx_errors++;
+                       bus->sdiodev->bus_if->dstats.rx_errors++;
                        bus->rx_toolong++;
                        brcmf_sdbrcm_rxfail(bus, false, false);
                        continue;
@@ -1984,7 +1995,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
                        /* Give up on data, request rtx of events */
                        brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n",
                                  rdlen, chan);
-                       bus->drvr->rx_dropped++;
+                       bus->sdiodev->bus_if->dstats.rx_dropped++;
                        brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
                        continue;
                }
@@ -2004,7 +2015,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished)
                                   : ((chan == SDPCM_DATA_CHANNEL) ? "data"
                                      : "test")), sdret);
                        brcmu_pkt_buf_free_skb(pkt);
-                       bus->drvr->rx_errors++;
+                       bus->sdiodev->bus_if->dstats.rx_errors++;
                        brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
                        continue;
                }
@@ -2053,16 +2064,17 @@ deliver:
                if (pkt->len == 0) {
                        brcmu_pkt_buf_free_skb(pkt);
                        continue;
-               } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
+               } else if (brcmf_proto_hdrpull(bus->sdiodev->dev, &ifidx,
+                          pkt) != 0) {
                        brcmf_dbg(ERROR, "rx protocol error\n");
                        brcmu_pkt_buf_free_skb(pkt);
-                       bus->drvr->rx_errors++;
+                       bus->sdiodev->bus_if->dstats.rx_errors++;
                        continue;
                }
 
                /* Unlock during rx call */
                up(&bus->sdsem);
-               brcmf_rx_packet(bus->drvr, ifidx, pkt);
+               brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
                down(&bus->sdsem);
        }
        rxcount = maxframes - rxleft;
@@ -2122,7 +2134,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
                if (skb_headroom(pkt) < pad) {
                        brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
                                  skb_headroom(pkt), pad);
-                       bus->drvr->tx_realloc++;
+                       bus->sdiodev->bus_if->tx_realloc++;
                        new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
                        if (!new) {
                                brcmf_dbg(ERROR, "couldn't allocate new %d-byte packet\n",
@@ -2230,7 +2242,7 @@ done:
        /* restore pkt buffer pointer before calling tx complete routine */
        skb_pull(pkt, SDPCM_HDRLEN + pad);
        up(&bus->sdsem);
-       brcmf_txcomplete(bus->drvr, pkt, ret != 0);
+       brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
        down(&bus->sdsem);
 
        if (free_pkt)
@@ -2249,8 +2261,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
        uint datalen;
        u8 tx_prec_map;
 
-       struct brcmf_pub *drvr = bus->drvr;
-
        brcmf_dbg(TRACE, "Enter\n");
 
        tx_prec_map = ~bus->flowcontrol;
@@ -2268,9 +2278,9 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 
                ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
                if (ret)
-                       bus->drvr->tx_errors++;
+                       bus->sdiodev->bus_if->dstats.tx_errors++;
                else
-                       bus->drvr->dstats.tx_bytes += datalen;
+                       bus->sdiodev->bus_if->dstats.tx_bytes += datalen;
 
                /* In poll mode, need to check for other events */
                if (!bus->intr && cnt) {
@@ -2287,13 +2297,97 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
        }
 
        /* Deflow-control stack if needed */
-       if (drvr->up && (drvr->bus_if->state == BRCMF_BUS_DATA) &&
-           drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
-               brcmf_txflowcontrol(drvr, 0, OFF);
+       if (bus->sdiodev->bus_if->drvr_up &&
+           (bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
+           bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
+               bus->txoff = OFF;
+               brcmf_txflowcontrol(bus->sdiodev->dev, 0, OFF);
+       }
 
        return cnt;
 }
 
+static void brcmf_sdbrcm_bus_stop(struct device *dev)
+{
+       u32 local_hostintmask;
+       u8 saveclk;
+       uint retries;
+       int err;
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio *bus = sdiodev->bus;
+
+       brcmf_dbg(TRACE, "Enter\n");
+
+       if (bus->watchdog_tsk) {
+               send_sig(SIGTERM, bus->watchdog_tsk, 1);
+               kthread_stop(bus->watchdog_tsk);
+               bus->watchdog_tsk = NULL;
+       }
+
+       if (bus->dpc_tsk && bus->dpc_tsk != current) {
+               send_sig(SIGTERM, bus->dpc_tsk, 1);
+               kthread_stop(bus->dpc_tsk);
+               bus->dpc_tsk = NULL;
+       }
+
+       down(&bus->sdsem);
+
+       bus_wake(bus);
+
+       /* Enable clock for device interrupts */
+       brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+
+       /* Disable and clear interrupts at the chip level also */
+       w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
+       local_hostintmask = bus->hostintmask;
+       bus->hostintmask = 0;
+
+       /* Change our idea of bus state */
+       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+
+       /* Force clocks on backplane to be sure F2 interrupt propagates */
+       saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
+                                       SBSDIO_FUNC1_CHIPCLKCSR, &err);
+       if (!err) {
+               brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
+                                      SBSDIO_FUNC1_CHIPCLKCSR,
+                                      (saveclk | SBSDIO_FORCE_HT), &err);
+       }
+       if (err)
+               brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
+
+       /* Turn off the bus (F2), free any pending packets */
+       brcmf_dbg(INTR, "disable SDIO interrupts\n");
+       brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
+                        SDIO_FUNC_ENABLE_1, NULL);
+
+       /* Clear any pending interrupts now that F2 is disabled */
+       w_sdreg32(bus, local_hostintmask,
+                 offsetof(struct sdpcmd_regs, intstatus), &retries);
+
+       /* Turn off the backplane clock (only) */
+       brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+
+       /* Clear the data packet queues */
+       brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
+
+       /* Clear any held glomming stuff */
+       if (bus->glomd)
+               brcmu_pkt_buf_free_skb(bus->glomd);
+       brcmf_sdbrcm_free_glom(bus);
+
+       /* Clear rx control and wake any waiters */
+       bus->rxlen = 0;
+       brcmf_sdbrcm_dcmd_resp_wake(bus);
+
+       /* Reset some F2 state stuff */
+       bus->rxskip = false;
+       bus->tx_seq = bus->rx_seq = 0;
+
+       up(&bus->sdsem);
+}
+
 static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
 {
        u32 intstatus, newstatus = 0;
@@ -2322,7 +2416,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                                               SBSDIO_DEVICE_CTL, &err);
                if (err) {
                        brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err);
-                       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+                       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                }
 #endif                         /* BCMDBG */
 
@@ -2332,7 +2426,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                if (err) {
                        brcmf_dbg(ERROR, "error reading CSR: %d\n",
                                  err);
-                       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+                       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                }
 
                brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
@@ -2345,7 +2439,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                        if (err) {
                                brcmf_dbg(ERROR, "error reading DEVCTL: %d\n",
                                          err);
-                               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+                               bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                        }
                        devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
                        brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
@@ -2353,7 +2447,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                        if (err) {
                                brcmf_dbg(ERROR, "error writing DEVCTL: %d\n",
                                          err);
-                               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+                               bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                        }
                        bus->clkstate = CLK_AVAIL;
                } else {
@@ -2509,11 +2603,11 @@ clkwait:
                 else await next interrupt */
        /* On failed register access, all bets are off:
                 no resched or interrupts */
-       if ((bus->drvr->bus_if->state == BRCMF_BUS_DOWN) ||
+       if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) ||
            brcmf_sdcard_regfail(bus->sdiodev)) {
                brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n",
                          brcmf_sdcard_regfail(bus->sdiodev));
-               bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+               bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                bus->intstatus = 0;
        } else if (bus->clkstate == CLK_PENDING) {
                brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
@@ -2550,7 +2644,7 @@ static int brcmf_sdbrcm_dpc_thread(void *data)
                if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
                        /* Call bus dpc unless it indicated down
                        (then clean stop) */
-                       if (bus->drvr->bus_if->state != BRCMF_BUS_DOWN) {
+                       if (bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN) {
                                if (brcmf_sdbrcm_dpc(bus))
                                        complete(&bus->dpc_wait);
                        } else {
@@ -2565,7 +2659,7 @@ static int brcmf_sdbrcm_dpc_thread(void *data)
        return 0;
 }
 
-int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
+static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
        int ret = -EBADE;
        uint datalen, prec;
@@ -2590,9 +2684,10 @@ int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 
        /* Priority based enq */
        spin_lock_bh(&bus->txqlock);
-       if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
+       if (brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec) ==
+           false) {
                skb_pull(pkt, SDPCM_HDRLEN);
-               brcmf_txcomplete(bus->drvr, pkt, false);
+               brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
                brcmu_pkt_buf_free_skb(pkt);
                brcmf_dbg(ERROR, "out of bus->txq !!!\n");
                ret = -ENOSR;
@@ -2601,8 +2696,10 @@ int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
        }
        spin_unlock_bh(&bus->txqlock);
 
-       if (pktq_len(&bus->txq) >= TXHI)
-               brcmf_txflowcontrol(bus->drvr, 0, ON);
+       if (pktq_len(&bus->txq) >= TXHI) {
+               bus->txoff = ON;
+               brcmf_txflowcontrol(bus->sdiodev->dev, 0, ON);
+       }
 
 #ifdef BCMDBG
        if (pktq_plen(&bus->txq, prec) > qcount[prec])
@@ -2799,7 +2896,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len)
        return ret;
 }
 
-int
+static int
 brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        u8 *frame;
@@ -2910,14 +3007,14 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
        up(&bus->sdsem);
 
        if (ret)
-               bus->drvr->tx_ctlerrs++;
+               bus->tx_ctlerrs++;
        else
-               bus->drvr->tx_ctlpkts++;
+               bus->tx_ctlpkts++;
 
        return ret ? -EIO : 0;
 }
 
-int
+static int
 brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        int timeleft;
@@ -2951,9 +3048,9 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
        }
 
        if (rxlen)
-               bus->drvr->rx_ctlpkts++;
+               bus->rx_ctlpkts++;
        else
-               bus->drvr->rx_ctlerrs++;
+               bus->rx_ctlerrs++;
 
        return rxlen ? (int)rxlen : -ETIMEDOUT;
 }
@@ -2965,7 +3062,7 @@ static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len)
        brcmf_dbg(TRACE, "Enter\n");
 
        /* Basic sanity checks */
-       if (bus->drvr->up) {
+       if (bus->sdiodev->bus_if->drvr_up) {
                bcmerror = -EISCONN;
                goto err;
        }
@@ -3121,7 +3218,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
                /* Allow HT Clock now that the ARM is running. */
                bus->alp_only = false;
 
-               bus->drvr->bus_if->state = BRCMF_BUS_LOAD;
+               bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
        }
 fail:
        return bcmerror;
@@ -3330,88 +3427,7 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
        return ret;
 }
 
-void brcmf_sdbrcm_bus_stop(struct device *dev)
-{
-       u32 local_hostintmask;
-       u8 saveclk;
-       uint retries;
-       int err;
-       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
-       struct brcmf_sdio *bus = sdiodev->bus;
-
-       brcmf_dbg(TRACE, "Enter\n");
-
-       if (bus->watchdog_tsk) {
-               send_sig(SIGTERM, bus->watchdog_tsk, 1);
-               kthread_stop(bus->watchdog_tsk);
-               bus->watchdog_tsk = NULL;
-       }
-
-       if (bus->dpc_tsk && bus->dpc_tsk != current) {
-               send_sig(SIGTERM, bus->dpc_tsk, 1);
-               kthread_stop(bus->dpc_tsk);
-               bus->dpc_tsk = NULL;
-       }
-
-       down(&bus->sdsem);
-
-       bus_wake(bus);
-
-       /* Enable clock for device interrupts */
-       brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
-       /* Disable and clear interrupts at the chip level also */
-       w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
-       local_hostintmask = bus->hostintmask;
-       bus->hostintmask = 0;
-
-       /* Change our idea of bus state */
-       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
-
-       /* Force clocks on backplane to be sure F2 interrupt propagates */
-       saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
-                                       SBSDIO_FUNC1_CHIPCLKCSR, &err);
-       if (!err) {
-               brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
-                                      SBSDIO_FUNC1_CHIPCLKCSR,
-                                      (saveclk | SBSDIO_FORCE_HT), &err);
-       }
-       if (err)
-               brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err);
-
-       /* Turn off the bus (F2), free any pending packets */
-       brcmf_dbg(INTR, "disable SDIO interrupts\n");
-       brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
-                        SDIO_FUNC_ENABLE_1, NULL);
-
-       /* Clear any pending interrupts now that F2 is disabled */
-       w_sdreg32(bus, local_hostintmask,
-                 offsetof(struct sdpcmd_regs, intstatus), &retries);
-
-       /* Turn off the backplane clock (only) */
-       brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
-       /* Clear the data packet queues */
-       brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
-
-       /* Clear any held glomming stuff */
-       if (bus->glomd)
-               brcmu_pkt_buf_free_skb(bus->glomd);
-       brcmf_sdbrcm_free_glom(bus);
-
-       /* Clear rx control and wake any waiters */
-       bus->rxlen = 0;
-       brcmf_sdbrcm_dcmd_resp_wake(bus);
-
-       /* Reset some F2 state stuff */
-       bus->rxskip = false;
-       bus->tx_seq = bus->rx_seq = 0;
-
-       up(&bus->sdsem);
-}
-
-int brcmf_sdbrcm_bus_init(struct device *dev)
+static int brcmf_sdbrcm_bus_init(struct device *dev)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
        struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
@@ -3430,11 +3446,11 @@ int brcmf_sdbrcm_bus_init(struct device *dev)
                        return -1;
        }
 
-       if (!bus->drvr)
+       if (!bus->sdiodev->bus_if->drvr)
                return 0;
 
        /* Start the watchdog timer */
-       bus->drvr->tickcnt = 0;
+       bus->tickcnt = 0;
        brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
 
        down(&bus->sdsem);
@@ -3526,7 +3542,7 @@ void brcmf_sdbrcm_isr(void *arg)
                return;
        }
 
-       if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN) {
+       if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
                brcmf_dbg(ERROR, "bus is down. we have nothing to do\n");
                return;
        }
@@ -3657,9 +3673,9 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
-       if (bus->drvr->maxctl) {
+       if (bus->sdiodev->bus_if->maxctl) {
                bus->rxblen =
-                   roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
+                   roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
                            ALIGNMENT) + BRCMF_SDALIGN;
                bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
                if (!(bus->rxbuf))
@@ -3782,7 +3798,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
        brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
                               SDIO_FUNC_ENABLE_1, NULL);
 
-       bus->drvr->bus_if->state = BRCMF_BUS_DOWN;
+       bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
        bus->sleeping = false;
        bus->rxflow = false;
 
@@ -3819,7 +3835,7 @@ brcmf_sdbrcm_watchdog_thread(void *data)
                if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
                        brcmf_sdbrcm_bus_watchdog(bus);
                        /* Count the tick for reference */
-                       bus->drvr->tickcnt++;
+                       bus->tickcnt++;
                } else
                        break;
        }
@@ -3865,10 +3881,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
                /* De-register interrupt handler */
                brcmf_sdcard_intr_dereg(bus->sdiodev);
 
-               if (bus->drvr) {
-                       brcmf_detach(bus->drvr);
+               if (bus->sdiodev->bus_if->drvr) {
+                       brcmf_detach(bus->sdiodev->dev);
                        brcmf_sdbrcm_release_dongle(bus);
-                       bus->drvr = NULL;
                }
 
                brcmf_sdbrcm_release_malloc(bus);
@@ -3941,9 +3956,15 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
                bus->dpc_tsk = NULL;
        }
 
+       /* Assign bus interface call back */
+       bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop;
+       bus->sdiodev->bus_if->brcmf_bus_init = brcmf_sdbrcm_bus_init;
+       bus->sdiodev->bus_if->brcmf_bus_txdata = brcmf_sdbrcm_bus_txdata;
+       bus->sdiodev->bus_if->brcmf_bus_txctl = brcmf_sdbrcm_bus_txctl;
+       bus->sdiodev->bus_if->brcmf_bus_rxctl = brcmf_sdbrcm_bus_rxctl;
        /* Attach to the brcmf/OS/network interface */
-       bus->drvr = brcmf_attach(bus, SDPCM_RESERVE, bus->sdiodev->dev);
-       if (!bus->drvr) {
+       ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
+       if (ret != 0) {
                brcmf_dbg(ERROR, "brcmf_attach failed\n");
                goto fail;
        }
@@ -3971,7 +3992,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        brcmf_dbg(INFO, "completed!!\n");
 
        /* if firmware path present try to download and bring up bus */
-       ret = brcmf_bus_start(bus->drvr);
+       ret = brcmf_bus_start(bus->sdiodev->dev);
        if (ret != 0) {
                if (ret == -ENOLINK) {
                        brcmf_dbg(ERROR, "dongle is not responding\n");
@@ -3980,7 +4001,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        }
 
        /* add interface and open for business */
-       if (brcmf_add_if((struct brcmf_info *)bus->drvr, 0, "wlan%d", NULL)) {
+       if (brcmf_add_if(bus->sdiodev->dev, 0, "wlan%d", NULL)) {
                brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
                goto fail;
        }
@@ -4016,7 +4037,7 @@ brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick)
        }
 
        /* don't start the wd until fw is loaded */
-       if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN)
+       if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN)
                return;
 
        if (wdtick) {
index a6048d78d29409ea6944174eb68ecaa3e3d2b857..11b2d7c97ba22072e8231fd02f2758e7d0bf5945 100644 (file)
@@ -26,7 +26,6 @@
 #include <brcmu_wifi.h>
 #include <brcmu_utils.h>
 #include <soc.h>
-#include "dhd.h"
 #include "dhd_dbg.h"
 #include "sdio_host.h"
 #include "sdio_chip.h"
index d36a2a855a6573f538089d07985791c7e5d5922d..0281d207d998faff6ce51441d9284606a36bf9d1 100644 (file)
 #define SUCCESS        0
 #define ERROR  1
 
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#define BRCMF_SDALIGN  (1 << 6)
+
+/* watchdog polling interval in ms */
+#define BRCMF_WD_POLL_MS       10
+
 struct brcmf_sdreg {
        int func;
        int offset;
        int value;
 };
 
+struct brcmf_sdio;
+
 struct brcmf_sdio_dev {
        struct sdio_func *func[SDIO_MAX_FUNCS];
        u8 num_funcs;                   /* Supported funcs on client */
@@ -262,4 +270,6 @@ extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
 extern void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev);
 extern void brcmf_sdbrcm_disconnect(void *ptr);
 extern void brcmf_sdbrcm_isr(void *arg);
+
+extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
 #endif                         /* _BRCM_SDH_H_ */
index 8d3bad7ea5d366f63fbfe56aeba7daf04b1e60b3..1ef7bfc2ab2522629ec7a81125f7043804c32899 100644 (file)
@@ -124,10 +124,10 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 {
        if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
            iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
+               cfg(priv)->base_params->num_of_queues =
                        iwlagn_mod_params.num_of_queues;
 
-       hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
+       hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
        hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
@@ -135,14 +135,14 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 
        hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
-       hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-       if (priv->cfg->rx_with_siso_diversity)
+       hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+       if (cfg(priv)->rx_with_siso_diversity)
                hw_params(priv).rx_chains_num = 1;
        else
                hw_params(priv).rx_chains_num =
-                       num_of_ant(priv->cfg->valid_rx_ant);
-       hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
-       hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
+                       num_of_ant(cfg(priv)->valid_rx_ant);
+       hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+       hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
 
        iwl1000_set_ct_threshold(priv);
 
index 0c4688d95b652be661562fb08690a661b3bbafd9..094693328dbb24ad971dc243052eb23b1b033df4 100644 (file)
@@ -86,7 +86,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
 {
        iwl_rf_config(priv);
 
-       if (priv->cfg->iq_invert)
+       if (cfg(priv)->iq_invert)
                iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
                            CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
 }
@@ -120,10 +120,10 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 {
        if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
            iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
+               cfg(priv)->base_params->num_of_queues =
                        iwlagn_mod_params.num_of_queues;
 
-       hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
+       hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
        hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
@@ -131,14 +131,14 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 
        hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
-       hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-       if (priv->cfg->rx_with_siso_diversity)
+       hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+       if (cfg(priv)->rx_with_siso_diversity)
                hw_params(priv).rx_chains_num = 1;
        else
                hw_params(priv).rx_chains_num =
-                       num_of_ant(priv->cfg->valid_rx_ant);
-       hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
-       hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
+                       num_of_ant(cfg(priv)->valid_rx_ant);
+       hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+       hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
 
        iwl2000_set_ct_threshold(priv);
 
@@ -254,13 +254,13 @@ static struct iwl_bt_params iwl2030_bt_params = {
        .iq_invert = true                                       \
 
 struct iwl_cfg iwl2000_2bgn_cfg = {
-       .name = "2000 Series 2x2 BGN",
+       .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
        IWL_DEVICE_2000,
        .ht_params = &iwl2000_ht_params,
 };
 
 struct iwl_cfg iwl2000_2bgn_d_cfg = {
-       .name = "2000D Series 2x2 BGN",
+       .name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
        IWL_DEVICE_2000,
        .ht_params = &iwl2000_ht_params,
 };
@@ -282,7 +282,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
        .iq_invert = true                                       \
 
 struct iwl_cfg iwl2030_2bgn_cfg = {
-       .name = "2000 Series 2x2 BGN/BT",
+       .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
        IWL_DEVICE_2030,
        .ht_params = &iwl2000_ht_params,
 };
@@ -304,13 +304,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
        .iq_invert = true                                       \
 
 struct iwl_cfg iwl105_bgn_cfg = {
-       .name = "105 Series 1x1 BGN",
+       .name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
        IWL_DEVICE_105,
        .ht_params = &iwl2000_ht_params,
 };
 
 struct iwl_cfg iwl105_bgn_d_cfg = {
-       .name = "105D Series 1x1 BGN",
+       .name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
        IWL_DEVICE_105,
        .ht_params = &iwl2000_ht_params,
 };
@@ -333,7 +333,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
        .iq_invert = true                                       \
 
 struct iwl_cfg iwl135_bgn_cfg = {
-       .name = "135 Series 1x1 BGN/BT",
+       .name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
        IWL_DEVICE_135,
        .ht_params = &iwl2000_ht_params,
 };
index 6706d7c10bd804761d3fc66da4363457b11aee7c..b3a365fea7bbd85b48cd22db06ccf0bdac1a5042 100644 (file)
@@ -166,10 +166,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 {
        if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
            iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
+               cfg(priv)->base_params->num_of_queues =
                        iwlagn_mod_params.num_of_queues;
 
-       hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
+       hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
        hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
@@ -178,10 +178,10 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
        hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
                                        BIT(IEEE80211_BAND_5GHZ);
 
-       hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-       hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
-       hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
-       hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
+       hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+       hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
+       hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+       hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
 
        iwl5000_set_ct_threshold(priv);
 
@@ -195,10 +195,10 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 {
        if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
            iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
+               cfg(priv)->base_params->num_of_queues =
                        iwlagn_mod_params.num_of_queues;
 
-       hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
+       hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
        hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
@@ -207,10 +207,10 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
        hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
                                        BIT(IEEE80211_BAND_5GHZ);
 
-       hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-       hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
-       hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
-       hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
+       hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+       hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
+       hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+       hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
 
        iwl5150_set_ct_threshold(priv);
 
index 3e277b6774f13bcf467b4e7de0b7b76939a96704..54b753399e6e8331006f6da436d0719412152e27 100644 (file)
@@ -102,14 +102,14 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
        iwl_rf_config(priv);
 
        /* no locking required for register write */
-       if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
+       if (cfg(priv)->pa_type == IWL_PA_INTERNAL) {
                /* 2x2 IPA phy type */
                iwl_write32(bus(priv), CSR_GP_DRIVER_REG,
                             CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
        }
        /* do additional nic configuration if needed */
-       if (priv->cfg->additional_nic_config)
-                       priv->cfg->additional_nic_config(priv);
+       if (cfg(priv)->additional_nic_config)
+                       cfg(priv)->additional_nic_config(priv);
 }
 
 static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -141,10 +141,10 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 {
        if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
            iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
-               priv->cfg->base_params->num_of_queues =
+               cfg(priv)->base_params->num_of_queues =
                        iwlagn_mod_params.num_of_queues;
 
-       hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues;
+       hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
        priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
 
        hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
@@ -153,14 +153,14 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
        hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
                                        BIT(IEEE80211_BAND_5GHZ);
 
-       hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-       if (priv->cfg->rx_with_siso_diversity)
+       hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
+       if (cfg(priv)->rx_with_siso_diversity)
                hw_params(priv).rx_chains_num = 1;
        else
                hw_params(priv).rx_chains_num =
-                       num_of_ant(priv->cfg->valid_rx_ant);
-       hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant;
-       hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant;
+                       num_of_ant(cfg(priv)->valid_rx_ant);
+       hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
+       hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
 
        iwl6000_set_ct_threshold(priv);
 
@@ -423,7 +423,7 @@ struct iwl_cfg iwl6030_2bg_cfg = {
 };
 
 struct iwl_cfg iwl6035_2agn_cfg = {
-       .name = "6035 Series 2x2 AGN/BT",
+       .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
        IWL_DEVICE_6030,
        .ht_params = &iwl6000_ht_params,
 };
index 16971a020297dab59e8efc8c99a052bd65ee384c..50ff849c9f67a5849e4f70bd394a855f3a712401 100644 (file)
@@ -513,7 +513,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
 
        iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
 
-       if (priv->cfg->base_params->hd_v2) {
+       if (cfg(priv)->base_params->hd_v2) {
                cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
                        HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
                cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
@@ -847,7 +847,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
                         * connect the first valid tx chain
                         */
                        first_chain =
-                               find_first_chain(priv->cfg->valid_tx_ant);
+                               find_first_chain(cfg(priv)->valid_tx_ant);
                        data->disconn_array[first_chain] = 0;
                        active_chains |= BIT(first_chain);
                        IWL_DEBUG_CALIB(priv,
@@ -890,7 +890,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
                        continue;
                }
 
-               delta_g = (priv->cfg->base_params->chain_noise_scale *
+               delta_g = (cfg(priv)->base_params->chain_noise_scale *
                        ((s32)average_noise[default_chain] -
                        (s32)average_noise[i])) / 1500;
 
@@ -1047,8 +1047,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
                return;
 
        /* Analyze signal for disconnected antenna */
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist) {
                /* Disable disconnected antenna algorithm for advanced
                   bt coex, assuming valid antennas are connected */
                data->active_chains = hw_params(priv).valid_rx_ant;
@@ -1082,7 +1082,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
 
        iwlagn_gain_computation(priv, average_noise,
                                min_average_noise_antenna_i, min_average_noise,
-                               find_first_chain(priv->cfg->valid_rx_ant));
+                               find_first_chain(cfg(priv)->valid_rx_ant));
 
        /* Some power changes may have been made during the calibration.
         * Update and commit the RXON
index 057f95233567ff63bb0b554eb8ce660e0acd1ad1..64cf439035c3854593f27e51a838826a714518dd 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
+#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -150,7 +151,7 @@ static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address)
 const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset)
 {
        u32 address = eeprom_indirect_address(shrd, offset);
-       BUG_ON(address >= shrd->priv->cfg->base_params->eeprom_size);
+       BUG_ON(address >= shrd->cfg->base_params->eeprom_size);
        return &shrd->eeprom[address];
 }
 
@@ -232,7 +233,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
                                IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
                                IWL_PAN_SCD_MULTICAST_MSK;
 
-       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
+       if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
                flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
 
        IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
@@ -374,15 +375,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
        BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
                        sizeof(basic.bt3_lookup_table));
 
-       if (priv->cfg->bt_params) {
-               if (priv->cfg->bt_params->bt_session_2) {
+       if (cfg(priv)->bt_params) {
+               if (cfg(priv)->bt_params->bt_session_2) {
                        bt_cmd_2000.prio_boost = cpu_to_le32(
-                               priv->cfg->bt_params->bt_prio_boost);
+                               cfg(priv)->bt_params->bt_prio_boost);
                        bt_cmd_2000.tx_prio_boost = 0;
                        bt_cmd_2000.rx_prio_boost = 0;
                } else {
                        bt_cmd_6000.prio_boost =
-                               priv->cfg->bt_params->bt_prio_boost;
+                               cfg(priv)->bt_params->bt_prio_boost;
                        bt_cmd_6000.tx_prio_boost = 0;
                        bt_cmd_6000.rx_prio_boost = 0;
                }
@@ -430,7 +431,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
                       priv->bt_full_concurrent ?
                       "full concurrency" : "3-wire");
 
-       if (priv->cfg->bt_params->bt_session_2) {
+       if (cfg(priv)->bt_params->bt_session_2) {
                memcpy(&bt_cmd_2000.basic, &basic,
                        sizeof(basic));
                ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
@@ -799,8 +800,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv)
  */
 static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
 {
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist &&
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist &&
            (priv->bt_full_concurrent ||
             priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
                /*
@@ -871,8 +872,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
        else
                active_chains = hw_params(priv).valid_rx_ant;
 
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist &&
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist &&
            (priv->bt_full_concurrent ||
             priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
                /*
@@ -1158,7 +1159,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
         * since the uCode will add 0x10 before using the value.
         */
        for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
-               seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
+               seq = priv->tid_data[IWL_AP_ID][i].seq_number;
                seq -= 0x10;
                wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
        }
@@ -1195,7 +1196,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
 
        priv->shrd->wowlan = true;
 
-       ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
+       ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN);
        if (ret)
                goto out;
 
index a23835a7797afc75e1f3415da9917af547eb1591..334b5ae8fdd454ac69d9f760e28359e2b97429b7 100644 (file)
@@ -1086,7 +1086,7 @@ done:
            (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
                rs_program_fix_rate(priv, lq_sta);
 #endif
-       if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
+       if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist)
                rs_bt_update_lq(priv, ctx, lq_sta);
 }
 
@@ -2273,7 +2273,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        tid = rs_tl_add_packet(lq_sta, hdr);
        if ((tid != IWL_MAX_TID_COUNT) &&
            (lq_sta->tx_agg_tid_en & (1 << tid))) {
-               tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid];
+               tid_data = &priv->tid_data[lq_sta->lq.sta_id][tid];
                if (tid_data->agg.state == IWL_AGG_OFF)
                        lq_sta->is_agg = 0;
                else
@@ -2645,8 +2645,7 @@ lq_update:
                            (lq_sta->tx_agg_tid_en & (1 << tid)) &&
                            (tid != IWL_MAX_TID_COUNT)) {
                                u8 sta_id = lq_sta->lq.sta_id;
-                               tid_data =
-                                  &priv->shrd->tid_data[sta_id][tid];
+                               tid_data = &priv->tid_data[sta_id][tid];
                                if (tid_data->agg.state == IWL_AGG_OFF) {
                                        IWL_DEBUG_RATE(priv,
                                                       "try to aggregate tid %d\n",
@@ -3055,11 +3054,11 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
         * overwrite if needed, pass aggregation time limit
         * to uCode in uSec
         */
-       if (priv && priv->cfg->bt_params &&
-           priv->cfg->bt_params->agg_time_limit &&
+       if (priv && cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->agg_time_limit &&
            priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
                lq_cmd->agg_params.agg_time_limit =
-                       cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
+                       cpu_to_le16(cfg(priv)->bt_params->agg_time_limit);
 }
 
 static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
index 9001c23f27bb1f6a8f4e8b42265ab46d6e489a42..b22b2976f899e037cb73884c1ef66b9af565386f 100644 (file)
@@ -318,7 +318,7 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
                                 unsigned int msecs)
 {
        int delta;
-       int threshold = priv->cfg->base_params->plcp_delta_threshold;
+       int threshold = cfg(priv)->base_params->plcp_delta_threshold;
 
        if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
                IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
@@ -583,8 +583,8 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
                iwlagn_rx_calc_noise(priv);
                queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
        }
-       if (priv->cfg->lib->temperature && change)
-               priv->cfg->lib->temperature(priv);
+       if (cfg(priv)->lib->temperature && change)
+               cfg(priv)->lib->temperature(priv);
        return 0;
 }
 
@@ -1136,8 +1136,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
        init_waitqueue_head(&priv->shrd->notif_waitq);
 
        /* Set up BT Rx handlers */
-       if (priv->cfg->lib->bt_rx_handler_setup)
-               priv->cfg->lib->bt_rx_handler_setup(priv);
+       if (cfg(priv)->lib->bt_rx_handler_setup)
+               cfg(priv)->lib->bt_rx_handler_setup(priv);
 
 }
 
index d21f535a3b4fdd84fcafd600e2945243958b128d..1c66594166216ead48f032417f34e10ea6ebd2f3 100644 (file)
@@ -296,9 +296,9 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
        }
 
        if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
-           priv->cfg->ht_params && priv->cfg->ht_params->smps_mode)
+           cfg(priv)->ht_params && cfg(priv)->ht_params->smps_mode)
                ieee80211_request_smps(ctx->vif,
-                                      priv->cfg->ht_params->smps_mode);
+                                      cfg(priv)->ht_params->smps_mode);
 
        return 0;
 }
@@ -445,8 +445,8 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
         * force CTS-to-self frames protection if RTS-CTS is not preferred
         * one aggregation protection method
         */
-       if (!(priv->cfg->ht_params &&
-             priv->cfg->ht_params->use_rts_for_aggregation))
+       if (!(cfg(priv)->ht_params &&
+             cfg(priv)->ht_params->use_rts_for_aggregation))
                ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
 
        if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
index 63d948d21c04895ba0944a4b25ccb04771d87b24..7353826095f110a8766d6c1a4425a71c49ba8a91 100644 (file)
@@ -130,25 +130,15 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
        return iwl_process_add_sta_resp(priv, addsta, pkt);
 }
 
-static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-       u16 size = (u16)sizeof(struct iwl_addsta_cmd);
-       struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
-       memcpy(addsta, cmd, size);
-       /* resrved in agn */
-       addsta->legacy_reserved = cpu_to_le16(0);
-       return size;
-}
-
 int iwl_send_add_sta(struct iwl_priv *priv,
                     struct iwl_addsta_cmd *sta, u8 flags)
 {
        int ret = 0;
-       u8 data[sizeof(*sta)];
        struct iwl_host_cmd cmd = {
                .id = REPLY_ADD_STA,
                .flags = flags,
-               .data = { data, },
+               .data = { sta, },
+               .len = { sizeof(*sta), },
        };
        u8 sta_id __maybe_unused = sta->sta.sta_id;
 
@@ -160,7 +150,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
                might_sleep();
        }
 
-       cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data);
        ret = iwl_trans_send_cmd(trans(priv), &cmd);
 
        if (ret || (flags & CMD_ASYNC))
@@ -463,6 +452,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
                       const u8 *addr)
 {
        unsigned long flags;
+       u8 tid;
 
        if (!iwl_is_ready(priv->shrd)) {
                IWL_DEBUG_INFO(priv,
@@ -501,6 +491,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
                priv->stations[sta_id].lq = NULL;
        }
 
+       for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+               memset(&priv->tid_data[sta_id][tid], 0,
+                       sizeof(priv->tid_data[sta_id][tid]));
+
        priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
 
        priv->num_stations--;
index c27180a73351752b59015900f90f174b34c0929d..b0dff7a753a56a5e60db10f6d5ab46dd024e7932 100644 (file)
@@ -633,7 +633,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
        INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
        INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
 
-       if (priv->cfg->base_params->adv_thermal_throttle) {
+       if (cfg(priv)->base_params->adv_thermal_throttle) {
                IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
                tt->restriction = kcalloc(IWL_TI_STATE_MAX,
                                          sizeof(struct iwl_tt_restriction),
index 81754cddba73b4763a815d2fa03afff77f74a326..c664c2726553f059b8e160c0552efc0b0b8e75b5 100644 (file)
@@ -74,8 +74,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
        else if (ieee80211_is_back_req(fc))
                tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
        else if (info->band == IEEE80211_BAND_2GHZ &&
-                priv->cfg->bt_params &&
-                priv->cfg->bt_params->advanced_bt_coexist &&
+                cfg(priv)->bt_params &&
+                cfg(priv)->bt_params->advanced_bt_coexist &&
                 (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
                 ieee80211_is_reassoc_req(fc) ||
                 skb->protocol == cpu_to_be16(ETH_P_PAE)))
@@ -191,8 +191,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
                rate_flags |= RATE_MCS_CCK_MSK;
 
        /* Set up antennas */
-        if (priv->cfg->bt_params &&
-            priv->cfg->bt_params->advanced_bt_coexist &&
+        if (cfg(priv)->bt_params &&
+            cfg(priv)->bt_params->advanced_bt_coexist &&
             priv->bt_full_concurrent) {
                /* operated as 1x1 in full concurrency mode */
                priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
@@ -262,8 +262,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        __le16 fc;
        u8 hdr_len;
-       u16 len;
-       u8 sta_id;
+       u16 len, seq_number = 0;
+       u8 sta_id, tid = IWL_MAX_TID_COUNT;
        unsigned long flags;
        bool is_agg = false;
 
@@ -368,9 +368,51 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        info->driver_data[0] = ctx;
        info->driver_data[1] = dev_cmd;
 
-       if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id))
+       if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
+               u8 *qc = NULL;
+               struct iwl_tid_data *tid_data;
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+               if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
+                       goto drop_unlock_sta;
+               tid_data = &priv->tid_data[sta_id][tid];
+
+               /* aggregation is on for this <sta,tid> */
+               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+                   tid_data->agg.state != IWL_AGG_ON) {
+                       IWL_ERR(priv, "TX_CTL_AMPDU while not in AGG:"
+                               " Tx flags = 0x%08x, agg.state = %d",
+                               info->flags, tid_data->agg.state);
+                       IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d",
+                               sta_id, tid, SEQ_TO_SN(tid_data->seq_number));
+                       goto drop_unlock_sta;
+               }
+
+               /* We can receive packets from the stack in IWL_AGG_{ON,OFF}
+                * only. Check this here.
+                */
+               if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
+                   tid_data->agg.state != IWL_AGG_OFF,
+                   "Tx while agg.state = %d", tid_data->agg.state))
+                       goto drop_unlock_sta;
+
+               seq_number = tid_data->seq_number;
+               seq_number &= IEEE80211_SCTL_SEQ;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(seq_number);
+               seq_number += 0x10;
+       }
+
+       /* Copy MAC header from skb into command buffer */
+       memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+       if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id, tid))
                goto drop_unlock_sta;
 
+       if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) &&
+           !ieee80211_has_morefrags(fc))
+               priv->tid_data[sta_id][tid].seq_number = seq_number;
+
        spin_unlock(&priv->shrd->sta_lock);
        spin_unlock_irqrestore(&priv->shrd->lock, flags);
 
@@ -395,10 +437,81 @@ drop_unlock_priv:
        return -1;
 }
 
+int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta, u16 tid)
+{
+       struct iwl_tid_data *tid_data;
+       unsigned long flags;
+       int sta_id;
+
+       sta_id = iwl_sta_id(sta);
+
+       if (sta_id == IWL_INVALID_STATION) {
+               IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+               return -ENXIO;
+       }
+
+       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
+       tid_data = &priv->tid_data[sta_id][tid];
+
+       switch (priv->tid_data[sta_id][tid].agg.state) {
+       case IWL_EMPTYING_HW_QUEUE_ADDBA:
+               /*
+               * This can happen if the peer stops aggregation
+               * again before we've had a chance to drain the
+               * queue we selected previously, i.e. before the
+               * session was really started completely.
+               */
+               IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
+               goto turn_off;
+       case IWL_AGG_ON:
+               break;
+       default:
+               IWL_WARN(priv, "Stopping AGG while state not ON "
+                        "or starting for %d on %d (%d)\n", sta_id, tid,
+                        priv->tid_data[sta_id][tid].agg.state);
+               spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+               return 0;
+       }
+
+       tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
+
+       /* There are still packets for this RA / TID in the HW */
+       if (tid_data->agg.ssn != tid_data->next_reclaimed) {
+               IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
+                                   "next_recl = %d",
+                                   tid_data->agg.ssn,
+                                   tid_data->next_reclaimed);
+               priv->tid_data[sta_id][tid].agg.state =
+                       IWL_EMPTYING_HW_QUEUE_DELBA;
+               spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+               return 0;
+       }
+
+       IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d",
+                           tid_data->agg.ssn);
+turn_off:
+       priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
+
+       /* do not restore/save irqs */
+       spin_unlock(&priv->shrd->sta_lock);
+       spin_lock(&priv->shrd->lock);
+
+       iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
+
+       spin_unlock_irqrestore(&priv->shrd->lock, flags);
+
+       ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
+       return 0;
+}
+
 int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+       struct iwl_tid_data *tid_data;
+       unsigned long flags;
        int sta_id;
        int ret;
 
@@ -413,7 +526,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
        if (unlikely(tid >= IWL_MAX_TID_COUNT))
                return -EINVAL;
 
-       if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) {
+       if (priv->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) {
                IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
                return -ENXIO;
        }
@@ -422,27 +535,136 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
        if (ret)
                return ret;
 
-       ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id,
-                                    tid, ssn);
+       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+
+       tid_data = &priv->tid_data[sta_id][tid];
+       tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
+
+       *ssn = tid_data->agg.ssn;
+
+       ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
+       if (ret) {
+               spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+               return ret;
+       }
+
+       if (*ssn == tid_data->next_reclaimed) {
+               IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d",
+                                   tid_data->agg.ssn);
+               tid_data->agg.state = IWL_AGG_ON;
+               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+       } else {
+               IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
+                                   "next_reclaimed = %d",
+                                   tid_data->agg.ssn,
+                                   tid_data->next_reclaimed);
+               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+       }
+
+       spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
 
        return ret;
 }
 
-int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta, u16 tid)
+int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta, u16 tid, u8 buf_size)
 {
-       int sta_id;
-       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+       struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
+       struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+       unsigned long flags;
+       u16 ssn;
 
-       sta_id = iwl_sta_id(sta);
+       buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
 
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
-               return -ENXIO;
+       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
+       ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
+       spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+
+       iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
+                              buf_size, ssn);
+
+       /*
+        * If the limit is 0, then it wasn't initialised yet,
+        * use the default. We can do that since we take the
+        * minimum below, and we don't want to go above our
+        * default due to hardware restrictions.
+        */
+       if (sta_priv->max_agg_bufsize == 0)
+               sta_priv->max_agg_bufsize =
+                       LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+       /*
+        * Even though in theory the peer could have different
+        * aggregation reorder buffer sizes for different sessions,
+        * our ucode doesn't allow for that and has a global limit
+        * for each station. Therefore, use the minimum of all the
+        * aggregation sessions and our default value.
+        */
+       sta_priv->max_agg_bufsize =
+               min(sta_priv->max_agg_bufsize, buf_size);
+
+       if (cfg(priv)->ht_params &&
+           cfg(priv)->ht_params->use_rts_for_aggregation) {
+               /*
+                * switch to RTS/CTS if it is the prefer protection
+                * method for HT traffic
+                */
+
+               sta_priv->lq_sta.lq.general_params.flags |=
+                       LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
        }
+       priv->agg_tids_count++;
+       IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+                    priv->agg_tids_count);
 
-       return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid,
-                                       sta_id, tid);
+       sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
+               sta_priv->max_agg_bufsize;
+
+       IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+                sta->addr, tid);
+
+       return iwl_send_lq_cmd(priv, ctx,
+                       &sta_priv->lq_sta.lq, CMD_ASYNC, false);
+}
+
+static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
+{
+       struct iwl_tid_data *tid_data = &priv->tid_data[sta_id][tid];
+       enum iwl_rxon_context_id ctx;
+       struct ieee80211_vif *vif;
+       u8 *addr;
+
+       lockdep_assert_held(&priv->shrd->sta_lock);
+
+       addr = priv->stations[sta_id].sta.sta.addr;
+       ctx = priv->stations[sta_id].ctxid;
+       vif = priv->contexts[ctx].vif;
+
+       switch (priv->tid_data[sta_id][tid].agg.state) {
+       case IWL_EMPTYING_HW_QUEUE_DELBA:
+               /* There are no packets for this RA / TID in the HW any more */
+               if (tid_data->agg.ssn == tid_data->next_reclaimed) {
+                       IWL_DEBUG_TX_QUEUES(priv,
+                               "Can continue DELBA flow ssn = next_recl ="
+                               " %d", tid_data->next_reclaimed);
+                       iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
+                       tid_data->agg.state = IWL_AGG_OFF;
+                       ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
+               }
+               break;
+       case IWL_EMPTYING_HW_QUEUE_ADDBA:
+               /* There are no packets for this RA / TID in the HW any more */
+               if (tid_data->agg.ssn == tid_data->next_reclaimed) {
+                       IWL_DEBUG_TX_QUEUES(priv,
+                               "Can continue ADDBA flow ssn = next_recl ="
+                               " %d", tid_data->next_reclaimed);
+                       tid_data->agg.state = IWL_AGG_ON;
+                       ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
+               }
+               break;
+       default:
+               break;
+       }
 }
 
 static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
@@ -582,7 +804,7 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
                IWLAGN_TX_RES_TID_POS;
        int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
                IWLAGN_TX_RES_RA_POS;
-       struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg;
+       struct iwl_ht_agg *agg = &priv->tid_data[sta_id][tid].agg;
        u32 status = le16_to_cpu(tx_resp->status.status);
        int i;
 
@@ -598,8 +820,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
         * notification again.
         */
        if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
-           priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+           cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist) {
                IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
        }
 
@@ -772,7 +994,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
        struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        struct ieee80211_hdr *hdr;
        u32 status = le16_to_cpu(tx_resp->status.status);
-       u32 ssn = iwlagn_get_scd_ssn(tx_resp);
+       u16 ssn = iwlagn_get_scd_ssn(tx_resp);
        int tid;
        int sta_id;
        int freed;
@@ -794,11 +1016,34 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
                iwl_rx_reply_tx_agg(priv, tx_resp);
 
        if (tx_resp->frame_count == 1) {
-               IWL_DEBUG_TX_REPLY(priv, "Q %d, ssn %d", txq_id, ssn);
+               u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
+               next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
+
+               if (is_agg) {
+                       /* If this is an aggregation queue, we can rely on the
+                        * ssn since the wifi sequence number corresponds to
+                        * the index in the TFD ring (%256).
+                        * The seq_ctl is the sequence control of the packet
+                        * to which this Tx response relates. But if there is a
+                        * hole in the bitmap of the BA we received, this Tx
+                        * response may allow to reclaim the hole and all the
+                        * subsequent packets that were already acked.
+                        * In that case, seq_ctl != ssn, and the next packet
+                        * to be reclaimed will be ssn and not seq_ctl.
+                        */
+                       next_reclaimed = ssn;
+               }
+
                __skb_queue_head_init(&skbs);
+               priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed;
+
+               IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
+                                         next_reclaimed);
+
                /*we can free until ssn % q.n_bd not inclusive */
-               iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
-                                 ssn, status, &skbs);
+               WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
+                                 ssn, status, &skbs));
+               iwlagn_check_ratid_empty(priv, sta_id, tid);
                freed = 0;
                while (!skb_queue_empty(&skbs)) {
                        skb = __skb_dequeue(&skbs);
@@ -893,27 +1138,24 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
 
        sta_id = ba_resp->sta_id;
        tid = ba_resp->tid;
-       agg = &priv->shrd->tid_data[sta_id][tid].agg;
+       agg = &priv->tid_data[sta_id][tid].agg;
 
        spin_lock_irqsave(&priv->shrd->sta_lock, flags);
 
-       if (unlikely(agg->txq_id != scd_flow)) {
-               /*
-                * FIXME: this is a uCode bug which need to be addressed,
-                * log the information and return for now!
-                * since it is possible happen very often and in order
-                * not to fill the syslog, don't enable the logging by default
-                */
-               IWL_DEBUG_TX_REPLY(priv,
-                       "BA scd_flow %d does not match txq_id %d\n",
-                       scd_flow, agg->txq_id);
+       if (unlikely(!agg->wait_for_ba)) {
+               if (unlikely(ba_resp->bitmap))
+                       IWL_ERR(priv, "Received BA when not expected\n");
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
                return 0;
        }
 
-       if (unlikely(!agg->wait_for_ba)) {
-               if (unlikely(ba_resp->bitmap))
-                       IWL_ERR(priv, "Received BA when not expected\n");
+       __skb_queue_head_init(&reclaimed_skbs);
+
+       /* Release all TFDs before the SSN, i.e. all TFDs in front of
+        * block-ack window (we assume that they've been successfully
+        * transmitted ... if not, it's too late anyway). */
+       if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
+                             ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
                return 0;
        }
@@ -925,7 +1167,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           ba_resp->sta_id);
        IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
                           "scd_flow = %d, scd_ssn = %d\n",
-                          ba_resp->tid, ba_resp->seq_ctl,
+                          ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl),
                           (unsigned long long)le64_to_cpu(ba_resp->bitmap),
                           scd_flow, ba_resp_scd_ssn);
 
@@ -946,13 +1188,9 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
                        ba_resp->txed, ba_resp->txed_2_done);
 
-       __skb_queue_head_init(&reclaimed_skbs);
+       priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn;
 
-       /* Release all TFDs before the SSN, i.e. all TFDs in front of
-        * block-ack window (we assume that they've been successfully
-        * transmitted ... if not, it's too late anyway). */
-       iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
-                         0, &reclaimed_skbs);
+       iwlagn_check_ratid_empty(priv, sta_id, tid);
        freed = 0;
        while (!skb_queue_empty(&reclaimed_skbs)) {
 
index f5fe42dbb3b0639001fb081fd2852515bc29ebc1..b5c7c5f0a753f4da5520982f16b0ca8292958691 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/div64.h>
 
 #include "iwl-eeprom.h"
+#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -515,7 +516,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
 
 static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
 {
-       const char *name_pre = priv->cfg->fw_name_pre;
+       const char *name_pre = cfg(priv)->fw_name_pre;
        char tag[8];
 
        if (first) {
@@ -524,14 +525,14 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
                strcpy(tag, UCODE_EXPERIMENTAL_TAG);
        } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
 #endif
-               priv->fw_index = priv->cfg->ucode_api_max;
+               priv->fw_index = cfg(priv)->ucode_api_max;
                sprintf(tag, "%d", priv->fw_index);
        } else {
                priv->fw_index--;
                sprintf(tag, "%d", priv->fw_index);
        }
 
-       if (priv->fw_index < priv->cfg->ucode_api_min) {
+       if (priv->fw_index < cfg(priv)->ucode_api_min) {
                IWL_ERR(priv, "no suitable firmware found!\n");
                return -ENOENT;
        }
@@ -836,9 +837,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        struct iwl_ucode_header *ucode;
        int err;
        struct iwlagn_firmware_pieces pieces;
-       const unsigned int api_max = priv->cfg->ucode_api_max;
-       unsigned int api_ok = priv->cfg->ucode_api_ok;
-       const unsigned int api_min = priv->cfg->ucode_api_min;
+       const unsigned int api_max = cfg(priv)->ucode_api_max;
+       unsigned int api_ok = cfg(priv)->ucode_api_ok;
+       const unsigned int api_min = cfg(priv)->ucode_api_min;
        u32 api_ver;
        char buildstr[25];
        u32 build;
@@ -1027,14 +1028,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
        else
                priv->init_evtlog_size =
-                       priv->cfg->base_params->max_event_log_size;
+                       cfg(priv)->base_params->max_event_log_size;
        priv->init_errlog_ptr = pieces.init_errlog_ptr;
        priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
        if (pieces.inst_evtlog_size)
                priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
        else
                priv->inst_evtlog_size =
-                       priv->cfg->base_params->max_event_log_size;
+                       cfg(priv)->base_params->max_event_log_size;
        priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
 #ifndef CONFIG_IWLWIFI_P2P
        ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
@@ -1043,7 +1044,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        priv->new_scan_threshold_behaviour =
                !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-       if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+       if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
                ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
 
        /*
@@ -1124,7 +1125,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
        spin_unlock_irqrestore(&priv->shrd->lock, flags);
        priv->thermal_throttle.ct_kill_toggle = false;
 
-       if (priv->cfg->base_params->support_ct_kill_exit) {
+       if (cfg(priv)->base_params->support_ct_kill_exit) {
                adv_cmd.critical_temperature_enter =
                        cpu_to_le32(hw_params(priv).ct_kill_threshold);
                adv_cmd.critical_temperature_exit =
@@ -1219,10 +1220,10 @@ int iwl_alive_start(struct iwl_priv *priv)
                return -ERFKILL;
 
        /* download priority table before any calibration request */
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist) {
                /* Configure Bluetooth device coexistence support */
-               if (priv->cfg->bt_params->bt_sco_disable)
+               if (cfg(priv)->bt_params->bt_sco_disable)
                        priv->bt_enable_pspoll = false;
                else
                        priv->bt_enable_pspoll = true;
@@ -1252,16 +1253,17 @@ int iwl_alive_start(struct iwl_priv *priv)
                iwl_send_bt_config(priv);
        }
 
-       if (hw_params(priv).calib_rt_cfg)
-               iwlagn_send_calib_cfg_rt(priv,
-                                        hw_params(priv).calib_rt_cfg);
+       /*
+        * Perform runtime calibrations, including DC calibration.
+        */
+       iwlagn_send_calib_cfg_rt(priv, IWL_CALIB_CFG_DC_IDX);
 
        ieee80211_wake_queues(priv->hw);
 
        priv->active_rate = IWL_RATES_MASK;
 
        /* Configure Tx antenna selection based on H/W config */
-       iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);
+       iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
 
        if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
                struct iwl_rxon_cmd *active_rxon =
@@ -1330,9 +1332,9 @@ void __iwl_down(struct iwl_priv *priv)
        priv->bt_status = 0;
        priv->cur_rssi_ctx = NULL;
        priv->bt_is_sco = 0;
-       if (priv->cfg->bt_params)
+       if (cfg(priv)->bt_params)
                priv->bt_traffic_load =
-                        priv->cfg->bt_params->bt_init_traffic_load;
+                        cfg(priv)->bt_params->bt_init_traffic_load;
        else
                priv->bt_traffic_load = 0;
        priv->bt_full_concurrent = false;
@@ -1514,8 +1516,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
        iwl_setup_scan_deferred_work(priv);
 
-       if (priv->cfg->lib->bt_setup_deferred_work)
-               priv->cfg->lib->bt_setup_deferred_work(priv);
+       if (cfg(priv)->lib->bt_setup_deferred_work)
+               cfg(priv)->lib->bt_setup_deferred_work(priv);
 
        init_timer(&priv->statistics_periodic);
        priv->statistics_periodic.data = (unsigned long)priv;
@@ -1532,8 +1534,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
-       if (priv->cfg->lib->cancel_deferred_work)
-               priv->cfg->lib->cancel_deferred_work(priv);
+       if (cfg(priv)->lib->cancel_deferred_work)
+               cfg(priv)->lib->cancel_deferred_work(priv);
 
        cancel_work_sync(&priv->run_time_calib_work);
        cancel_work_sync(&priv->beacon_update);
@@ -1602,8 +1604,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
        iwl_init_scan_params(priv);
 
        /* init bt coex */
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist) {
                priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
                priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
                priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
@@ -1667,18 +1669,18 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
                hw_params(priv).rx_page_order =
                        get_order(IWL_RX_BUF_SIZE_4K);
 
-       if (iwlagn_mod_params.disable_11n)
-               priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
+       if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
+               cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
        hw_params(priv).num_ampdu_queues =
-               priv->cfg->base_params->num_of_ampdu_queues;
+               cfg(priv)->base_params->num_of_ampdu_queues;
        hw_params(priv).shadow_reg_enable =
-               priv->cfg->base_params->shadow_reg_enable;
-       hw_params(priv).sku = priv->cfg->sku;
-       hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout;
+               cfg(priv)->base_params->shadow_reg_enable;
+       hw_params(priv).sku = cfg(priv)->sku;
+       hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
 
        /* Device-specific setup */
-       return priv->cfg->lib->set_hw_params(priv);
+       return cfg(priv)->lib->set_hw_params(priv);
 }
 
 
@@ -1757,7 +1759,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        iwl_debug_config(priv);
 
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-       priv->cfg = cfg;
+       cfg(priv) = cfg;
 
        /* is antenna coupling more than 35dB ? */
        priv->bt_ant_couple_ok =
@@ -1791,7 +1793,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
         ***********************/
        hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
-               priv->cfg->name, hw_rev);
+               cfg(priv)->name, hw_rev);
 
        err = iwl_trans_request_irq(trans(priv));
        if (err)
@@ -1915,12 +1917,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
        set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
 
        iwl_testmode_cleanup(priv);
-       iwl_leds_exit(priv);
-
-       if (priv->mac80211_registered) {
-               ieee80211_unregister_hw(priv->hw);
-               priv->mac80211_registered = 0;
-       }
+       iwlagn_mac_unregister(priv);
 
        iwl_tt_exit(priv);
 
@@ -1999,8 +1996,9 @@ module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
 MODULE_PARM_DESC(queues_num, "number of hw queues.");
-module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO);
-MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
+module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
+MODULE_PARM_DESC(11n_disable,
+       "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
 module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
index eb453ea41c41e05b44ad45deae8cc82c06ba6f93..f84fb3c535639980f9e5f9d2ae157b236085d92c 100644 (file)
@@ -91,6 +91,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv);
 struct ieee80211_hw *iwl_alloc_all(void);
 int iwlagn_mac_setup_register(struct iwl_priv *priv,
                              struct iwlagn_ucode_capabilities *capa);
+void iwlagn_mac_unregister(struct iwl_priv *priv);
 
 /* RXON */
 int iwlagn_set_pan_params(struct iwl_priv *priv);
@@ -108,11 +109,6 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
 int iwlagn_rx_calib_result(struct iwl_priv *priv,
                            struct iwl_rx_mem_buffer *rxb,
                            struct iwl_device_cmd *cmd);
-int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
-void iwl_send_prio_tbl(struct iwl_trans *trans);
-int iwlagn_run_init_ucode(struct iwl_priv *priv);
-int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
-                                enum iwl_ucode_type ucode_type);
 
 /* lib */
 int iwlagn_send_tx_power(struct iwl_priv *priv);
@@ -137,6 +133,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv);
 int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
 int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta, u16 tid, u8 buf_size);
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta, u16 tid);
 int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
@@ -356,7 +354,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
 void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
 void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
 
-extern int iwlagn_init_alive_start(struct iwl_priv *priv);
 extern int iwl_alive_start(struct iwl_priv *priv);
 /* svtool */
 #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
index 08b97594e3057c303237fda4846ea3b92240ee43..940d5038b39c2d93966f64dbcbf17efe25bc8bd6 100644 (file)
@@ -122,7 +122,8 @@ struct iwl_bus;
  * struct iwl_bus_ops - bus specific operations
  * @get_pm_support: must returns true if the bus can go to sleep
  * @apm_config: will be called during the config of the APM
- * @get_hw_id: prints the hw_id in the provided buffer
+ * @get_hw_id_string: prints the hw_id in the provided buffer
+ * @get_hw_id: get hw_id in u32
  * @write8: write a byte to register at offset ofs
  * @write32: write a dword to register at offset ofs
  * @wread32: read a dword at register at offset ofs
@@ -130,7 +131,8 @@ struct iwl_bus;
 struct iwl_bus_ops {
        bool (*get_pm_support)(struct iwl_bus *bus);
        void (*apm_config)(struct iwl_bus *bus);
-       void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
+       void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len);
+       u32 (*get_hw_id)(struct iwl_bus *bus);
        void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
        void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
        u32 (*read32)(struct iwl_bus *bus, u32 ofs);
@@ -172,9 +174,15 @@ static inline void bus_apm_config(struct iwl_bus *bus)
        bus->ops->apm_config(bus);
 }
 
-static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
+static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[],
+               int buf_len)
 {
-       bus->ops->get_hw_id(bus, buf, buf_len);
+       bus->ops->get_hw_id_string(bus, buf, buf_len);
+}
+
+static inline u32 bus_get_hw_id(struct iwl_bus *bus)
+{
+       return bus->ops->get_hw_id(bus);
 }
 
 static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val)
index 3b6f48bfe0e396b21482bcb626d1598d69b721bc..7bcfa781e0b914594c9157d561a7509d2a32a291 100644 (file)
@@ -60,8 +60,8 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
 
        ht_info->ht_supported = true;
 
-       if (priv->cfg->ht_params &&
-           priv->cfg->ht_params->ht_greenfield_support)
+       if (cfg(priv)->ht_params &&
+           cfg(priv)->ht_params->ht_greenfield_support)
                ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
        ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
        max_bit_rate = MAX_BIT_RATE_20_MHZ;
@@ -76,11 +76,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
                ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
 
        ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
-       if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
-               ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
        ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
-       if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
-               ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
 
        ht_info->mcs.rx_mask[0] = 0xFF;
        if (rx_chains_num >= 2)
@@ -141,7 +137,7 @@ int iwl_init_geos(struct iwl_priv *priv)
        sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
        sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
 
-       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
+       if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
                iwl_init_ht_hw_capab(priv, &sband->ht_cap,
                                         IEEE80211_BAND_5GHZ);
 
@@ -151,7 +147,7 @@ int iwl_init_geos(struct iwl_priv *priv)
        sband->bitrates = rates;
        sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
 
-       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
+       if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
                iwl_init_ht_hw_capab(priv, &sband->ht_cap,
                                         IEEE80211_BAND_2GHZ);
 
@@ -206,12 +202,12 @@ int iwl_init_geos(struct iwl_priv *priv)
        priv->tx_power_next = max_tx_power;
 
        if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-            priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+            cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
                char buf[32];
-               bus_get_hw_id(bus(priv), buf, sizeof(buf));
+               bus_get_hw_id_string(bus(priv), buf, sizeof(buf));
                IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
                        "Please send your %s to maintainer.\n", buf);
-               priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
+               cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
        }
 
        IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
@@ -966,9 +962,9 @@ int iwl_apm_init(struct iwl_priv *priv)
        bus_apm_config(bus(priv));
 
        /* Configure analog phase-lock-loop before activating to D0A */
-       if (priv->cfg->base_params->pll_cfg_val)
+       if (cfg(priv)->base_params->pll_cfg_val)
                iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG,
-                           priv->cfg->base_params->pll_cfg_val);
+                           cfg(priv)->base_params->pll_cfg_val);
 
        /*
         * Set "initialization complete" bit to move adapter from
@@ -1465,7 +1461,7 @@ void iwl_bg_watchdog(unsigned long data)
        if (iwl_is_rfkill(priv->shrd))
                return;
 
-       timeout = priv->cfg->base_params->wd_timeout;
+       timeout = cfg(priv)->base_params->wd_timeout;
        if (timeout == 0)
                return;
 
@@ -1490,11 +1486,11 @@ void iwl_bg_watchdog(unsigned long data)
 
 void iwl_setup_watchdog(struct iwl_priv *priv)
 {
-       unsigned int timeout = priv->cfg->base_params->wd_timeout;
+       unsigned int timeout = cfg(priv)->base_params->wd_timeout;
 
        if (!iwlagn_mod_params.wd_disable) {
                /* use system default */
-               if (timeout && !priv->cfg->base_params->wd_disable)
+               if (timeout && !cfg(priv)->base_params->wd_disable)
                        mod_timer(&priv->watchdog,
                                jiffies +
                                msecs_to_jiffies(IWL_WD_TICK(timeout)));
@@ -1584,34 +1580,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
        return cpu_to_le32(res);
 }
 
-void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
-                                enum iwl_rxon_context_id ctx,
-                                u8 sta_id, u8 tid)
-{
-       struct ieee80211_vif *vif;
-       u8 *addr = priv->stations[sta_id].sta.sta.addr;
-
-       if (ctx == NUM_IWL_RXON_CTX)
-               ctx = priv->stations[sta_id].ctxid;
-       vif = priv->contexts[ctx].vif;
-
-       ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
-}
-
-void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
-                               enum iwl_rxon_context_id ctx,
-                               u8 sta_id, u8 tid)
-{
-       struct ieee80211_vif *vif;
-       u8 *addr = priv->stations[sta_id].sta.sta.addr;
-
-       if (ctx == NUM_IWL_RXON_CTX)
-               ctx = priv->stations[sta_id].ctxid;
-       vif = priv->contexts[ctx].vif;
-
-       ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
-}
-
 void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
 {
        wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
@@ -1619,8 +1587,7 @@ void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
 
 void iwl_nic_config(struct iwl_priv *priv)
 {
-       priv->cfg->lib->nic_config(priv);
-
+       cfg(priv)->lib->nic_config(priv);
 }
 
 void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
index 6da53a36c1bed2015473e28d305f3a724979b71f..7bf76ab94dd21afb5fc8d80351eca3788d8452fa 100644 (file)
@@ -142,8 +142,6 @@ struct iwl_base_params {
  * @bt_init_traffic_load: specify initial bt traffic load
  * @bt_prio_boost: default bt priority boost value
  * @agg_time_limit: maximum number of uSec in aggregation
- * @ampdu_factor: Maximum A-MPDU length factor
- * @ampdu_density: Minimum A-MPDU spacing
  * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
  */
 struct iwl_bt_params {
@@ -151,8 +149,6 @@ struct iwl_bt_params {
        u8 bt_init_traffic_load;
        u8 bt_prio_boost;
        u16 agg_time_limit;
-       u8 ampdu_factor;
-       u8 ampdu_density;
        bool bt_sco_disable;
        bool bt_session_2;
 };
@@ -165,77 +161,6 @@ struct iwl_ht_params {
        enum ieee80211_smps_mode smps_mode;
 };
 
-/**
- * struct iwl_cfg
- * @name: Offical name of the device
- * @fw_name_pre: Firmware filename prefix. The api version and extension
- *     (.ucode) will be added to filename before loading from disk. The
- *     filename is constructed as fw_name_pre<api>.ucode.
- * @ucode_api_max: Highest version of uCode API supported by driver.
- * @ucode_api_ok: oldest version of the uCode API that is OK to load
- *     without a warning, for use in transitions
- * @ucode_api_min: Lowest version of uCode API supported by driver.
- * @valid_tx_ant: valid transmit antenna
- * @valid_rx_ant: valid receive antenna
- * @sku: sku information from EEPROM
- * @eeprom_ver: EEPROM version
- * @eeprom_calib_ver: EEPROM calibration version
- * @lib: pointer to the lib ops
- * @additional_nic_config: additional nic configuration
- * @base_params: pointer to basic parameters
- * @ht_params: point to ht patameters
- * @bt_params: pointer to bt parameters
- * @pa_type: used by 6000 series only to identify the type of Power Amplifier
- * @need_temp_offset_calib: need to perform temperature offset calibration
- * @no_xtal_calib: some devices do not need crystal calibration data,
- *     don't send it to those
- * @scan_antennas: available antenna for scan operation
- * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
- * @adv_pm: advance power management
- * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
- * @internal_wimax_coex: internal wifi/wimax combo device
- * @iq_invert: I/Q inversion
- * @temp_offset_v2: support v2 of temperature offset calibration
- *
- * We enable the driver to be backward compatible wrt API version. The
- * driver specifies which APIs it supports (with @ucode_api_max being the
- * highest and @ucode_api_min the lowest). Firmware will only be loaded if
- * it has a supported API version.
- *
- * The ideal usage of this infrastructure is to treat a new ucode API
- * release as a new hardware revision.
- */
-struct iwl_cfg {
-       /* params specific to an individual device within a device family */
-       const char *name;
-       const char *fw_name_pre;
-       const unsigned int ucode_api_max;
-       const unsigned int ucode_api_ok;
-       const unsigned int ucode_api_min;
-       u8   valid_tx_ant;
-       u8   valid_rx_ant;
-       u16  sku;
-       u16  eeprom_ver;
-       u16  eeprom_calib_ver;
-       const struct iwl_lib_ops *lib;
-       void (*additional_nic_config)(struct iwl_priv *priv);
-       /* params not likely to change within a device family */
-       struct iwl_base_params *base_params;
-       /* params likely to change within a device family */
-       struct iwl_ht_params *ht_params;
-       struct iwl_bt_params *bt_params;
-       enum iwl_pa_type pa_type;         /* if used set to IWL_PA_SYSTEM */
-       const bool need_temp_offset_calib; /* if used set to true */
-       const bool no_xtal_calib;
-       u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
-       enum iwl_led_mode led_mode;
-       const bool adv_pm;
-       const bool rx_with_siso_diversity;
-       const bool internal_wimax_coex;
-       const bool iq_invert;
-       const bool temp_offset_v2;
-};
-
 /***************************
  *   L i b                 *
  ***************************/
@@ -368,8 +293,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 
 static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
 {
-       return priv->cfg->bt_params &&
-              priv->cfg->bt_params->advanced_bt_coexist;
+       return cfg(priv)->bt_params &&
+              cfg(priv)->bt_params->advanced_bt_coexist;
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
index 6bf6845e1a51f4cec02a8cda17688d866fdf80fb..04a3343f4610faf4e654b5232c2d0d29f6773c75 100644 (file)
@@ -372,15 +372,13 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
                                 i, station->sta.sta.addr,
                                 station->sta.station_flags_msk);
                pos += scnprintf(buf + pos, bufsz - pos,
-                               "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n");
+                               "TID\tseq_num\trate_n_flags\n");
 
                for (j = 0; j < IWL_MAX_TID_COUNT; j++) {
-                       tid_data = &priv->shrd->tid_data[i][j];
+                       tid_data = &priv->tid_data[i][j];
                        pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d:\t%#x\t%#x\t%u\t%#x",
+                               "%d:\t%#x\t%#x",
                                j, tid_data->seq_number,
-                               tid_data->agg.txq_id,
-                               tid_data->tfds_in_queue,
                                tid_data->agg.rate_n_flags);
 
                        if (tid_data->agg.wait_for_ba)
@@ -408,7 +406,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
        const u8 *ptr;
        char *buf;
        u16 eeprom_ver;
-       size_t eeprom_len = priv->cfg->base_params->eeprom_size;
+       size_t eeprom_len = cfg(priv)->base_params->eeprom_size;
        buf_size = 4 * eeprom_len + 256;
 
        if (eeprom_len % 16) {
@@ -1542,15 +1540,15 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
        if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
                pos += scnprintf(buf + pos, bufsz - pos,
                        "tx power: (1/2 dB step)\n");
-               if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
+               if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
                        pos += scnprintf(buf + pos, bufsz - pos,
                                        fmt_hex, "antenna A:",
                                        tx->tx_power.ant_a);
-               if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
+               if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
                        pos += scnprintf(buf + pos, bufsz - pos,
                                        fmt_hex, "antenna B:",
                                        tx->tx_power.ant_b);
-               if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
+               if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
                        pos += scnprintf(buf + pos, bufsz - pos,
                                        fmt_hex, "antenna C:",
                                        tx->tx_power.ant_c);
@@ -2221,7 +2219,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
        const size_t bufsz = sizeof(buf);
 
        pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
-                       priv->cfg->base_params->plcp_delta_threshold);
+                       cfg(priv)->base_params->plcp_delta_threshold);
 
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
@@ -2243,10 +2241,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
                return -EINVAL;
        if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
                (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
-               priv->cfg->base_params->plcp_delta_threshold =
+               cfg(priv)->base_params->plcp_delta_threshold =
                        IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
        else
-               priv->cfg->base_params->plcp_delta_threshold = plcp;
+               cfg(priv)->base_params->plcp_delta_threshold = plcp;
        return count;
 }
 
@@ -2348,7 +2346,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
        if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
                timeout = IWL_DEF_WD_TIMEOUT;
 
-       priv->cfg->base_params->wd_timeout = timeout;
+       cfg(priv)->base_params->wd_timeout = timeout;
        iwl_setup_watchdog(priv);
        return count;
 }
@@ -2408,10 +2406,10 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
        char buf[40];
        const size_t bufsz = sizeof(buf);
 
-       if (priv->cfg->ht_params)
+       if (cfg(priv)->ht_params)
                pos += scnprintf(buf + pos, bufsz - pos,
                         "use %s for aggregation\n",
-                        (priv->cfg->ht_params->use_rts_for_aggregation) ?
+                        (cfg(priv)->ht_params->use_rts_for_aggregation) ?
                                "rts/cts" : "cts-to-self");
        else
                pos += scnprintf(buf + pos, bufsz - pos, "N/A");
@@ -2428,7 +2426,7 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
        int buf_size;
        int rts;
 
-       if (!priv->cfg->ht_params)
+       if (!cfg(priv)->ht_params)
                return -EINVAL;
 
        memset(buf, 0, sizeof(buf));
@@ -2438,9 +2436,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
        if (sscanf(buf, "%d", &rts) != 1)
                return -EINVAL;
        if (rts)
-               priv->cfg->ht_params->use_rts_for_aggregation = true;
+               cfg(priv)->ht_params->use_rts_for_aggregation = true;
        else
-               priv->cfg->ht_params->use_rts_for_aggregation = false;
+               cfg(priv)->ht_params->use_rts_for_aggregation = false;
        return count;
 }
 
index 69ecf6e2e658ae1c0e777d4b5f36faf185c8148b..e54a4d11e5845316bbb2b1067b9e958e35b0dbaf 100644 (file)
@@ -189,6 +189,69 @@ struct iwl_qos_info {
        struct iwl_qosparam_cmd def_qos_parm;
 };
 
+/**
+ * enum iwl_agg_state
+ *
+ * The state machine of the BA agreement establishment / tear down.
+ * These states relate to a specific RA / TID.
+ *
+ * @IWL_AGG_OFF: aggregation is not used
+ * @IWL_AGG_ON: aggregation session is up
+ * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
+ *     HW queue to be empty from packets for this RA /TID.
+ * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
+ *     HW queue to be empty from packets for this RA /TID.
+ */
+enum iwl_agg_state {
+       IWL_AGG_OFF = 0,
+       IWL_AGG_ON,
+       IWL_EMPTYING_HW_QUEUE_ADDBA,
+       IWL_EMPTYING_HW_QUEUE_DELBA,
+};
+
+/**
+ * struct iwl_ht_agg - aggregation state machine
+
+ * This structs holds the states for the BA agreement establishment and tear
+ * down. It also holds the state during the BA session itself. This struct is
+ * duplicated for each RA / TID.
+
+ * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
+ *     Tx response (REPLY_TX), and the block ack notification
+ *     (REPLY_COMPRESSED_BA).
+ * @state: state of the BA agreement establishment / tear down.
+ * @txq_id: Tx queue used by the BA session - used by the transport layer.
+ *     Needed by the upper layer for debugfs only.
+ * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or
+ *     the first packet to be sent in legacy HW queue in Tx AGG stop flow.
+ *     Basically when next_reclaimed reaches ssn, we can tell mac80211 that
+ *     we are ready to finish the Tx AGG stop / start flow.
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ */
+struct iwl_ht_agg {
+       u32 rate_n_flags;
+       enum iwl_agg_state state;
+       u16 txq_id;
+       u16 ssn;
+       bool wait_for_ba;
+};
+
+/**
+ * struct iwl_tid_data - one for each RA / TID
+
+ * This structs holds the states for each RA / TID.
+
+ * @seq_number: the next WiFi sequence number to use
+ * @next_reclaimed: the WiFi sequence number of the next packet to be acked.
+ *     This is basically (last acked packet++).
+ * @agg: aggregation state machine
+ */
+struct iwl_tid_data {
+       u16 seq_number;
+       u16 next_reclaimed;
+       struct iwl_ht_agg agg;
+};
+
 /*
  * Structure should be accessed with sta_lock held. When station addition
  * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
@@ -512,16 +575,6 @@ enum iwl_access_mode {
        IWL_OTP_ACCESS_RELATIVE,
 };
 
-/**
- * enum iwl_pa_type - Power Amplifier type
- * @IWL_PA_SYSTEM:  based on uCode configuration
- * @IWL_PA_INTERNAL: use Internal only
- */
-enum iwl_pa_type {
-       IWL_PA_SYSTEM = 0,
-       IWL_PA_INTERNAL = 1,
-};
-
 /* reply_tx_statistics (for _agn devices) */
 struct reply_tx_error_statistics {
        u32 pp_delay;
@@ -776,7 +829,6 @@ struct iwl_priv {
        struct ieee80211_channel *ieee_channels;
        struct ieee80211_rate *ieee_rates;
        struct kmem_cache *tx_cmd_pool;
-       struct iwl_cfg *cfg;
 
        enum ieee80211_band band;
 
@@ -880,6 +932,7 @@ struct iwl_priv {
        int num_stations;
        struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
        unsigned long ucode_key_table;
+       struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
 
        u8 mac80211_registered;
 
index f9d3319ecad5b9f6cb1c9f32bae83f59cc2f4a90..9b212a8f30bb8789bb4bd5c214e7841bd4672cf7 100644 (file)
@@ -90,6 +90,35 @@ TRACE_EVENT(iwlwifi_dev_iowrite32,
        TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
 );
 
+TRACE_EVENT(iwlwifi_dev_irq,
+       TP_PROTO(void *priv),
+       TP_ARGS(priv),
+       TP_STRUCT__entry(
+               PRIV_ENTRY
+       ),
+       TP_fast_assign(
+               PRIV_ASSIGN;
+       ),
+       /* TP_printk("") doesn't compile */
+       TP_printk("%d", 0)
+);
+
+TRACE_EVENT(iwlwifi_dev_ict_read,
+       TP_PROTO(void *priv, u32 index, u32 value),
+       TP_ARGS(priv, index, value),
+       TP_STRUCT__entry(
+               PRIV_ENTRY
+               __field(u32, index)
+               __field(u32, value)
+       ),
+       TP_fast_assign(
+               PRIV_ASSIGN;
+               __entry->index = index;
+               __entry->value = value;
+       ),
+       TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value)
+);
+
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_ucode
 
index 6fcc7d586b248592e5526df606aceeaf8a2ab3dc..c1eda9724f42f41059b4e161f60a64d7b7f7bdf0 100644 (file)
@@ -230,8 +230,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
        eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
        calib_ver = iwl_eeprom_calib_version(priv->shrd);
 
-       if (eeprom_ver < priv->cfg->eeprom_ver ||
-           calib_ver < priv->cfg->eeprom_calib_ver)
+       if (eeprom_ver < cfg(priv)->eeprom_ver ||
+           calib_ver < cfg(priv)->eeprom_calib_ver)
                goto err;
 
        IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
@@ -241,8 +241,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
 err:
        IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
                  "CALIB=0x%x < 0x%x\n",
-                 eeprom_ver, priv->cfg->eeprom_ver,
-                 calib_ver,  priv->cfg->eeprom_calib_ver);
+                 eeprom_ver, cfg(priv)->eeprom_ver,
+                 calib_ver,  cfg(priv)->eeprom_calib_ver);
        return -EINVAL;
 
 }
@@ -252,35 +252,35 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
        struct iwl_shared *shrd = priv->shrd;
        u16 radio_cfg;
 
-       if (!priv->cfg->sku) {
+       if (!cfg(priv)->sku) {
                /* not using sku overwrite */
-               priv->cfg->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
-               if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
-                   !priv->cfg->ht_params) {
+               cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
+               if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+                   !cfg(priv)->ht_params) {
                        IWL_ERR(priv, "Invalid 11n configuration\n");
                        return -EINVAL;
                }
        }
-       if (!priv->cfg->sku) {
+       if (!cfg(priv)->sku) {
                IWL_ERR(priv, "Invalid device sku\n");
                return -EINVAL;
        }
 
-       IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
+       IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku);
 
-       if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
+       if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) {
                /* not using .cfg overwrite */
                radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
-               priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
-               priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
-               if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
-                       IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
-                               priv->cfg->valid_tx_ant,
-                               priv->cfg->valid_rx_ant);
+               cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
+               cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
+               if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) {
+                       IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
+                               cfg(priv)->valid_tx_ant,
+                               cfg(priv)->valid_rx_ant);
                        return -EINVAL;
                }
-               IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
-                        priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
+               IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
+                        cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant);
        }
        /*
         * for some special cases,
@@ -369,7 +369,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus)
                 * CSR auto clock gate disable bit -
                 * this is only applicable for HW with OTP shadow RAM
                 */
-               if (priv(bus)->cfg->base_params->shadow_ram_support)
+               if (cfg(bus)->base_params->shadow_ram_support)
                        iwl_set_bit(bus, CSR_DBG_LINK_PWR_MGMT_REG,
                                CSR_RESET_LINK_PWR_MGMT_DISABLED);
        }
@@ -489,7 +489,7 @@ static int iwl_find_otp_image(struct iwl_bus *bus,
                }
                /* more in the link list, continue */
                usedblocks++;
-       } while (usedblocks <= priv(bus)->cfg->base_params->max_ll_items);
+       } while (usedblocks <= cfg(bus)->base_params->max_ll_items);
 
        /* OTP has no valid blocks */
        IWL_DEBUG_EEPROM(bus, "OTP has no valid blocks\n");
@@ -629,7 +629,7 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
                                 ((txp->delta_20_in_40 & 0xf0) >> 4),
                                 (txp->delta_20_in_40 & 0x0f));
 
-               max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx,
+               max_txp_avg = iwl_get_max_txpower_avg(cfg(priv), txp_array, idx,
                                                      &max_txp_avg_halfdbm);
 
                /*
@@ -667,7 +667,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
        if (trans(priv)->nvm_device_type == -ENOENT)
                return -ENOENT;
        /* allocate eeprom */
-       sz = priv->cfg->base_params->eeprom_size;
+       sz = cfg(priv)->base_params->eeprom_size;
        IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
        shrd->eeprom = kzalloc(sz, GFP_KERNEL);
        if (!shrd->eeprom) {
@@ -709,7 +709,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
                             CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
                             CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
                /* traversing the linked list if no shadow ram supported */
-               if (!priv->cfg->base_params->shadow_ram_support) {
+               if (!cfg(priv)->base_params->shadow_ram_support) {
                        if (iwl_find_otp_image(bus(priv), &validblockaddr)) {
                                ret = -ENOENT;
                                goto done;
@@ -776,7 +776,7 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
                        const u8 **eeprom_ch_index)
 {
        struct iwl_shared *shrd = priv->shrd;
-       u32 offset = priv->cfg->lib->
+       u32 offset = cfg(priv)->lib->
                        eeprom_ops.regulatory_bands[eep_band - 1];
        switch (eep_band) {
        case 1:         /* 2.4GHz band */
@@ -983,9 +983,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
        }
 
        /* Check if we do have HT40 channels */
-       if (priv->cfg->lib->eeprom_ops.regulatory_bands[5] ==
+       if (cfg(priv)->lib->eeprom_ops.regulatory_bands[5] ==
            EEPROM_REGULATORY_BAND_NO_HT40 &&
-           priv->cfg->lib->eeprom_ops.regulatory_bands[6] ==
+           cfg(priv)->lib->eeprom_ops.regulatory_bands[6] ==
            EEPROM_REGULATORY_BAND_NO_HT40)
                return 0;
 
@@ -1021,8 +1021,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
         * driver need to process addition information
         * to determine the max channel tx power limits
         */
-       if (priv->cfg->lib->eeprom_ops.update_enhanced_txpower)
-               priv->cfg->lib->eeprom_ops.update_enhanced_txpower(priv);
+       if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower)
+               cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv);
 
        return 0;
 }
index 3464cad7e38ccf9998e68b575e051eac74b47ca8..d57ea6484bbedf7529f47d6d79d4f79695bd6e19 100644 (file)
@@ -283,16 +283,29 @@ u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr)
        return value;
 }
 
-void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
+int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr,
+                               void *buf, int words)
 {
        unsigned long flags;
+       int offs, result = 0;
+       u32 *vals = buf;
 
        spin_lock_irqsave(&bus->reg_lock, flags);
        if (!iwl_grab_nic_access(bus)) {
                iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr);
                wmb();
-               iwl_write32(bus, HBUS_TARG_MEM_WDAT, val);
+
+               for (offs = 0; offs < words; offs++)
+                       iwl_write32(bus, HBUS_TARG_MEM_WDAT, vals[offs]);
                iwl_release_nic_access(bus);
-       }
+       } else
+               result = -EBUSY;
        spin_unlock_irqrestore(&bus->reg_lock, flags);
+
+       return result;
+}
+
+int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val)
+{
+       return _iwl_write_targ_mem_words(bus, addr, &val, 1);
 }
index ced2cbeb6eae56d3243fecc38798e64f78e5c69b..aae2eeb331a8e277e8cb668c9bfab6ddc5bad799 100644 (file)
@@ -85,6 +85,9 @@ void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr,
                                         (bufsize) / sizeof(u32));\
        } while (0)
 
+int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr,
+                             void *buf, int words);
+
 u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr);
-void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
+int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val);
 #endif
index eb541735296cd0b5733fecd19611cc8967db394a..14dcbfcdc0fd3247a74f69f55460d9198840b1f9 100644 (file)
@@ -137,11 +137,11 @@ static int iwl_led_cmd(struct iwl_priv *priv,
        }
 
        IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
-                       priv->cfg->base_params->led_compensation);
+                       cfg(priv)->base_params->led_compensation);
        led_cmd.on = iwl_blink_compensation(priv, on,
-                               priv->cfg->base_params->led_compensation);
+                               cfg(priv)->base_params->led_compensation);
        led_cmd.off = iwl_blink_compensation(priv, off,
-                               priv->cfg->base_params->led_compensation);
+                               cfg(priv)->base_params->led_compensation);
 
        ret = iwl_send_led_cmd(priv, &led_cmd);
        if (!ret) {
@@ -178,7 +178,7 @@ void iwl_leds_init(struct iwl_priv *priv)
        int ret;
 
        if (mode == IWL_LED_DEFAULT)
-               mode = priv->cfg->led_mode;
+               mode = cfg(priv)->led_mode;
 
        priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
                                   wiphy_name(priv->hw->wiphy));
index 1c93dfef6933b826c5a0c0187bfd88ae76606f39..2550b3c7dcbf4d26ed7a111944bf91ae0648bd79 100644 (file)
@@ -36,20 +36,6 @@ struct iwl_priv;
 #define IWL_LED_ACTIVITY       (0<<1)
 #define IWL_LED_LINK           (1<<1)
 
-/*
- * LED mode
- *    IWL_LED_DEFAULT:  use device default
- *    IWL_LED_RF_STATE: turn LED on/off based on RF state
- *                     LED ON  = RF ON
- *                     LED OFF = RF OFF
- *    IWL_LED_BLINK:    adjust led blink rate based on blink table
- */
-enum iwl_led_mode {
-       IWL_LED_DEFAULT,
-       IWL_LED_RF_STATE,
-       IWL_LED_BLINK,
-};
-
 void iwlagn_led_enable(struct iwl_priv *priv);
 void iwl_leds_init(struct iwl_priv *priv);
 void iwl_leds_exit(struct iwl_priv *priv);
index e3944f4e4fd622cada27c13b66278db2ee540120..f980e574e1f90dc38b2c9bc426107b9bb1fd400a 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/div64.h>
 
 #include "iwl-eeprom.h"
+#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -160,7 +161,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
        hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
-       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
+       if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
                hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                             IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -233,6 +234,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
                priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &priv->bands[IEEE80211_BAND_5GHZ];
 
+       hw->wiphy->hw_version = bus_get_hw_id(bus(priv));
+
        iwl_leds_init(priv);
 
        ret = ieee80211_register_hw(priv->hw);
@@ -245,6 +248,15 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
        return 0;
 }
 
+void iwlagn_mac_unregister(struct iwl_priv *priv)
+{
+       if (!priv->mac80211_registered)
+               return;
+       iwl_leds_exit(priv);
+       ieee80211_unregister_hw(priv->hw);
+       priv->mac80211_registered = 0;
+}
+
 static int __iwl_up(struct iwl_priv *priv)
 {
        struct iwl_rxon_context *ctx;
@@ -265,13 +277,13 @@ static int __iwl_up(struct iwl_priv *priv)
                }
        }
 
-       ret = iwlagn_run_init_ucode(priv);
+       ret = iwl_run_init_ucode(trans(priv));
        if (ret) {
                IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
                goto error;
        }
 
-       ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
+       ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR);
        if (ret) {
                IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
                goto error;
@@ -611,12 +623,11 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        struct iwl_priv *priv = hw->priv;
        int ret = -EINVAL;
        struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
-       struct iwl_rxon_context *ctx =  iwl_rxon_ctx_from_vif(vif);
 
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
                     sta->addr, tid);
 
-       if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
+       if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE))
                return -EACCES;
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -624,6 +635,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
+               if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+                       break;
                IWL_DEBUG_HT(priv, "start Rx\n");
                ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
                break;
@@ -634,6 +647,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                        ret = 0;
                break;
        case IEEE80211_AMPDU_TX_START:
+               if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+                       break;
                IWL_DEBUG_HT(priv, "start Tx\n");
                ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
                break;
@@ -647,8 +662,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
                        ret = 0;
-               if (!priv->agg_tids_count && priv->cfg->ht_params &&
-                   priv->cfg->ht_params->use_rts_for_aggregation) {
+               if (!priv->agg_tids_count && cfg(priv)->ht_params &&
+                   cfg(priv)->ht_params->use_rts_for_aggregation) {
                        /*
                         * switch off RTS/CTS if it was previously enabled
                         */
@@ -659,54 +674,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                }
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
-               buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
-
-               iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta),
-                               tid, buf_size);
-
-               /*
-                * If the limit is 0, then it wasn't initialised yet,
-                * use the default. We can do that since we take the
-                * minimum below, and we don't want to go above our
-                * default due to hardware restrictions.
-                */
-               if (sta_priv->max_agg_bufsize == 0)
-                       sta_priv->max_agg_bufsize =
-                               LINK_QUAL_AGG_FRAME_LIMIT_DEF;
-
-               /*
-                * Even though in theory the peer could have different
-                * aggregation reorder buffer sizes for different sessions,
-                * our ucode doesn't allow for that and has a global limit
-                * for each station. Therefore, use the minimum of all the
-                * aggregation sessions and our default value.
-                */
-               sta_priv->max_agg_bufsize =
-                       min(sta_priv->max_agg_bufsize, buf_size);
-
-               if (priv->cfg->ht_params &&
-                   priv->cfg->ht_params->use_rts_for_aggregation) {
-                       /*
-                        * switch to RTS/CTS if it is the prefer protection
-                        * method for HT traffic
-                        */
-
-                       sta_priv->lq_sta.lq.general_params.flags |=
-                               LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-               }
-               priv->agg_tids_count++;
-               IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
-                            priv->agg_tids_count);
-
-               sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
-                       sta_priv->max_agg_bufsize;
-
-               iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
-                               &sta_priv->lq_sta.lq, CMD_ASYNC, false);
-
-               IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
-                        sta->addr, tid);
-               ret = 0;
+               ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
                break;
        }
        mutex_unlock(&priv->shrd->mutex);
@@ -792,7 +760,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
        if (!iwl_is_associated_ctx(ctx))
                goto out;
 
-       if (!priv->cfg->lib->set_channel_switch)
+       if (!cfg(priv)->lib->set_channel_switch)
                goto out;
 
        ch = channel->hw_value;
@@ -832,7 +800,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
         */
        set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
        priv->switch_channel = cpu_to_le16(ch);
-       if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) {
+       if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
                clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
                priv->switch_channel = 0;
                ieee80211_chswitch_done(ctx->vif, false);
@@ -1125,8 +1093,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
        IWL_DEBUG_MAC80211(priv, "enter\n");
        mutex_lock(&priv->shrd->mutex);
 
-       if (priv->cfg->bt_params &&
-                       priv->cfg->bt_params->advanced_bt_coexist) {
+       if (cfg(priv)->bt_params &&
+                       cfg(priv)->bt_params->advanced_bt_coexist) {
                if (rssi_event == RSSI_EVENT_LOW)
                        priv->bt_enable_pspoll = true;
                else if (rssi_event == RSSI_EVENT_HIGH)
@@ -1237,7 +1205,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
                return err;
        }
 
-       if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
+       if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist &&
            vif->type == NL80211_IFTYPE_ADHOC) {
                /*
                 * pretend to have high BT traffic as long as we
index 850ec8e51b176738544b755bdbea8687e1f0b3be..fb30ea7ca96b54d43aa1bf0048d52a7c0f4df161 100644 (file)
@@ -135,7 +135,7 @@ static void iwl_pci_apm_config(struct iwl_bus *bus)
        }
 }
 
-static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
+static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[],
                              int buf_len)
 {
        struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
@@ -144,6 +144,13 @@ static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
                 pci_dev->subsystem_device);
 }
 
+static u32 iwl_pci_get_hw_id(struct iwl_bus *bus)
+{
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+       return (pci_dev->device << 16) + pci_dev->subsystem_device;
+}
+
 static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val)
 {
        iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
@@ -163,6 +170,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
 static const struct iwl_bus_ops bus_ops_pci = {
        .get_pm_support = iwl_pci_is_pm_supported,
        .apm_config = iwl_pci_apm_config,
+       .get_hw_id_string = iwl_pci_get_hw_id_string,
        .get_hw_id = iwl_pci_get_hw_id,
        .write8 = iwl_pci_write8,
        .write32 = iwl_pci_write32,
index 4eaab204322d5e672ac8e93cf4d1cb2934136a15..2b188a6025b319ac7fcc3aa804b117ba3d29bdca 100644 (file)
@@ -167,7 +167,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
        u8 skip;
        u32 slp_itrvl;
 
-       if (priv->cfg->adv_pm) {
+       if (cfg(priv)->adv_pm) {
                table = apm_range_2;
                if (period <= IWL_DTIM_RANGE_1_MAX)
                        table = apm_range_1;
@@ -221,7 +221,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
                cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
        if (iwl_advanced_bt_coexist(priv)) {
-               if (!priv->cfg->bt_params->bt_sco_disable)
+               if (!cfg(priv)->bt_params->bt_sco_disable)
                        cmd->flags |= IWL_POWER_BT_SCO_ENA;
                else
                        cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
@@ -307,7 +307,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
                cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
        if (iwl_advanced_bt_coexist(priv)) {
-               if (!priv->cfg->bt_params->bt_sco_disable)
+               if (!cfg(priv)->bt_params->bt_sco_disable)
                        cmd->flags |= IWL_POWER_BT_SCO_ENA;
                else
                        cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
@@ -350,7 +350,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
 
        if (priv->shrd->wowlan)
                iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
-       else if (!priv->cfg->base_params->no_idle_support &&
+       else if (!cfg(priv)->base_params->no_idle_support &&
                 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
                iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
        else if (iwl_tt_is_low_power_state(priv)) {
index 359d2182757bbbb6c567b2fb9cb4d7291021df4c..084aa2c4ccfb272dab28d57fbc9969644360f314 100644 (file)
@@ -691,8 +691,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
                 * Internal scans are passive, so we can indiscriminately set
                 * the BT ignore flag on 2.4 GHz since it applies to TX only.
                 */
-               if (priv->cfg->bt_params &&
-                   priv->cfg->bt_params->advanced_bt_coexist)
+               if (cfg(priv)->bt_params &&
+                   cfg(priv)->bt_params->advanced_bt_coexist)
                        scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
                break;
        case IEEE80211_BAND_5GHZ:
@@ -733,12 +733,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 
        band = priv->scan_band;
 
-       if (priv->cfg->scan_rx_antennas[band])
-               rx_ant = priv->cfg->scan_rx_antennas[band];
+       if (cfg(priv)->scan_rx_antennas[band])
+               rx_ant = cfg(priv)->scan_rx_antennas[band];
 
        if (band == IEEE80211_BAND_2GHZ &&
-           priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+           cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist) {
                /* transmit 2.4 GHz probes only on first antenna */
                scan_tx_antennas = first_antenna(scan_tx_antennas);
        }
@@ -762,8 +762,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 
                rx_ant = first_antenna(active_chains);
        }
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist &&
+       if (cfg(priv)->bt_params &&
+           cfg(priv)->bt_params->advanced_bt_coexist &&
            priv->bt_full_concurrent) {
                /* operated as 1x1 in full concurrency mode */
                rx_ant = first_antenna(rx_ant);
index 29a7284aa3ef9ff60cb0c9154f70f1b583b39538..dc55cc4a8108191fbdb84ccdb7296cd25d394d98 100644 (file)
@@ -94,7 +94,6 @@
  * This implementation is iwl-pci.c
  */
 
-struct iwl_cfg;
 struct iwl_bus;
 struct iwl_priv;
 struct iwl_trans;
@@ -108,6 +107,10 @@ struct iwl_trans_ops;
 
 extern struct iwl_mod_params iwlagn_mod_params;
 
+#define IWL_DISABLE_HT_ALL     BIT(0)
+#define IWL_DISABLE_HT_TXAGG   BIT(1)
+#define IWL_DISABLE_HT_RXAGG   BIT(2)
+
 /**
  * struct iwl_mod_params
  *
@@ -115,7 +118,8 @@ extern struct iwl_mod_params iwlagn_mod_params;
  *
  * @sw_crypto: using hardware encryption, default = 0
  * @num_of_queues: number of tx queue, HW dependent
- * @disable_11n: 11n capabilities enabled, default = 0
+ * @disable_11n: disable 11n capabilities, default = 0,
+ *     use IWL_DISABLE_HT_* constants
  * @amsdu_size_8K: enable 8K amsdu size, default = 1
  * @antenna: both antennas (use diversity), default = 0
  * @restart_fw: restart firmware, default = 1
@@ -136,7 +140,7 @@ extern struct iwl_mod_params iwlagn_mod_params;
 struct iwl_mod_params {
        int sw_crypto;
        int num_of_queues;
-       int disable_11n;
+       unsigned int disable_11n;
        int amsdu_size_8K;
        int antenna;
        int restart_fw;
@@ -175,7 +179,6 @@ struct iwl_mod_params {
  * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
  *     relevant for 1000, 6000 and up
  * @wd_timeout: TX queues watchdog timeout
- * @calib_rt_cfg: setup runtime calibrations for the hw
  * @struct iwl_sensitivity_ranges: range of sensitivity values
  */
 struct iwl_hw_params {
@@ -195,68 +198,9 @@ struct iwl_hw_params {
        u32 ct_kill_exit_threshold;
        unsigned int wd_timeout;
 
-       u32 calib_rt_cfg;
        const struct iwl_sensitivity_ranges *sens;
 };
 
-/**
- * enum iwl_agg_state
- *
- * The state machine of the BA agreement establishment / tear down.
- * These states relate to a specific RA / TID.
- *
- * @IWL_AGG_OFF: aggregation is not used
- * @IWL_AGG_ON: aggregation session is up
- * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
- *     HW queue to be empty from packets for this RA /TID.
- * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
- *     HW queue to be empty from packets for this RA /TID.
- */
-enum iwl_agg_state {
-       IWL_AGG_OFF = 0,
-       IWL_AGG_ON,
-       IWL_EMPTYING_HW_QUEUE_ADDBA,
-       IWL_EMPTYING_HW_QUEUE_DELBA,
-};
-
-/**
- * struct iwl_ht_agg - aggregation state machine
-
- * This structs holds the states for the BA agreement establishment and tear
- * down. It also holds the state during the BA session itself. This struct is
- * duplicated for each RA / TID.
-
- * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
- *     Tx response (REPLY_TX), and the block ack notification
- *     (REPLY_COMPRESSED_BA).
- * @state: state of the BA agreement establishment / tear down.
- * @txq_id: Tx queue used by the BA session - used by the transport layer.
- *     Needed by the upper layer for debugfs only.
- * @wait_for_ba: Expect block-ack before next Tx reply
- */
-struct iwl_ht_agg {
-       u32 rate_n_flags;
-       enum iwl_agg_state state;
-       u16 txq_id;
-       bool wait_for_ba;
-};
-
-/**
- * struct iwl_tid_data - one for each RA / TID
-
- * This structs holds the states for each RA / TID.
-
- * @seq_number: the next WiFi sequence number to use
- * @tfds_in_queue: number of packets sent to the HW queues.
- *     Exported for debugfs only
- * @agg: aggregation state machine
- */
-struct iwl_tid_data {
-       u16 seq_number;
-       u16 tfds_in_queue;
-       struct iwl_ht_agg agg;
-};
-
 /**
  * enum iwl_ucode_type
  *
@@ -303,6 +247,101 @@ struct iwl_notification_wait {
        bool triggered, aborted;
 };
 
+/**
+ * enum iwl_pa_type - Power Amplifier type
+ * @IWL_PA_SYSTEM:  based on uCode configuration
+ * @IWL_PA_INTERNAL: use Internal only
+ */
+enum iwl_pa_type {
+       IWL_PA_SYSTEM = 0,
+       IWL_PA_INTERNAL = 1,
+};
+
+/*
+ * LED mode
+ *    IWL_LED_DEFAULT:  use device default
+ *    IWL_LED_RF_STATE: turn LED on/off based on RF state
+ *                     LED ON  = RF ON
+ *                     LED OFF = RF OFF
+ *    IWL_LED_BLINK:    adjust led blink rate based on blink table
+ */
+enum iwl_led_mode {
+       IWL_LED_DEFAULT,
+       IWL_LED_RF_STATE,
+       IWL_LED_BLINK,
+};
+
+/**
+ * struct iwl_cfg
+ * @name: Offical name of the device
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ *     (.ucode) will be added to filename before loading from disk. The
+ *     filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_ok: oldest version of the uCode API that is OK to load
+ *     without a warning, for use in transitions
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @valid_tx_ant: valid transmit antenna
+ * @valid_rx_ant: valid receive antenna
+ * @sku: sku information from EEPROM
+ * @eeprom_ver: EEPROM version
+ * @eeprom_calib_ver: EEPROM calibration version
+ * @lib: pointer to the lib ops
+ * @additional_nic_config: additional nic configuration
+ * @base_params: pointer to basic parameters
+ * @ht_params: point to ht patameters
+ * @bt_params: pointer to bt parameters
+ * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+ * @need_temp_offset_calib: need to perform temperature offset calibration
+ * @no_xtal_calib: some devices do not need crystal calibration data,
+ *     don't send it to those
+ * @scan_rx_antennas: available antenna for scan operation
+ * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
+ * @adv_pm: advance power management
+ * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
+ * @internal_wimax_coex: internal wifi/wimax combo device
+ * @iq_invert: I/Q inversion
+ * @temp_offset_v2: support v2 of temperature offset calibration
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version.
+ *
+ * The ideal usage of this infrastructure is to treat a new ucode API
+ * release as a new hardware revision.
+ */
+struct iwl_cfg {
+       /* params specific to an individual device within a device family */
+       const char *name;
+       const char *fw_name_pre;
+       const unsigned int ucode_api_max;
+       const unsigned int ucode_api_ok;
+       const unsigned int ucode_api_min;
+       u8   valid_tx_ant;
+       u8   valid_rx_ant;
+       u16  sku;
+       u16  eeprom_ver;
+       u16  eeprom_calib_ver;
+       const struct iwl_lib_ops *lib;
+       void (*additional_nic_config)(struct iwl_priv *priv);
+       /* params not likely to change within a device family */
+       struct iwl_base_params *base_params;
+       /* params likely to change within a device family */
+       struct iwl_ht_params *ht_params;
+       struct iwl_bt_params *bt_params;
+       enum iwl_pa_type pa_type;         /* if used set to IWL_PA_SYSTEM */
+       const bool need_temp_offset_calib; /* if used set to true */
+       const bool no_xtal_calib;
+       u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
+       enum iwl_led_mode led_mode;
+       const bool adv_pm;
+       const bool rx_with_siso_diversity;
+       const bool internal_wimax_coex;
+       const bool iq_invert;
+       const bool temp_offset_v2;
+};
+
 /**
  * struct iwl_shared - shared fields for all the layers of the driver
  *
@@ -311,15 +350,20 @@ struct iwl_notification_wait {
  * @ucode_owner: IWL_OWNERSHIP_*
  * @cmd_queue: command queue number
  * @status: STATUS_*
+ * @wowlan: are we running wowlan uCode
  * @valid_contexts: microcode/device supports multiple contexts
  * @bus: pointer to the bus layer data
+ * @cfg: see struct iwl_cfg
  * @priv: pointer to the upper layer data
+ * @trans: pointer to the transport layer data
  * @hw_params: see struct iwl_hw_params
  * @workqueue: the workqueue used by all the layers of the driver
  * @lock: protect general shared data
  * @sta_lock: protects the station table.
  *     If lock and sta_lock are needed, lock must be acquired first.
  * @mutex:
+ * @wait_command_queue: the wait_queue for SYNC host command nad uCode load
+ * @eeprom: pointer to the eeprom/OTP image
  * @ucode_type: indicator of loaded ucode image
  * @notif_waits: things waiting for notification
  * @notif_wait_lock: lock protecting notification
@@ -340,6 +384,7 @@ struct iwl_shared {
        u8 valid_contexts;
 
        struct iwl_bus *bus;
+       struct iwl_cfg *cfg;
        struct iwl_priv *priv;
        struct iwl_trans *trans;
        struct iwl_hw_params hw_params;
@@ -349,8 +394,6 @@ struct iwl_shared {
        spinlock_t sta_lock;
        struct mutex mutex;
 
-       struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
-
        wait_queue_head_t wait_command_queue;
 
        /* eeprom -- this is in the card's little endian byte order */
@@ -373,6 +416,7 @@ struct iwl_shared {
 
 /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
 #define priv(_m)       ((_m)->shrd->priv)
+#define cfg(_m)                ((_m)->shrd->cfg)
 #define bus(_m)                ((_m)->shrd->bus)
 #define trans(_m)      ((_m)->shrd->trans)
 #define hw_params(_m)  ((_m)->shrd->hw_params)
@@ -494,12 +538,6 @@ int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
                                 struct iwl_device_cmd *cmd);
 
 int iwlagn_hw_valid_rtc_data_addr(u32 addr);
-void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
-                                enum iwl_rxon_context_id ctx,
-                                u8 sta_id, u8 tid);
-void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
-                               enum iwl_rxon_context_id ctx,
-                               u8 sta_id, u8 tid);
 void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
 void iwl_nic_config(struct iwl_priv *priv);
 void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
index a874eb7b5f8e3e0920aec32e416f9d26e83d102b..4a5cddd2d56bfb867a21c6d00f49cd219743ce2a 100644 (file)
@@ -70,6 +70,7 @@
 #include <net/mac80211.h>
 #include <net/netlink.h>
 
+#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
@@ -380,7 +381,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
        iwl_init_notification_wait(priv->shrd, &calib_wait,
                                      CALIBRATION_COMPLETE_NOTIFICATION,
                                      NULL, NULL);
-       ret = iwlagn_init_alive_start(priv);
+       ret = iwl_init_alive_start(trans(priv));
        if (ret) {
                IWL_DEBUG_INFO(priv,
                        "Error configuring init calibration: %d\n", ret);
@@ -417,16 +418,16 @@ cfg_init_calib_error:
 static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 {
        struct iwl_priv *priv = hw->priv;
+       struct iwl_trans *trans = trans(priv);
        struct sk_buff *skb;
        unsigned char *rsp_data_ptr = NULL;
        int status = 0, rsp_data_len = 0;
-       char buf[32], *ptr = NULL;
-       unsigned int num, devid;
+       u32 devid;
 
        switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
        case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
-               rsp_data_ptr = (unsigned char *)priv->cfg->name;
-               rsp_data_len = strlen(priv->cfg->name);
+               rsp_data_ptr = (unsigned char *)cfg(priv)->name;
+               rsp_data_len = strlen(cfg(priv)->name);
                skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
                                                        rsp_data_len + 20);
                if (!skb) {
@@ -445,7 +446,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                break;
 
        case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
-               status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
+               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
                if (status)
                        IWL_DEBUG_INFO(priv,
                                "Error loading init ucode: %d\n", status);
@@ -453,11 +454,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
        case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
                iwl_testmode_cfg_init_calib(priv);
-               iwl_trans_stop_device(trans(priv));
+               iwl_trans_stop_device(trans);
                break;
 
        case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
-               status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
+               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
                if (status) {
                        IWL_DEBUG_INFO(priv,
                                "Error loading runtime ucode: %d\n", status);
@@ -471,8 +472,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
        case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
                iwl_scan_cancel_timeout(priv, 200);
-               iwl_trans_stop_device(trans(priv));
-               status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
+               iwl_trans_stop_device(trans);
+               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
                if (status) {
                        IWL_DEBUG_INFO(priv,
                                "Error loading WOWLAN ucode: %d\n", status);
@@ -487,7 +488,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
        case IWL_TM_CMD_APP2DEV_GET_EEPROM:
                if (priv->shrd->eeprom) {
                        skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
-                               priv->cfg->base_params->eeprom_size + 20);
+                               cfg(priv)->base_params->eeprom_size + 20);
                        if (!skb) {
                                IWL_DEBUG_INFO(priv,
                                       "Error allocating memory\n");
@@ -496,7 +497,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                        NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
                                IWL_TM_CMD_DEV2APP_EEPROM_RSP);
                        NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
-                               priv->cfg->base_params->eeprom_size,
+                               cfg(priv)->base_params->eeprom_size,
                                priv->shrd->eeprom);
                        status = cfg80211_testmode_reply(skb);
                        if (status < 0)
@@ -532,14 +533,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                break;
 
        case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
-               bus_get_hw_id(bus(priv), buf, sizeof(buf));
-               ptr = buf;
-               strsep(&ptr, ":");
-               sscanf(strsep(&ptr, ":"), "%x", &num);
-               sscanf(strsep(&ptr, ":"), "%x", &devid);
-               IWL_INFO(priv, "Device ID = 0x%04x, SubDevice ID= 0x%04x\n",
-                               num, devid);
-               devid |= (num << 16);
+               devid = bus_get_hw_id(bus(priv));
+               IWL_INFO(priv, "hw version: 0x%x\n", devid);
 
                skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
                if (!skb) {
index 5a384b309b097df902aaf1700f56ebb449fa8d06..f6debf91d7b514036baf05530af28507440cab3e 100644 (file)
@@ -219,9 +219,7 @@ struct iwl_trans_pcie {
 
        /* INT ICT Table */
        __le32 *ict_tbl;
-       void *ict_tbl_vir;
        dma_addr_t ict_tbl_dma;
-       dma_addr_t aligned_ict_tbl_dma;
        int ict_index;
        u32 inta;
        bool use_ict;
@@ -236,6 +234,7 @@ struct iwl_trans_pcie {
        const u8 *ac_to_fifo[NUM_IWL_RXON_CTX];
        const u8 *ac_to_queue[NUM_IWL_RXON_CTX];
        u8 mcast_queue[NUM_IWL_RXON_CTX];
+       u8 agg_txq[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
 
        struct iwl_tx_queue *txq;
        unsigned long txq_ctx_active_msk;
@@ -280,20 +279,16 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans,
 void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
                                           struct iwl_tx_queue *txq,
                                           u16 byte_cnt);
-void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id);
 int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
-                                 enum iwl_rxon_context_id ctx, int sta_id,
-                                 int tid);
+                                 int sta_id, int tid);
 void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index);
 void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
                             struct iwl_tx_queue *txq,
                             int tx_fifo_id, int scd_retry);
-int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
-                               enum iwl_rxon_context_id ctx, int sta_id,
-                               int tid, u16 *ssn);
+int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, int sta_id, int tid);
 void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
                                 enum iwl_rxon_context_id ctx,
-                                int sta_id, int tid, int frame_limit);
+                                int sta_id, int tid, int frame_limit, u16 ssn);
 void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
        int index, enum dma_data_direction dma_dir);
 int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
index 2ee00e0f39d346e6f71287d5b4ffc057ff3de676..752493f00406a0a808c0984d0ddc96b215ce3fb1 100644 (file)
@@ -672,7 +672,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
 {
        struct iwl_priv *priv = priv(trans);
        /* W/A for WiFi/WiMAX coex and WiMAX own the RF */
-       if (priv->cfg->internal_wimax_coex &&
+       if (cfg(priv)->internal_wimax_coex &&
            (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) &
                        APMS_CLK_VAL_MRB_FUNC_MODE) ||
             (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) &
@@ -1151,7 +1151,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
  * ICT functions
  *
  ******************************************************************************/
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* a device (PCI-E) page is 4096 bytes long */
+#define ICT_SHIFT      12
+#define ICT_SIZE       (1 << ICT_SHIFT)
+#define ICT_COUNT      (ICT_SIZE / sizeof(u32))
 
 /* Free dram table */
 void iwl_free_isr_ict(struct iwl_trans *trans)
@@ -1159,21 +1163,19 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie =
                IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       if (trans_pcie->ict_tbl_vir) {
-               dma_free_coherent(bus(trans)->dev,
-                                 (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-                                 trans_pcie->ict_tbl_vir,
+       if (trans_pcie->ict_tbl) {
+               dma_free_coherent(bus(trans)->dev, ICT_SIZE,
+                                 trans_pcie->ict_tbl,
                                  trans_pcie->ict_tbl_dma);
-               trans_pcie->ict_tbl_vir = NULL;
-               memset(&trans_pcie->ict_tbl_dma, 0,
-                       sizeof(trans_pcie->ict_tbl_dma));
-               memset(&trans_pcie->aligned_ict_tbl_dma, 0,
-                       sizeof(trans_pcie->aligned_ict_tbl_dma));
+               trans_pcie->ict_tbl = NULL;
+               trans_pcie->ict_tbl_dma = 0;
        }
 }
 
 
-/* allocate dram shared table it is a PAGE_SIZE aligned
+/*
+ * allocate dram shared table, it is an aligned memory
+ * block of ICT_SIZE.
  * also reset all data related to ICT table interrupt.
  */
 int iwl_alloc_isr_ict(struct iwl_trans *trans)
@@ -1181,36 +1183,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie =
                IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       /* allocate shrared data table */
-       trans_pcie->ict_tbl_vir =
-               dma_alloc_coherent(bus(trans)->dev,
-                                  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-                                  &trans_pcie->ict_tbl_dma, GFP_KERNEL);
-       if (!trans_pcie->ict_tbl_vir)
+       trans_pcie->ict_tbl =
+               dma_alloc_coherent(bus(trans)->dev, ICT_SIZE,
+                                  &trans_pcie->ict_tbl_dma,
+                                  GFP_KERNEL);
+       if (!trans_pcie->ict_tbl)
                return -ENOMEM;
 
-       /* align table to PAGE_SIZE boundary */
-       trans_pcie->aligned_ict_tbl_dma =
-               ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
-
-       IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
-                          (unsigned long long)trans_pcie->ict_tbl_dma,
-                          (unsigned long long)trans_pcie->aligned_ict_tbl_dma,
-                          (int)(trans_pcie->aligned_ict_tbl_dma -
-                          trans_pcie->ict_tbl_dma));
+       /* just an API sanity check ... it is guaranteed to be aligned */
+       if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) {
+               iwl_free_isr_ict(trans);
+               return -EINVAL;
+       }
 
-       trans_pcie->ict_tbl =  trans_pcie->ict_tbl_vir +
-                         (trans_pcie->aligned_ict_tbl_dma -
-                         trans_pcie->ict_tbl_dma);
+       IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
+                     (unsigned long long)trans_pcie->ict_tbl_dma);
 
-       IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
-                            trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
-                       (int)(trans_pcie->aligned_ict_tbl_dma -
-                           trans_pcie->ict_tbl_dma));
+       IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
 
        /* reset table and index to all 0 */
-       memset(trans_pcie->ict_tbl_vir, 0,
-               (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+       memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
        trans_pcie->ict_index = 0;
 
        /* add periodic RX interrupt */
@@ -1228,23 +1220,20 @@ int iwl_reset_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie =
                IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       if (!trans_pcie->ict_tbl_vir)
+       if (!trans_pcie->ict_tbl)
                return 0;
 
        spin_lock_irqsave(&trans->shrd->lock, flags);
        iwl_disable_interrupts(trans);
 
-       memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+       memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
 
-       val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
+       val = trans_pcie->ict_tbl_dma >> ICT_SHIFT;
 
        val |= CSR_DRAM_INT_TBL_ENABLE;
        val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
 
-       IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
-                       "aligned dma address %Lx\n",
-                       val,
-                       (unsigned long long)trans_pcie->aligned_ict_tbl_dma);
+       IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val);
 
        iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
        trans_pcie->use_ict = true;
@@ -1281,6 +1270,8 @@ static irqreturn_t iwl_isr(int irq, void *data)
        if (!trans)
                return IRQ_NONE;
 
+       trace_iwlwifi_dev_irq(priv(trans));
+
        trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        spin_lock_irqsave(&trans->shrd->lock, flags);
@@ -1355,6 +1346,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
        struct iwl_trans_pcie *trans_pcie;
        u32 inta, inta_mask;
        u32 val = 0;
+       u32 read;
        unsigned long flags;
 
        if (!trans)
@@ -1368,6 +1360,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
        if (!trans_pcie->use_ict)
                return iwl_isr(irq, data);
 
+       trace_iwlwifi_dev_irq(priv(trans));
+
        spin_lock_irqsave(&trans->shrd->lock, flags);
 
        /* Disable (but don't clear!) interrupts here to avoid
@@ -1382,24 +1376,29 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
        /* Ignore interrupt if there's nothing in NIC to service.
         * This may be due to IRQ shared with another device,
         * or due to sporadic interrupts thrown from our NIC. */
-       if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) {
+       read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+       trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read);
+       if (!read) {
                IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
                goto none;
        }
 
-       /* read all entries that not 0 start with ict_index */
-       while (trans_pcie->ict_tbl[trans_pcie->ict_index]) {
-
-               val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+       /*
+        * Collect all entries up to the first 0, starting from ict_index;
+        * note we already read at ict_index.
+        */
+       do {
+               val |= read;
                IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n",
-                               trans_pcie->ict_index,
-                               le32_to_cpu(
-                                 trans_pcie->ict_tbl[trans_pcie->ict_index]));
+                               trans_pcie->ict_index, read);
                trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
                trans_pcie->ict_index =
                        iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
 
-       }
+               read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
+               trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index,
+                                          read);
+       } while (read);
 
        /* We should not get this value, just ignore it. */
        if (val == 0xffffffff)
@@ -1426,7 +1425,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
        if (likely(inta))
                tasklet_schedule(&trans_pcie->irq_tasklet);
        else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-                       !trans_pcie->inta) {
+                !trans_pcie->inta) {
                /* Allow interrupt if was disabled by this handler and
                 * no tasklet was schedules, We should not enable interrupt,
                 * tasklet will enable it.
@@ -1442,7 +1441,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
         * only Re-enable if disabled by irq.
         */
        if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
-               !trans_pcie->inta)
+           !trans_pcie->inta)
                iwl_enable_interrupts(trans);
 
        spin_unlock_irqrestore(&trans->shrd->lock, flags);
index 79331fb10aa5664395624b5adcab7caedcdd0c16..bd29568177e6354eb2f6523c0a782155221072a5 100644 (file)
@@ -408,6 +408,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id)
 void iwl_trans_set_wr_ptrs(struct iwl_trans *trans,
                                int txq_id, u32 index)
 {
+       IWL_DEBUG_TX_QUEUES(trans, "Q %d  WrPtr: %d", txq_id, index & 0xff);
        iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR,
                        (index & 0xff) | (txq_id << 8));
        iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index);
@@ -446,14 +447,21 @@ static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
        return -EINVAL;
 }
 
+static inline bool is_agg_txqid_valid(struct iwl_trans *trans, int txq_id)
+{
+       if (txq_id < IWLAGN_FIRST_AMPDU_QUEUE)
+               return false;
+       return txq_id < (IWLAGN_FIRST_AMPDU_QUEUE +
+               hw_params(trans).num_ampdu_queues);
+}
+
 void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
                                 enum iwl_rxon_context_id ctx, int sta_id,
-                                int tid, int frame_limit)
+                                int tid, int frame_limit, u16 ssn)
 {
-       int tx_fifo, txq_id, ssn_idx;
+       int tx_fifo, txq_id;
        u16 ra_tid;
        unsigned long flags;
-       struct iwl_tid_data *tid_data;
 
        struct iwl_trans_pcie *trans_pcie =
                IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -469,11 +477,15 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
                return;
        }
 
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       ssn_idx = SEQ_TO_SN(tid_data->seq_number);
-       txq_id = tid_data->agg.txq_id;
-       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
+       txq_id = trans_pcie->agg_txq[sta_id][tid];
+       if (WARN_ON_ONCE(is_agg_txqid_valid(trans, txq_id) == false)) {
+               IWL_ERR(trans,
+                       "queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
+                       IWLAGN_FIRST_AMPDU_QUEUE +
+                       hw_params(trans).num_ampdu_queues - 1);
+               return;
+       }
 
        ra_tid = BUILD_RAxTID(sta_id, tid);
 
@@ -493,9 +505,9 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
 
        /* Place first TFD at index corresponding to start sequence number.
         * Assumes that ssn_idx is valid (!= 0xFFF) */
-       trans_pcie->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-       trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-       iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx);
+       trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff);
+       trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff);
+       iwl_trans_set_wr_ptrs(trans, txq_id, ssn);
 
        /* Set up Tx window size and frame limit for this queue */
        iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr +
@@ -539,12 +551,9 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
 }
 
 int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
-                               enum iwl_rxon_context_id ctx, int sta_id,
-                               int tid, u16 *ssn)
+                               int sta_id, int tid)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_tid_data *tid_data;
-       unsigned long flags;
        int txq_id;
 
        txq_id = iwlagn_txq_ctx_activate_free(trans);
@@ -553,118 +562,39 @@ int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans,
                return -ENXIO;
        }
 
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
-       tid_data->agg.txq_id = txq_id;
+       trans_pcie->agg_txq[sta_id][tid] = txq_id;
        iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id);
 
-       if (tid_data->tfds_in_queue == 0) {
-               IWL_DEBUG_TX_QUEUES(trans, "HW queue is empty\n");
-               tid_data->agg.state = IWL_AGG_ON;
-               iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
-       } else {
-               IWL_DEBUG_TX_QUEUES(trans,
-                                   "HW queue is NOT empty: %d packets in HW"
-                                   " queue\n", tid_data->tfds_in_queue);
-               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-       }
-       spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-
        return 0;
 }
 
-void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id)
+int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
-
-       iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
-
-       trans_pcie->txq[txq_id].q.read_ptr = 0;
-       trans_pcie->txq[txq_id].q.write_ptr = 0;
-       /* supposes that ssn_idx is valid (!= 0xFFF) */
-       iwl_trans_set_wr_ptrs(trans, txq_id, 0);
+       u8 txq_id = trans_pcie->agg_txq[sta_id][tid];
 
-       iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
-       iwl_txq_ctx_deactivate(trans_pcie, txq_id);
-       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
-}
-
-int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans,
-                                 enum iwl_rxon_context_id ctx, int sta_id,
-                                 int tid)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       unsigned long flags;
-       int read_ptr, write_ptr;
-       struct iwl_tid_data *tid_data;
-       int txq_id;
-
-       spin_lock_irqsave(&trans->shrd->sta_lock, flags);
-
-       tid_data = &trans->shrd->tid_data[sta_id][tid];
-       txq_id = tid_data->agg.txq_id;
-
-       if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-           (IWLAGN_FIRST_AMPDU_QUEUE +
-               hw_params(trans).num_ampdu_queues <= txq_id)) {
+       if (WARN_ON_ONCE(is_agg_txqid_valid(trans, txq_id) == false)) {
                IWL_ERR(trans,
                        "queue number out of range: %d, must be %d to %d\n",
                        txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
                        IWLAGN_FIRST_AMPDU_QUEUE +
                        hw_params(trans).num_ampdu_queues - 1);
-               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
                return -EINVAL;
        }
 
-       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /*
-               * This can happen if the peer stops aggregation
-               * again before we've had a chance to drain the
-               * queue we selected previously, i.e. before the
-               * session was really started completely.
-               */
-               IWL_DEBUG_HT(trans, "AGG stop before setup done\n");
-               goto turn_off;
-       case IWL_AGG_ON:
-               break;
-       default:
-               IWL_WARN(trans, "Stopping AGG while state not ON "
-                        "or starting for %d on %d (%d)\n", sta_id, tid,
-                        trans->shrd->tid_data[sta_id][tid].agg.state);
-               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-               return 0;
-       }
-
-       write_ptr = trans_pcie->txq[txq_id].q.write_ptr;
-       read_ptr = trans_pcie->txq[txq_id].q.read_ptr;
-
-       /* The queue is not empty */
-       if (write_ptr != read_ptr) {
-               IWL_DEBUG_TX_QUEUES(trans,
-                                   "Stopping a non empty AGG HW QUEUE\n");
-               trans->shrd->tid_data[sta_id][tid].agg.state =
-                       IWL_EMPTYING_HW_QUEUE_DELBA;
-               spin_unlock_irqrestore(&trans->shrd->sta_lock, flags);
-               return 0;
-       }
-
-       IWL_DEBUG_TX_QUEUES(trans, "HW queue is empty\n");
-turn_off:
-       trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
-
-       /* do not restore/save irqs */
-       spin_unlock(&trans->shrd->sta_lock);
-       spin_lock(&trans->shrd->lock);
-
-       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
+       iwlagn_tx_queue_stop_scheduler(trans, txq_id);
 
-       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+       iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id));
 
-       iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid);
+       trans_pcie->agg_txq[sta_id][tid] = 0;
+       trans_pcie->txq[txq_id].q.read_ptr = 0;
+       trans_pcie->txq[txq_id].q.write_ptr = 0;
+       /* supposes that ssn_idx is valid (!= 0xFFF) */
+       iwl_trans_set_wr_ptrs(trans, txq_id, 0);
 
+       iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id));
+       iwl_txq_ctx_deactivate(trans_pcie, txq_id);
+       iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0);
        return 0;
 }
 
index 3cf62c363bc00ab43f49d5336f576de928462466..cb9da25bd81d9e1fb1ad2855d2915fdf99d2f7a2 100644 (file)
@@ -1044,7 +1044,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 
 static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
-               u8 sta_id)
+               u8 sta_id, u8 tid)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -1058,13 +1058,12 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        dma_addr_t txcmd_phys;
        dma_addr_t scratch_phys;
        u16 len, firstlen, secondlen;
-       u16 seq_number = 0;
        u8 wait_write_ptr = 0;
        u8 txq_id;
-       u8 tid = 0;
        bool is_agg = false;
        __le16 fc = hdr->frame_control;
        u8 hdr_len = ieee80211_hdrlen(fc);
+       u16 __maybe_unused wifi_seq;
 
        /*
         * Send this frame after DTIM -- there's a special queue
@@ -1085,44 +1084,28 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                txq_id =
                    trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)];
 
-       if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
-               u8 *qc = NULL;
-               struct iwl_tid_data *tid_data;
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               tid_data = &trans->shrd->tid_data[sta_id][tid];
-
-               if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
-                       return -1;
-
-               seq_number = tid_data->seq_number;
-               seq_number &= IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(seq_number);
-               /* aggregation is on for this <sta,tid> */
-               if (info->flags & IEEE80211_TX_CTL_AMPDU) {
-                       if (WARN_ON_ONCE(tid_data->agg.state != IWL_AGG_ON)) {
-                               IWL_ERR(trans, "TX_CTL_AMPDU while not in AGG:"
-                                       " Tx flags = 0x%08x, agg.state = %d",
-                                       info->flags, tid_data->agg.state);
-                               IWL_ERR(trans, "sta_id = %d, tid = %d "
-                                       "txq_id = %d, seq_num = %d", sta_id,
-                                       tid, tid_data->agg.txq_id,
-                                       seq_number >> 4);
-                       }
-                       txq_id = tid_data->agg.txq_id;
-                       is_agg = true;
-               }
-               seq_number += 0x10;
+       /* aggregation is on for this <sta,tid> */
+       if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+               WARN_ON(tid >= IWL_MAX_TID_COUNT);
+               txq_id = trans_pcie->agg_txq[sta_id][tid];
+               is_agg = true;
        }
 
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
-
        txq = &trans_pcie->txq[txq_id];
        q = &txq->q;
 
+       /* In AGG mode, the index in the ring must correspond to the WiFi
+        * sequence number. This is a HW requirements to help the SCD to parse
+        * the BA.
+        * Check here that the packets are in the right place on the ring.
+        */
+#ifdef CONFIG_IWLWIFI_DEBUG
+       wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
+       WARN_ONCE(is_agg && ((wifi_seq & 0xff) != q->write_ptr),
+                 "Q: %d WiFi Seq %d tfdNum %d",
+                 txq_id, wifi_seq, q->write_ptr);
+#endif
+
        /* Set up driver data for this TFD */
        txq->skbs[q->write_ptr] = skb;
        txq->cmd[q->write_ptr] = dev_cmd;
@@ -1220,13 +1203,6 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
        iwl_txq_update_write_ptr(trans, txq);
 
-       if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue++;
-               if (!ieee80211_has_morefrags(fc))
-                       trans->shrd->tid_data[sta_id][tid].seq_number =
-                               seq_number;
-       }
-
        /*
         * At this point the frame is "transmitted" successfully
         * and we will get a TX status notification eventually,
@@ -1275,85 +1251,30 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
        return 0;
 }
 
-static int iwlagn_txq_check_empty(struct iwl_trans *trans,
-                          int sta_id, u8 tid, int txq_id)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       struct iwl_queue *q = &trans_pcie->txq[txq_id].q;
-       struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
-
-       lockdep_assert_held(&trans->shrd->sta_lock);
-
-       switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_DELBA:
-               /* We are reclaiming the last packet of the */
-               /* aggregated HW queue */
-               if ((txq_id  == tid_data->agg.txq_id) &&
-                   (q->read_ptr == q->write_ptr)) {
-                       IWL_DEBUG_TX_QUEUES(trans,
-                               "HW queue empty: continue DELBA flow\n");
-                       iwl_trans_pcie_txq_agg_disable(trans, txq_id);
-                       tid_data->agg.state = IWL_AGG_OFF;
-                       iwl_stop_tx_ba_trans_ready(priv(trans),
-                                                  NUM_IWL_RXON_CTX,
-                                                  sta_id, tid);
-                       iwl_wake_queue(trans, &trans_pcie->txq[txq_id],
-                                      "DELBA flow complete");
-               }
-               break;
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /* We are reclaiming the last packet of the queue */
-               if (tid_data->tfds_in_queue == 0) {
-                       IWL_DEBUG_TX_QUEUES(trans,
-                               "HW queue empty: continue ADDBA flow\n");
-                       tid_data->agg.state = IWL_AGG_ON;
-                       iwl_start_tx_ba_trans_ready(priv(trans),
-                                                   NUM_IWL_RXON_CTX,
-                                                   sta_id, tid);
-               }
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
-                           int sta_id, int tid, int freed)
-{
-       lockdep_assert_held(&trans->shrd->sta_lock);
-
-       if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
-       else {
-               IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
-                       trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
-                       freed);
-               trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
-       }
-}
-
-static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
+static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
                      int txq_id, int ssn, u32 status,
                      struct sk_buff_head *skbs)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
-       enum iwl_agg_state agg_state;
        /* n_bd is usually 256 => n_bd - 1 = 0xff */
        int tfd_num = ssn & (txq->q.n_bd - 1);
        int freed = 0;
-       bool cond;
 
        txq->time_stamp = jiffies;
 
-       if (txq->sched_retry) {
-               agg_state =
-                       trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
-               cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
-       } else {
-               cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
+       if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
+                    txq_id != trans_pcie->agg_txq[sta_id][tid])) {
+               /*
+                * FIXME: this is a uCode bug which need to be addressed,
+                * log the information and return for now.
+                * Since it is can possibly happen very often and in order
+                * not to fill the syslog, don't use IWL_ERR or IWL_WARN
+                */
+               IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, "
+                       "agg_txq[sta_id[tid] %d", txq_id,
+                       trans_pcie->agg_txq[sta_id][tid]);
+               return 1;
        }
 
        if (txq->q.read_ptr != tfd_num) {
@@ -1361,12 +1282,12 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
                                txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
                                tfd_num, ssn);
                freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
-               if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
+               if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
+                  (!txq->sched_retry ||
+                  status != TX_STATUS_FAIL_PASSIVE_NO_RX))
                        iwl_wake_queue(trans, txq, "Packets reclaimed");
        }
-
-       iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
-       iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
+       return 0;
 }
 
 static void iwl_trans_pcie_free(struct iwl_trans *trans)
index f94a6ee5f82f6693d866bab58d606652eae87112..e6bf3f554772354ed816c2e707b5fed2f3d28105 100644 (file)
@@ -178,20 +178,18 @@ struct iwl_trans_ops {
 
        int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
                struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
-               u8 sta_id);
-       void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
+               u8 sta_id, u8 tid);
+       int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
                        int txq_id, int ssn, u32 status,
                        struct sk_buff_head *skbs);
 
        int (*tx_agg_disable)(struct iwl_trans *trans,
-                             enum iwl_rxon_context_id ctx, int sta_id,
-                             int tid);
+                             int sta_id, int tid);
        int (*tx_agg_alloc)(struct iwl_trans *trans,
-                           enum iwl_rxon_context_id ctx, int sta_id, int tid,
-                           u16 *ssn);
+                           int sta_id, int tid);
        void (*tx_agg_setup)(struct iwl_trans *trans,
                             enum iwl_rxon_context_id ctx, int sta_id, int tid,
-                            int frame_limit);
+                            int frame_limit, u16 ssn);
 
        void (*kick_nic)(struct iwl_trans *trans);
 
@@ -305,39 +303,38 @@ int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
 
 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
                struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
-               u8 sta_id)
+               u8 sta_id, u8 tid)
 {
-       return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
+       return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id, tid);
 }
 
-static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
+static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
                                 int tid, int txq_id, int ssn, u32 status,
                                 struct sk_buff_head *skbs)
 {
-       trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
+       return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
+                                  status, skbs);
 }
 
 static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
-                                           enum iwl_rxon_context_id ctx,
                                            int sta_id, int tid)
 {
-       return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid);
+       return trans->ops->tx_agg_disable(trans, sta_id, tid);
 }
 
 static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
-                                        enum iwl_rxon_context_id ctx,
-                                        int sta_id, int tid, u16 *ssn)
+                                        int sta_id, int tid)
 {
-       return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn);
+       return trans->ops->tx_agg_alloc(trans, sta_id, tid);
 }
 
 
 static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
                                           enum iwl_rxon_context_id ctx,
                                           int sta_id, int tid,
-                                          int frame_limit)
+                                          int frame_limit, u16 ssn)
 {
-       trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit);
+       trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
 }
 
 static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
index 0577212ad3f35cc90ea89ec30be44c1f174b8889..36a1b5b2585898094d158c7a5f874958d35c7851 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
 
+#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
@@ -213,23 +214,23 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
 /*
  *  Calibration
  */
-static int iwl_set_Xtal_calib(struct iwl_priv *priv)
+static int iwl_set_Xtal_calib(struct iwl_trans *trans)
 {
        struct iwl_calib_xtal_freq_cmd cmd;
        __le16 *xtal_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
+               (__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL);
 
        iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
        cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
        cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
-       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
 }
 
-static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
+static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
 {
        struct iwl_calib_temperature_offset_cmd cmd;
        __le16 *offset_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv->shrd,
+               (__le16 *)iwl_eeprom_query_addr(trans->shrd,
                                                EEPROM_RAW_TEMPERATURE);
 
        memset(&cmd, 0, sizeof(cmd));
@@ -238,45 +239,45 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
        if (!(cmd.radio_sensor_offset))
                cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
 
-       IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
+       IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n",
                        le16_to_cpu(cmd.radio_sensor_offset));
-       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
 }
 
-static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
+static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans)
 {
        struct iwl_calib_temperature_offset_v2_cmd cmd;
-       __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
+       __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(trans->shrd,
                                     EEPROM_KELVIN_TEMPERATURE);
        __le16 *offset_calib_low =
-               (__le16 *)iwl_eeprom_query_addr(priv->shrd,
+               (__le16 *)iwl_eeprom_query_addr(trans->shrd,
                                                EEPROM_RAW_TEMPERATURE);
        struct iwl_eeprom_calib_hdr *hdr;
 
        memset(&cmd, 0, sizeof(cmd));
        iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
-       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
+       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(trans->shrd,
                                                        EEPROM_CALIB_ALL);
        memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
                sizeof(*offset_calib_high));
        memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
                sizeof(*offset_calib_low));
        if (!(cmd.radio_sensor_offset_low)) {
-               IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
+               IWL_DEBUG_CALIB(trans, "no info in EEPROM, use default\n");
                cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
                cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
        }
        memcpy(&cmd.burntVoltageRef, &hdr->voltage,
                sizeof(hdr->voltage));
 
-       IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
+       IWL_DEBUG_CALIB(trans, "Radio sensor offset high: %d\n",
                        le16_to_cpu(cmd.radio_sensor_offset_high));
-       IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
+       IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n",
                        le16_to_cpu(cmd.radio_sensor_offset_low));
-       IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
+       IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n",
                        le16_to_cpu(cmd.burntVoltageRef));
 
-       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
 }
 
 static int iwl_send_calib_cfg(struct iwl_trans *trans)
@@ -316,26 +317,26 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv,
        return 0;
 }
 
-int iwlagn_init_alive_start(struct iwl_priv *priv)
+int iwl_init_alive_start(struct iwl_trans *trans)
 {
        int ret;
 
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist) {
+       if (cfg(trans)->bt_params &&
+           cfg(trans)->bt_params->advanced_bt_coexist) {
                /*
                 * Tell uCode we are ready to perform calibration
                 * need to perform this before any calibration
                 * no need to close the envlope since we are going
                 * to load the runtime uCode later.
                 */
-               ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
+               ret = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN,
                        BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
                if (ret)
                        return ret;
 
        }
 
-       ret = iwl_send_calib_cfg(trans(priv));
+       ret = iwl_send_calib_cfg(trans);
        if (ret)
                return ret;
 
@@ -343,21 +344,21 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
         * temperature offset calibration is only needed for runtime ucode,
         * so prepare the value now.
         */
-       if (priv->cfg->need_temp_offset_calib) {
-               if (priv->cfg->temp_offset_v2)
-                       return iwl_set_temperature_offset_calib_v2(priv);
+       if (cfg(trans)->need_temp_offset_calib) {
+               if (cfg(trans)->temp_offset_v2)
+                       return iwl_set_temperature_offset_calib_v2(trans);
                else
-                       return iwl_set_temperature_offset_calib(priv);
+                       return iwl_set_temperature_offset_calib(trans);
        }
 
        return 0;
 }
 
-static int iwl_send_wimax_coex(struct iwl_priv *priv)
+static int iwl_send_wimax_coex(struct iwl_trans *trans)
 {
        struct iwl_wimax_coex_cmd coex_cmd;
 
-       if (priv->cfg->base_params->support_wimax_coexist) {
+       if (cfg(trans)->base_params->support_wimax_coexist) {
                /* UnMask wake up src at associated sleep */
                coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
 
@@ -376,7 +377,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv)
                /* coexistence is disabled */
                memset(&coex_cmd, 0, sizeof(coex_cmd));
        }
-       return iwl_trans_send_cmd_pdu(trans(priv),
+       return iwl_trans_send_cmd_pdu(trans,
                                COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
                                sizeof(coex_cmd), &coex_cmd);
 }
@@ -431,8 +432,9 @@ int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
 }
 
 
-static int iwl_alive_notify(struct iwl_priv *priv)
+static int iwl_alive_notify(struct iwl_trans *trans)
 {
+       struct iwl_priv *priv = priv(trans);
        struct iwl_rxon_context *ctx;
        int ret;
 
@@ -445,21 +447,21 @@ static int iwl_alive_notify(struct iwl_priv *priv)
        if (!priv->tx_cmd_pool)
                return -ENOMEM;
 
-       iwl_trans_tx_start(trans(priv));
+       iwl_trans_tx_start(trans);
        for_each_context(priv, ctx)
                ctx->last_tx_rejected = false;
 
-       ret = iwl_send_wimax_coex(priv);
+       ret = iwl_send_wimax_coex(trans);
        if (ret)
                return ret;
 
-       if (!priv->cfg->no_xtal_calib) {
-               ret = iwl_set_Xtal_calib(priv);
+       if (!cfg(priv)->no_xtal_calib) {
+               ret = iwl_set_Xtal_calib(trans);
                if (ret)
                        return ret;
        }
 
-       return iwl_send_calib_results(trans(priv));
+       return iwl_send_calib_results(trans);
 }
 
 
@@ -545,7 +547,7 @@ static int iwl_verify_ucode(struct iwl_trans *trans,
        return -EIO;
 }
 
-struct iwlagn_alive_data {
+struct iwl_alive_data {
        bool valid;
        u8 subtype;
 };
@@ -554,7 +556,7 @@ static void iwl_alive_fn(struct iwl_trans *trans,
                            struct iwl_rx_packet *pkt,
                            void *data)
 {
-       struct iwlagn_alive_data *alive_data = data;
+       struct iwl_alive_data *alive_data = data;
        struct iwl_alive_resp *palive;
 
        palive = &pkt->u.alive_frame;
@@ -640,12 +642,11 @@ void iwl_abort_notification_waits(struct iwl_shared *shrd)
 #define UCODE_ALIVE_TIMEOUT    HZ
 #define UCODE_CALIB_TIMEOUT    (2*HZ)
 
-int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
+int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
                                 enum iwl_ucode_type ucode_type)
 {
        struct iwl_notification_wait alive_wait;
-       struct iwlagn_alive_data alive_data;
-       struct iwl_trans *trans = trans(priv);
+       struct iwl_alive_data alive_data;
        int ret;
        enum iwl_ucode_type old_type;
 
@@ -680,7 +681,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
        }
 
        if (!alive_data.valid) {
-               IWL_ERR(priv, "Loaded ucode is not valid!\n");
+               IWL_ERR(trans, "Loaded ucode is not valid!\n");
                trans->shrd->ucode_type = old_type;
                return -EIO;
        }
@@ -701,9 +702,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                msleep(5);
        }
 
-       ret = iwl_alive_notify(priv);
+       ret = iwl_alive_notify(trans);
        if (ret) {
-               IWL_WARN(priv,
+               IWL_WARN(trans,
                        "Could not complete ALIVE transition: %d\n", ret);
                trans->shrd->ucode_type = old_type;
                return ret;
@@ -712,30 +713,30 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
        return 0;
 }
 
-int iwlagn_run_init_ucode(struct iwl_priv *priv)
+int iwl_run_init_ucode(struct iwl_trans *trans)
 {
        struct iwl_notification_wait calib_wait;
        int ret;
 
-       lockdep_assert_held(&priv->shrd->mutex);
+       lockdep_assert_held(&trans->shrd->mutex);
 
        /* No init ucode required? Curious, but maybe ok */
-       if (!trans(priv)->ucode_init.code.len)
+       if (!trans->ucode_init.code.len)
                return 0;
 
-       if (priv->shrd->ucode_type != IWL_UCODE_NONE)
+       if (trans->shrd->ucode_type != IWL_UCODE_NONE)
                return 0;
 
-       iwl_init_notification_wait(priv->shrd, &calib_wait,
+       iwl_init_notification_wait(trans->shrd, &calib_wait,
                                      CALIBRATION_COMPLETE_NOTIFICATION,
                                      NULL, NULL);
 
        /* Will also start the device */
-       ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
+       ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
        if (ret)
                goto error;
 
-       ret = iwlagn_init_alive_start(priv);
+       ret = iwl_init_alive_start(trans);
        if (ret)
                goto error;
 
@@ -743,15 +744,15 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
         * Some things may run in the background now, but we
         * just wait for the calibration complete notification.
         */
-       ret = iwl_wait_notification(priv->shrd, &calib_wait,
+       ret = iwl_wait_notification(trans->shrd, &calib_wait,
                                        UCODE_CALIB_TIMEOUT);
 
        goto out;
 
  error:
-       iwl_remove_notification(priv->shrd, &calib_wait);
+       iwl_remove_notification(trans->shrd, &calib_wait);
  out:
        /* Whatever happened, stop the device */
-       iwl_trans_stop_device(trans(priv));
+       iwl_trans_stop_device(trans);
        return ret;
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h
new file mode 100644 (file)
index 0000000..1850110
--- /dev/null
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_wifi_h__
+#define __iwl_wifi_h__
+
+#include "iwl-shared.h"
+
+int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
+void iwl_send_prio_tbl(struct iwl_trans *trans);
+int iwl_init_alive_start(struct iwl_trans *trans);
+int iwl_run_init_ucode(struct iwl_trans *trans);
+int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
+                                enum iwl_ucode_type ucode_type);
+#endif  /* __iwl_wifi_h__ */
index d1d84e0e30fcfd2e6a19aa11dbdc6e6db2c77112..a7cd311cb1b74fe3bacd5e73b41b882d38752b54 100644 (file)
@@ -731,9 +731,11 @@ static void lbs_scan_worker(struct work_struct *work)
                le16_to_cpu(scan_cmd->hdr.size),
                lbs_ret_scan, 0);
 
-       if (priv->scan_channel >= priv->scan_req->n_channels)
+       if (priv->scan_channel >= priv->scan_req->n_channels) {
                /* Mark scan done */
+               cancel_delayed_work(&priv->scan_work);
                lbs_scan_done(priv);
+       }
 
        /* Restart network */
        if (carrier)
@@ -762,12 +764,12 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal,
                request->n_ssids, request->n_channels, request->ie_len);
 
        priv->scan_channel = 0;
-       queue_delayed_work(priv->work_thread, &priv->scan_work,
-               msecs_to_jiffies(50));
-
        priv->scan_req = request;
        priv->internal_scan = internal;
 
+       queue_delayed_work(priv->work_thread, &priv->scan_work,
+               msecs_to_jiffies(50));
+
        lbs_deb_leave(LBS_DEB_CFG80211);
 }
 
index 787dbe2aa4085dbcee9ad94a608cdd28f93758d3..c3b6c4652cd6cd87d6a5fd8e22506013bcfe1e92 100644 (file)
  * This function maps the nl802.11 channel type into driver channel type.
  *
  * The mapping is as follows -
- *      NL80211_CHAN_NO_HT     -> NO_SEC_CHANNEL
- *      NL80211_CHAN_HT20      -> NO_SEC_CHANNEL
- *      NL80211_CHAN_HT40PLUS  -> SEC_CHANNEL_ABOVE
- *      NL80211_CHAN_HT40MINUS -> SEC_CHANNEL_BELOW
- *      Others                 -> NO_SEC_CHANNEL
+ *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE
+ *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE
+ *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
+ *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
+ *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
  */
-static int
-mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type
-                                                 channel_type)
+static u8
+mwifiex_cfg80211_channel_type_to_sec_chan_offset(enum nl80211_channel_type
+                                                channel_type)
 {
        switch (channel_type) {
        case NL80211_CHAN_NO_HT:
        case NL80211_CHAN_HT20:
-               return NO_SEC_CHANNEL;
+               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
        case NL80211_CHAN_HT40PLUS:
-               return SEC_CHANNEL_ABOVE;
+               return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
        case NL80211_CHAN_HT40MINUS:
-               return SEC_CHANNEL_BELOW;
+               return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
        default:
-               return NO_SEC_CHANNEL;
-       }
-}
-
-/*
- * This function maps the driver channel type into nl802.11 channel type.
- *
- * The mapping is as follows -
- *      NO_SEC_CHANNEL      -> NL80211_CHAN_HT20
- *      SEC_CHANNEL_ABOVE   -> NL80211_CHAN_HT40PLUS
- *      SEC_CHANNEL_BELOW   -> NL80211_CHAN_HT40MINUS
- *      Others              -> NL80211_CHAN_HT20
- */
-static enum nl80211_channel_type
-mwifiex_channels_to_cfg80211_channel_type(int channel_type)
-{
-       switch (channel_type) {
-       case NO_SEC_CHANNEL:
-               return NL80211_CHAN_HT20;
-       case SEC_CHANNEL_ABOVE:
-               return NL80211_CHAN_HT40PLUS;
-       case SEC_CHANNEL_BELOW:
-               return NL80211_CHAN_HT40MINUS;
-       default:
-               return NL80211_CHAN_HT20;
+               return IEEE80211_HT_PARAM_CHA_SEC_NONE;
        }
 }
 
@@ -331,37 +307,51 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
                       enum nl80211_channel_type channel_type)
 {
        struct mwifiex_chan_freq_power cfp;
-       struct mwifiex_ds_band_cfg band_cfg;
        u32 config_bands = 0;
        struct wiphy *wiphy = priv->wdev->wiphy;
+       struct mwifiex_adapter *adapter = priv->adapter;
 
        if (chan) {
-               memset(&band_cfg, 0, sizeof(band_cfg));
                /* Set appropriate bands */
-               if (chan->band == IEEE80211_BAND_2GHZ)
-                       config_bands = BAND_B | BAND_G | BAND_GN;
-               else
-                       config_bands = BAND_AN | BAND_A;
-               if (priv->bss_mode == NL80211_IFTYPE_STATION
-                   || priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) {
-                       band_cfg.config_bands = config_bands;
-               } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-                       band_cfg.config_bands = config_bands;
-                       band_cfg.adhoc_start_band = config_bands;
+               if (chan->band == IEEE80211_BAND_2GHZ) {
+                       if (channel_type == NL80211_CHAN_NO_HT)
+                               if (priv->adapter->config_bands == BAND_B ||
+                                         priv->adapter->config_bands == BAND_G)
+                                       config_bands =
+                                               priv->adapter->config_bands;
+                               else
+                                       config_bands = BAND_B | BAND_G;
+                       else
+                               config_bands = BAND_B | BAND_G | BAND_GN;
+               } else {
+                       if (channel_type == NL80211_CHAN_NO_HT)
+                               config_bands = BAND_A;
+                       else
+                               config_bands = BAND_AN | BAND_A;
                }
 
-               band_cfg.sec_chan_offset =
-                       mwifiex_cfg80211_channel_type_to_mwifiex_channels
+               if (!((config_bands | adapter->fw_bands) &
+                                               ~adapter->fw_bands)) {
+                       adapter->config_bands = config_bands;
+                       if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+                               adapter->adhoc_start_band = config_bands;
+                               if ((config_bands & BAND_GN) ||
+                                               (config_bands & BAND_AN))
+                                       adapter->adhoc_11n_enabled = true;
+                               else
+                                       adapter->adhoc_11n_enabled = false;
+                       }
+               }
+               adapter->sec_chan_offset =
+                       mwifiex_cfg80211_channel_type_to_sec_chan_offset
                        (channel_type);
-
-               if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
-                       return -EFAULT;
+               adapter->channel_type = channel_type;
 
                mwifiex_send_domain_info_cmd_fw(wiphy);
        }
 
        wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and "
-               "mode %d\n", config_bands, band_cfg.sec_chan_offset,
+               "mode %d\n", config_bands, adapter->sec_chan_offset,
                priv->bss_mode);
        if (!chan)
                return 0;
@@ -697,9 +687,9 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
                                const u8 *peer,
                                const struct cfg80211_bitrate_mask *mask)
 {
-       struct mwifiex_ds_band_cfg band_cfg;
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        int index = 0, mode = 0, i;
+       struct mwifiex_adapter *adapter = priv->adapter;
 
        /* Currently only 2.4GHz is supported */
        for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
@@ -721,16 +711,15 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
                        mode |=  BAND_B;
        }
 
-       memset(&band_cfg, 0, sizeof(band_cfg));
-       band_cfg.config_bands = mode;
-
-       if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
-               band_cfg.adhoc_start_band = mode;
-
-       band_cfg.sec_chan_offset = NO_SEC_CHANNEL;
-
-       if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
-               return -EFAULT;
+       if (!((mode | adapter->fw_bands) & ~adapter->fw_bands)) {
+               adapter->config_bands = mode;
+               if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
+                       adapter->adhoc_start_band = mode;
+                       adapter->adhoc_11n_enabled = false;
+               }
+       }
+       adapter->sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+       adapter->channel_type = NL80211_CHAN_NO_HT;
 
        wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
                                (mode & BAND_B) ? "b" : "",
@@ -850,8 +839,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
 
        if (channel)
                ret = mwifiex_set_rf_channel(priv, channel,
-                               mwifiex_channels_to_cfg80211_channel_type
-                               (priv->adapter->chan_offset));
+                                               priv->adapter->channel_type);
 
        ret = mwifiex_set_encode(priv, NULL, 0, 0, 1);  /* Disable keys */
 
index 62b863907698028f07a5abb51d33bde8c3a96681..51c5417c569c42570e0a3300c59529c2c6af767c 100644 (file)
@@ -376,8 +376,6 @@ enum mwifiex_chan_scan_mode_bitmasks {
        MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
 };
 
-#define SECOND_CHANNEL_BELOW    0x30
-#define SECOND_CHANNEL_ABOVE    0x10
 struct mwifiex_chan_scan_param_set {
        u8 radio_type;
        u8 chan_number;
index 244c728ef9dcc63f968617e7e557874d8f4f4977..e05b417a3fae8b54d5e632f477dc5885c8a2697f 100644 (file)
@@ -246,7 +246,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
        memset(adapter->event_body, 0, sizeof(adapter->event_body));
        adapter->hw_dot_11n_dev_cap = 0;
        adapter->hw_dev_mcs_support = 0;
-       adapter->chan_offset = 0;
+       adapter->sec_chan_offset = 0;
        adapter->adhoc_11n_enabled = false;
 
        mwifiex_wmm_init(adapter);
index e0b68e7c8ca2344c18c7db200223636bc543b7df..d5d81f1fe41c9c5b310e21cf0778284a43478f86 100644 (file)
@@ -62,17 +62,6 @@ enum {
        BAND_AN = 16,
 };
 
-#define NO_SEC_CHANNEL               0
-#define SEC_CHANNEL_ABOVE            1
-#define SEC_CHANNEL_BELOW            3
-
-struct mwifiex_ds_band_cfg {
-       u32 config_bands;
-       u32 adhoc_start_band;
-       u32 adhoc_channel;
-       u32 sec_chan_offset;
-};
-
 enum {
        ADHOC_IDLE,
        ADHOC_STARTED,
index 1c4981367e508fbaa45fd6e5648452e75da5ee7c..0b0eb5efba9dd4206d08b8f79c817319ab4c8037 100644 (file)
@@ -885,12 +885,14 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                       = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
                if (adapter->adhoc_start_band & BAND_GN
                    || adapter->adhoc_start_band & BAND_AN) {
-                       if (adapter->chan_offset == SEC_CHANNEL_ABOVE)
+                       if (adapter->sec_chan_offset ==
+                                           IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
                                chan_tlv->chan_scan_param[0].radio_type |=
-                                       SECOND_CHANNEL_ABOVE;
-                       else if (adapter->chan_offset == SEC_CHANNEL_BELOW)
+                                       (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
+                       else if (adapter->sec_chan_offset ==
+                                           IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
                                chan_tlv->chan_scan_param[0].radio_type |=
-                                       SECOND_CHANNEL_BELOW;
+                                       (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
                }
                dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n",
                       chan_tlv->chan_scan_param[0].radio_type);
@@ -936,8 +938,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 
                ht_info->ht_info.control_chan =
                        (u8) priv->curr_bss_params.bss_descriptor.channel;
-               if (adapter->chan_offset) {
-                       ht_info->ht_info.ht_param = adapter->chan_offset;
+               if (adapter->sec_chan_offset) {
+                       ht_info->ht_info.ht_param = adapter->sec_chan_offset;
                        ht_info->ht_info.ht_param |=
                                        IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
                }
index 9207fc64641e265d99a6b30ef9ab4c3dcc9047eb..3186aa437f421272f929ebdfb8872312c768782f 100644 (file)
@@ -640,7 +640,8 @@ struct mwifiex_adapter {
        u32 hw_dot_11n_dev_cap;
        u8 hw_dev_mcs_support;
        u8 adhoc_11n_enabled;
-       u8 chan_offset;
+       u8 sec_chan_offset;
+       enum nl80211_channel_type channel_type;
        struct mwifiex_dbg dbg;
        u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
        u32 arp_filter_size;
@@ -954,8 +955,6 @@ int mwifiex_main_process(struct mwifiex_adapter *);
 
 int mwifiex_bss_set_channel(struct mwifiex_private *,
                            struct mwifiex_chan_freq_power *cfp);
-int mwifiex_set_radio_band_cfg(struct mwifiex_private *,
-                        struct mwifiex_ds_band_cfg *);
 int mwifiex_get_bss_info(struct mwifiex_private *,
                         struct mwifiex_bss_info *);
 int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
index e2e715666bcabf36815f088a914a8ee20fd7c9b8..6396d3318ead1e3b3afb26858d57873a228022b4 100644 (file)
@@ -500,7 +500,6 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
        struct ieee80211_channel *ch;
        struct mwifiex_adapter *adapter = priv->adapter;
        int chan_idx = 0, i;
-       u8 scan_type;
 
        for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) {
 
@@ -514,19 +513,20 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
                        if (ch->flags & IEEE80211_CHAN_DISABLED)
                                continue;
                        scan_chan_list[chan_idx].radio_type = band;
-                       scan_type = ch->flags & IEEE80211_CHAN_PASSIVE_SCAN;
+
                        if (user_scan_in &&
                                user_scan_in->chan_list[0].scan_time)
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16((u16) user_scan_in->
                                        chan_list[0].scan_time);
-                       else if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
+                       else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16(adapter->passive_scan_time);
                        else
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16(adapter->active_scan_time);
-                       if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
+
+                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
                                scan_chan_list[chan_idx].chan_scan_mode_bitmap
                                        |= MWIFIEX_PASSIVE_SCAN;
                        else
index ea6518d1c9e323c3adec7a28996b8f0fa3e71898..6e443ffa0465c7ecb93a0ab8165f90fe6127bd0f 100644 (file)
@@ -748,7 +748,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
                                cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A);
 
                rf_type = le16_to_cpu(rf_chan->rf_type);
-               SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
+               SET_SECONDARYCHAN(rf_type, priv->adapter->sec_chan_offset);
                rf_chan->current_channel = cpu_to_le16(*channel);
        }
        rf_chan->action = cpu_to_le16(cmd_action);
index 6d990c798a20f83b7be40334b3305b9cd7f57efa..e40196dfdea06dba7a4185440cd71ea8830c2a92 100644 (file)
@@ -471,67 +471,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
        return 0;
 }
 
-/*
- * The function sets band configurations.
- *
- * it performs extra checks to make sure the Ad-Hoc
- * band and channel are compatible. Otherwise it returns an error.
- *
- */
-int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv,
-                              struct mwifiex_ds_band_cfg *radio_cfg)
-{
-       struct mwifiex_adapter *adapter = priv->adapter;
-       u8 infra_band, adhoc_band;
-       u32 adhoc_channel;
-
-       infra_band = (u8) radio_cfg->config_bands;
-       adhoc_band = (u8) radio_cfg->adhoc_start_band;
-       adhoc_channel = radio_cfg->adhoc_channel;
-
-       /* SET Infra band */
-       if ((infra_band | adapter->fw_bands) & ~adapter->fw_bands)
-               return -1;
-
-       adapter->config_bands = infra_band;
-
-       /* SET Ad-hoc Band */
-       if ((adhoc_band | adapter->fw_bands) & ~adapter->fw_bands)
-               return -1;
-
-       if (adhoc_band)
-               adapter->adhoc_start_band = adhoc_band;
-       adapter->chan_offset = (u8) radio_cfg->sec_chan_offset;
-       /*
-        * If no adhoc_channel is supplied verify if the existing adhoc
-        * channel compiles with new adhoc_band
-        */
-       if (!adhoc_channel) {
-               if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211
-                    (priv, adapter->adhoc_start_band,
-                    priv->adhoc_channel)) {
-                       /* Pass back the default channel */
-                       radio_cfg->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
-                       if ((adapter->adhoc_start_band & BAND_A)
-                           || (adapter->adhoc_start_band & BAND_AN))
-                               radio_cfg->adhoc_channel =
-                                       DEFAULT_AD_HOC_CHANNEL_A;
-               }
-       } else {        /* Retrurn error if adhoc_band and
-                          adhoc_channel combination is invalid */
-               if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211
-                   (priv, adapter->adhoc_start_band, (u16) adhoc_channel))
-                       return -1;
-               priv->adhoc_channel = (u8) adhoc_channel;
-       }
-       if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN))
-               adapter->adhoc_11n_enabled = true;
-       else
-               adapter->adhoc_11n_enabled = false;
-
-       return 0;
-}
-
 /*
  * The function disables auto deep sleep mode.
  */
index e75d5c8d62cc712966cca6998e4ab64452331a98..036491f08e9b3c2bb7945263b97f1c0b22671d21 100644 (file)
@@ -5044,14 +5044,14 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
                break;
        case IEEE80211_AMPDU_TX_STOP:
-               if (stream == NULL)
-                       break;
-               if (stream->state == AMPDU_STREAM_ACTIVE) {
-                       spin_unlock(&priv->stream_lock);
-                       mwl8k_destroy_ba(hw, stream);
-                       spin_lock(&priv->stream_lock);
+               if (stream) {
+                       if (stream->state == AMPDU_STREAM_ACTIVE) {
+                               spin_unlock(&priv->stream_lock);
+                               mwl8k_destroy_ba(hw, stream);
+                               spin_lock(&priv->stream_lock);
+                       }
+                       mwl8k_remove_stream(hw, stream);
                }
-               mwl8k_remove_stream(hw, stream);
                ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
index b1df1a774948ff00326efafedce16c1df820bf39..ee01d2e883a08ecd7418a71989463bd6d7f66809 100644 (file)
@@ -1159,6 +1159,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x7392, 0x7722) },
        /* Encore */
        { USB_DEVICE(0x203d, 0x14a1) },
+       /* Fujitsu Stylistic 550 */
+       { USB_DEVICE(0x1690, 0x0761) },
        /* Gemtek */
        { USB_DEVICE(0x15a9, 0x0010) },
        /* Gigabyte */
index 74c0214367040beb33d4b343c9cc9a53ed75aed9..8d6eb0f56c031b7b4b7ac2d43756c88cd9b0f28b 100644 (file)
@@ -449,6 +449,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
        /* <4> locks */
        mutex_init(&rtlpriv->locks.conf_mutex);
        mutex_init(&rtlpriv->locks.ps_mutex);
+       spin_lock_init(&rtlpriv->locks.ips_lock);
        spin_lock_init(&rtlpriv->locks.irq_th_lock);
        spin_lock_init(&rtlpriv->locks.h2c_lock);
        spin_lock_init(&rtlpriv->locks.rf_ps_lock);
index a14a68b246354a9674320be31a142f335ba14ea4..130fdd99d57336de7ebf4475ddf783365f43a24b 100644 (file)
@@ -237,11 +237,12 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        enum rf_pwrstate rtstate;
+       unsigned long flags;
 
        if (mac->opmode != NL80211_IFTYPE_STATION)
                return;
 
-       mutex_lock(&rtlpriv->locks.ps_mutex);
+       spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
 
        if (ppsc->inactiveps) {
                rtstate = ppsc->rfpwr_state;
@@ -257,7 +258,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
                }
        }
 
-       mutex_unlock(&rtlpriv->locks.ps_mutex);
+       spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
 }
 
 /*for FW LPS*/
index 9b7d60c0bf8062e1df6d35e0567f5b181ffd292c..cdaf1429fa0b30b6322f31d21f48f5216e51f7d3 100644 (file)
@@ -1547,6 +1547,7 @@ struct rtl_locks {
        struct mutex ps_mutex;
 
        /*spin lock */
+       spinlock_t ips_lock;
        spinlock_t irq_th_lock;
        spinlock_t h2c_lock;
        spinlock_t rf_ps_lock;
index e0d2179794854487723ee8ea18d792202c892a1f..25990bd38be633d57bc17ae13573875f3cce4a7a 100644 (file)
@@ -1835,6 +1835,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
                      wlvif->bss_type == BSS_TYPE_IBSS)))
                return -EINVAL;
 
+       /* flush all pending packets */
+       wl1271_tx_work_locked(wl);
+
        if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
                ret = wl12xx_croc(wl, wlvif->dev_role_id);
                if (ret < 0)
index 00ce794eebaebb305cf706bfe385bd2c9846b06e..d3280df68f5dee8de32537c22e6200f53fa69e60 100644 (file)
@@ -267,8 +267,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
                wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT "
                             "(status 0x%0x)", mbox->scheduled_scan_status);
                if (wl->sched_scanning) {
-                       wl1271_scan_sched_scan_stop(wl);
                        ieee80211_sched_scan_stopped(wl->hw);
+                       wl->sched_scanning = false;
                }
        }
 
index c3058419e227bb9bf35f5c91f94aeb9edbc3c24e..d5f55a149de5e43216ad46c7ebf0d4825e9d0628 100644 (file)
@@ -450,7 +450,16 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
        if (wl->state == WL1271_STATE_OFF)
                goto out;
 
+       if (dev->operstate != IF_OPER_UP)
+               goto out;
+       /*
+        * The correct behavior should be just getting the appropriate wlvif
+        * from the given dev, but currently we don't have a mac80211
+        * interface for it.
+        */
        wl12xx_for_each_wlvif_sta(wl, wlvif) {
+               struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
                if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
                        continue;
 
@@ -458,7 +467,8 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
                if (ret < 0)
                        goto out;
 
-               wl1271_check_operstate(wl, wlvif, dev->operstate);
+               wl1271_check_operstate(wl, wlvif,
+                                      ieee80211_get_operstate(vif));
 
                wl1271_ps_elp_sleep(wl);
        }
@@ -2036,6 +2046,11 @@ out:
        return booted;
 }
 
+static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif)
+{
+       return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID;
+}
+
 static int wl1271_op_add_interface(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif)
 {
@@ -2184,7 +2199,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
                if (ret < 0)
                        goto deinit;
 
-               if (wlvif->bss_type == BSS_TYPE_STA_BSS) {
+               if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
+                   wlvif->bss_type == BSS_TYPE_IBSS) {
+                       if (wl12xx_dev_role_started(wlvif))
+                               wl12xx_stop_dev(wl, wlvif);
+
                        ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
                        if (ret < 0)
                                goto deinit;
@@ -2269,6 +2288,17 @@ out:
        cancel_work_sync(&wl->recovery_work);
 }
 
+static int wl12xx_op_change_interface(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif *vif,
+                                     enum nl80211_iftype new_type, bool p2p)
+{
+       wl1271_op_remove_interface(hw, vif);
+
+       vif->type = ieee80211_iftype_p2p(new_type, p2p);
+       vif->p2p = p2p;
+       return wl1271_op_add_interface(hw, vif);
+}
+
 static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                          bool set_assoc)
 {
@@ -2358,25 +2388,18 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif)
        wlvif->rate_set = wlvif->basic_rate_set;
 }
 
-static bool wl12xx_is_roc(struct wl1271 *wl)
-{
-       u8 role_id;
-
-       role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
-       if (role_id >= WL12XX_MAX_ROLES)
-               return false;
-
-       return true;
-}
-
 static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                                  bool idle)
 {
        int ret;
+       bool cur_idle = !test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
+
+       if (idle == cur_idle)
+               return 0;
 
        if (idle) {
                /* no need to croc if we weren't busy (e.g. during boot) */
-               if (wl12xx_is_roc(wl)) {
+               if (wl12xx_dev_role_started(wlvif)) {
                        ret = wl12xx_stop_dev(wl, wlvif);
                        if (ret < 0)
                                goto out;
@@ -2391,7 +2414,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                        ACX_KEEP_ALIVE_TPL_INVALID);
                if (ret < 0)
                        goto out;
-               set_bit(WL1271_FLAG_IDLE, &wl->flags);
+               clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
        } else {
                /* The current firmware only supports sched_scan in idle */
                if (wl->sched_scanning) {
@@ -2402,7 +2425,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                ret = wl12xx_start_dev(wl, wlvif);
                if (ret < 0)
                        goto out;
-               clear_bit(WL1271_FLAG_IDLE, &wl->flags);
+               set_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
        }
 
 out:
@@ -2446,7 +2469,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 
                        if (test_bit(WLVIF_FLAG_STA_ASSOCIATED,
                                     &wlvif->flags)) {
-                               if (wl12xx_is_roc(wl)) {
+                               if (wl12xx_dev_role_started(wlvif)) {
                                        /* roaming */
                                        ret = wl12xx_croc(wl,
                                                          wlvif->dev_role_id);
@@ -2463,7 +2486,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                                 * not idle. otherwise, CROC will be called
                                 * anyway.
                                 */
-                               if (wl12xx_is_roc(wl) &&
+                               if (wl12xx_dev_role_started(wlvif) &&
                                    !(conf->flags & IEEE80211_CONF_IDLE)) {
                                        ret = wl12xx_stop_dev(wl, wlvif);
                                        if (ret < 0)
@@ -3010,15 +3033,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
        if (ret < 0)
                goto out;
 
+       if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
+           test_bit(wlvif->role_id, wl->roc_map)) {
+               /* don't allow scanning right now */
+               ret = -EBUSY;
+               goto out_sleep;
+       }
+
        /* cancel ROC before scanning */
-       if (wl12xx_is_roc(wl)) {
-               if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
-                       /* don't allow scanning right now */
-                       ret = -EBUSY;
-                       goto out_sleep;
-               }
+       if (wl12xx_dev_role_started(wlvif))
                wl12xx_stop_dev(wl, wlvif);
-       }
 
        ret = wl1271_scan(hw->priv, vif, ssid, len, req);
 out_sleep:
@@ -3829,9 +3853,9 @@ sta_not_found:
                }
                /*
                 * stop device role if started (we might already be in
-                * STA role). TODO: make it better.
+                * STA/IBSS role).
                 */
-               if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) {
+               if (wl12xx_dev_role_started(wlvif)) {
                        ret = wl12xx_stop_dev(wl, wlvif);
                        if (ret < 0)
                                goto out;
@@ -3948,31 +3972,8 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw,
        else
                ps_scheme = CONF_PS_SCHEME_LEGACY;
 
-       if (wl->state == WL1271_STATE_OFF) {
-               /*
-                * If the state is off, the parameters will be recorded and
-                * configured on init. This happens in AP-mode.
-                */
-               struct conf_tx_ac_category *conf_ac =
-                       &wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)];
-               struct conf_tx_tid *conf_tid =
-                       &wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)];
-
-               conf_ac->ac = wl1271_tx_get_queue(queue);
-               conf_ac->cw_min = (u8)params->cw_min;
-               conf_ac->cw_max = params->cw_max;
-               conf_ac->aifsn = params->aifs;
-               conf_ac->tx_op_limit = params->txop << 5;
-
-               conf_tid->queue_id = wl1271_tx_get_queue(queue);
-               conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF;
-               conf_tid->tsid = wl1271_tx_get_queue(queue);
-               conf_tid->ps_scheme = ps_scheme;
-               conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY;
-               conf_tid->apsd_conf[0] = 0;
-               conf_tid->apsd_conf[1] = 0;
+       if (!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
                goto out;
-       }
 
        ret = wl1271_ps_elp_wakeup(wl);
        if (ret < 0)
@@ -4629,6 +4630,7 @@ static const struct ieee80211_ops wl1271_ops = {
        .stop = wl1271_op_stop,
        .add_interface = wl1271_op_add_interface,
        .remove_interface = wl1271_op_remove_interface,
+       .change_interface = wl12xx_op_change_interface,
 #ifdef CONFIG_PM
        .suspend = wl1271_op_suspend,
        .resume = wl1271_op_resume,
index a7a11088dd3104f2f8b9a2941d567c20bba822b1..a2bdacdd7e1dd742ae9398ef70c1d2eb1c8037d2 100644 (file)
@@ -53,8 +53,11 @@ void wl1271_elp_work(struct work_struct *work)
                goto out;
 
        wl12xx_for_each_wlvif(wl, wlvif) {
+               if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+                       goto out;
+
                if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
-                   !test_bit(WL1271_FLAG_IDLE, &wl->flags))
+                   test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
                        goto out;
        }
 
@@ -78,8 +81,11 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
                return;
 
        wl12xx_for_each_wlvif(wl, wlvif) {
+               if (wlvif->bss_type == BSS_TYPE_AP_BSS)
+                       return;
+
                if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
-                   !test_bit(WL1271_FLAG_IDLE, &wl->flags))
+                   test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
                        return;
        }
 
index 8599dab1fe2a53e22c4ae60d7a7ed2afd1d176ff..e24111ececc5c64ba40cf87133b1193b93b0aaa5 100644 (file)
@@ -437,18 +437,19 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
 
                        if (flags & IEEE80211_CHAN_RADAR) {
                                channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
+
                                channels[j].passive_duration =
                                        cpu_to_le16(c->dwell_time_dfs);
-                       }
-                       else if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {
+                       } else {
                                channels[j].passive_duration =
                                        cpu_to_le16(c->dwell_time_passive);
-                       } else {
-                               channels[j].min_duration =
-                                       cpu_to_le16(c->min_dwell_time_active);
-                               channels[j].max_duration =
-                                       cpu_to_le16(c->max_dwell_time_active);
                        }
+
+                       channels[j].min_duration =
+                               cpu_to_le16(c->min_dwell_time_active);
+                       channels[j].max_duration =
+                               cpu_to_le16(c->max_dwell_time_active);
+
                        channels[j].tx_power_att = req->channels[i]->max_power;
                        channels[j].channel = req->channels[i]->hw_value;
 
@@ -703,7 +704,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
        if (wlvif->bss_type != BSS_TYPE_STA_BSS)
                return -EOPNOTSUPP;
 
-       if (!test_bit(WL1271_FLAG_IDLE, &wl->flags))
+       if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
                return -EBUSY;
 
        start = kzalloc(sizeof(*start), GFP_KERNEL);
@@ -753,7 +754,6 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl)
                wl1271_error("failed to send sched scan stop command");
                goto out_free;
        }
-       wl->sched_scanning = false;
 
 out_free:
        kfree(stop);
index d21f71ff6f64c9326d0719b34e567740b609a54c..b2b09cd0202256c4a623c65f6870160f5fa106b9 100644 (file)
@@ -241,7 +241,6 @@ enum wl12xx_flags {
        WL1271_FLAG_IN_ELP,
        WL1271_FLAG_ELP_REQUESTED,
        WL1271_FLAG_IRQ_RUNNING,
-       WL1271_FLAG_IDLE,
        WL1271_FLAG_FW_TX_BUSY,
        WL1271_FLAG_DUMMY_PACKET_PENDING,
        WL1271_FLAG_SUSPENDED,
@@ -262,6 +261,7 @@ enum wl12xx_vif_flags {
        WLVIF_FLAG_PSPOLL_FAILURE,
        WLVIF_FLAG_CS_PROGRESS,
        WLVIF_FLAG_AP_PROBE_RESP_SET,
+       WLVIF_FLAG_IN_USE,
 };
 
 struct wl1271_link {
index 3c96b332184ee059c91ef3452e498a9e7ad7223d..998e95895f9dc8beed8cd3d7c3b06f1e72259b90 100644 (file)
@@ -1,3 +1,24 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/wl12xx.h>
index f795cb7dccdda2011b62b1ea63f5d0d5ccc87143..0f5ff37398206d0cb30f866244879be020b99ed5 100644 (file)
@@ -1655,6 +1655,7 @@ enum nl80211_sta_bss_param {
  *     containing info as possible, see &enum nl80211_sta_bss_param
  * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
  * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
+ * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -1677,6 +1678,7 @@ enum nl80211_sta_info {
        NL80211_STA_INFO_BSS_PARAM,
        NL80211_STA_INFO_CONNECTED_TIME,
        NL80211_STA_INFO_STA_FLAGS,
+       NL80211_STA_INFO_BEACON_LOSS,
 
        /* keep last */
        __NL80211_STA_INFO_AFTER_LAST,
index 980e59f37d4f8cb6b487570189b328683d311b5b..abaad6ed9b83e7b65da14b7a30ae3a175f2992b4 100644 (file)
@@ -250,32 +250,10 @@ extern void bt_sysfs_cleanup(void);
 
 extern struct dentry *bt_debugfs;
 
-#ifdef CONFIG_BT_L2CAP
 int l2cap_init(void);
 void l2cap_exit(void);
-#else
-static inline int l2cap_init(void)
-{
-       return 0;
-}
-
-static inline void l2cap_exit(void)
-{
-}
-#endif
 
-#ifdef CONFIG_BT_SCO
 int sco_init(void);
 void sco_exit(void);
-#else
-static inline int sco_init(void)
-{
-       return 0;
-}
-
-static inline void sco_exit(void)
-{
-}
-#endif
 
 #endif /* __BLUETOOTH_H */
index 67ad984303484bfa0b87776fd08e3e812083c42a..5b2fed5eebf2e32063d59be921b2a830b9eaa8ea 100644 (file)
@@ -210,6 +210,7 @@ enum {
 
 #define LMP_EV4                0x01
 #define LMP_EV5                0x02
+#define LMP_NO_BREDR   0x20
 #define LMP_LE         0x40
 
 #define LMP_SNIFF_SUBR 0x02
@@ -279,6 +280,10 @@ enum {
 #define HCI_ERROR_LOCAL_HOST_TERM      0x16
 #define HCI_ERROR_PAIRING_NOT_ALLOWED  0x18
 
+/* Flow control modes */
+#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00
+#define HCI_FLOW_CTL_MODE_BLOCK_BASED  0x01
+
 /* -----  HCI Commands ---- */
 #define HCI_OP_NOP                     0x0000
 
@@ -745,6 +750,14 @@ struct hci_rp_read_bd_addr {
        bdaddr_t bdaddr;
 } __packed;
 
+#define HCI_OP_READ_DATA_BLOCK_SIZE    0x100a
+struct hci_rp_read_data_block_size {
+       __u8     status;
+       __le16   max_acl_len;
+       __le16   block_len;
+       __le16   num_blocks;
+} __packed;
+
 #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY        0x0c1c
 struct hci_cp_write_page_scan_activity {
        __le16   interval;
@@ -791,6 +804,9 @@ struct hci_cp_le_set_scan_param {
        __u8    filter_policy;
 } __packed;
 
+#define LE_SCANNING_DISABLED           0x00
+#define LE_SCANNING_ENABLED            0x01
+
 #define HCI_OP_LE_SET_SCAN_ENABLE      0x200c
 struct hci_cp_le_set_scan_enable {
        __u8     enable;
@@ -966,9 +982,14 @@ struct hci_ev_role_change {
 } __packed;
 
 #define HCI_EV_NUM_COMP_PKTS           0x13
+struct hci_comp_pkts_info {
+       __le16   handle;
+       __le16   count;
+} __packed;
+
 struct hci_ev_num_comp_pkts {
        __u8     num_hndl;
-       /* variable length part */
+       struct hci_comp_pkts_info handles[0];
 } __packed;
 
 #define HCI_EV_MODE_CHANGE             0x14
index ea4395f1d26000214027baee3ed401353cb671b3..5e2e984584968f0e6beea90c8657eb1639a1cba2 100644 (file)
 #include <linux/interrupt.h>
 #include <net/bluetooth/hci.h>
 
-/* HCI upper protocols */
-#define HCI_PROTO_L2CAP        0
-#define HCI_PROTO_SCO  1
-
 /* HCI priority */
 #define HCI_PRIO_MAX   7
 
@@ -54,25 +50,17 @@ struct inquiry_entry {
 };
 
 struct inquiry_cache {
-       spinlock_t              lock;
        __u32                   timestamp;
        struct inquiry_entry    *list;
 };
 
 struct hci_conn_hash {
        struct list_head list;
-       spinlock_t       lock;
        unsigned int     acl_num;
        unsigned int     sco_num;
        unsigned int     le_num;
 };
 
-struct hci_chan_hash {
-       struct list_head list;
-       spinlock_t       lock;
-       unsigned int     num;
-};
-
 struct bdaddr_list {
        struct list_head list;
        bdaddr_t bdaddr;
@@ -124,7 +112,7 @@ struct adv_entry {
 #define NUM_REASSEMBLY 4
 struct hci_dev {
        struct list_head list;
-       spinlock_t      lock;
+       struct mutex    lock;
        atomic_t        refcnt;
 
        char            name[8];
@@ -188,6 +176,11 @@ struct hci_dev {
        unsigned int    sco_pkts;
        unsigned int    le_pkts;
 
+       __u16           block_len;
+       __u16           block_mtu;
+       __u16           num_blocks;
+       __u16           block_cnt;
+
        unsigned long   acl_last_tx;
        unsigned long   sco_last_tx;
        unsigned long   le_last_tx;
@@ -200,10 +193,13 @@ struct hci_dev {
        __u16                   discov_timeout;
        struct delayed_work     discov_off;
 
+       struct delayed_work     service_cache;
+
        struct timer_list       cmd_timer;
-       struct tasklet_struct   cmd_task;
-       struct tasklet_struct   rx_task;
-       struct tasklet_struct   tx_task;
+
+       struct work_struct      rx_work;
+       struct work_struct      cmd_work;
+       struct work_struct      tx_work;
 
        struct sk_buff_head     rx_q;
        struct sk_buff_head     raw_q;
@@ -232,7 +228,7 @@ struct hci_dev {
        struct list_head        remote_oob_data;
 
        struct list_head        adv_entries;
-       struct timer_list       adv_timer;
+       struct delayed_work     adv_work;
 
        struct hci_dev_stats    stat;
 
@@ -301,21 +297,19 @@ struct hci_conn {
        unsigned int    sent;
 
        struct sk_buff_head data_q;
-       struct hci_chan_hash chan_hash;
+       struct list_head chan_list;
 
-       struct timer_list disc_timer;
+       struct delayed_work disc_work;
        struct timer_list idle_timer;
        struct timer_list auto_accept_timer;
 
-       struct work_struct work_add;
-       struct work_struct work_del;
-
        struct device   dev;
        atomic_t        devref;
 
        struct hci_dev  *hdev;
        void            *l2cap_data;
        void            *sco_data;
+       void            *smp_conn;
 
        struct hci_conn *link;
 
@@ -332,25 +326,31 @@ struct hci_chan {
        unsigned int    sent;
 };
 
-extern struct hci_proto *hci_proto[];
 extern struct list_head hci_dev_list;
 extern struct list_head hci_cb_list;
 extern rwlock_t hci_dev_list_lock;
 extern rwlock_t hci_cb_list_lock;
 
+/* ----- HCI interface to upper protocols ----- */
+extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
+extern int l2cap_disconn_ind(struct hci_conn *hcon);
+extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
+extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
+extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+
+extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+
 /* ----- Inquiry cache ----- */
 #define INQUIRY_CACHE_AGE_MAX   (HZ*30)   /* 30 seconds */
 #define INQUIRY_ENTRY_AGE_MAX   (HZ*60)   /* 60 seconds */
 
-#define inquiry_cache_lock(c)          spin_lock(&c->lock)
-#define inquiry_cache_unlock(c)                spin_unlock(&c->lock)
-#define inquiry_cache_lock_bh(c)       spin_lock_bh(&c->lock)
-#define inquiry_cache_unlock_bh(c)     spin_unlock_bh(&c->lock)
-
 static inline void inquiry_cache_init(struct hci_dev *hdev)
 {
        struct inquiry_cache *c = &hdev->inq_cache;
-       spin_lock_init(&c->lock);
        c->list = NULL;
 }
 
@@ -390,15 +390,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
        INIT_LIST_HEAD(&h->list);
-       spin_lock_init(&h->lock);
        h->acl_num = 0;
        h->sco_num = 0;
+       h->le_num = 0;
 }
 
 static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       list_add(&c->list, &h->list);
+       list_add_rcu(&c->list, &h->list);
        switch (c->type) {
        case ACL_LINK:
                h->acl_num++;
@@ -416,7 +416,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       list_del(&c->list);
+
+       list_del_rcu(&c->list);
+       synchronize_rcu();
+
        switch (c->type) {
        case ACL_LINK:
                h->acl_num--;
@@ -451,14 +454,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
                                                                __u16 handle)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->handle == handle)
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->handle == handle) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
+       rcu_read_unlock();
+
        return NULL;
 }
 
@@ -466,14 +473,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
                                                        __u8 type, bdaddr_t *ba)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->type == type && !bacmp(&c->dst, ba))
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->type == type && !bacmp(&c->dst, ba)) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
+
+       rcu_read_unlock();
+
        return NULL;
 }
 
@@ -481,37 +493,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
                                                        __u8 type, __u16 state)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
        struct hci_conn  *c;
 
-       list_for_each(p, &h->list) {
-               c = list_entry(p, struct hci_conn, list);
-               if (c->type == type && c->state == state)
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
+               if (c->type == type && c->state == state) {
+                       rcu_read_unlock();
                        return c;
+               }
        }
-       return NULL;
-}
 
-static inline void hci_chan_hash_init(struct hci_conn *c)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       INIT_LIST_HEAD(&h->list);
-       spin_lock_init(&h->lock);
-       h->num = 0;
-}
+       rcu_read_unlock();
 
-static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       list_add(&chan->list, &h->list);
-       h->num++;
-}
-
-static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan)
-{
-       struct hci_chan_hash *h = &c->chan_hash;
-       list_del(&chan->list);
-       h->num--;
+       return NULL;
 }
 
 void hci_acl_connect(struct hci_conn *conn);
@@ -527,7 +522,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
 
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 int hci_chan_del(struct hci_chan *chan);
-void hci_chan_hash_flush(struct hci_conn *conn);
+void hci_chan_list_flush(struct hci_conn *conn);
 
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
                                                __u8 sec_level, __u8 auth_type);
@@ -538,7 +533,6 @@ int hci_conn_change_link_key(struct hci_conn *conn);
 int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
-void hci_conn_enter_sniff_mode(struct hci_conn *conn);
 
 void hci_conn_hold_device(struct hci_conn *conn);
 void hci_conn_put_device(struct hci_conn *conn);
@@ -546,7 +540,7 @@ void hci_conn_put_device(struct hci_conn *conn);
 static inline void hci_conn_hold(struct hci_conn *conn)
 {
        atomic_inc(&conn->refcnt);
-       del_timer(&conn->disc_timer);
+       cancel_delayed_work_sync(&conn->disc_work);
 }
 
 static inline void hci_conn_put(struct hci_conn *conn)
@@ -565,7 +559,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
                } else {
                        timeo = msecs_to_jiffies(10);
                }
-               mod_timer(&conn->disc_timer, jiffies + timeo);
+               cancel_delayed_work_sync(&conn->disc_work);
+               queue_delayed_work(conn->hdev->workqueue,
+                                       &conn->disc_work, jiffies + timeo);
        }
 }
 
@@ -597,10 +593,8 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
        try_module_get(d->owner) ? __hci_dev_hold(d) : NULL;    \
 })
 
-#define hci_dev_lock(d)                spin_lock(&d->lock)
-#define hci_dev_unlock(d)      spin_unlock(&d->lock)
-#define hci_dev_lock_bh(d)     spin_lock_bh(&d->lock)
-#define hci_dev_unlock_bh(d)   spin_unlock_bh(&d->lock)
+#define hci_dev_lock(d)                mutex_lock(&d->lock)
+#define hci_dev_unlock(d)      mutex_unlock(&d->lock)
 
 struct hci_dev *hci_dev_get(int index);
 struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
@@ -685,53 +679,40 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_host_le_capable(dev)   ((dev)->extfeatures[0] & LMP_HOST_LE)
 
 /* ----- HCI protocols ----- */
-struct hci_proto {
-       char            *name;
-       unsigned int    id;
-       unsigned long   flags;
-
-       void            *priv;
-
-       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr,
-                                                               __u8 type);
-       int (*connect_cfm)      (struct hci_conn *conn, __u8 status);
-       int (*disconn_ind)      (struct hci_conn *conn);
-       int (*disconn_cfm)      (struct hci_conn *conn, __u8 reason);
-       int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb,
-                                                               __u16 flags);
-       int (*recv_scodata)     (struct hci_conn *conn, struct sk_buff *skb);
-       int (*security_cfm)     (struct hci_conn *conn, __u8 status,
-                                                               __u8 encrypt);
-};
-
 static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
                                                                __u8 type)
 {
-       register struct hci_proto *hp;
-       int mask = 0;
-
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->connect_ind)
-               mask |= hp->connect_ind(hdev, bdaddr, type);
+       switch (type) {
+       case ACL_LINK:
+               return l2cap_connect_ind(hdev, bdaddr);
 
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->connect_ind)
-               mask |= hp->connect_ind(hdev, bdaddr, type);
+       case SCO_LINK:
+       case ESCO_LINK:
+               return sco_connect_ind(hdev, bdaddr);
 
-       return mask;
+       default:
+               BT_ERR("unknown link type %d", type);
+               return -EINVAL;
+       }
 }
 
 static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
 {
-       register struct hci_proto *hp;
+       switch (conn->type) {
+       case ACL_LINK:
+       case LE_LINK:
+               l2cap_connect_cfm(conn, status);
+               break;
 
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->connect_cfm)
-               hp->connect_cfm(conn, status);
+       case SCO_LINK:
+       case ESCO_LINK:
+               sco_connect_cfm(conn, status);
+               break;
 
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->connect_cfm)
-               hp->connect_cfm(conn, status);
+       default:
+               BT_ERR("unknown link type %d", conn->type);
+               break;
+       }
 
        if (conn->connect_cfm_cb)
                conn->connect_cfm_cb(conn, status);
@@ -739,31 +720,29 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
 
 static inline int hci_proto_disconn_ind(struct hci_conn *conn)
 {
-       register struct hci_proto *hp;
-       int reason = HCI_ERROR_REMOTE_USER_TERM;
-
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->disconn_ind)
-               reason = hp->disconn_ind(conn);
+       if (conn->type != ACL_LINK && conn->type != LE_LINK)
+               return HCI_ERROR_REMOTE_USER_TERM;
 
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->disconn_ind)
-               reason = hp->disconn_ind(conn);
-
-       return reason;
+       return l2cap_disconn_ind(conn);
 }
 
 static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
 {
-       register struct hci_proto *hp;
+       switch (conn->type) {
+       case ACL_LINK:
+       case LE_LINK:
+               l2cap_disconn_cfm(conn, reason);
+               break;
 
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->disconn_cfm)
-               hp->disconn_cfm(conn, reason);
+       case SCO_LINK:
+       case ESCO_LINK:
+               sco_disconn_cfm(conn, reason);
+               break;
 
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->disconn_cfm)
-               hp->disconn_cfm(conn, reason);
+       default:
+               BT_ERR("unknown link type %d", conn->type);
+               break;
+       }
 
        if (conn->disconn_cfm_cb)
                conn->disconn_cfm_cb(conn, reason);
@@ -771,21 +750,16 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
 
 static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
 {
-       register struct hci_proto *hp;
        __u8 encrypt;
 
+       if (conn->type != ACL_LINK && conn->type != LE_LINK)
+               return;
+
        if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
                return;
 
        encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
-
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->security_cfm)
-               hp->security_cfm(conn, status, encrypt);
-
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->security_cfm)
-               hp->security_cfm(conn, status, encrypt);
+       l2cap_security_cfm(conn, status, encrypt);
 
        if (conn->security_cfm_cb)
                conn->security_cfm_cb(conn, status);
@@ -794,23 +768,15 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
 static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
                                                                __u8 encrypt)
 {
-       register struct hci_proto *hp;
-
-       hp = hci_proto[HCI_PROTO_L2CAP];
-       if (hp && hp->security_cfm)
-               hp->security_cfm(conn, status, encrypt);
+       if (conn->type != ACL_LINK && conn->type != LE_LINK)
+               return;
 
-       hp = hci_proto[HCI_PROTO_SCO];
-       if (hp && hp->security_cfm)
-               hp->security_cfm(conn, status, encrypt);
+       l2cap_security_cfm(conn, status, encrypt);
 
        if (conn->security_cfm_cb)
                conn->security_cfm_cb(conn, status);
 }
 
-int hci_register_proto(struct hci_proto *hproto);
-int hci_unregister_proto(struct hci_proto *hproto);
-
 /* ----- HCI callbacks ----- */
 struct hci_cb {
        struct list_head list;
@@ -835,13 +801,13 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
 
        encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
 
-       read_lock_bh(&hci_cb_list_lock);
+       read_lock(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
                if (cb->security_cfm)
                        cb->security_cfm(conn, status, encrypt);
        }
-       read_unlock_bh(&hci_cb_list_lock);
+       read_unlock(&hci_cb_list_lock);
 }
 
 static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
@@ -857,26 +823,26 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
 
        hci_proto_encrypt_cfm(conn, status, encrypt);
 
-       read_lock_bh(&hci_cb_list_lock);
+       read_lock(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
                if (cb->security_cfm)
                        cb->security_cfm(conn, status, encrypt);
        }
-       read_unlock_bh(&hci_cb_list_lock);
+       read_unlock(&hci_cb_list_lock);
 }
 
 static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
 {
        struct list_head *p;
 
-       read_lock_bh(&hci_cb_list_lock);
+       read_lock(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
                if (cb->key_change_cfm)
                        cb->key_change_cfm(conn, status);
        }
-       read_unlock_bh(&hci_cb_list_lock);
+       read_unlock(&hci_cb_list_lock);
 }
 
 static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
@@ -884,13 +850,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
 {
        struct list_head *p;
 
-       read_lock_bh(&hci_cb_list_lock);
+       read_lock(&hci_cb_list_lock);
        list_for_each(p, &hci_cb_list) {
                struct hci_cb *cb = list_entry(p, struct hci_cb, list);
                if (cb->role_switch_cfm)
                        cb->role_switch_cfm(conn, status, role);
        }
-       read_unlock_bh(&hci_cb_list_lock);
+       read_unlock(&hci_cb_list_lock);
 }
 
 int hci_register_cb(struct hci_cb *hcb);
@@ -960,12 +926,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
 
+/* HCI socket flags */
+#define HCI_PI_MGMT_INIT       0
+
 struct hci_pinfo {
        struct bt_sock    bt;
        struct hci_dev    *hdev;
        struct hci_filter filter;
        __u32             cmsg_mask;
        unsigned short   channel;
+       unsigned long     flags;
 };
 
 /* HCI security filter */
index 72632f155e4321552fef5cafdc4f5be9743fddd2..68f5891506925f3101389b2afed34900231291c2 100644 (file)
@@ -482,10 +482,11 @@ struct l2cap_chan {
        __u32           remote_acc_lat;
        __u32           remote_flush_to;
 
-       struct timer_list       chan_timer;
-       struct timer_list       retrans_timer;
-       struct timer_list       monitor_timer;
-       struct timer_list       ack_timer;
+       struct delayed_work     chan_timer;
+       struct delayed_work     retrans_timer;
+       struct delayed_work     monitor_timer;
+       struct delayed_work     ack_timer;
+
        struct sk_buff          *tx_send_head;
        struct sk_buff_head     tx_q;
        struct sk_buff_head     srej_q;
@@ -521,7 +522,7 @@ struct l2cap_conn {
        __u8            info_state;
        __u8            info_ident;
 
-       struct timer_list info_timer;
+       struct delayed_work info_timer;
 
        spinlock_t      lock;
 
@@ -531,11 +532,11 @@ struct l2cap_conn {
 
        __u8            disc_reason;
 
-       struct timer_list security_timer;
+       struct delayed_work  security_timer;
        struct smp_chan *smp_chan;
 
        struct list_head chan_l;
-       rwlock_t        chan_lock;
+       struct mutex    chan_lock;
 };
 
 #define L2CAP_INFO_CL_MTU_REQ_SENT     0x01
@@ -594,6 +595,34 @@ enum {
        FLAG_EFS_ENABLE,
 };
 
+static inline void l2cap_chan_hold(struct l2cap_chan *c)
+{
+       atomic_inc(&c->refcnt);
+}
+
+static inline void l2cap_chan_put(struct l2cap_chan *c)
+{
+       if (atomic_dec_and_test(&c->refcnt))
+               kfree(c);
+}
+
+static inline void l2cap_set_timer(struct l2cap_chan *chan,
+                                       struct delayed_work *work, long timeout)
+{
+       BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
+
+       if (!__cancel_delayed_work(work))
+               l2cap_chan_hold(chan);
+       schedule_delayed_work(work, timeout);
+}
+
+static inline void l2cap_clear_timer(struct l2cap_chan *chan,
+                                       struct delayed_work *work)
+{
+       if (__cancel_delayed_work(work))
+               l2cap_chan_put(chan);
+}
+
 #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
 #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
 #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
@@ -805,7 +834,8 @@ int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
 struct l2cap_chan *l2cap_chan_create(struct sock *sk);
 void l2cap_chan_close(struct l2cap_chan *chan, int reason);
 void l2cap_chan_destroy(struct l2cap_chan *chan);
-int l2cap_chan_connect(struct l2cap_chan *chan);
+inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+                                                               bdaddr_t *dst);
 int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
                                                                u32 priority);
 void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
index 3b6880690a78ea0bb970cb6db2ed1299bb3bfac8..be65d34178839e6426f245ab64a6f4c55ad3e826 100644 (file)
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list {
 /* Reserve one extra byte for names in management messages so that they
  * are always guaranteed to be nul-terminated */
 #define MGMT_MAX_NAME_LENGTH           (HCI_MAX_NAME_LENGTH + 1)
+#define MGMT_MAX_SHORT_NAME_LENGTH     (10 + 1)
+
+#define MGMT_SETTING_POWERED           0x00000001
+#define MGMT_SETTING_CONNECTABLE       0x00000002
+#define MGMT_SETTING_FAST_CONNECTABLE  0x00000004
+#define MGMT_SETTING_DISCOVERABLE      0x00000008
+#define MGMT_SETTING_PAIRABLE          0x00000010
+#define MGMT_SETTING_LINK_SECURITY     0x00000020
+#define MGMT_SETTING_SSP               0x00000040
+#define MGMT_SETTING_BREDR             0x00000080
+#define MGMT_SETTING_HS                        0x00000100
+#define MGMT_SETTING_LE                        0x00000200
 
 #define MGMT_OP_READ_INFO              0x0004
 struct mgmt_rp_read_info {
-       __u8 type;
-       __u8 powered;
-       __u8 connectable;
-       __u8 discoverable;
-       __u8 pairable;
-       __u8 sec_mode;
        bdaddr_t bdaddr;
+       __u8 version;
+       __le16 manufacturer;
+       __le32 supported_settings;
+       __le32 current_settings;
        __u8 dev_class[3];
-       __u8 features[8];
-       __u16 manufacturer;
-       __u8 hci_ver;
-       __u16 hci_rev;
        __u8 name[MGMT_MAX_NAME_LENGTH];
+       __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
 } __packed;
 
 struct mgmt_mode {
@@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable {
 
 #define MGMT_OP_SET_CONNECTABLE                0x0007
 
-#define MGMT_OP_SET_PAIRABLE           0x0008
+#define MGMT_OP_SET_FAST_CONNECTABLE   0x0008
 
-#define MGMT_OP_ADD_UUID               0x0009
-struct mgmt_cp_add_uuid {
-       __u8 uuid[16];
-       __u8 svc_hint;
-} __packed;
+#define MGMT_OP_SET_PAIRABLE           0x0009
 
-#define MGMT_OP_REMOVE_UUID            0x000A
-struct mgmt_cp_remove_uuid {
-       __u8 uuid[16];
-} __packed;
+#define MGMT_OP_SET_LINK_SECURITY      0x000A
 
-#define MGMT_OP_SET_DEV_CLASS          0x000B
+#define MGMT_OP_SET_SSP                        0x000B
+
+#define MGMT_OP_SET_HS                 0x000C
+
+#define MGMT_OP_SET_LE                 0x000D
+
+#define MGMT_OP_SET_DEV_CLASS          0x000E
 struct mgmt_cp_set_dev_class {
        __u8 major;
        __u8 minor;
 } __packed;
 
-#define MGMT_OP_SET_SERVICE_CACHE      0x000C
-struct mgmt_cp_set_service_cache {
-       __u8 enable;
+#define MGMT_OP_SET_LOCAL_NAME         0x000F
+struct mgmt_cp_set_local_name {
+       __u8 name[MGMT_MAX_NAME_LENGTH];
+} __packed;
+
+#define MGMT_OP_ADD_UUID               0x0010
+struct mgmt_cp_add_uuid {
+       __u8 uuid[16];
+       __u8 svc_hint;
+} __packed;
+
+#define MGMT_OP_REMOVE_UUID            0x0011
+struct mgmt_cp_remove_uuid {
+       __u8 uuid[16];
 } __packed;
 
 struct mgmt_link_key_info {
@@ -124,14 +141,14 @@ struct mgmt_link_key_info {
        u8 pin_len;
 } __packed;
 
-#define MGMT_OP_LOAD_LINK_KEYS         0x000D
+#define MGMT_OP_LOAD_LINK_KEYS         0x0012
 struct mgmt_cp_load_link_keys {
        __u8 debug_keys;
        __le16 key_count;
        struct mgmt_link_key_info keys[0];
 } __packed;
 
-#define MGMT_OP_REMOVE_KEYS            0x000E
+#define MGMT_OP_REMOVE_KEYS            0x0013
 struct mgmt_cp_remove_keys {
        bdaddr_t bdaddr;
        __u8 disconnect;
@@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys {
        __u8 status;
 };
 
-#define MGMT_OP_DISCONNECT             0x000F
+#define MGMT_OP_DISCONNECT             0x0014
 struct mgmt_cp_disconnect {
        bdaddr_t bdaddr;
 } __packed;
@@ -160,13 +177,13 @@ struct mgmt_addr_info {
        __u8 type;
 } __packed;
 
-#define MGMT_OP_GET_CONNECTIONS                0x0010
+#define MGMT_OP_GET_CONNECTIONS                0x0015
 struct mgmt_rp_get_connections {
        __le16 conn_count;
        struct mgmt_addr_info addr[0];
 } __packed;
 
-#define MGMT_OP_PIN_CODE_REPLY         0x0011
+#define MGMT_OP_PIN_CODE_REPLY         0x0016
 struct mgmt_cp_pin_code_reply {
        bdaddr_t bdaddr;
        __u8 pin_len;
@@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply {
        uint8_t status;
 } __packed;
 
-#define MGMT_OP_PIN_CODE_NEG_REPLY     0x0012
+#define MGMT_OP_PIN_CODE_NEG_REPLY     0x0017
 struct mgmt_cp_pin_code_neg_reply {
        bdaddr_t bdaddr;
 } __packed;
 
-#define MGMT_OP_SET_IO_CAPABILITY      0x0013
+#define MGMT_OP_SET_IO_CAPABILITY      0x0018
 struct mgmt_cp_set_io_capability {
        __u8 io_capability;
 } __packed;
 
-#define MGMT_OP_PAIR_DEVICE            0x0014
+#define MGMT_OP_PAIR_DEVICE            0x0019
 struct mgmt_cp_pair_device {
        struct mgmt_addr_info addr;
        __u8 io_cap;
@@ -197,7 +214,7 @@ struct mgmt_rp_pair_device {
        __u8 status;
 } __packed;
 
-#define MGMT_OP_USER_CONFIRM_REPLY     0x0015
+#define MGMT_OP_USER_CONFIRM_REPLY     0x001A
 struct mgmt_cp_user_confirm_reply {
        bdaddr_t bdaddr;
 } __packed;
@@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply {
        __u8 status;
 } __packed;
 
-#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016
+#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001B
+struct mgmt_cp_user_confirm_neg_reply {
+       bdaddr_t bdaddr;
+} __packed;
 
-#define MGMT_OP_SET_LOCAL_NAME         0x0017
-struct mgmt_cp_set_local_name {
-       __u8 name[MGMT_MAX_NAME_LENGTH];
+#define MGMT_OP_USER_PASSKEY_REPLY     0x001C
+struct mgmt_cp_user_passkey_reply {
+       bdaddr_t bdaddr;
+       __le32 passkey;
+} __packed;
+struct mgmt_rp_user_passkey_reply {
+       bdaddr_t bdaddr;
+       __u8 status;
 } __packed;
 
-#define MGMT_OP_READ_LOCAL_OOB_DATA    0x0018
+#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001D
+struct mgmt_cp_user_passkey_neg_reply {
+       bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_READ_LOCAL_OOB_DATA    0x001E
 struct mgmt_rp_read_local_oob_data {
        __u8 hash[16];
        __u8 randomizer[16];
 } __packed;
 
-#define MGMT_OP_ADD_REMOTE_OOB_DATA    0x0019
+#define MGMT_OP_ADD_REMOTE_OOB_DATA    0x001F
 struct mgmt_cp_add_remote_oob_data {
        bdaddr_t bdaddr;
        __u8 hash[16];
        __u8 randomizer[16];
 } __packed;
 
-#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A
+#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0020
 struct mgmt_cp_remove_remote_oob_data {
        bdaddr_t bdaddr;
 } __packed;
 
-#define MGMT_OP_START_DISCOVERY                0x001B
+#define MGMT_OP_START_DISCOVERY                0x0021
 struct mgmt_cp_start_discovery {
        __u8 type;
 } __packed;
 
-#define MGMT_OP_STOP_DISCOVERY         0x001C
+#define MGMT_OP_STOP_DISCOVERY         0x0022
 
-#define MGMT_OP_BLOCK_DEVICE           0x001D
-struct mgmt_cp_block_device {
+#define MGMT_OP_CONFIRM_NAME           0x0023
+struct mgmt_cp_confirm_name {
        bdaddr_t bdaddr;
+       __u8 name_known;
 } __packed;
-
-#define MGMT_OP_UNBLOCK_DEVICE         0x001E
-struct mgmt_cp_unblock_device {
+struct mgmt_rp_confirm_name {
        bdaddr_t bdaddr;
+       __u8 status;
 } __packed;
 
-#define MGMT_OP_SET_FAST_CONNECTABLE   0x001F
-struct mgmt_cp_set_fast_connectable {
-       __u8 enable;
-} __packed;
-
-#define MGMT_OP_USER_PASSKEY_REPLY     0x0020
-struct mgmt_cp_user_passkey_reply {
+#define MGMT_OP_BLOCK_DEVICE           0x0024
+struct mgmt_cp_block_device {
        bdaddr_t bdaddr;
-       __le32 passkey;
 } __packed;
 
-#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021
-struct mgmt_cp_user_passkey_neg_reply {
+#define MGMT_OP_UNBLOCK_DEVICE         0x0025
+struct mgmt_cp_unblock_device {
        bdaddr_t bdaddr;
 } __packed;
 
@@ -285,81 +309,82 @@ struct mgmt_ev_controller_error {
 
 #define MGMT_EV_INDEX_REMOVED          0x0005
 
-#define MGMT_EV_POWERED                        0x0006
+#define MGMT_EV_NEW_SETTINGS           0x0006
 
-#define MGMT_EV_DISCOVERABLE           0x0007
-
-#define MGMT_EV_CONNECTABLE            0x0008
+#define MGMT_EV_CLASS_OF_DEV_CHANGED   0x0007
+struct mgmt_ev_class_of_dev_changed {
+       __u8 dev_class[3];
+};
 
-#define MGMT_EV_PAIRABLE               0x0009
+#define MGMT_EV_LOCAL_NAME_CHANGED     0x0008
+struct mgmt_ev_local_name_changed {
+       __u8 name[MGMT_MAX_NAME_LENGTH];
+       __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+} __packed;
 
-#define MGMT_EV_NEW_LINK_KEY           0x000A
+#define MGMT_EV_NEW_LINK_KEY           0x0009
 struct mgmt_ev_new_link_key {
        __u8 store_hint;
        struct mgmt_link_key_info key;
 } __packed;
 
-#define MGMT_EV_CONNECTED              0x000B
+#define MGMT_EV_CONNECTED              0x000A
 
-#define MGMT_EV_DISCONNECTED           0x000C
+#define MGMT_EV_DISCONNECTED           0x000B
 
-#define MGMT_EV_CONNECT_FAILED         0x000D
+#define MGMT_EV_CONNECT_FAILED         0x000C
 struct mgmt_ev_connect_failed {
        struct mgmt_addr_info addr;
        __u8 status;
 } __packed;
 
-#define MGMT_EV_PIN_CODE_REQUEST       0x000E
+#define MGMT_EV_PIN_CODE_REQUEST       0x000D
 struct mgmt_ev_pin_code_request {
        bdaddr_t bdaddr;
        __u8 secure;
 } __packed;
 
-#define MGMT_EV_USER_CONFIRM_REQUEST   0x000F
+#define MGMT_EV_USER_CONFIRM_REQUEST   0x000E
 struct mgmt_ev_user_confirm_request {
        bdaddr_t bdaddr;
        __u8 confirm_hint;
        __le32 value;
 } __packed;
 
+#define MGMT_EV_USER_PASSKEY_REQUEST   0x000F
+struct mgmt_ev_user_passkey_request {
+       bdaddr_t bdaddr;
+} __packed;
+
 #define MGMT_EV_AUTH_FAILED            0x0010
 struct mgmt_ev_auth_failed {
        bdaddr_t bdaddr;
        __u8 status;
 } __packed;
 
-#define MGMT_EV_LOCAL_NAME_CHANGED     0x0011
-struct mgmt_ev_local_name_changed {
-       __u8 name[MGMT_MAX_NAME_LENGTH];
-} __packed;
-
-#define MGMT_EV_DEVICE_FOUND           0x0012
+#define MGMT_EV_DEVICE_FOUND           0x0011
 struct mgmt_ev_device_found {
        struct mgmt_addr_info addr;
        __u8 dev_class[3];
        __s8 rssi;
+       __u8 confirm_name;
        __u8 eir[HCI_MAX_EIR_LENGTH];
 } __packed;
 
-#define MGMT_EV_REMOTE_NAME            0x0013
+#define MGMT_EV_REMOTE_NAME            0x0012
 struct mgmt_ev_remote_name {
        bdaddr_t bdaddr;
        __u8 name[MGMT_MAX_NAME_LENGTH];
 } __packed;
 
-#define MGMT_EV_DISCOVERING            0x0014
+#define MGMT_EV_DISCOVERING            0x0013
 
-#define MGMT_EV_DEVICE_BLOCKED         0x0015
+#define MGMT_EV_DEVICE_BLOCKED         0x0014
 struct mgmt_ev_device_blocked {
        bdaddr_t bdaddr;
 } __packed;
 
-#define MGMT_EV_DEVICE_UNBLOCKED       0x0016
+#define MGMT_EV_DEVICE_UNBLOCKED       0x0015
 struct mgmt_ev_device_unblocked {
        bdaddr_t bdaddr;
 } __packed;
-
-#define MGMT_EV_USER_PASSKEY_REQUEST   0x0017
-struct mgmt_ev_user_passkey_request {
-       bdaddr_t bdaddr;
-} __packed;
index 15b97d54944195b19f52d57434a01f5443407d92..aeaf5fa2b9f15e9c0b6c5cd0ba41af510a012464 100644 (file)
@@ -115,6 +115,10 @@ struct smp_cmd_security_req {
 #define SMP_MIN_ENC_KEY_SIZE           7
 #define SMP_MAX_ENC_KEY_SIZE           16
 
+#define SMP_FLAG_TK_VALID      1
+#define SMP_FLAG_CFM_PENDING   2
+#define SMP_FLAG_MITM_AUTH     3
+
 struct smp_chan {
        struct l2cap_conn *conn;
        u8              preq[7]; /* SMP Pairing Request */
@@ -124,6 +128,7 @@ struct smp_chan {
        u8              pcnf[16]; /* SMP Pairing Confirm */
        u8              tk[16]; /* SMP Temporary Key */
        u8              smp_key_size;
+       unsigned long   smp_flags;
        struct crypto_blkcipher *tfm;
        struct work_struct confirm;
        struct work_struct random;
@@ -134,6 +139,7 @@ struct smp_chan {
 int smp_conn_security(struct l2cap_conn *conn, __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);
+int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
 
 void smp_chan_destroy(struct l2cap_conn *conn);
 
index 9f85fca0b676606e0f04c4baa3a80bf6888778c4..15f4be7d768e48e740b5b58f39ba76813e79e2f6 100644 (file)
@@ -505,6 +505,7 @@ struct station_parameters {
  * @STATION_INFO_CONNECTED_TIME: @connected_time filled
  * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
  * @STATION_INFO_STA_FLAGS: @sta_flags filled
+ * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled
  */
 enum station_info_flags {
        STATION_INFO_INACTIVE_TIME      = 1<<0,
@@ -525,7 +526,8 @@ enum station_info_flags {
        STATION_INFO_BSS_PARAM          = 1<<15,
        STATION_INFO_CONNECTED_TIME     = 1<<16,
        STATION_INFO_ASSOC_REQ_IES      = 1<<17,
-       STATION_INFO_STA_FLAGS          = 1<<18
+       STATION_INFO_STA_FLAGS          = 1<<18,
+       STATION_INFO_BEACON_LOSS_COUNT  = 1<<19
 };
 
 /**
@@ -623,6 +625,7 @@ struct sta_bss_parameters {
  *     the cfg80211_new_sta() calls to notify user space of the IEs.
  * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets.
  * @sta_flags: station flags mask & values
+ * @beacon_loss_count: Number of times beacon loss event has triggered.
  */
 struct station_info {
        u32 filled;
@@ -650,6 +653,8 @@ struct station_info {
        const u8 *assoc_req_ies;
        size_t assoc_req_ies_len;
 
+       u32 beacon_loss_count;
+
        /*
         * Note: Add a new enum station_info_flags value for each new field and
         * use it to check which fields are initialized.
index 5b5c8a7e26d7756923fa285784acbf257f4e8938..2a7523edd9b5a0cd783d86130c163796d844845f 100644 (file)
@@ -3502,9 +3502,12 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
  *
  * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have
  *     changed, rate control algorithm can update its internal state if needed.
+ * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed, the rate
+ *     control algorithm needs to adjust accordingly.
  */
 enum rate_control_changed {
-       IEEE80211_RC_HT_CHANGED = BIT(0)
+       IEEE80211_RC_HT_CHANGED         = BIT(0),
+       IEEE80211_RC_SMPS_CHANGED       = BIT(1),
 };
 
 /**
index bfb3dc03c9de31a63db88876fa803df4d550aa84..9ec85eb8853dc378286e4c482f23b70fc2eeb7c2 100644 (file)
@@ -6,7 +6,11 @@ menuconfig BT
        tristate "Bluetooth subsystem support"
        depends on NET && !S390
        depends on RFKILL || !RFKILL
+       select CRC16
        select CRYPTO
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_AES
+       select CRYPTO_ECB
        help
          Bluetooth is low-cost, low-power, short-range wireless technology.
          It was designed as a replacement for cables and other short-range
@@ -15,10 +19,12 @@ menuconfig BT
          Bluetooth can be found at <http://www.bluetooth.com/>.
 
          Linux Bluetooth subsystem consist of several layers:
-            Bluetooth Core (HCI device and connection manager, scheduler)
+            Bluetooth Core
+               HCI device and connection manager, scheduler
+               SCO audio links
+               L2CAP (Logical Link Control and Adaptation Protocol)
+               SMP (Security Manager Protocol) on LE (Low Energy) links
             HCI Device drivers (Interface to the hardware)
-            SCO Module (SCO audio links)
-            L2CAP Module (Logical Link Control and Adaptation Protocol)
             RFCOMM Module (RFCOMM Protocol)  
             BNEP Module (Bluetooth Network Encapsulation Protocol)
             CMTP Module (CAPI Message Transport Protocol)
@@ -33,31 +39,6 @@ menuconfig BT
          to Bluetooth kernel modules are provided in the BlueZ packages.  For
          more information, see <http://www.bluez.org/>.
 
-if BT != n
-
-config BT_L2CAP
-       bool "L2CAP protocol support"
-       select CRC16
-       select CRYPTO
-       select CRYPTO_BLKCIPHER
-       select CRYPTO_AES
-       select CRYPTO_ECB
-       help
-         L2CAP (Logical Link Control and Adaptation Protocol) provides
-         connection oriented and connection-less data transport.  L2CAP
-         support is required for most Bluetooth applications.
-
-         Also included is support for SMP (Security Manager Protocol) which
-         is the security layer on top of LE (Low Energy) links.
-
-config BT_SCO
-       bool "SCO links support"
-       help
-         SCO link provides voice transport over Bluetooth.  SCO support is
-         required for voice applications like Headset and Audio.
-
-endif
-
 source "net/bluetooth/rfcomm/Kconfig"
 
 source "net/bluetooth/bnep/Kconfig"
index 9b67f3d08fa4750296645ec2b06c89dd1ff61ed0..2dc5a5700f533191558381d8bcc0b16016b185a6 100644 (file)
@@ -8,6 +8,5 @@ obj-$(CONFIG_BT_BNEP)   += bnep/
 obj-$(CONFIG_BT_CMTP)  += cmtp/
 obj-$(CONFIG_BT_HIDP)  += hidp/
 
-bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP)   += l2cap_core.o l2cap_sock.o smp.o
-bluetooth-$(CONFIG_BT_SCO)     += sco.o
+bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
+       hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o
index 062124cd89cf2a560cff39b80b7f3cbcdb66c1a3..cdcfcabb34ab8daf5b2275f52084c055926dac73 100644 (file)
@@ -199,15 +199,14 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
 
        BT_DBG("parent %p", parent);
 
-       local_bh_disable();
        list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
                sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
 
-               bh_lock_sock(sk);
+               lock_sock(sk);
 
                /* FIXME: Is this check still needed */
                if (sk->sk_state == BT_CLOSED) {
-                       bh_unlock_sock(sk);
+                       release_sock(sk);
                        bt_accept_unlink(sk);
                        continue;
                }
@@ -218,14 +217,12 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
                        if (newsock)
                                sock_graft(sk, newsock);
 
-                       bh_unlock_sock(sk);
-                       local_bh_enable();
+                       release_sock(sk);
                        return sk;
                }
 
-               bh_unlock_sock(sk);
+               release_sock(sk);
        }
-       local_bh_enable();
 
        return NULL;
 }
index 35158b036d54293c370967ad446ed3aa0c7d1e38..71791fc9f6b1f93269880071af6150e3d67d2d72 100644 (file)
@@ -1,6 +1,6 @@
 config BT_BNEP
        tristate "BNEP protocol support"
-       depends on BT && BT_L2CAP
+       depends on BT
        select CRC32
        help
          BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
index d6b0382f6f3ad6f7c48394a05e6b960a799c62a5..94cbf42ce155b290ab0a4da9e975432006a6b6de 100644 (file)
@@ -1,6 +1,6 @@
 config BT_CMTP
        tristate "CMTP protocol support"
-       depends on BT && BT_L2CAP && ISDN_CAPI
+       depends on BT && ISDN_CAPI
        help
          CMTP (CAPI Message Transport Protocol) is a transport layer
          for CAPI messages.  CMTP is required for the Bluetooth Common
index 3fa08dda825e23b9f583ecbc336656be2b070ac9..3db432473ad5214efc902f5bbaa36f631114defa 100644 (file)
@@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status)
        }
 }
 
-static void hci_conn_timeout(unsigned long arg)
+static void hci_conn_timeout(struct work_struct *work)
 {
-       struct hci_conn *conn = (void *) arg;
+       struct hci_conn *conn = container_of(work, struct hci_conn,
+                                                       disc_work.work);
        struct hci_dev *hdev = conn->hdev;
        __u8 reason;
 
@@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg)
        hci_dev_unlock(hdev);
 }
 
+/* Enter sniff mode */
+static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       BT_DBG("conn %p mode %d", conn, conn->mode);
+
+       if (test_bit(HCI_RAW, &hdev->flags))
+               return;
+
+       if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
+               return;
+
+       if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
+               return;
+
+       if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
+               struct hci_cp_sniff_subrate cp;
+               cp.handle             = cpu_to_le16(conn->handle);
+               cp.max_latency        = cpu_to_le16(0);
+               cp.min_remote_timeout = cpu_to_le16(0);
+               cp.min_local_timeout  = cpu_to_le16(0);
+               hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
+       }
+
+       if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
+               struct hci_cp_sniff_mode cp;
+               cp.handle       = cpu_to_le16(conn->handle);
+               cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
+               cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
+               cp.attempt      = cpu_to_le16(4);
+               cp.timeout      = cpu_to_le16(1);
+               hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
+       }
+}
+
 static void hci_conn_idle(unsigned long arg)
 {
        struct hci_conn *conn = (void *) arg;
@@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg)
        struct hci_conn *conn = (void *) arg;
        struct hci_dev *hdev = conn->hdev;
 
-       hci_dev_lock(hdev);
-
        hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
                                                                &conn->dst);
-
-       hci_dev_unlock(hdev);
 }
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
@@ -374,9 +407,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        skb_queue_head_init(&conn->data_q);
 
-       hci_chan_hash_init(conn);
+       INIT_LIST_HEAD(&conn->chan_list);;
 
-       setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
+       INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
        setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
        setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
                                                        (unsigned long) conn);
@@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        hci_dev_hold(hdev);
 
-       tasklet_disable(&hdev->tx_task);
-
        hci_conn_hash_add(hdev, conn);
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
@@ -395,8 +426,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        hci_conn_init_sysfs(conn);
 
-       tasklet_enable(&hdev->tx_task);
-
        return conn;
 }
 
@@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn)
 
        del_timer(&conn->idle_timer);
 
-       del_timer(&conn->disc_timer);
+       cancel_delayed_work_sync(&conn->disc_work);
 
        del_timer(&conn->auto_accept_timer);
 
@@ -432,16 +461,13 @@ int hci_conn_del(struct hci_conn *conn)
                }
        }
 
-       tasklet_disable(&hdev->tx_task);
 
-       hci_chan_hash_flush(conn);
+       hci_chan_list_flush(conn);
 
        hci_conn_hash_del(hdev, conn);
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
 
-       tasklet_enable(&hdev->tx_task);
-
        skb_queue_purge(&conn->data_q);
 
        hci_conn_put_device(conn);
@@ -461,7 +487,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
 
        BT_DBG("%s -> %s", batostr(src), batostr(dst));
 
-       read_lock_bh(&hci_dev_list_lock);
+       read_lock(&hci_dev_list_lock);
 
        list_for_each_entry(d, &hci_dev_list, list) {
                if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
@@ -486,7 +512,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
        if (hdev)
                hdev = hci_dev_hold(hdev);
 
-       read_unlock_bh(&hci_dev_list_lock);
+       read_unlock(&hci_dev_list_lock);
        return hdev;
 }
 EXPORT_SYMBOL(hci_get_route);
@@ -767,57 +793,15 @@ timer:
                        jiffies + msecs_to_jiffies(hdev->idle_timeout));
 }
 
-/* Enter sniff mode */
-void hci_conn_enter_sniff_mode(struct hci_conn *conn)
-{
-       struct hci_dev *hdev = conn->hdev;
-
-       BT_DBG("conn %p mode %d", conn, conn->mode);
-
-       if (test_bit(HCI_RAW, &hdev->flags))
-               return;
-
-       if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
-               return;
-
-       if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
-               return;
-
-       if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
-               struct hci_cp_sniff_subrate cp;
-               cp.handle             = cpu_to_le16(conn->handle);
-               cp.max_latency        = cpu_to_le16(0);
-               cp.min_remote_timeout = cpu_to_le16(0);
-               cp.min_local_timeout  = cpu_to_le16(0);
-               hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
-       }
-
-       if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
-               struct hci_cp_sniff_mode cp;
-               cp.handle       = cpu_to_le16(conn->handle);
-               cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
-               cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
-               cp.attempt      = cpu_to_le16(4);
-               cp.timeout      = cpu_to_le16(1);
-               hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
-       }
-}
-
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
-       struct list_head *p;
+       struct hci_conn *c;
 
        BT_DBG("hdev %s", hdev->name);
 
-       p = h->list.next;
-       while (p != &h->list) {
-               struct hci_conn *c;
-
-               c = list_entry(p, struct hci_conn, list);
-               p = p->next;
-
+       list_for_each_entry_rcu(c, &h->list, list) {
                c->state = BT_CLOSED;
 
                hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
@@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg)
 
        ci = cl->conn_info;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        list_for_each_entry(c, &hdev->conn_hash.list, list) {
                bacpy(&(ci + n)->bdaddr, &c->dst);
                (ci + n)->handle = c->handle;
@@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg)
                if (++n >= req.conn_num)
                        break;
        }
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        cl->dev_id = hdev->id;
        cl->conn_num = n;
@@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
        if (copy_from_user(&req, arg, sizeof(req)))
                return -EFAULT;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
        if (conn) {
                bacpy(&ci.bdaddr, &conn->dst);
@@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
                ci.state = conn->state;
                ci.link_mode = conn->link_mode;
        }
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        if (!conn)
                return -ENOENT;
@@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
        if (copy_from_user(&req, arg, sizeof(req)))
                return -EFAULT;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
        if (conn)
                req.type = conn->auth_type;
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        if (!conn)
                return -ENOENT;
@@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
        chan->conn = conn;
        skb_queue_head_init(&chan->data_q);
 
-       tasklet_disable(&hdev->tx_task);
-       hci_chan_hash_add(conn, chan);
-       tasklet_enable(&hdev->tx_task);
+       list_add_rcu(&chan->list, &conn->chan_list);
 
        return chan;
 }
@@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan)
 
        BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
 
-       tasklet_disable(&hdev->tx_task);
-       hci_chan_hash_del(conn, chan);
-       tasklet_enable(&hdev->tx_task);
+       list_del_rcu(&chan->list);
+
+       synchronize_rcu();
 
        skb_queue_purge(&chan->data_q);
        kfree(chan);
@@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan)
        return 0;
 }
 
-void hci_chan_hash_flush(struct hci_conn *conn)
+void hci_chan_list_flush(struct hci_conn *conn)
 {
-       struct hci_chan_hash *h = &conn->chan_hash;
-       struct hci_chan *chan, *tmp;
+       struct hci_chan *chan;
 
        BT_DBG("conn %p", conn);
 
-       list_for_each_entry_safe(chan, tmp, &h->list, list)
+       list_for_each_entry_rcu(chan, &conn->chan_list, list)
                hci_chan_del(chan);
 }
index ce3727ecc0c40b80d9d7d5681fafbf5efbf3f7ef..6d38d80195cb40c43ae6c292a7406e58d64d05b3 100644 (file)
@@ -1,6 +1,7 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
+   Copyright (C) 2011 ProFUSION Embedded Systems
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
 
 int enable_hs;
 
-static void hci_cmd_task(unsigned long arg);
-static void hci_rx_task(unsigned long arg);
-static void hci_tx_task(unsigned long arg);
-
-static DEFINE_RWLOCK(hci_task_lock);
+static void hci_rx_work(struct work_struct *work);
+static void hci_cmd_work(struct work_struct *work);
+static void hci_tx_work(struct work_struct *work);
 
 /* HCI device list */
 LIST_HEAD(hci_dev_list);
@@ -70,10 +69,6 @@ DEFINE_RWLOCK(hci_dev_list_lock);
 LIST_HEAD(hci_cb_list);
 DEFINE_RWLOCK(hci_cb_list_lock);
 
-/* HCI protocols */
-#define HCI_MAX_PROTO  2
-struct hci_proto *hci_proto[HCI_MAX_PROTO];
-
 /* HCI notifiers list */
 static ATOMIC_NOTIFIER_HEAD(hci_notifier);
 
@@ -192,33 +187,20 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
        hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
 }
 
-static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
+static void bredr_init(struct hci_dev *hdev)
 {
        struct hci_cp_delete_stored_link_key cp;
-       struct sk_buff *skb;
        __le16 param;
        __u8 flt_type;
 
-       BT_DBG("%s %ld", hdev->name, opt);
-
-       /* Driver initialization */
-
-       /* Special commands */
-       while ((skb = skb_dequeue(&hdev->driver_init))) {
-               bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
-               skb->dev = (void *) hdev;
-
-               skb_queue_tail(&hdev->cmd_q, skb);
-               tasklet_schedule(&hdev->cmd_task);
-       }
-       skb_queue_purge(&hdev->driver_init);
+       hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
 
        /* Mandatory initialization */
 
        /* Reset */
        if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
-                       set_bit(HCI_RESET, &hdev->flags);
-                       hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
+               set_bit(HCI_RESET, &hdev->flags);
+               hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
        }
 
        /* Read Local Supported Features */
@@ -257,6 +239,51 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
        hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
 }
 
+static void amp_init(struct hci_dev *hdev)
+{
+       hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
+
+       /* Reset */
+       hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
+
+       /* Read Local Version */
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
+}
+
+static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
+{
+       struct sk_buff *skb;
+
+       BT_DBG("%s %ld", hdev->name, opt);
+
+       /* Driver initialization */
+
+       /* Special commands */
+       while ((skb = skb_dequeue(&hdev->driver_init))) {
+               bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
+               skb->dev = (void *) hdev;
+
+               skb_queue_tail(&hdev->cmd_q, skb);
+               queue_work(hdev->workqueue, &hdev->cmd_work);
+       }
+       skb_queue_purge(&hdev->driver_init);
+
+       switch (hdev->dev_type) {
+       case HCI_BREDR:
+               bredr_init(hdev);
+               break;
+
+       case HCI_AMP:
+               amp_init(hdev);
+               break;
+
+       default:
+               BT_ERR("Unknown device type %d", hdev->dev_type);
+               break;
+       }
+
+}
+
 static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
 {
        BT_DBG("%s", hdev->name);
@@ -433,14 +460,14 @@ int hci_inquiry(void __user *arg)
        if (!hdev)
                return -ENODEV;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
                                inquiry_cache_empty(hdev) ||
                                ir.flags & IREQ_CACHE_FLUSH) {
                inquiry_cache_flush(hdev);
                do_inquiry = 1;
        }
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        timeo = ir.length * msecs_to_jiffies(2000);
 
@@ -462,9 +489,9 @@ int hci_inquiry(void __user *arg)
                goto done;
        }
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        BT_DBG("num_rsp %d", ir.num_rsp);
 
@@ -541,15 +568,15 @@ int hci_dev_open(__u16 dev)
                set_bit(HCI_UP, &hdev->flags);
                hci_notify(hdev, HCI_DEV_UP);
                if (!test_bit(HCI_SETUP, &hdev->flags)) {
-                       hci_dev_lock_bh(hdev);
+                       hci_dev_lock(hdev);
                        mgmt_powered(hdev, 1);
-                       hci_dev_unlock_bh(hdev);
+                       hci_dev_unlock(hdev);
                }
        } else {
                /* Init failed, cleanup */
-               tasklet_kill(&hdev->rx_task);
-               tasklet_kill(&hdev->tx_task);
-               tasklet_kill(&hdev->cmd_task);
+               flush_work(&hdev->tx_work);
+               flush_work(&hdev->cmd_work);
+               flush_work(&hdev->rx_work);
 
                skb_queue_purge(&hdev->cmd_q);
                skb_queue_purge(&hdev->rx_q);
@@ -585,9 +612,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
                return 0;
        }
 
-       /* Kill RX and TX tasks */
-       tasklet_kill(&hdev->rx_task);
-       tasklet_kill(&hdev->tx_task);
+       /* Flush RX and TX works */
+       flush_work(&hdev->tx_work);
+       flush_work(&hdev->rx_work);
 
        if (hdev->discov_timeout > 0) {
                cancel_delayed_work(&hdev->discov_off);
@@ -597,10 +624,13 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
                cancel_delayed_work(&hdev->power_off);
 
-       hci_dev_lock_bh(hdev);
+       if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
+               cancel_delayed_work(&hdev->service_cache);
+
+       hci_dev_lock(hdev);
        inquiry_cache_flush(hdev);
        hci_conn_hash_flush(hdev);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        hci_notify(hdev, HCI_DEV_DOWN);
 
@@ -617,8 +647,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
                clear_bit(HCI_INIT, &hdev->flags);
        }
 
-       /* Kill cmd task */
-       tasklet_kill(&hdev->cmd_task);
+       /* flush cmd  work */
+       flush_work(&hdev->cmd_work);
 
        /* Drop queues */
        skb_queue_purge(&hdev->rx_q);
@@ -636,9 +666,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
         * and no tasks are scheduled. */
        hdev->close(hdev);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        mgmt_powered(hdev, 0);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        /* Clear flags */
        hdev->flags = 0;
@@ -672,7 +702,6 @@ int hci_dev_reset(__u16 dev)
                return -ENODEV;
 
        hci_req_lock(hdev);
-       tasklet_disable(&hdev->tx_task);
 
        if (!test_bit(HCI_UP, &hdev->flags))
                goto done;
@@ -681,10 +710,10 @@ int hci_dev_reset(__u16 dev)
        skb_queue_purge(&hdev->rx_q);
        skb_queue_purge(&hdev->cmd_q);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        inquiry_cache_flush(hdev);
        hci_conn_hash_flush(hdev);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        if (hdev->flush)
                hdev->flush(hdev);
@@ -697,7 +726,6 @@ int hci_dev_reset(__u16 dev)
                                        msecs_to_jiffies(HCI_INIT_TIMEOUT));
 
 done:
-       tasklet_enable(&hdev->tx_task);
        hci_req_unlock(hdev);
        hci_dev_put(hdev);
        return ret;
@@ -816,7 +844,7 @@ int hci_get_dev_list(void __user *arg)
 
        dr = dl->dev_req;
 
-       read_lock_bh(&hci_dev_list_lock);
+       read_lock(&hci_dev_list_lock);
        list_for_each_entry(hdev, &hci_dev_list, list) {
                if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
                        cancel_delayed_work(&hdev->power_off);
@@ -830,7 +858,7 @@ int hci_get_dev_list(void __user *arg)
                if (++n >= dev_num)
                        break;
        }
-       read_unlock_bh(&hci_dev_list_lock);
+       read_unlock(&hci_dev_list_lock);
 
        dl->dev_num = n;
        size = sizeof(*dl) + n * sizeof(*dr);
@@ -939,7 +967,7 @@ static void hci_power_on(struct work_struct *work)
                return;
 
        if (test_bit(HCI_AUTO_OFF, &hdev->flags))
-               queue_delayed_work(hdev->workqueue, &hdev->power_off,
+               schedule_delayed_work(&hdev->power_off,
                                        msecs_to_jiffies(AUTO_OFF_TIMEOUT));
 
        if (test_and_clear_bit(HCI_SETUP, &hdev->flags))
@@ -967,13 +995,13 @@ static void hci_discov_off(struct work_struct *work)
 
        BT_DBG("%s", hdev->name);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
 
        hdev->discov_timeout = 0;
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 }
 
 int hci_uuids_clear(struct hci_dev *hdev)
@@ -1207,7 +1235,7 @@ static void hci_cmd_timer(unsigned long arg)
 
        BT_ERR("%s command tx timeout", hdev->name);
        atomic_set(&hdev->cmd_cnt, 1);
-       tasklet_schedule(&hdev->cmd_task);
+       queue_work(hdev->workqueue, &hdev->cmd_work);
 }
 
 struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
@@ -1340,9 +1368,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
        return mgmt_device_unblocked(hdev, bdaddr);
 }
 
-static void hci_clear_adv_cache(unsigned long arg)
+static void hci_clear_adv_cache(struct work_struct *work)
 {
-       struct hci_dev *hdev = (void *) arg;
+       struct hci_dev *hdev = container_of(work, struct hci_dev,
+                                                       adv_work.work);
 
        hci_dev_lock(hdev);
 
@@ -1429,7 +1458,7 @@ int hci_register_dev(struct hci_dev *hdev)
         */
        id = (hdev->dev_type == HCI_BREDR) ? 0 : 1;
 
-       write_lock_bh(&hci_dev_list_lock);
+       write_lock(&hci_dev_list_lock);
 
        /* Find first available device id */
        list_for_each(p, &hci_dev_list) {
@@ -1443,7 +1472,7 @@ int hci_register_dev(struct hci_dev *hdev)
        list_add_tail(&hdev->list, head);
 
        atomic_set(&hdev->refcnt, 1);
-       spin_lock_init(&hdev->lock);
+       mutex_init(&hdev->lock);
 
        hdev->flags = 0;
        hdev->dev_flags = 0;
@@ -1456,9 +1485,10 @@ int hci_register_dev(struct hci_dev *hdev)
        hdev->sniff_max_interval = 800;
        hdev->sniff_min_interval = 80;
 
-       tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev);
-       tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev);
-       tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev);
+       INIT_WORK(&hdev->rx_work, hci_rx_work);
+       INIT_WORK(&hdev->cmd_work, hci_cmd_work);
+       INIT_WORK(&hdev->tx_work, hci_tx_work);
+
 
        skb_queue_head_init(&hdev->rx_q);
        skb_queue_head_init(&hdev->cmd_q);
@@ -1487,9 +1517,8 @@ int hci_register_dev(struct hci_dev *hdev)
        INIT_LIST_HEAD(&hdev->remote_oob_data);
 
        INIT_LIST_HEAD(&hdev->adv_entries);
-       setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
-                                               (unsigned long) hdev);
 
+       INIT_DELAYED_WORK(&hdev->adv_work, hci_clear_adv_cache);
        INIT_WORK(&hdev->power_on, hci_power_on);
        INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
 
@@ -1499,9 +1528,10 @@ int hci_register_dev(struct hci_dev *hdev)
 
        atomic_set(&hdev->promisc, 0);
 
-       write_unlock_bh(&hci_dev_list_lock);
+       write_unlock(&hci_dev_list_lock);
 
-       hdev->workqueue = create_singlethread_workqueue(hdev->name);
+       hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
+                                                       WQ_MEM_RECLAIM, 1);
        if (!hdev->workqueue) {
                error = -ENOMEM;
                goto err;
@@ -1522,7 +1552,7 @@ int hci_register_dev(struct hci_dev *hdev)
 
        set_bit(HCI_AUTO_OFF, &hdev->flags);
        set_bit(HCI_SETUP, &hdev->flags);
-       queue_work(hdev->workqueue, &hdev->power_on);
+       schedule_work(&hdev->power_on);
 
        hci_notify(hdev, HCI_DEV_REG);
 
@@ -1531,9 +1561,9 @@ int hci_register_dev(struct hci_dev *hdev)
 err_wqueue:
        destroy_workqueue(hdev->workqueue);
 err:
-       write_lock_bh(&hci_dev_list_lock);
+       write_lock(&hci_dev_list_lock);
        list_del(&hdev->list);
-       write_unlock_bh(&hci_dev_list_lock);
+       write_unlock(&hci_dev_list_lock);
 
        return error;
 }
@@ -1546,9 +1576,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
        BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
 
-       write_lock_bh(&hci_dev_list_lock);
+       write_lock(&hci_dev_list_lock);
        list_del(&hdev->list);
-       write_unlock_bh(&hci_dev_list_lock);
+       write_unlock(&hci_dev_list_lock);
 
        hci_dev_do_close(hdev);
 
@@ -1557,9 +1587,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
        if (!test_bit(HCI_INIT, &hdev->flags) &&
                                        !test_bit(HCI_SETUP, &hdev->flags)) {
-               hci_dev_lock_bh(hdev);
+               hci_dev_lock(hdev);
                mgmt_index_removed(hdev);
-               hci_dev_unlock_bh(hdev);
+               hci_dev_unlock(hdev);
        }
 
        /* mgmt_index_removed should take care of emptying the
@@ -1575,17 +1605,17 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
        hci_del_sysfs(hdev);
 
-       del_timer(&hdev->adv_timer);
+       cancel_delayed_work_sync(&hdev->adv_work);
 
        destroy_workqueue(hdev->workqueue);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        hci_blacklist_clear(hdev);
        hci_uuids_clear(hdev);
        hci_link_keys_clear(hdev);
        hci_remote_oob_data_clear(hdev);
        hci_adv_entries_clear(hdev);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        __hci_dev_put(hdev);
 }
@@ -1623,9 +1653,8 @@ int hci_recv_frame(struct sk_buff *skb)
        /* Time stamp */
        __net_timestamp(skb);
 
-       /* Queue frame for rx task */
        skb_queue_tail(&hdev->rx_q, skb);
-       tasklet_schedule(&hdev->rx_task);
+       queue_work(hdev->workqueue, &hdev->rx_work);
 
        return 0;
 }
@@ -1797,59 +1826,13 @@ EXPORT_SYMBOL(hci_recv_stream_fragment);
 
 /* ---- Interface to upper protocols ---- */
 
-/* Register/Unregister protocols.
- * hci_task_lock is used to ensure that no tasks are running. */
-int hci_register_proto(struct hci_proto *hp)
-{
-       int err = 0;
-
-       BT_DBG("%p name %s id %d", hp, hp->name, hp->id);
-
-       if (hp->id >= HCI_MAX_PROTO)
-               return -EINVAL;
-
-       write_lock_bh(&hci_task_lock);
-
-       if (!hci_proto[hp->id])
-               hci_proto[hp->id] = hp;
-       else
-               err = -EEXIST;
-
-       write_unlock_bh(&hci_task_lock);
-
-       return err;
-}
-EXPORT_SYMBOL(hci_register_proto);
-
-int hci_unregister_proto(struct hci_proto *hp)
-{
-       int err = 0;
-
-       BT_DBG("%p name %s id %d", hp, hp->name, hp->id);
-
-       if (hp->id >= HCI_MAX_PROTO)
-               return -EINVAL;
-
-       write_lock_bh(&hci_task_lock);
-
-       if (hci_proto[hp->id])
-               hci_proto[hp->id] = NULL;
-       else
-               err = -ENOENT;
-
-       write_unlock_bh(&hci_task_lock);
-
-       return err;
-}
-EXPORT_SYMBOL(hci_unregister_proto);
-
 int hci_register_cb(struct hci_cb *cb)
 {
        BT_DBG("%p name %s", cb, cb->name);
 
-       write_lock_bh(&hci_cb_list_lock);
+       write_lock(&hci_cb_list_lock);
        list_add(&cb->list, &hci_cb_list);
-       write_unlock_bh(&hci_cb_list_lock);
+       write_unlock(&hci_cb_list_lock);
 
        return 0;
 }
@@ -1859,9 +1842,9 @@ int hci_unregister_cb(struct hci_cb *cb)
 {
        BT_DBG("%p name %s", cb, cb->name);
 
-       write_lock_bh(&hci_cb_list_lock);
+       write_lock(&hci_cb_list_lock);
        list_del(&cb->list);
-       write_unlock_bh(&hci_cb_list_lock);
+       write_unlock(&hci_cb_list_lock);
 
        return 0;
 }
@@ -1922,7 +1905,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
                hdev->init_last_cmd = opcode;
 
        skb_queue_tail(&hdev->cmd_q, skb);
-       tasklet_schedule(&hdev->cmd_task);
+       queue_work(hdev->workqueue, &hdev->cmd_work);
 
        return 0;
 }
@@ -1977,7 +1960,7 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
                skb_shinfo(skb)->frag_list = NULL;
 
                /* Queue all fragments atomically */
-               spin_lock_bh(&queue->lock);
+               spin_lock(&queue->lock);
 
                __skb_queue_tail(queue, skb);
 
@@ -1995,7 +1978,7 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
                        __skb_queue_tail(queue, skb);
                } while (list);
 
-               spin_unlock_bh(&queue->lock);
+               spin_unlock(&queue->lock);
        }
 }
 
@@ -2012,7 +1995,7 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
 
        hci_queue_acl(conn, &chan->data_q, skb, flags);
 
-       tasklet_schedule(&hdev->tx_task);
+       queue_work(hdev->workqueue, &hdev->tx_work);
 }
 EXPORT_SYMBOL(hci_send_acl);
 
@@ -2035,7 +2018,7 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
        bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
 
        skb_queue_tail(&conn->data_q, skb);
-       tasklet_schedule(&hdev->tx_task);
+       queue_work(hdev->workqueue, &hdev->tx_work);
 }
 EXPORT_SYMBOL(hci_send_sco);
 
@@ -2050,7 +2033,10 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
 
        /* We don't have to lock device here. Connections are always
         * added and removed with TX task disabled. */
-       list_for_each_entry(c, &h->list, list) {
+
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &h->list, list) {
                if (c->type != type || skb_queue_empty(&c->data_q))
                        continue;
 
@@ -2068,6 +2054,8 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
                        break;
        }
 
+       rcu_read_unlock();
+
        if (conn) {
                int cnt, q;
 
@@ -2103,14 +2091,18 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
 
        BT_ERR("%s link tx timeout", hdev->name);
 
+       rcu_read_lock();
+
        /* Kill stalled connections */
-       list_for_each_entry(c, &h->list, list) {
+       list_for_each_entry_rcu(c, &h->list, list) {
                if (c->type == type && c->sent) {
                        BT_ERR("%s killing stalled connection %s",
                                hdev->name, batostr(&c->dst));
                        hci_acl_disconn(c, 0x13);
                }
        }
+
+       rcu_read_unlock();
 }
 
 static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
@@ -2124,8 +2116,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
 
        BT_DBG("%s", hdev->name);
 
-       list_for_each_entry(conn, &h->list, list) {
-               struct hci_chan_hash *ch;
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(conn, &h->list, list) {
                struct hci_chan *tmp;
 
                if (conn->type != type)
@@ -2136,9 +2129,7 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
 
                conn_num++;
 
-               ch = &conn->chan_hash;
-
-               list_for_each_entry(tmp, &ch->list, list) {
+               list_for_each_entry_rcu(tmp, &conn->chan_list, list) {
                        struct sk_buff *skb;
 
                        if (skb_queue_empty(&tmp->data_q))
@@ -2166,6 +2157,8 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
                        break;
        }
 
+       rcu_read_unlock();
+
        if (!chan)
                return NULL;
 
@@ -2199,8 +2192,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
 
        BT_DBG("%s", hdev->name);
 
-       list_for_each_entry(conn, &h->list, list) {
-               struct hci_chan_hash *ch;
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(conn, &h->list, list) {
                struct hci_chan *chan;
 
                if (conn->type != type)
@@ -2211,8 +2205,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
 
                num++;
 
-               ch = &conn->chan_hash;
-               list_for_each_entry(chan, &ch->list, list) {
+               list_for_each_entry_rcu(chan, &conn->chan_list, list) {
                        struct sk_buff *skb;
 
                        if (chan->sent) {
@@ -2236,6 +2229,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
                if (hci_conn_num(hdev, type) == num)
                        break;
        }
+
+       rcu_read_unlock();
+
 }
 
 static inline void hci_sched_acl(struct hci_dev *hdev)
@@ -2386,13 +2382,11 @@ static inline void hci_sched_le(struct hci_dev *hdev)
                hci_prio_recalculate(hdev, LE_LINK);
 }
 
-static void hci_tx_task(unsigned long arg)
+static void hci_tx_work(struct work_struct *work)
 {
-       struct hci_dev *hdev = (struct hci_dev *) arg;
+       struct hci_dev *hdev = container_of(work, struct hci_dev, tx_work);
        struct sk_buff *skb;
 
-       read_lock(&hci_task_lock);
-
        BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
                hdev->sco_cnt, hdev->le_cnt);
 
@@ -2409,8 +2403,6 @@ static void hci_tx_task(unsigned long arg)
        /* Send next queued raw (unknown type) packet */
        while ((skb = skb_dequeue(&hdev->raw_q)))
                hci_send_frame(skb);
-
-       read_unlock(&hci_task_lock);
 }
 
 /* ----- HCI RX task (incoming data processing) ----- */
@@ -2437,16 +2429,11 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_unlock(hdev);
 
        if (conn) {
-               register struct hci_proto *hp;
-
-               hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
+               hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
 
                /* Send to upper protocol */
-               hp = hci_proto[HCI_PROTO_L2CAP];
-               if (hp && hp->recv_acldata) {
-                       hp->recv_acldata(conn, skb, flags);
-                       return;
-               }
+               l2cap_recv_acldata(conn, skb, flags);
+               return;
        } else {
                BT_ERR("%s ACL packet for unknown connection handle %d",
                        hdev->name, handle);
@@ -2475,14 +2462,9 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_unlock(hdev);
 
        if (conn) {
-               register struct hci_proto *hp;
-
                /* Send to upper protocol */
-               hp = hci_proto[HCI_PROTO_SCO];
-               if (hp && hp->recv_scodata) {
-                       hp->recv_scodata(conn, skb);
-                       return;
-               }
+               sco_recv_scodata(conn, skb);
+               return;
        } else {
                BT_ERR("%s SCO packet for unknown connection handle %d",
                        hdev->name, handle);
@@ -2491,15 +2473,13 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        kfree_skb(skb);
 }
 
-static void hci_rx_task(unsigned long arg)
+static void hci_rx_work(struct work_struct *work)
 {
-       struct hci_dev *hdev = (struct hci_dev *) arg;
+       struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
        struct sk_buff *skb;
 
        BT_DBG("%s", hdev->name);
 
-       read_lock(&hci_task_lock);
-
        while ((skb = skb_dequeue(&hdev->rx_q))) {
                if (atomic_read(&hdev->promisc)) {
                        /* Send copy to the sockets */
@@ -2524,6 +2504,7 @@ static void hci_rx_task(unsigned long arg)
                /* Process frame */
                switch (bt_cb(skb)->pkt_type) {
                case HCI_EVENT_PKT:
+                       BT_DBG("%s Event packet", hdev->name);
                        hci_event_packet(hdev, skb);
                        break;
 
@@ -2542,13 +2523,11 @@ static void hci_rx_task(unsigned long arg)
                        break;
                }
        }
-
-       read_unlock(&hci_task_lock);
 }
 
-static void hci_cmd_task(unsigned long arg)
+static void hci_cmd_work(struct work_struct *work)
 {
-       struct hci_dev *hdev = (struct hci_dev *) arg;
+       struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
        struct sk_buff *skb;
 
        BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
@@ -2572,7 +2551,7 @@ static void hci_cmd_task(unsigned long arg)
                                  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
                } else {
                        skb_queue_head(&hdev->cmd_q, skb);
-                       tasklet_schedule(&hdev->cmd_task);
+                       queue_work(hdev->workqueue, &hdev->cmd_work);
                }
        }
 }
index 918dc09164bac5ca8a372d6cf81533a5cc2d54a9..4221bd256bddfd89e147f1605f0dd334aa042ea6 100644 (file)
@@ -378,11 +378,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
 
-       if (hdev->notify) {
-               tasklet_disable(&hdev->tx_task);
+       if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
-               tasklet_enable(&hdev->tx_task);
-       }
 }
 
 static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
@@ -409,11 +406,8 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb
 
        BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
 
-       if (hdev->notify) {
-               tasklet_disable(&hdev->tx_task);
+       if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
-               tasklet_enable(&hdev->tx_task);
-       }
 }
 
 static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
@@ -562,6 +556,9 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
 static void hci_setup(struct hci_dev *hdev)
 {
+       if (hdev->dev_type != HCI_BREDR)
+               return;
+
        hci_setup_event_mask(hdev);
 
        if (hdev->hci_ver > BLUETOOTH_VER_1_1)
@@ -773,6 +770,28 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
        hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status);
 }
 
+static void hci_cc_read_data_block_size(struct hci_dev *hdev,
+                                                       struct sk_buff *skb)
+{
+       struct hci_rp_read_data_block_size *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+       if (rp->status)
+               return;
+
+       hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
+       hdev->block_len = __le16_to_cpu(rp->block_len);
+       hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
+
+       hdev->block_cnt = hdev->num_blocks;
+
+       BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
+                                       hdev->block_cnt, hdev->block_len);
+
+       hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status);
+}
+
 static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -1014,18 +1033,28 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
        if (!cp)
                return;
 
-       if (cp->enable == 0x01) {
+       switch (cp->enable) {
+       case LE_SCANNING_ENABLED:
                set_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
-               del_timer(&hdev->adv_timer);
+               cancel_delayed_work_sync(&hdev->adv_work);
 
                hci_dev_lock(hdev);
                hci_adv_entries_clear(hdev);
                hci_dev_unlock(hdev);
-       } else if (cp->enable == 0x00) {
+               break;
+
+       case LE_SCANNING_DISABLED:
                clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
-               mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+               cancel_delayed_work_sync(&hdev->adv_work);
+               queue_delayed_work(hdev->workqueue, &hdev->adv_work,
+                                                jiffies + ADV_CLEAR_TIMEOUT);
+               break;
+
+       default:
+               BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
+               break;
        }
 }
 
@@ -2022,6 +2051,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_read_bd_addr(hdev, skb);
                break;
 
+       case HCI_OP_READ_DATA_BLOCK_SIZE:
+               hci_cc_read_data_block_size(hdev, skb);
+               break;
+
        case HCI_OP_WRITE_CA_TIMEOUT:
                hci_cc_write_ca_timeout(hdev, skb);
                break;
@@ -2116,7 +2149,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
        if (ev->ncmd) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
-                       tasklet_schedule(&hdev->cmd_task);
+                       queue_work(hdev->workqueue, &hdev->cmd_work);
        }
 }
 
@@ -2198,7 +2231,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
-                       tasklet_schedule(&hdev->cmd_task);
+                       queue_work(hdev->workqueue, &hdev->cmd_work);
        }
 }
 
@@ -2231,56 +2264,68 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
 static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
-       __le16 *ptr;
        int i;
 
        skb_pull(skb, sizeof(*ev));
 
        BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
 
+       if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
+               BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode);
+               return;
+       }
+
        if (skb->len < ev->num_hndl * 4) {
                BT_DBG("%s bad parameters", hdev->name);
                return;
        }
 
-       tasklet_disable(&hdev->tx_task);
-
-       for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) {
+       for (i = 0; i < ev->num_hndl; i++) {
+               struct hci_comp_pkts_info *info = &ev->handles[i];
                struct hci_conn *conn;
                __u16  handle, count;
 
-               handle = get_unaligned_le16(ptr++);
-               count  = get_unaligned_le16(ptr++);
+               handle = __le16_to_cpu(info->handle);
+               count  = __le16_to_cpu(info->count);
 
                conn = hci_conn_hash_lookup_handle(hdev, handle);
-               if (conn) {
-                       conn->sent -= count;
-
-                       if (conn->type == ACL_LINK) {
+               if (!conn)
+                       continue;
+
+               conn->sent -= count;
+
+               switch (conn->type) {
+               case ACL_LINK:
+                       hdev->acl_cnt += count;
+                       if (hdev->acl_cnt > hdev->acl_pkts)
+                               hdev->acl_cnt = hdev->acl_pkts;
+                       break;
+
+               case LE_LINK:
+                       if (hdev->le_pkts) {
+                               hdev->le_cnt += count;
+                               if (hdev->le_cnt > hdev->le_pkts)
+                                       hdev->le_cnt = hdev->le_pkts;
+                       } else {
                                hdev->acl_cnt += count;
                                if (hdev->acl_cnt > hdev->acl_pkts)
                                        hdev->acl_cnt = hdev->acl_pkts;
-                       } else if (conn->type == LE_LINK) {
-                               if (hdev->le_pkts) {
-                                       hdev->le_cnt += count;
-                                       if (hdev->le_cnt > hdev->le_pkts)
-                                               hdev->le_cnt = hdev->le_pkts;
-                               } else {
-                                       hdev->acl_cnt += count;
-                                       if (hdev->acl_cnt > hdev->acl_pkts)
-                                               hdev->acl_cnt = hdev->acl_pkts;
-                               }
-                       } else {
-                               hdev->sco_cnt += count;
-                               if (hdev->sco_cnt > hdev->sco_pkts)
-                                       hdev->sco_cnt = hdev->sco_pkts;
                        }
+                       break;
+
+               case SCO_LINK:
+                       hdev->sco_cnt += count;
+                       if (hdev->sco_cnt > hdev->sco_pkts)
+                               hdev->sco_cnt = hdev->sco_pkts;
+                       break;
+
+               default:
+                       BT_ERR("Unknown type %d conn %p", conn->type, conn);
+                       break;
                }
        }
 
-       tasklet_schedule(&hdev->tx_task);
-
-       tasklet_enable(&hdev->tx_task);
+       queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
 static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
index 78746cfa16598adf3109669ac526f0224e0ffd8f..6d94616af3129b3519c914c3458eb30cad40de05 100644 (file)
@@ -188,11 +188,11 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_blacklist_add(hdev, &bdaddr);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return err;
 }
@@ -205,11 +205,11 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_blacklist_del(hdev, &bdaddr);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return err;
 }
@@ -343,8 +343,11 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
        if (haddr.hci_channel > HCI_CHANNEL_CONTROL)
                return -EINVAL;
 
-       if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt)
-               return -EINVAL;
+       if (haddr.hci_channel == HCI_CHANNEL_CONTROL) {
+               if (!enable_mgmt)
+                       return -EINVAL;
+               set_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags);
+       }
 
        lock_sock(sk);
 
@@ -535,10 +538,10 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
 
                if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
                        skb_queue_tail(&hdev->raw_q, skb);
-                       tasklet_schedule(&hdev->tx_task);
+                       queue_work(hdev->workqueue, &hdev->tx_work);
                } else {
                        skb_queue_tail(&hdev->cmd_q, skb);
-                       tasklet_schedule(&hdev->cmd_task);
+                       queue_work(hdev->workqueue, &hdev->cmd_work);
                }
        } else {
                if (!capable(CAP_NET_RAW)) {
@@ -547,7 +550,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                skb_queue_tail(&hdev->raw_q, skb);
-               tasklet_schedule(&hdev->tx_task);
+               queue_work(hdev->workqueue, &hdev->tx_work);
        }
 
        err = len;
index c62d254a1379f5cf255b97863f6df4009ce4a7d4..52109561423514fcbd16e1c1895d2e9f7ee7a490 100644 (file)
@@ -89,11 +89,35 @@ static struct device_type bt_link = {
        .release = bt_link_release,
 };
 
-static void add_conn(struct work_struct *work)
+/*
+ * The rfcomm tty device will possibly retain even when conn
+ * is down, and sysfs doesn't support move zombie device,
+ * so we should move the device before conn device is destroyed.
+ */
+static int __match_tty(struct device *dev, void *data)
+{
+       return !strncmp(dev_name(dev), "rfcomm", 6);
+}
+
+void hci_conn_init_sysfs(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       BT_DBG("conn %p", conn);
+
+       conn->dev.type = &bt_link;
+       conn->dev.class = bt_class;
+       conn->dev.parent = &hdev->dev;
+
+       device_initialize(&conn->dev);
+}
+
+void hci_conn_add_sysfs(struct hci_conn *conn)
 {
-       struct hci_conn *conn = container_of(work, struct hci_conn, work_add);
        struct hci_dev *hdev = conn->hdev;
 
+       BT_DBG("conn %p", conn);
+
        dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
 
        dev_set_drvdata(&conn->dev, conn);
@@ -106,19 +130,8 @@ static void add_conn(struct work_struct *work)
        hci_dev_hold(hdev);
 }
 
-/*
- * The rfcomm tty device will possibly retain even when conn
- * is down, and sysfs doesn't support move zombie device,
- * so we should move the device before conn device is destroyed.
- */
-static int __match_tty(struct device *dev, void *data)
-{
-       return !strncmp(dev_name(dev), "rfcomm", 6);
-}
-
-static void del_conn(struct work_struct *work)
+void hci_conn_del_sysfs(struct hci_conn *conn)
 {
-       struct hci_conn *conn = container_of(work, struct hci_conn, work_del);
        struct hci_dev *hdev = conn->hdev;
 
        if (!device_is_registered(&conn->dev))
@@ -140,36 +153,6 @@ static void del_conn(struct work_struct *work)
        hci_dev_put(hdev);
 }
 
-void hci_conn_init_sysfs(struct hci_conn *conn)
-{
-       struct hci_dev *hdev = conn->hdev;
-
-       BT_DBG("conn %p", conn);
-
-       conn->dev.type = &bt_link;
-       conn->dev.class = bt_class;
-       conn->dev.parent = &hdev->dev;
-
-       device_initialize(&conn->dev);
-
-       INIT_WORK(&conn->work_add, add_conn);
-       INIT_WORK(&conn->work_del, del_conn);
-}
-
-void hci_conn_add_sysfs(struct hci_conn *conn)
-{
-       BT_DBG("conn %p", conn);
-
-       queue_work(conn->hdev->workqueue, &conn->work_add);
-}
-
-void hci_conn_del_sysfs(struct hci_conn *conn)
-{
-       BT_DBG("conn %p", conn);
-
-       queue_work(conn->hdev->workqueue, &conn->work_del);
-}
-
 static inline char *host_bustostr(int bus)
 {
        switch (bus) {
@@ -403,7 +386,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
        struct inquiry_cache *cache = &hdev->inq_cache;
        struct inquiry_entry *e;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        for (e = cache->list; e; e = e->next) {
                struct inquiry_data *data = &e->data;
@@ -416,7 +399,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
                           data->rssi, data->ssp_mode, e->timestamp);
        }
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return 0;
 }
@@ -438,12 +421,12 @@ static int blacklist_show(struct seq_file *f, void *p)
        struct hci_dev *hdev = f->private;
        struct bdaddr_list *b;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        list_for_each_entry(b, &hdev->blacklist, list)
                seq_printf(f, "%s\n", batostr(&b->bdaddr));
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return 0;
 }
@@ -482,12 +465,12 @@ static int uuids_show(struct seq_file *f, void *p)
        struct hci_dev *hdev = f->private;
        struct bt_uuid *uuid;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        list_for_each_entry(uuid, &hdev->uuids, list)
                print_bt_uuid(f, uuid->uuid);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return 0;
 }
@@ -508,11 +491,11 @@ static int auto_accept_delay_set(void *data, u64 val)
 {
        struct hci_dev *hdev = data;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        hdev->auto_accept_delay = val;
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return 0;
 }
@@ -521,11 +504,11 @@ static int auto_accept_delay_get(void *data, u64 *val)
 {
        struct hci_dev *hdev = data;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        *val = hdev->auto_accept_delay;
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        return 0;
 }
index 86a91543172a7e1ddcd88538d13c4750599bfdbb..4deaca78e91ea1853027db58f05441e8e8a3975f 100644 (file)
@@ -1,6 +1,6 @@
 config BT_HIDP
        tristate "HIDP protocol support"
-       depends on BT && BT_L2CAP && INPUT && HID_SUPPORT
+       depends on BT && INPUT && HID_SUPPORT
        select HID
        help
          HIDP (Human Interface Device Protocol) is a transport layer
index 3c2d888925d7a8436b19ef8d1562fe9a7943a780..d478be11d562995ae08c65bc8198c187ee686d61 100644 (file)
@@ -795,11 +795,11 @@ static struct hci_conn *hidp_get_connection(struct hidp_session *session)
        if (!hdev)
                return NULL;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
        if (conn)
                hci_conn_hold_device(conn);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
 
        hci_dev_put(hdev);
 
index 9bc22e4c4c616249196ebc1b14fb2209c8e7a44f..aa78d8c4b93be75f630e1389b4886ffdd4ab3623 100644 (file)
@@ -3,6 +3,7 @@
    Copyright (C) 2000-2001 Qualcomm Incorporated
    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
    Copyright (C) 2010 Google Inc.
+   Copyright (C) 2011 ProFUSION Embedded Systems
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -76,37 +77,38 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP channels ---- */
 
-static inline void chan_hold(struct l2cap_chan *c)
-{
-       atomic_inc(&c->refcnt);
-}
-
-static inline void chan_put(struct l2cap_chan *c)
-{
-       if (atomic_dec_and_test(&c->refcnt))
-               kfree(c);
-}
-
 static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
 {
-       struct l2cap_chan *c;
+       struct l2cap_chan *c, *r = NULL;
 
-       list_for_each_entry(c, &conn->chan_l, list) {
-               if (c->dcid == cid)
-                       return c;
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &conn->chan_l, list) {
+               if (c->dcid == cid) {
+                       r = c;
+                       break;
+               }
        }
-       return NULL;
+
+       rcu_read_unlock();
+       return r;
 }
 
 static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
 {
-       struct l2cap_chan *c;
+       struct l2cap_chan *c, *r = NULL;
 
-       list_for_each_entry(c, &conn->chan_l, list) {
-               if (c->scid == cid)
-                       return c;
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &conn->chan_l, list) {
+               if (c->scid == cid) {
+                       r = c;
+                       break;
+               }
        }
-       return NULL;
+
+       rcu_read_unlock();
+       return r;
 }
 
 /* Find channel with given SCID.
@@ -115,34 +117,36 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci
 {
        struct l2cap_chan *c;
 
-       read_lock(&conn->chan_lock);
        c = __l2cap_get_chan_by_scid(conn, cid);
        if (c)
-               bh_lock_sock(c->sk);
-       read_unlock(&conn->chan_lock);
+               lock_sock(c->sk);
        return c;
 }
 
 static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
 {
-       struct l2cap_chan *c;
+       struct l2cap_chan *c, *r = NULL;
 
-       list_for_each_entry(c, &conn->chan_l, list) {
-               if (c->ident == ident)
-                       return c;
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(c, &conn->chan_l, list) {
+               if (c->ident == ident) {
+                       r = c;
+                       break;
+               }
        }
-       return NULL;
+
+       rcu_read_unlock();
+       return r;
 }
 
 static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
 {
        struct l2cap_chan *c;
 
-       read_lock(&conn->chan_lock);
        c = __l2cap_get_chan_by_ident(conn, ident);
        if (c)
-               bh_lock_sock(c->sk);
-       read_unlock(&conn->chan_lock);
+               lock_sock(c->sk);
        return c;
 }
 
@@ -213,22 +217,6 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
        return 0;
 }
 
-static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
-{
-       BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
-
-       if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
-               chan_hold(chan);
-}
-
-static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
-{
-       BT_DBG("chan %p state %d", chan, chan->state);
-
-       if (timer_pending(timer) && del_timer(timer))
-               chan_put(chan);
-}
-
 static char *state_to_string(int state)
 {
        switch(state) {
@@ -264,23 +252,16 @@ static void l2cap_state_change(struct l2cap_chan *chan, int state)
        chan->ops->state_change(chan->data, state);
 }
 
-static void l2cap_chan_timeout(unsigned long arg)
+static void l2cap_chan_timeout(struct work_struct *work)
 {
-       struct l2cap_chan *chan = (struct l2cap_chan *) arg;
+       struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
+                                                       chan_timer.work);
        struct sock *sk = chan->sk;
        int reason;
 
        BT_DBG("chan %p state %d", chan, chan->state);
 
-       bh_lock_sock(sk);
-
-       if (sock_owned_by_user(sk)) {
-               /* sk is owned by user. Try again later */
-               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-               bh_unlock_sock(sk);
-               chan_put(chan);
-               return;
-       }
+       lock_sock(sk);
 
        if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
                reason = ECONNREFUSED;
@@ -292,10 +273,10 @@ static void l2cap_chan_timeout(unsigned long arg)
 
        l2cap_chan_close(chan, reason);
 
-       bh_unlock_sock(sk);
+       release_sock(sk);
 
        chan->ops->close(chan->data);
-       chan_put(chan);
+       l2cap_chan_put(chan);
 }
 
 struct l2cap_chan *l2cap_chan_create(struct sock *sk)
@@ -312,7 +293,7 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
        list_add(&chan->global_l, &chan_list);
        write_unlock_bh(&chan_list_lock);
 
-       setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
+       INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
 
        chan->state = BT_OPEN;
 
@@ -329,10 +310,10 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
        list_del(&chan->global_l);
        write_unlock_bh(&chan_list_lock);
 
-       chan_put(chan);
+       l2cap_chan_put(chan);
 }
 
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
+static 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,
                        chan->psm, chan->dcid);
@@ -371,9 +352,9 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
        chan->local_acc_lat     = L2CAP_DEFAULT_ACC_LAT;
        chan->local_flush_to    = L2CAP_DEFAULT_FLUSH_TO;
 
-       chan_hold(chan);
+       l2cap_chan_hold(chan);
 
-       list_add(&chan->list, &conn->chan_l);
+       list_add_rcu(&chan->list, &conn->chan_l);
 }
 
 /* Delete channel.
@@ -390,10 +371,10 @@ static void l2cap_chan_del(struct l2cap_chan *chan, int err)
 
        if (conn) {
                /* Delete from channel list */
-               write_lock_bh(&conn->chan_lock);
-               list_del(&chan->list);
-               write_unlock_bh(&conn->chan_lock);
-               chan_put(chan);
+               list_del_rcu(&chan->list);
+               synchronize_rcu();
+
+               l2cap_chan_put(chan);
 
                chan->conn = NULL;
                hci_conn_put(conn->hcon);
@@ -707,7 +688,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
                conn->info_ident = l2cap_get_ident(conn);
 
-               mod_timer(&conn->info_timer, jiffies +
+               schedule_delayed_work(&conn->info_timer,
                                        msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
 
                l2cap_send_cmd(conn, conn->info_ident,
@@ -759,13 +740,13 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
 /* ---- L2CAP connections ---- */
 static void l2cap_conn_start(struct l2cap_conn *conn)
 {
-       struct l2cap_chan *chan, *tmp;
+       struct l2cap_chan *chan;
 
        BT_DBG("conn %p", conn);
 
-       read_lock(&conn->chan_lock);
+       rcu_read_lock();
 
-       list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
 
                bh_lock_sock(sk);
@@ -789,9 +770,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                        &chan->conf_state)) {
                                /* l2cap_chan_close() calls list_del(chan)
                                 * so release the lock */
-                               read_unlock(&conn->chan_lock);
                                l2cap_chan_close(chan, ECONNRESET);
-                               read_lock(&conn->chan_lock);
                                bh_unlock_sock(sk);
                                continue;
                        }
@@ -847,7 +826,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&conn->chan_lock);
+       rcu_read_unlock();
 }
 
 /* Find socket with cid and source bdaddr.
@@ -898,7 +877,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        parent = pchan->sk;
 
-       bh_lock_sock(parent);
+       lock_sock(parent);
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
@@ -912,8 +891,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        sk = chan->sk;
 
-       write_lock_bh(&conn->chan_lock);
-
        hci_conn_hold(conn->hcon);
 
        bacpy(&bt_sk(sk)->src, conn->src);
@@ -921,17 +898,15 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        bt_accept_enqueue(parent, sk);
 
-       __l2cap_chan_add(conn, chan);
+       l2cap_chan_add(conn, chan);
 
        __set_chan_timer(chan, sk->sk_sndtimeo);
 
        l2cap_state_change(chan, BT_CONNECTED);
        parent->sk_data_ready(parent, 0);
 
-       write_unlock_bh(&conn->chan_lock);
-
 clean:
-       bh_unlock_sock(parent);
+       release_sock(parent);
 }
 
 static void l2cap_chan_ready(struct sock *sk)
@@ -963,9 +938,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
        if (conn->hcon->out && conn->hcon->type == LE_LINK)
                smp_conn_security(conn, conn->hcon->pending_sec_level);
 
-       read_lock(&conn->chan_lock);
+       rcu_read_lock();
 
-       list_for_each_entry(chan, &conn->chan_l, list) {
+       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
 
                bh_lock_sock(sk);
@@ -985,7 +960,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&conn->chan_lock);
+       rcu_read_unlock();
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
@@ -995,21 +970,22 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
 
        BT_DBG("conn %p", conn);
 
-       read_lock(&conn->chan_lock);
+       rcu_read_lock();
 
-       list_for_each_entry(chan, &conn->chan_l, list) {
+       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
 
                if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
                        sk->sk_err = err;
        }
 
-       read_unlock(&conn->chan_lock);
+       rcu_read_unlock();
 }
 
-static void l2cap_info_timeout(unsigned long arg)
+static void l2cap_info_timeout(struct work_struct *work)
 {
-       struct l2cap_conn *conn = (void *) arg;
+       struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
+                                                       info_timer.work);
 
        conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
        conn->info_ident = 0;
@@ -1033,19 +1009,19 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        /* Kill channels */
        list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
                sk = chan->sk;
-               bh_lock_sock(sk);
+               lock_sock(sk);
                l2cap_chan_del(chan, err);
-               bh_unlock_sock(sk);
+               release_sock(sk);
                chan->ops->close(chan->data);
        }
 
        hci_chan_del(conn->hchan);
 
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-               del_timer_sync(&conn->info_timer);
+               __cancel_delayed_work(&conn->info_timer);
 
        if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
-               del_timer(&conn->security_timer);
+               __cancel_delayed_work(&conn->security_timer);
                smp_chan_destroy(conn);
        }
 
@@ -1053,9 +1029,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        kfree(conn);
 }
 
-static void security_timeout(unsigned long arg)
+static void security_timeout(struct work_struct *work)
 {
-       struct l2cap_conn *conn = (void *) arg;
+       struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
+                                               security_timer.work);
 
        l2cap_conn_del(conn->hcon, ETIMEDOUT);
 }
@@ -1095,29 +1072,19 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
        conn->feat_mask = 0;
 
        spin_lock_init(&conn->lock);
-       rwlock_init(&conn->chan_lock);
 
        INIT_LIST_HEAD(&conn->chan_l);
 
        if (hcon->type == LE_LINK)
-               setup_timer(&conn->security_timer, security_timeout,
-                                               (unsigned long) conn);
+               INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
        else
-               setup_timer(&conn->info_timer, l2cap_info_timeout,
-                                               (unsigned long) conn);
+               INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
 
        conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
 
        return conn;
 }
 
-static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
-{
-       write_lock_bh(&conn->chan_lock);
-       __l2cap_chan_add(conn, chan);
-       write_unlock_bh(&conn->chan_lock);
-}
-
 /* ---- Socket interface ---- */
 
 /* Find socket with psm and source bdaddr.
@@ -1153,11 +1120,10 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr
        return c1;
 }
 
-int l2cap_chan_connect(struct l2cap_chan *chan)
+inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
 {
        struct sock *sk = chan->sk;
        bdaddr_t *src = &bt_sk(sk)->src;
-       bdaddr_t *dst = &bt_sk(sk)->dst;
        struct l2cap_conn *conn;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
@@ -1171,7 +1137,62 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
        if (!hdev)
                return -EHOSTUNREACH;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
+
+       lock_sock(sk);
+
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
+                                       chan->chan_type != L2CAP_CHAN_RAW) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       switch (chan->mode) {
+       case L2CAP_MODE_BASIC:
+               break;
+       case L2CAP_MODE_ERTM:
+       case L2CAP_MODE_STREAMING:
+               if (!disable_ertm)
+                       break;
+               /* fall through */
+       default:
+               err = -ENOTSUPP;
+               goto done;
+       }
+
+       switch (sk->sk_state) {
+       case BT_CONNECT:
+       case BT_CONNECT2:
+       case BT_CONFIG:
+               /* Already connecting */
+               err = 0;
+               goto done;
+
+       case BT_CONNECTED:
+               /* Already connected */
+               err = -EISCONN;
+               goto done;
+
+       case BT_OPEN:
+       case BT_BOUND:
+               /* Can connect */
+               break;
+
+       default:
+               err = -EBADFD;
+               goto done;
+       }
+
+       /* Set destination address and psm */
+       bacpy(&bt_sk(sk)->dst, src);
+       chan->psm = psm;
+       chan->dcid = cid;
 
        auth_type = l2cap_get_auth_type(chan);
 
@@ -1214,7 +1235,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
        err = 0;
 
 done:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
        return err;
 }
@@ -1251,17 +1272,18 @@ int __l2cap_wait_ack(struct sock *sk)
        return err;
 }
 
-static void l2cap_monitor_timeout(unsigned long arg)
+static void l2cap_monitor_timeout(struct work_struct *work)
 {
-       struct l2cap_chan *chan = (void *) arg;
+       struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
+                                                       monitor_timer.work);
        struct sock *sk = chan->sk;
 
        BT_DBG("chan %p", chan);
 
-       bh_lock_sock(sk);
+       lock_sock(sk);
        if (chan->retry_count >= chan->remote_max_tx) {
                l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
-               bh_unlock_sock(sk);
+               release_sock(sk);
                return;
        }
 
@@ -1269,24 +1291,25 @@ static void l2cap_monitor_timeout(unsigned long arg)
        __set_monitor_timer(chan);
 
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
-       bh_unlock_sock(sk);
+       release_sock(sk);
 }
 
-static void l2cap_retrans_timeout(unsigned long arg)
+static void l2cap_retrans_timeout(struct work_struct *work)
 {
-       struct l2cap_chan *chan = (void *) arg;
+       struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
+                                                       retrans_timer.work);
        struct sock *sk = chan->sk;
 
        BT_DBG("chan %p", chan);
 
-       bh_lock_sock(sk);
+       lock_sock(sk);
        chan->retry_count = 1;
        __set_monitor_timer(chan);
 
        set_bit(CONN_WAIT_F, &chan->conn_state);
 
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
-       bh_unlock_sock(sk);
+       release_sock(sk);
 }
 
 static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
@@ -1778,8 +1801,9 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 
        BT_DBG("conn %p", conn);
 
-       read_lock(&conn->chan_lock);
-       list_for_each_entry(chan, &conn->chan_l, list) {
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
                if (chan->chan_type != L2CAP_CHAN_RAW)
                        continue;
@@ -1794,7 +1818,8 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
                if (chan->ops->recv(chan->data, nskb))
                        kfree_skb(nskb);
        }
-       read_unlock(&conn->chan_lock);
+
+       rcu_read_unlock();
 }
 
 /* ---- L2CAP signalling commands ---- */
@@ -1955,37 +1980,33 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
                                                        (unsigned long) &efs);
 }
 
-static void l2cap_ack_timeout(unsigned long arg)
+static void l2cap_ack_timeout(struct work_struct *work)
 {
-       struct l2cap_chan *chan = (void *) arg;
+       struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
+                                                       ack_timer.work);
 
-       bh_lock_sock(chan->sk);
+       BT_DBG("chan %p", chan);
+
+       lock_sock(chan->sk);
        l2cap_send_ack(chan);
-       bh_unlock_sock(chan->sk);
+       release_sock(chan->sk);
 }
 
 static inline void l2cap_ertm_init(struct l2cap_chan *chan)
 {
-       struct sock *sk = chan->sk;
-
        chan->expected_ack_seq = 0;
        chan->unacked_frames = 0;
        chan->buffer_seq = 0;
        chan->num_acked = 0;
        chan->frames_sent = 0;
 
-       setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
-                                                       (unsigned long) chan);
-       setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
-                                                       (unsigned long) chan);
-       setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
+       INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
+       INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
+       INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
 
        skb_queue_head_init(&chan->srej_q);
 
        INIT_LIST_HEAD(&chan->srej_l);
-
-
-       sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
 }
 
 static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
@@ -2553,7 +2574,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
                                        cmd->ident == conn->info_ident) {
-               del_timer(&conn->info_timer);
+               __cancel_delayed_work(&conn->info_timer);
 
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
                conn->info_ident = 0;
@@ -2586,7 +2607,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        parent = pchan->sk;
 
-       bh_lock_sock(parent);
+       lock_sock(parent);
 
        /* Check if the ACL is secure enough (if not SDP) */
        if (psm != cpu_to_le16(0x0001) &&
@@ -2610,11 +2631,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        sk = chan->sk;
 
-       write_lock_bh(&conn->chan_lock);
-
        /* Check if we already have channel with that dcid */
        if (__l2cap_get_chan_by_dcid(conn, scid)) {
-               write_unlock_bh(&conn->chan_lock);
                sock_set_flag(sk, SOCK_ZAPPED);
                chan->ops->close(chan->data);
                goto response;
@@ -2629,7 +2647,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        bt_accept_enqueue(parent, sk);
 
-       __l2cap_chan_add(conn, chan);
+       l2cap_chan_add(conn, chan);
 
        dcid = chan->scid;
 
@@ -2660,10 +2678,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                status = L2CAP_CS_NO_INFO;
        }
 
-       write_unlock_bh(&conn->chan_lock);
-
 response:
-       bh_unlock_sock(parent);
+       release_sock(parent);
 
 sendresp:
        rsp.scid   = cpu_to_le16(scid);
@@ -2679,7 +2695,7 @@ sendresp:
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
                conn->info_ident = l2cap_get_ident(conn);
 
-               mod_timer(&conn->info_timer, jiffies +
+               schedule_delayed_work(&conn->info_timer,
                                        msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
 
                l2cap_send_cmd(conn, conn->info_ident,
@@ -2745,19 +2761,11 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                break;
 
        default:
-               /* don't delete l2cap channel if sk is owned by user */
-               if (sock_owned_by_user(sk)) {
-                       l2cap_state_change(chan, BT_DISCONN);
-                       __clear_chan_timer(chan);
-                       __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-                       break;
-               }
-
                l2cap_chan_del(chan, ECONNREFUSED);
                break;
        }
 
-       bh_unlock_sock(sk);
+       release_sock(sk);
        return 0;
 }
 
@@ -2879,7 +2887,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        }
 
 unlock:
-       bh_unlock_sock(sk);
+       release_sock(sk);
        return 0;
 }
 
@@ -2986,7 +2994,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        }
 
 done:
-       bh_unlock_sock(sk);
+       release_sock(sk);
        return 0;
 }
 
@@ -3015,17 +3023,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
        sk->sk_shutdown = SHUTDOWN_MASK;
 
-       /* don't delete l2cap channel if sk is owned by user */
-       if (sock_owned_by_user(sk)) {
-               l2cap_state_change(chan, BT_DISCONN);
-               __clear_chan_timer(chan);
-               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-               bh_unlock_sock(sk);
-               return 0;
-       }
-
        l2cap_chan_del(chan, ECONNRESET);
-       bh_unlock_sock(sk);
+       release_sock(sk);
 
        chan->ops->close(chan->data);
        return 0;
@@ -3049,17 +3048,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 
        sk = chan->sk;
 
-       /* don't delete l2cap channel if sk is owned by user */
-       if (sock_owned_by_user(sk)) {
-               l2cap_state_change(chan, BT_DISCONN);
-               __clear_chan_timer(chan);
-               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-               bh_unlock_sock(sk);
-               return 0;
-       }
-
        l2cap_chan_del(chan, 0);
-       bh_unlock_sock(sk);
+       release_sock(sk);
 
        chan->ops->close(chan->data);
        return 0;
@@ -3130,7 +3120,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
                        conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
                return 0;
 
-       del_timer(&conn->info_timer);
+       __cancel_delayed_work(&conn->info_timer);
 
        if (result != L2CAP_IR_SUCCESS) {
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
@@ -4247,12 +4237,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
                break;
 
        case L2CAP_MODE_ERTM:
-               if (!sock_owned_by_user(sk)) {
-                       l2cap_ertm_data_rcv(sk, skb);
-               } else {
-                       if (sk_add_backlog(sk, skb))
-                               goto drop;
-               }
+               l2cap_ertm_data_rcv(sk, skb);
 
                goto done;
 
@@ -4302,7 +4287,7 @@ drop:
 
 done:
        if (sk)
-               bh_unlock_sock(sk);
+               release_sock(sk);
 
        return 0;
 }
@@ -4318,7 +4303,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
 
        sk = chan->sk;
 
-       bh_lock_sock(sk);
+       lock_sock(sk);
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 
@@ -4336,7 +4321,7 @@ drop:
 
 done:
        if (sk)
-               bh_unlock_sock(sk);
+               release_sock(sk);
        return 0;
 }
 
@@ -4351,7 +4336,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct
 
        sk = chan->sk;
 
-       bh_lock_sock(sk);
+       lock_sock(sk);
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 
@@ -4369,7 +4354,7 @@ drop:
 
 done:
        if (sk)
-               bh_unlock_sock(sk);
+               release_sock(sk);
        return 0;
 }
 
@@ -4419,14 +4404,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 
 /* ---- L2CAP interface with lower layer (HCI) ---- */
 
-static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        int exact = 0, lm1 = 0, lm2 = 0;
        struct l2cap_chan *c;
 
-       if (type != ACL_LINK)
-               return -EINVAL;
-
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
        /* Find listening sockets and check their link_mode */
@@ -4453,15 +4435,12 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
        return exact ? lm1 : lm2;
 }
 
-static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
+int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
        struct l2cap_conn *conn;
 
        BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
-       if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
-               return -EINVAL;
-
        if (!status) {
                conn = l2cap_conn_add(hcon, status);
                if (conn)
@@ -4472,27 +4451,22 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
        return 0;
 }
 
-static int l2cap_disconn_ind(struct hci_conn *hcon)
+int l2cap_disconn_ind(struct hci_conn *hcon)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
 
        BT_DBG("hcon %p", hcon);
 
-       if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
+       if (!conn)
                return HCI_ERROR_REMOTE_USER_TERM;
-
        return conn->disc_reason;
 }
 
-static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
+int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
        BT_DBG("hcon %p reason %d", hcon, reason);
 
-       if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
-               return -EINVAL;
-
        l2cap_conn_del(hcon, bt_to_errno(reason));
-
        return 0;
 }
 
@@ -4513,7 +4487,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
        }
 }
 
-static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
+int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
        struct l2cap_chan *chan;
@@ -4525,12 +4499,12 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
        if (hcon->type == LE_LINK) {
                smp_distribute_keys(conn, 0);
-               del_timer(&conn->security_timer);
+               __cancel_delayed_work(&conn->security_timer);
        }
 
-       read_lock(&conn->chan_lock);
+       rcu_read_lock();
 
-       list_for_each_entry(chan, &conn->chan_l, list) {
+       list_for_each_entry_rcu(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
 
                bh_lock_sock(sk);
@@ -4608,12 +4582,12 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&conn->chan_lock);
+       rcu_read_unlock();
 
        return 0;
 }
 
-static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
 
@@ -4674,11 +4648,11 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
                                BT_ERR("Frame exceeding recv MTU (len %d, "
                                                        "MTU %d)", len,
                                                        chan->imtu);
-                               bh_unlock_sock(sk);
+                               release_sock(sk);
                                l2cap_conn_unreliable(conn, ECOMM);
                                goto drop;
                        }
-                       bh_unlock_sock(sk);
+                       release_sock(sk);
                }
 
                /* Allocate skb for the complete frame (with header) */
@@ -4760,17 +4734,6 @@ static const struct file_operations l2cap_debugfs_fops = {
 
 static struct dentry *l2cap_debugfs;
 
-static struct hci_proto l2cap_hci_proto = {
-       .name           = "L2CAP",
-       .id             = HCI_PROTO_L2CAP,
-       .connect_ind    = l2cap_connect_ind,
-       .connect_cfm    = l2cap_connect_cfm,
-       .disconn_ind    = l2cap_disconn_ind,
-       .disconn_cfm    = l2cap_disconn_cfm,
-       .security_cfm   = l2cap_security_cfm,
-       .recv_acldata   = l2cap_recv_acldata
-};
-
 int __init l2cap_init(void)
 {
        int err;
@@ -4779,13 +4742,6 @@ int __init l2cap_init(void)
        if (err < 0)
                return err;
 
-       err = hci_register_proto(&l2cap_hci_proto);
-       if (err < 0) {
-               BT_ERR("L2CAP protocol registration failed");
-               bt_sock_unregister(BTPROTO_L2CAP);
-               goto error;
-       }
-
        if (bt_debugfs) {
                l2cap_debugfs = debugfs_create_file("l2cap", 0444,
                                        bt_debugfs, NULL, &l2cap_debugfs_fops);
@@ -4794,19 +4750,11 @@ int __init l2cap_init(void)
        }
 
        return 0;
-
-error:
-       l2cap_cleanup_sockets();
-       return err;
 }
 
 void l2cap_exit(void)
 {
        debugfs_remove(l2cap_debugfs);
-
-       if (hci_unregister_proto(&l2cap_hci_proto) < 0)
-               BT_ERR("L2CAP protocol unregistration failed");
-
        l2cap_cleanup_sockets();
 }
 
index f73704321a77d0eaf74b3570da554855405a0358..9ca5616166f7ad911204044b4a0dec80d6b1e099 100644 (file)
@@ -3,6 +3,7 @@
    Copyright (C) 2000-2001 Qualcomm Incorporated
    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
    Copyright (C) 2010 Google Inc.
+   Copyright (C) 2011 ProFUSION Embedded Systems
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -122,70 +123,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
        if (la.l2_cid && la.l2_psm)
                return -EINVAL;
 
-       lock_sock(sk);
-
-       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED
-                       && !(la.l2_psm || la.l2_cid)) {
-               err = -EINVAL;
-               goto done;
-       }
-
-       switch (chan->mode) {
-       case L2CAP_MODE_BASIC:
-               break;
-       case L2CAP_MODE_ERTM:
-       case L2CAP_MODE_STREAMING:
-               if (!disable_ertm)
-                       break;
-               /* fall through */
-       default:
-               err = -ENOTSUPP;
-               goto done;
-       }
-
-       switch (sk->sk_state) {
-       case BT_CONNECT:
-       case BT_CONNECT2:
-       case BT_CONFIG:
-               /* Already connecting */
-               goto wait;
-
-       case BT_CONNECTED:
-               /* Already connected */
-               err = -EISCONN;
-               goto done;
-
-       case BT_OPEN:
-       case BT_BOUND:
-               /* Can connect */
-               break;
-
-       default:
-               err = -EBADFD;
-               goto done;
-       }
-
-       /* PSM must be odd and lsb of upper byte must be 0 */
-       if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && !la.l2_cid &&
-                                       chan->chan_type != L2CAP_CHAN_RAW) {
-               err = -EINVAL;
-               goto done;
-       }
-
-       /* Set destination address and psm */
-       bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
-       chan->psm = la.l2_psm;
-       chan->dcid = la.l2_cid;
-
-       err = l2cap_chan_connect(l2cap_pi(sk)->chan);
+       err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);
        if (err)
                goto done;
 
-wait:
        err = bt_sock_wait_state(sk, BT_CONNECTED,
                        sock_sndtimeo(sk, flags & O_NONBLOCK));
 done:
-       release_sock(sk);
+       if (sock_owned_by_user(sk))
+               release_sock(sk);
        return err;
 }
 
index 1ce549bae241809104194b8ed545a81c35821586..2540944d871ffa0946565d78b6d23a9503a7f1c2 100644 (file)
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/smp.h>
 
 #define MGMT_VERSION   0
 #define MGMT_REVISION  1
 
 #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
 
+#define SERVICE_CACHE_TIMEOUT (5 * 1000)
+
 struct pending_cmd {
        struct list_head list;
        u16 opcode;
@@ -243,6 +246,262 @@ static int read_index_list(struct sock *sk)
        return err;
 }
 
+static u32 get_supported_settings(struct hci_dev *hdev)
+{
+       u32 settings = 0;
+
+       settings |= MGMT_SETTING_POWERED;
+       settings |= MGMT_SETTING_CONNECTABLE;
+       settings |= MGMT_SETTING_FAST_CONNECTABLE;
+       settings |= MGMT_SETTING_DISCOVERABLE;
+       settings |= MGMT_SETTING_PAIRABLE;
+
+       if (hdev->features[6] & LMP_SIMPLE_PAIR)
+               settings |= MGMT_SETTING_SSP;
+
+       if (!(hdev->features[4] & LMP_NO_BREDR)) {
+               settings |= MGMT_SETTING_BREDR;
+               settings |= MGMT_SETTING_LINK_SECURITY;
+       }
+
+       if (hdev->features[4] & LMP_LE)
+               settings |= MGMT_SETTING_LE;
+
+       return settings;
+}
+
+static u32 get_current_settings(struct hci_dev *hdev)
+{
+       u32 settings = 0;
+
+       if (test_bit(HCI_UP, &hdev->flags))
+               settings |= MGMT_SETTING_POWERED;
+       else
+               return settings;
+
+       if (test_bit(HCI_PSCAN, &hdev->flags))
+               settings |= MGMT_SETTING_CONNECTABLE;
+
+       if (test_bit(HCI_ISCAN, &hdev->flags))
+               settings |= MGMT_SETTING_DISCOVERABLE;
+
+       if (test_bit(HCI_PAIRABLE, &hdev->flags))
+               settings |= MGMT_SETTING_PAIRABLE;
+
+       if (!(hdev->features[4] & LMP_NO_BREDR))
+               settings |= MGMT_SETTING_BREDR;
+
+       if (hdev->extfeatures[0] & LMP_HOST_LE)
+               settings |= MGMT_SETTING_LE;
+
+       if (test_bit(HCI_AUTH, &hdev->flags))
+               settings |= MGMT_SETTING_LINK_SECURITY;
+
+       if (hdev->ssp_mode > 0)
+               settings |= MGMT_SETTING_SSP;
+
+       return settings;
+}
+
+#define EIR_FLAGS              0x01 /* flags */
+#define EIR_UUID16_SOME                0x02 /* 16-bit UUID, more available */
+#define EIR_UUID16_ALL         0x03 /* 16-bit UUID, all listed */
+#define EIR_UUID32_SOME                0x04 /* 32-bit UUID, more available */
+#define EIR_UUID32_ALL         0x05 /* 32-bit UUID, all listed */
+#define EIR_UUID128_SOME       0x06 /* 128-bit UUID, more available */
+#define EIR_UUID128_ALL                0x07 /* 128-bit UUID, all listed */
+#define EIR_NAME_SHORT         0x08 /* shortened local name */
+#define EIR_NAME_COMPLETE      0x09 /* complete local name */
+#define EIR_TX_POWER           0x0A /* transmit power level */
+#define EIR_DEVICE_ID          0x10 /* device ID */
+
+#define PNP_INFO_SVCLASS_ID            0x1200
+
+static u8 bluetooth_base_uuid[] = {
+                       0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+                       0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static u16 get_uuid16(u8 *uuid128)
+{
+       u32 val;
+       int i;
+
+       for (i = 0; i < 12; i++) {
+               if (bluetooth_base_uuid[i] != uuid128[i])
+                       return 0;
+       }
+
+       memcpy(&val, &uuid128[12], 4);
+
+       val = le32_to_cpu(val);
+       if (val > 0xffff)
+               return 0;
+
+       return (u16) val;
+}
+
+static void create_eir(struct hci_dev *hdev, u8 *data)
+{
+       u8 *ptr = data;
+       u16 eir_len = 0;
+       u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
+       int i, truncated = 0;
+       struct bt_uuid *uuid;
+       size_t name_len;
+
+       name_len = strlen(hdev->dev_name);
+
+       if (name_len > 0) {
+               /* EIR Data type */
+               if (name_len > 48) {
+                       name_len = 48;
+                       ptr[1] = EIR_NAME_SHORT;
+               } else
+                       ptr[1] = EIR_NAME_COMPLETE;
+
+               /* EIR Data length */
+               ptr[0] = name_len + 1;
+
+               memcpy(ptr + 2, hdev->dev_name, name_len);
+
+               eir_len += (name_len + 2);
+               ptr += (name_len + 2);
+       }
+
+       memset(uuid16_list, 0, sizeof(uuid16_list));
+
+       /* Group all UUID16 types */
+       list_for_each_entry(uuid, &hdev->uuids, list) {
+               u16 uuid16;
+
+               uuid16 = get_uuid16(uuid->uuid);
+               if (uuid16 == 0)
+                       return;
+
+               if (uuid16 < 0x1100)
+                       continue;
+
+               if (uuid16 == PNP_INFO_SVCLASS_ID)
+                       continue;
+
+               /* Stop if not enough space to put next UUID */
+               if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
+                       truncated = 1;
+                       break;
+               }
+
+               /* Check for duplicates */
+               for (i = 0; uuid16_list[i] != 0; i++)
+                       if (uuid16_list[i] == uuid16)
+                               break;
+
+               if (uuid16_list[i] == 0) {
+                       uuid16_list[i] = uuid16;
+                       eir_len += sizeof(u16);
+               }
+       }
+
+       if (uuid16_list[0] != 0) {
+               u8 *length = ptr;
+
+               /* EIR Data type */
+               ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
+
+               ptr += 2;
+               eir_len += 2;
+
+               for (i = 0; uuid16_list[i] != 0; i++) {
+                       *ptr++ = (uuid16_list[i] & 0x00ff);
+                       *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
+               }
+
+               /* EIR Data length */
+               *length = (i * sizeof(u16)) + 1;
+       }
+}
+
+static int update_eir(struct hci_dev *hdev)
+{
+       struct hci_cp_write_eir cp;
+
+       if (!(hdev->features[6] & LMP_EXT_INQ))
+               return 0;
+
+       if (hdev->ssp_mode == 0)
+               return 0;
+
+       if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
+               return 0;
+
+       memset(&cp, 0, sizeof(cp));
+
+       create_eir(hdev, cp.data);
+
+       if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
+               return 0;
+
+       memcpy(hdev->eir, cp.data, sizeof(cp.data));
+
+       return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+}
+
+static u8 get_service_classes(struct hci_dev *hdev)
+{
+       struct bt_uuid *uuid;
+       u8 val = 0;
+
+       list_for_each_entry(uuid, &hdev->uuids, list)
+               val |= uuid->svc_hint;
+
+       return val;
+}
+
+static int update_class(struct hci_dev *hdev)
+{
+       u8 cod[3];
+
+       BT_DBG("%s", hdev->name);
+
+       if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
+               return 0;
+
+       cod[0] = hdev->minor_class;
+       cod[1] = hdev->major_class;
+       cod[2] = get_service_classes(hdev);
+
+       if (memcmp(cod, hdev->dev_class, 3) == 0)
+               return 0;
+
+       return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
+}
+
+static void service_cache_off(struct work_struct *work)
+{
+       struct hci_dev *hdev = container_of(work, struct hci_dev,
+                                                       service_cache.work);
+
+       if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags))
+               return;
+
+       hci_dev_lock(hdev);
+
+       update_eir(hdev);
+       update_class(hdev);
+
+       hci_dev_unlock(hdev);
+}
+
+static void mgmt_init_hdev(struct hci_dev *hdev)
+{
+       if (!test_and_set_bit(HCI_MGMT, &hdev->flags))
+               INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
+
+       if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->flags))
+               schedule_delayed_work(&hdev->service_cache,
+                               msecs_to_jiffies(SERVICE_CACHE_TIMEOUT));
+}
+
 static int read_controller_info(struct sock *sk, u16 index)
 {
        struct mgmt_rp_read_info rp;
@@ -258,36 +517,27 @@ static int read_controller_info(struct sock *sk, u16 index)
        if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
                cancel_delayed_work_sync(&hdev->power_off);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
-       set_bit(HCI_MGMT, &hdev->flags);
+       if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
+               mgmt_init_hdev(hdev);
 
        memset(&rp, 0, sizeof(rp));
 
-       rp.type = hdev->dev_type;
+       bacpy(&rp.bdaddr, &hdev->bdaddr);
 
-       rp.powered = test_bit(HCI_UP, &hdev->flags);
-       rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
-       rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
-       rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
+       rp.version = hdev->hci_ver;
 
-       if (test_bit(HCI_AUTH, &hdev->flags))
-               rp.sec_mode = 3;
-       else if (hdev->ssp_mode > 0)
-               rp.sec_mode = 4;
-       else
-               rp.sec_mode = 2;
+       put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
+
+       rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
+       rp.current_settings = cpu_to_le32(get_current_settings(hdev));
 
-       bacpy(&rp.bdaddr, &hdev->bdaddr);
-       memcpy(rp.features, hdev->features, 8);
        memcpy(rp.dev_class, hdev->dev_class, 3);
-       put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
-       rp.hci_ver = hdev->hci_ver;
-       put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
 
        memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
@@ -366,13 +616,11 @@ static void mgmt_pending_remove(struct pending_cmd *cmd)
        mgmt_pending_free(cmd);
 }
 
-static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
+static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
 {
-       struct mgmt_mode rp;
+       __le32 settings = cpu_to_le32(get_current_settings(hdev));
 
-       rp.val = val;
-
-       return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
+       return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
 }
 
 static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
@@ -395,11 +643,11 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
                return cmd_status(sk, index, MGMT_OP_SET_POWERED,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        up = test_bit(HCI_UP, &hdev->flags);
        if ((cp->val && up) || (!cp->val && !up)) {
-               err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val);
+               err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
                goto failed;
        }
 
@@ -416,14 +664,14 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
        }
 
        if (cp->val)
-               queue_work(hdev->workqueue, &hdev->power_on);
+               schedule_work(&hdev->power_on);
        else
-               queue_work(hdev->workqueue, &hdev->power_off.work);
+               schedule_work(&hdev->power_off.work);
 
        err = 0;
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
        return err;
 }
@@ -450,7 +698,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
@@ -467,8 +715,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
 
        if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
                                        test_bit(HCI_PSCAN, &hdev->flags)) {
-               err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE,
-                                                               cp->val);
+               err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
                goto failed;
        }
 
@@ -493,7 +740,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
                hdev->discov_timeout = get_unaligned_le16(&cp->timeout);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -521,7 +768,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
@@ -537,8 +784,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
        }
 
        if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
-               err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE,
-                                                               cp->val);
+               err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
                goto failed;
        }
 
@@ -558,7 +804,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -596,8 +842,9 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
 static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
                                                                        u16 len)
 {
-       struct mgmt_mode *cp, ev;
+       struct mgmt_mode *cp;
        struct hci_dev *hdev;
+       __le32 ev;
        int err;
 
        cp = (void *) data;
@@ -613,201 +860,28 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (cp->val)
                set_bit(HCI_PAIRABLE, &hdev->flags);
        else
                clear_bit(HCI_PAIRABLE, &hdev->flags);
 
-       err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val);
+       err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
        if (err < 0)
                goto failed;
 
-       ev.val = cp->val;
+       ev = cpu_to_le32(get_current_settings(hdev));
 
-       err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk);
+       err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
 }
 
-#define EIR_FLAGS              0x01 /* flags */
-#define EIR_UUID16_SOME                0x02 /* 16-bit UUID, more available */
-#define EIR_UUID16_ALL         0x03 /* 16-bit UUID, all listed */
-#define EIR_UUID32_SOME                0x04 /* 32-bit UUID, more available */
-#define EIR_UUID32_ALL         0x05 /* 32-bit UUID, all listed */
-#define EIR_UUID128_SOME       0x06 /* 128-bit UUID, more available */
-#define EIR_UUID128_ALL                0x07 /* 128-bit UUID, all listed */
-#define EIR_NAME_SHORT         0x08 /* shortened local name */
-#define EIR_NAME_COMPLETE      0x09 /* complete local name */
-#define EIR_TX_POWER           0x0A /* transmit power level */
-#define EIR_DEVICE_ID          0x10 /* device ID */
-
-#define PNP_INFO_SVCLASS_ID            0x1200
-
-static u8 bluetooth_base_uuid[] = {
-                       0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
-                       0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static u16 get_uuid16(u8 *uuid128)
-{
-       u32 val;
-       int i;
-
-       for (i = 0; i < 12; i++) {
-               if (bluetooth_base_uuid[i] != uuid128[i])
-                       return 0;
-       }
-
-       memcpy(&val, &uuid128[12], 4);
-
-       val = le32_to_cpu(val);
-       if (val > 0xffff)
-               return 0;
-
-       return (u16) val;
-}
-
-static void create_eir(struct hci_dev *hdev, u8 *data)
-{
-       u8 *ptr = data;
-       u16 eir_len = 0;
-       u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
-       int i, truncated = 0;
-       struct bt_uuid *uuid;
-       size_t name_len;
-
-       name_len = strlen(hdev->dev_name);
-
-       if (name_len > 0) {
-               /* EIR Data type */
-               if (name_len > 48) {
-                       name_len = 48;
-                       ptr[1] = EIR_NAME_SHORT;
-               } else
-                       ptr[1] = EIR_NAME_COMPLETE;
-
-               /* EIR Data length */
-               ptr[0] = name_len + 1;
-
-               memcpy(ptr + 2, hdev->dev_name, name_len);
-
-               eir_len += (name_len + 2);
-               ptr += (name_len + 2);
-       }
-
-       memset(uuid16_list, 0, sizeof(uuid16_list));
-
-       /* Group all UUID16 types */
-       list_for_each_entry(uuid, &hdev->uuids, list) {
-               u16 uuid16;
-
-               uuid16 = get_uuid16(uuid->uuid);
-               if (uuid16 == 0)
-                       return;
-
-               if (uuid16 < 0x1100)
-                       continue;
-
-               if (uuid16 == PNP_INFO_SVCLASS_ID)
-                       continue;
-
-               /* Stop if not enough space to put next UUID */
-               if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
-                       truncated = 1;
-                       break;
-               }
-
-               /* Check for duplicates */
-               for (i = 0; uuid16_list[i] != 0; i++)
-                       if (uuid16_list[i] == uuid16)
-                               break;
-
-               if (uuid16_list[i] == 0) {
-                       uuid16_list[i] = uuid16;
-                       eir_len += sizeof(u16);
-               }
-       }
-
-       if (uuid16_list[0] != 0) {
-               u8 *length = ptr;
-
-               /* EIR Data type */
-               ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
-
-               ptr += 2;
-               eir_len += 2;
-
-               for (i = 0; uuid16_list[i] != 0; i++) {
-                       *ptr++ = (uuid16_list[i] & 0x00ff);
-                       *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
-               }
-
-               /* EIR Data length */
-               *length = (i * sizeof(u16)) + 1;
-       }
-}
-
-static int update_eir(struct hci_dev *hdev)
-{
-       struct hci_cp_write_eir cp;
-
-       if (!(hdev->features[6] & LMP_EXT_INQ))
-               return 0;
-
-       if (hdev->ssp_mode == 0)
-               return 0;
-
-       if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
-               return 0;
-
-       memset(&cp, 0, sizeof(cp));
-
-       create_eir(hdev, cp.data);
-
-       if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
-               return 0;
-
-       memcpy(hdev->eir, cp.data, sizeof(cp.data));
-
-       return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
-}
-
-static u8 get_service_classes(struct hci_dev *hdev)
-{
-       struct bt_uuid *uuid;
-       u8 val = 0;
-
-       list_for_each_entry(uuid, &hdev->uuids, list)
-               val |= uuid->svc_hint;
-
-       return val;
-}
-
-static int update_class(struct hci_dev *hdev)
-{
-       u8 cod[3];
-
-       BT_DBG("%s", hdev->name);
-
-       if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
-               return 0;
-
-       cod[0] = hdev->minor_class;
-       cod[1] = hdev->major_class;
-       cod[2] = get_service_classes(hdev);
-
-       if (memcmp(cod, hdev->dev_class, 3) == 0)
-               return 0;
-
-       return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
-}
-
 static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
 {
        struct mgmt_cp_add_uuid *cp;
@@ -828,7 +902,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
                return cmd_status(sk, index, MGMT_OP_ADD_UUID,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
        if (!uuid) {
@@ -852,7 +926,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
        err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -879,7 +953,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
                return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
                err = hci_uuids_clear(hdev);
@@ -915,7 +989,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
        err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
 
 unlock:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -941,62 +1015,24 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        hdev->major_class = cp->major;
        hdev->minor_class = cp->minor;
 
+       if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) {
+               hci_dev_unlock(hdev);
+               cancel_delayed_work_sync(&hdev->service_cache);
+               hci_dev_lock(hdev);
+               update_eir(hdev);
+       }
+
        err = update_class(hdev);
 
        if (err == 0)
                err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
 
-       hci_dev_unlock_bh(hdev);
-       hci_dev_put(hdev);
-
-       return err;
-}
-
-static int set_service_cache(struct sock *sk, u16 index,  unsigned char *data,
-                                                                       u16 len)
-{
-       struct hci_dev *hdev;
-       struct mgmt_cp_set_service_cache *cp;
-       int err;
-
-       cp = (void *) data;
-
-       if (len != sizeof(*cp))
-               return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
-                                               MGMT_STATUS_INVALID_PARAMS);
-
-       hdev = hci_dev_get(index);
-       if (!hdev)
-               return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
-                                               MGMT_STATUS_INVALID_PARAMS);
-
-       hci_dev_lock_bh(hdev);
-
-       BT_DBG("hci%u enable %d", index, cp->enable);
-
-       if (cp->enable) {
-               set_bit(HCI_SERVICE_CACHE, &hdev->flags);
-               err = 0;
-       } else {
-               clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
-               err = update_class(hdev);
-               if (err == 0)
-                       err = update_eir(hdev);
-       }
-
-       if (err == 0)
-               err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
-                                                                       0);
-       else
-               cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, -err);
-
-
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1035,7 +1071,7 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
        BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
                                                                key_count);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        hci_link_keys_clear(hdev);
 
@@ -1055,7 +1091,7 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
 
        cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return 0;
@@ -1083,7 +1119,7 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        memset(&rp, 0, sizeof(rp));
        bacpy(&rp.bdaddr, &cp->bdaddr);
@@ -1124,7 +1160,7 @@ unlock:
        if (err < 0)
                err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
                                                                sizeof(rp));
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1152,7 +1188,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
                return cmd_status(sk, index, MGMT_OP_DISCONNECT,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
@@ -1190,7 +1226,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1232,7 +1268,7 @@ static int get_connections(struct sock *sk, u16 index)
                return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        count = 0;
        list_for_each(p, &hdev->conn_hash.list) {
@@ -1264,7 +1300,7 @@ static int get_connections(struct sock *sk, u16 index)
 
 unlock:
        kfree(rp);
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
        return err;
 }
@@ -1312,7 +1348,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
@@ -1355,7 +1391,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1381,7 +1417,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
@@ -1392,7 +1428,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
        err = send_pin_code_neg_reply(sk, index, hdev, cp);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1417,14 +1453,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        hdev->io_capability = cp->io_capability;
 
        BT_DBG("%s IO capability set to 0x%02x", hdev->name,
                                                        hdev->io_capability);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
@@ -1505,7 +1541,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
                return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        sec_level = BT_SECURITY_MEDIUM;
        if (cp->io_cap == 0x03)
@@ -1562,7 +1598,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
        err = 0;
 
 unlock:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1581,7 +1617,7 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
                return cmd_status(sk, index, mgmt_op,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
@@ -1607,8 +1643,15 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
                }
 
                /* Continue with pairing via SMP */
+               err = smp_user_confirm_reply(conn, mgmt_op, passkey);
+
+               if (!err)
+                       err = cmd_status(sk, index, mgmt_op,
+                                                       MGMT_STATUS_SUCCESS);
+               else
+                       err = cmd_status(sk, index, mgmt_op,
+                                                       MGMT_STATUS_FAILED);
 
-               err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_SUCCESS);
                goto done;
        }
 
@@ -1632,7 +1675,7 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
                mgmt_pending_remove(cmd);
 
 done:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1656,7 +1699,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
 static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
                                                                        u16 len)
 {
-       struct mgmt_cp_user_confirm_reply *cp = (void *) data;
+       struct mgmt_cp_user_confirm_neg_reply *cp = data;
 
        BT_DBG("");
 
@@ -1720,7 +1763,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
        if (!cmd) {
@@ -1735,7 +1778,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1754,7 +1797,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
                return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
@@ -1785,7 +1828,7 @@ static int read_local_oob_data(struct sock *sk, u16 index)
                mgmt_pending_remove(cmd);
 
 unlock:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1809,7 +1852,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
                                                                cp->randomizer);
@@ -1820,7 +1863,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
                err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
                                                                        0);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1844,7 +1887,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
                return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
        if (err < 0)
@@ -1854,7 +1897,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
                err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
                                                                NULL, 0);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1879,7 +1922,7 @@ static int start_discovery(struct sock *sk, u16 index,
                return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (!test_bit(HCI_UP, &hdev->flags)) {
                err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
@@ -1898,7 +1941,7 @@ static int start_discovery(struct sock *sk, u16 index,
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1917,7 +1960,7 @@ static int stop_discovery(struct sock *sk, u16 index)
                return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
        if (!cmd) {
@@ -1930,7 +1973,7 @@ static int stop_discovery(struct sock *sk, u16 index)
                mgmt_pending_remove(cmd);
 
 failed:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1954,7 +1997,7 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_blacklist_add(hdev, &cp->bdaddr);
        if (err < 0)
@@ -1964,7 +2007,7 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
                err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
                                                        NULL, 0);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1988,7 +2031,7 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
                return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
                                                MGMT_STATUS_INVALID_PARAMS);
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        err = hci_blacklist_del(hdev, &cp->bdaddr);
 
@@ -1999,7 +2042,7 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
                err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
                                                                NULL, 0);
 
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -2009,7 +2052,7 @@ static int set_fast_connectable(struct sock *sk, u16 index,
                                        unsigned char *data, u16 len)
 {
        struct hci_dev *hdev;
-       struct mgmt_cp_set_fast_connectable *cp = (void *) data;
+       struct mgmt_mode *cp = (void *) data;
        struct hci_cp_write_page_scan_activity acp;
        u8 type;
        int err;
@@ -2027,7 +2070,7 @@ static int set_fast_connectable(struct sock *sk, u16 index,
 
        hci_dev_lock(hdev);
 
-       if (cp->enable) {
+       if (cp->val) {
                type = PAGE_SCAN_TYPE_INTERLACED;
                acp.interval = 0x0024;  /* 22.5 msec page scan interval */
        } else {
@@ -2111,6 +2154,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
        case MGMT_OP_SET_CONNECTABLE:
                err = set_connectable(sk, index, buf + sizeof(*hdr), len);
                break;
+       case MGMT_OP_SET_FAST_CONNECTABLE:
+               err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
+                                                               len);
+               break;
        case MGMT_OP_SET_PAIRABLE:
                err = set_pairable(sk, index, buf + sizeof(*hdr), len);
                break;
@@ -2123,9 +2170,6 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
        case MGMT_OP_SET_DEV_CLASS:
                err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
                break;
-       case MGMT_OP_SET_SERVICE_CACHE:
-               err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
-               break;
        case MGMT_OP_LOAD_LINK_KEYS:
                err = load_link_keys(sk, index, buf + sizeof(*hdr), len);
                break;
@@ -2189,10 +2233,6 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
        case MGMT_OP_UNBLOCK_DEVICE:
                err = unblock_device(sk, index, buf + sizeof(*hdr), len);
                break;
-       case MGMT_OP_SET_FAST_CONNECTABLE:
-               err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
-                                                               len);
-               break;
        default:
                BT_DBG("Unknown op %u", opcode);
                err = cmd_status(sk, index, opcode,
@@ -2235,17 +2275,14 @@ int mgmt_index_removed(struct hci_dev *hdev)
 struct cmd_lookup {
        u8 val;
        struct sock *sk;
+       struct hci_dev *hdev;
 };
 
-static void mode_rsp(struct pending_cmd *cmd, void *data)
+static void settings_rsp(struct pending_cmd *cmd, void *data)
 {
-       struct mgmt_mode *cp = cmd->param;
        struct cmd_lookup *match = data;
 
-       if (cp->val != match->val)
-               return;
-
-       send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
+       send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
 
        list_del(&cmd->list);
 
@@ -2259,20 +2296,21 @@ static void mode_rsp(struct pending_cmd *cmd, void *data)
 
 int mgmt_powered(struct hci_dev *hdev, u8 powered)
 {
-       struct mgmt_mode ev;
-       struct cmd_lookup match = { powered, NULL };
+       struct cmd_lookup match = { powered, NULL, hdev };
+       __le32 ev;
        int ret;
 
-       mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match);
+       mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
        if (!powered) {
                u8 status = ENETDOWN;
                mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
        }
 
-       ev.val = powered;
+       ev = cpu_to_le32(get_current_settings(hdev));
 
-       ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk);
+       ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
+                                                               match.sk);
 
        if (match.sk)
                sock_put(match.sk);
@@ -2282,17 +2320,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
 
 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 {
-       struct mgmt_mode ev;
-       struct cmd_lookup match = { discoverable, NULL };
+       struct cmd_lookup match = { discoverable, NULL, hdev };
+       __le32 ev;
        int ret;
 
-       mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match);
+       mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match);
 
-       ev.val = discoverable;
+       ev = cpu_to_le32(get_current_settings(hdev));
 
-       ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev),
+       ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
                                                                match.sk);
-
        if (match.sk)
                sock_put(match.sk);
 
@@ -2301,15 +2338,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
 {
-       struct mgmt_mode ev;
-       struct cmd_lookup match = { connectable, NULL };
+       __le32 ev;
+       struct cmd_lookup match = { connectable, NULL, hdev };
        int ret;
 
-       mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match);
+       mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
+                                                               &match);
 
-       ev.val = connectable;
+       ev = cpu_to_le32(get_current_settings(hdev));
 
-       ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk);
+       ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk);
 
        if (match.sk)
                sock_put(match.sk);
index 405a0e61e7dc565447596eb4c1aadf7246d732c6..22e718b554e4e8a7650f4b8d09c8df91b0d714c2 100644 (file)
@@ -1,6 +1,6 @@
 config BT_RFCOMM
        tristate "RFCOMM protocol support"
-       depends on BT && BT_L2CAP
+       depends on BT
        help
          RFCOMM provides connection oriented stream transport.  RFCOMM
          support is required for Dialup Networking, OBEX and other Bluetooth
index eac849b935a1c2fd2cea704e26adb1b1373ed450..501649bf5596d0373d6b6dd3be791dd1345ad33e 100644 (file)
@@ -65,8 +65,7 @@ static DEFINE_MUTEX(rfcomm_mutex);
 
 static LIST_HEAD(session_list);
 
-static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len,
-                                                       u32 priority);
+static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len);
 static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci);
 static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci);
 static int rfcomm_queue_disc(struct rfcomm_dlc *d);
@@ -748,32 +747,23 @@ void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *d
 }
 
 /* ---- RFCOMM frame sending ---- */
-static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len,
-                                                       u32 priority)
+static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
 {
-       struct socket *sock = s->sock;
-       struct sock *sk = sock->sk;
        struct kvec iv = { data, len };
        struct msghdr msg;
 
-       BT_DBG("session %p len %d priority %u", s, len, priority);
-
-       if (sk->sk_priority != priority) {
-               lock_sock(sk);
-               sk->sk_priority = priority;
-               release_sock(sk);
-       }
+       BT_DBG("session %p len %d", s, len);
 
        memset(&msg, 0, sizeof(msg));
 
-       return kernel_sendmsg(sock, &msg, &iv, 1, len);
+       return kernel_sendmsg(s->sock, &msg, &iv, 1, len);
 }
 
 static int rfcomm_send_cmd(struct rfcomm_session *s, struct rfcomm_cmd *cmd)
 {
        BT_DBG("%p cmd %u", s, cmd->ctrl);
 
-       return rfcomm_send_frame(s, (void *) cmd, sizeof(*cmd), HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, (void *) cmd, sizeof(*cmd));
 }
 
 static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
@@ -829,8 +819,6 @@ static int rfcomm_queue_disc(struct rfcomm_dlc *d)
        if (!skb)
                return -ENOMEM;
 
-       skb->priority = HCI_PRIO_MAX;
-
        cmd = (void *) __skb_put(skb, sizeof(*cmd));
        cmd->addr = d->addr;
        cmd->ctrl = __ctrl(RFCOMM_DISC, 1);
@@ -878,7 +866,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d)
@@ -920,7 +908,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
@@ -958,7 +946,7 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
@@ -985,7 +973,7 @@ static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig)
@@ -1012,7 +1000,7 @@ static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
@@ -1034,7 +1022,7 @@ static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
@@ -1056,7 +1044,7 @@ static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
@@ -1107,7 +1095,7 @@ static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits)
 
        *ptr = __fcs(buf); ptr++;
 
-       return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
+       return rfcomm_send_frame(s, buf, ptr - buf);
 }
 
 static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
@@ -1786,8 +1774,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
                return skb_queue_len(&d->tx_queue);
 
        while (d->tx_credits && (skb = skb_dequeue(&d->tx_queue))) {
-               err = rfcomm_send_frame(d->session, skb->data, skb->len,
-                                                       skb->priority);
+               err = rfcomm_send_frame(d->session, skb->data, skb->len);
                if (err < 0) {
                        skb_queue_head(&d->tx_queue, skb);
                        break;
index a0d11b8738317bcfd1a62e6b49d4d84a8b6fdd86..5dc2f2126fac669a2f1b961efb8ce665768da2f2 100644 (file)
@@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk)
        if (!hdev)
                return -EHOSTUNREACH;
 
-       hci_dev_lock_bh(hdev);
+       hci_dev_lock(hdev);
 
        if (lmp_esco_capable(hdev) && !disable_esco)
                type = ESCO_LINK;
@@ -225,7 +225,7 @@ static int sco_connect(struct sock *sk)
        }
 
 done:
-       hci_dev_unlock_bh(hdev);
+       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
        return err;
 }
@@ -893,15 +893,12 @@ done:
 }
 
 /* ----- SCO interface with lower layer (HCI) ----- */
-static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        register struct sock *sk;
        struct hlist_node *node;
        int lm = 0;
 
-       if (type != SCO_LINK && type != ESCO_LINK)
-               return -EINVAL;
-
        BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
        /* Find listening sockets */
@@ -921,13 +918,9 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
        return lm;
 }
 
-static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
+int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
 {
        BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
-
-       if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return -EINVAL;
-
        if (!status) {
                struct sco_conn *conn;
 
@@ -940,19 +933,15 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
        return 0;
 }
 
-static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
+int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 {
        BT_DBG("hcon %p reason %d", hcon, reason);
 
-       if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-               return -EINVAL;
-
        sco_conn_del(hcon, bt_to_errno(reason));
-
        return 0;
 }
 
-static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
+int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
 {
        struct sco_conn *conn = hcon->sco_data;
 
@@ -1028,15 +1017,6 @@ static const struct net_proto_family sco_sock_family_ops = {
        .create = sco_sock_create,
 };
 
-static struct hci_proto sco_hci_proto = {
-       .name           = "SCO",
-       .id             = HCI_PROTO_SCO,
-       .connect_ind    = sco_connect_ind,
-       .connect_cfm    = sco_connect_cfm,
-       .disconn_cfm    = sco_disconn_cfm,
-       .recv_scodata   = sco_recv_scodata
-};
-
 int __init sco_init(void)
 {
        int err;
@@ -1051,13 +1031,6 @@ int __init sco_init(void)
                goto error;
        }
 
-       err = hci_register_proto(&sco_hci_proto);
-       if (err < 0) {
-               BT_ERR("SCO protocol registration failed");
-               bt_sock_unregister(BTPROTO_SCO);
-               goto error;
-       }
-
        if (bt_debugfs) {
                sco_debugfs = debugfs_create_file("sco", 0444,
                                        bt_debugfs, NULL, &sco_debugfs_fops);
@@ -1081,9 +1054,6 @@ void __exit sco_exit(void)
        if (bt_sock_unregister(BTPROTO_SCO) < 0)
                BT_ERR("SCO socket unregistration failed");
 
-       if (hci_unregister_proto(&sco_hci_proto) < 0)
-               BT_ERR("SCO protocol unregistration failed");
-
        proto_unregister(&sco_proto);
 }
 
index 0b96737d0ad36a27a7aaf8ed76dd9543ca0c2300..32c47de303440846fce21b5c02e53c89e08e92d8 100644 (file)
@@ -23,6 +23,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/mgmt.h>
 #include <net/bluetooth/smp.h>
 #include <linux/crypto.h>
 #include <linux/scatterlist.h>
@@ -184,28 +185,50 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
        skb->priority = HCI_PRIO_MAX;
        hci_send_acl(conn->hchan, skb, 0);
 
-       mod_timer(&conn->security_timer, jiffies +
+       cancel_delayed_work_sync(&conn->security_timer);
+       schedule_delayed_work(&conn->security_timer,
                                        msecs_to_jiffies(SMP_TIMEOUT));
 }
 
+static __u8 authreq_to_seclevel(__u8 authreq)
+{
+       if (authreq & SMP_AUTH_MITM)
+               return BT_SECURITY_HIGH;
+       else
+               return BT_SECURITY_MEDIUM;
+}
+
+static __u8 seclevel_to_authreq(__u8 sec_level)
+{
+       switch (sec_level) {
+       case BT_SECURITY_HIGH:
+               return SMP_AUTH_MITM | SMP_AUTH_BONDING;
+       case BT_SECURITY_MEDIUM:
+               return SMP_AUTH_BONDING;
+       default:
+               return SMP_AUTH_NONE;
+       }
+}
+
 static void build_pairing_cmd(struct l2cap_conn *conn,
                                struct smp_cmd_pairing *req,
                                struct smp_cmd_pairing *rsp,
                                __u8 authreq)
 {
-       u8 dist_keys;
+       u8 dist_keys = 0;
 
-       dist_keys = 0;
        if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
                dist_keys = SMP_DIST_ENC_KEY;
                authreq |= SMP_AUTH_BONDING;
+       } else {
+               authreq &= ~SMP_AUTH_BONDING;
        }
 
        if (rsp == NULL) {
                req->io_capability = conn->hcon->io_capability;
                req->oob_flag = SMP_OOB_NOT_PRESENT;
                req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
-               req->init_key_dist = dist_keys;
+               req->init_key_dist = 0;
                req->resp_key_dist = dist_keys;
                req->auth_req = authreq;
                return;
@@ -214,7 +237,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
        rsp->io_capability = conn->hcon->io_capability;
        rsp->oob_flag = SMP_OOB_NOT_PRESENT;
        rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
-       rsp->init_key_dist = req->init_key_dist & dist_keys;
+       rsp->init_key_dist = 0;
        rsp->resp_key_dist = req->resp_key_dist & dist_keys;
        rsp->auth_req = authreq;
 }
@@ -240,10 +263,99 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
 
        clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
-       del_timer(&conn->security_timer);
+       cancel_delayed_work_sync(&conn->security_timer);
        smp_chan_destroy(conn);
 }
 
+#define JUST_WORKS     0x00
+#define JUST_CFM       0x01
+#define REQ_PASSKEY    0x02
+#define CFM_PASSKEY    0x03
+#define REQ_OOB                0x04
+#define OVERLAP                0xFF
+
+static const u8 gen_method[5][5] = {
+       { JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
+       { JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
+       { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
+       { JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
+       { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
+};
+
+static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
+                                               u8 local_io, u8 remote_io)
+{
+       struct hci_conn *hcon = conn->hcon;
+       struct smp_chan *smp = conn->smp_chan;
+       u8 method;
+       u32 passkey = 0;
+       int ret = 0;
+
+       /* Initialize key for JUST WORKS */
+       memset(smp->tk, 0, sizeof(smp->tk));
+       clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
+
+       BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
+
+       /* If neither side wants MITM, use JUST WORKS */
+       /* If either side has unknown io_caps, use JUST WORKS */
+       /* Otherwise, look up method from the table */
+       if (!(auth & SMP_AUTH_MITM) ||
+                       local_io > SMP_IO_KEYBOARD_DISPLAY ||
+                       remote_io > SMP_IO_KEYBOARD_DISPLAY)
+               method = JUST_WORKS;
+       else
+               method = gen_method[local_io][remote_io];
+
+       /* If not bonding, don't ask user to confirm a Zero TK */
+       if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
+               method = JUST_WORKS;
+
+       /* If Just Works, Continue with Zero TK */
+       if (method == JUST_WORKS) {
+               set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
+               return 0;
+       }
+
+       /* Not Just Works/Confirm results in MITM Authentication */
+       if (method != JUST_CFM)
+               set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
+
+       /* If both devices have Keyoard-Display I/O, the master
+        * Confirms and the slave Enters the passkey.
+        */
+       if (method == OVERLAP) {
+               if (hcon->link_mode & HCI_LM_MASTER)
+                       method = CFM_PASSKEY;
+               else
+                       method = REQ_PASSKEY;
+       }
+
+       /* Generate random passkey. Not valid until confirmed. */
+       if (method == CFM_PASSKEY) {
+               u8 key[16];
+
+               memset(key, 0, sizeof(key));
+               get_random_bytes(&passkey, sizeof(passkey));
+               passkey %= 1000000;
+               put_unaligned_le32(passkey, key);
+               swap128(key, smp->tk);
+               BT_DBG("PassKey: %d", passkey);
+       }
+
+       hci_dev_lock(hcon->hdev);
+
+       if (method == REQ_PASSKEY)
+               ret = mgmt_user_passkey_request(hcon->hdev, conn->dst);
+       else
+               ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
+                                               cpu_to_le32(passkey), 0);
+
+       hci_dev_unlock(hcon->hdev);
+
+       return ret;
+}
+
 static void confirm_work(struct work_struct *work)
 {
        struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
@@ -276,6 +388,8 @@ static void confirm_work(struct work_struct *work)
                goto error;
        }
 
+       clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
+
        swap128(res, cp.confirm_val);
        smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
 
@@ -381,6 +495,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
 
        smp->conn = conn;
        conn->smp_chan = smp;
+       conn->hcon->smp_conn = conn;
 
        hci_conn_hold(conn->hcon);
 
@@ -398,18 +513,64 @@ void smp_chan_destroy(struct l2cap_conn *conn)
 
        kfree(smp);
        conn->smp_chan = NULL;
+       conn->hcon->smp_conn = NULL;
        hci_conn_put(conn->hcon);
 }
 
+int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
+{
+       struct l2cap_conn *conn = hcon->smp_conn;
+       struct smp_chan *smp;
+       u32 value;
+       u8 key[16];
+
+       BT_DBG("");
+
+       if (!conn)
+               return -ENOTCONN;
+
+       smp = conn->smp_chan;
+
+       switch (mgmt_op) {
+       case MGMT_OP_USER_PASSKEY_REPLY:
+               value = le32_to_cpu(passkey);
+               memset(key, 0, sizeof(key));
+               BT_DBG("PassKey: %d", value);
+               put_unaligned_le32(value, key);
+               swap128(key, smp->tk);
+               /* Fall Through */
+       case MGMT_OP_USER_CONFIRM_REPLY:
+               set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
+               break;
+       case MGMT_OP_USER_PASSKEY_NEG_REPLY:
+       case MGMT_OP_USER_CONFIRM_NEG_REPLY:
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               return 0;
+       default:
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               return -EOPNOTSUPP;
+       }
+
+       /* If it is our turn to send Pairing Confirm, do so now */
+       if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
+               queue_work(hcon->hdev->workqueue, &smp->confirm);
+
+       return 0;
+}
+
 static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct smp_cmd_pairing rsp, *req = (void *) skb->data;
        struct smp_chan *smp;
        u8 key_size;
+       u8 auth = SMP_AUTH_NONE;
        int ret;
 
        BT_DBG("conn %p", conn);
 
+       if (conn->hcon->link_mode & HCI_LM_MASTER)
+               return SMP_CMD_NOTSUPP;
+
        if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
                smp = smp_chan_create(conn);
 
@@ -419,19 +580,16 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
        memcpy(&smp->preq[1], req, sizeof(*req));
        skb_pull(skb, sizeof(*req));
 
-       if (req->oob_flag)
-               return SMP_OOB_NOT_AVAIL;
+       /* We didn't start the pairing, so match remote */
+       if (req->auth_req & SMP_AUTH_BONDING)
+               auth = req->auth_req;
 
-       /* We didn't start the pairing, so no requirements */
-       build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
+       build_pairing_cmd(conn, req, &rsp, auth);
 
        key_size = min(req->max_key_size, rsp.max_key_size);
        if (check_enc_key_size(conn, key_size))
                return SMP_ENC_KEY_SIZE;
 
-       /* Just works */
-       memset(smp->tk, 0, sizeof(smp->tk));
-
        ret = smp_rand(smp->prnd);
        if (ret)
                return SMP_UNSPECIFIED;
@@ -441,6 +599,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
        smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
 
+       /* Request setup of TK */
+       ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
+       if (ret)
+               return SMP_UNSPECIFIED;
+
        return 0;
 }
 
@@ -449,11 +612,14 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
        struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
        struct smp_chan *smp = conn->smp_chan;
        struct hci_dev *hdev = conn->hcon->hdev;
-       u8 key_size;
+       u8 key_size, auth = SMP_AUTH_NONE;
        int ret;
 
        BT_DBG("conn %p", conn);
 
+       if (!(conn->hcon->link_mode & HCI_LM_MASTER))
+               return SMP_CMD_NOTSUPP;
+
        skb_pull(skb, sizeof(*rsp));
 
        req = (void *) &smp->preq[1];
@@ -462,12 +628,6 @@ 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;
 
-       if (rsp->oob_flag)
-               return SMP_OOB_NOT_AVAIL;
-
-       /* Just works */
-       memset(smp->tk, 0, sizeof(smp->tk));
-
        ret = smp_rand(smp->prnd);
        if (ret)
                return SMP_UNSPECIFIED;
@@ -475,6 +635,22 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
 
+       if ((req->auth_req & SMP_AUTH_BONDING) &&
+                       (rsp->auth_req & SMP_AUTH_BONDING))
+               auth = SMP_AUTH_BONDING;
+
+       auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
+
+       ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
+       if (ret)
+               return SMP_UNSPECIFIED;
+
+       set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
+
+       /* Can't compose response until we have been confirmed */
+       if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
+               return 0;
+
        queue_work(hdev->workqueue, &smp->confirm);
 
        return 0;
@@ -496,8 +672,10 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
                swap128(smp->prnd, random);
                smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
                                                                random);
-       } else {
+       } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
                queue_work(hdev->workqueue, &smp->confirm);
+       } else {
+               set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
        }
 
        return 0;
@@ -550,7 +728,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
 
        BT_DBG("conn %p", conn);
 
-       hcon->pending_sec_level = BT_SECURITY_MEDIUM;
+       hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
 
        if (smp_ltk_encrypt(conn))
                return 0;
@@ -577,6 +755,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
 {
        struct hci_conn *hcon = conn->hcon;
        struct smp_chan *smp = conn->smp_chan;
+       __u8 authreq;
 
        BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
 
@@ -597,18 +776,22 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
                return 0;
 
        smp = smp_chan_create(conn);
+       if (!smp)
+               return 1;
+
+       authreq = seclevel_to_authreq(sec_level);
 
        if (hcon->link_mode & HCI_LM_MASTER) {
                struct smp_cmd_pairing cp;
 
-               build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE);
+               build_pairing_cmd(conn, &cp, NULL, authreq);
                smp->preq[0] = SMP_CMD_PAIRING_REQ;
                memcpy(&smp->preq[1], &cp, sizeof(cp));
 
                smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
        } else {
                struct smp_cmd_security_req cp;
-               cp.auth_req = SMP_AUTH_NONE;
+               cp.auth_req = authreq;
                smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
        }
 
@@ -637,7 +820,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
 
        skb_pull(skb, sizeof(*rp));
 
-       hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
+       hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
                                                rp->ediv, rp->rand, smp->tk);
 
        smp_distribute_keys(conn, 1);
@@ -800,7 +983,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
 
        if (conn->hcon->out || force) {
                clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
-               del_timer(&conn->security_timer);
+               cancel_delayed_work_sync(&conn->security_timer);
                smp_chan_destroy(conn);
        }
 
index e92f98d327462cde5b7761b33dd039ba4b935d7a..76be6174419879363aba7c0b4834d9eeb018241f 100644 (file)
@@ -392,6 +392,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 #endif
 
        spin_lock_bh(&sta->lock);
+       sta->ampdu_mlme.last_addba_req_time[tid] = jiffies;
        sta->ampdu_mlme.addba_req_num[tid]++;
        spin_unlock_bh(&sta->lock);
 
@@ -492,6 +493,24 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
                goto err_unlock_sta;
        }
 
+       /*
+        * if we have tried more than HT_AGG_BURST_RETRIES times we
+        * will spread our requests in time to avoid stalling connection
+        * for too long
+        */
+       if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_BURST_RETRIES &&
+           time_before(jiffies, sta->ampdu_mlme.last_addba_req_time[tid] +
+                       HT_AGG_RETRIES_PERIOD)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
+               printk(KERN_DEBUG "BA request denied - "
+                      "waiting a grace period after %d failed requests "
+                      "on tid %u\n",
+                      sta->ampdu_mlme.addba_req_num[tid], tid);
+#endif /* CONFIG_MAC80211_HT_DEBUG */
+               ret = -EBUSY;
+               goto err_unlock_sta;
+       }
+
        tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
        /* check if the TID is not in aggregation flow already */
        if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
index 66ad9d9af87f8f8d13ef199fe8b366207194f9ed..850bb96bd6805204685083dde687b8097bd19b0f 100644 (file)
@@ -355,7 +355,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                        STATION_INFO_RX_DROP_MISC |
                        STATION_INFO_BSS_PARAM |
                        STATION_INFO_CONNECTED_TIME |
-                       STATION_INFO_STA_FLAGS;
+                       STATION_INFO_STA_FLAGS |
+                       STATION_INFO_BEACON_LOSS_COUNT;
 
        do_posix_clock_monotonic_gettime(&uptime);
        sinfo->connected_time = uptime.tv_sec - sta->last_connected;
@@ -368,6 +369,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
        sinfo->tx_retries = sta->tx_retry_count;
        sinfo->tx_failed = sta->tx_retry_failed;
        sinfo->rx_dropped_misc = sta->rx_dropped;
+       sinfo->beacon_loss_count = sta->beacon_loss_count;
 
        if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
            (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
index a984f1f60ddbc7ab0370ce3665415260f2a7ef2e..57989a046fcace8570efa32612d09d5e9d345cc7 100644 (file)
@@ -1381,6 +1381,14 @@ void ieee80211_beacon_connection_loss_work(struct work_struct *work)
        struct ieee80211_sub_if_data *sdata =
                container_of(work, struct ieee80211_sub_if_data,
                             u.mgd.beacon_connection_loss_work);
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct sta_info *sta;
+
+       if (ifmgd->associated) {
+               sta = sta_info_get(sdata, ifmgd->bssid);
+               if (sta)
+                       sta->beacon_loss_count++;
+       }
 
        if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
                __ieee80211_connection_loss(sdata);
index 2be5b7d69ad71aea6c33e65e20e6441703ff8211..59f124c58333a3c7bcedc92b38b3cfccfa020f28 100644 (file)
@@ -28,6 +28,7 @@
 #include "wpa.h"
 #include "tkip.h"
 #include "wme.h"
+#include "rate.h"
 
 /*
  * monitor mode reception
@@ -1826,7 +1827,12 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        }
 
        if (xmit_skb) {
-               /* send to wireless media */
+               /*
+                * Send to wireless media and increase priority by 256 to
+                * keep the received priority instead of reclassifying
+                * the frame (see cfg80211_classify8021d).
+                */
+               xmit_skb->priority += 256;
                xmit_skb->protocol = htons(ETH_P_802_3);
                skb_reset_network_header(xmit_skb);
                skb_reset_mac_header(xmit_skb);
@@ -2233,6 +2239,63 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                return RX_DROP_UNUSABLE;
 
        switch (mgmt->u.action.category) {
+       case WLAN_CATEGORY_HT:
+               /* reject HT action frames from stations not supporting HT */
+               if (!rx->sta->sta.ht_cap.ht_supported)
+                       goto invalid;
+
+               if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+                   sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   sdata->vif.type != NL80211_IFTYPE_AP &&
+                   sdata->vif.type != NL80211_IFTYPE_ADHOC)
+                       break;
+
+               /* verify action & smps_control are present */
+               if (len < IEEE80211_MIN_ACTION_SIZE + 2)
+                       goto invalid;
+
+               switch (mgmt->u.action.u.ht_smps.action) {
+               case WLAN_HT_ACTION_SMPS: {
+                       struct ieee80211_supported_band *sband;
+                       u8 smps;
+
+                       /* convert to HT capability */
+                       switch (mgmt->u.action.u.ht_smps.smps_control) {
+                       case WLAN_HT_SMPS_CONTROL_DISABLED:
+                               smps = WLAN_HT_CAP_SM_PS_DISABLED;
+                               break;
+                       case WLAN_HT_SMPS_CONTROL_STATIC:
+                               smps = WLAN_HT_CAP_SM_PS_STATIC;
+                               break;
+                       case WLAN_HT_SMPS_CONTROL_DYNAMIC:
+                               smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
+                               break;
+                       default:
+                               goto invalid;
+                       }
+                       smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+                       /* if no change do nothing */
+                       if ((rx->sta->sta.ht_cap.cap &
+                                       IEEE80211_HT_CAP_SM_PS) == smps)
+                               goto handled;
+
+                       rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS;
+                       rx->sta->sta.ht_cap.cap |= smps;
+
+                       sband = rx->local->hw.wiphy->bands[status->band];
+
+                       rate_control_rate_update(local, sband, rx->sta,
+                                                IEEE80211_RC_SMPS_CHANGED,
+                                                local->_oper_channel_type);
+                       goto handled;
+               }
+               default:
+                       goto invalid;
+               }
+
+               break;
        case WLAN_CATEGORY_BACK:
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
index 2db01e9541e7ea579ebde1ef8370f75e646c0320..f0d3b483dabd5a00ebd513e1976b4228d46d34c0 100644 (file)
@@ -822,10 +822,13 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
         * until the aggregation stop completes. Refer
         * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936
         */
+
+       mutex_lock(&sta->ampdu_mlme.mtx);
+
        for (i = 0; i < STA_TID_NUM; i++) {
-               if (!sta->ampdu_mlme.tid_tx[i])
+               tid_tx = rcu_dereference_protected_tid_tx(sta, i);
+               if (!tid_tx)
                        continue;
-               tid_tx = sta->ampdu_mlme.tid_tx[i];
                if (skb_queue_len(&tid_tx->pending)) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                        wiphy_debug(local->hw.wiphy, "TX A-MPDU  purging %d "
@@ -837,6 +840,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
                kfree_rcu(tid_tx, rcu_head);
        }
 
+       mutex_unlock(&sta->ampdu_mlme.mtx);
+
        sta_info_free(local, sta);
 
        return 0;
@@ -941,6 +946,9 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
 
        mutex_lock(&local->sta_mtx);
        list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+               if (sdata != sta->sdata)
+                       continue;
+
                if (time_after(jiffies, sta->last_rx + exp_time)) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
                        printk(KERN_DEBUG "%s: expiring inactive STA %pM\n",
index 15b3bb7d8629769b1e4756f58e29daeb160bca02..6f77f12dc3fc313410964a91f318e48f1319d86c 100644 (file)
@@ -83,7 +83,9 @@ enum ieee80211_sta_state {
 
 #define STA_TID_NUM 16
 #define ADDBA_RESP_INTERVAL HZ
-#define HT_AGG_MAX_RETRIES             0x3
+#define HT_AGG_MAX_RETRIES             15
+#define HT_AGG_BURST_RETRIES           3
+#define HT_AGG_RETRIES_PERIOD          (15 * HZ)
 
 #define HT_AGG_STATE_DRV_READY         0
 #define HT_AGG_STATE_RESPONSE_RECEIVED 1
@@ -179,6 +181,7 @@ struct tid_ampdu_rx {
  * @tid_tx: aggregation info for Tx per TID
  * @tid_start_tx: sessions where start was requested
  * @addba_req_num: number of times addBA request has been sent.
+ * @last_addba_req_time: timestamp of the last addBA request.
  * @dialog_token_allocator: dialog token enumerator for each new session;
  * @work: work struct for starting/stopping aggregation
  * @tid_rx_timer_expired: bitmap indicating on which TIDs the
@@ -198,6 +201,7 @@ struct sta_ampdu_mlme {
        struct work_struct work;
        struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM];
        struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM];
+       unsigned long last_addba_req_time[STA_TID_NUM];
        u8 addba_req_num[STA_TID_NUM];
        u8 dialog_token_allocator;
 };
@@ -271,6 +275,7 @@ struct sta_ampdu_mlme {
  *     EAP frames before association
  * @sta: station information we share with the driver
  * @sta_state: duplicates information about station state (for debug)
+ * @beacon_loss_count: number of times beacon loss has triggered
  */
 struct sta_info {
        /* General information, mostly static */
@@ -363,6 +368,7 @@ struct sta_info {
 #endif
 
        unsigned int lost_packets;
+       unsigned int beacon_loss_count;
 
        /* should be right in front of sta to be in the same cache line */
        bool dummy;
index 67756b23eac54f9dc932eb12393dda9cfa48a01e..1d32680807d67f3729bb19724d9c09ba2f4cc599 100644 (file)
@@ -554,11 +554,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
                                goto enqueue;
                        }
                }
-
+               mutex_unlock(&local->socket_lock);
        }
 
-       mutex_unlock(&local->socket_lock);
-
        reason = LLCP_DM_NOBOUND;
        goto fail;
 
@@ -956,7 +954,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
        skb_queue_purge(&local->tx_queue);
        destroy_workqueue(local->tx_wq);
        destroy_workqueue(local->rx_wq);
-       kfree(local->rx_pending);
+       kfree_skb(local->rx_pending);
        kfree(local);
 }
 
index 2c2c4015c68b61be5121df63e6c9130c302c9275..6d28d75995b036e2da23410836313716efd9318f 100644 (file)
@@ -60,11 +60,11 @@ void nfc_llcp_exit(void);
 
 #else
 
-void nfc_llcp_mac_is_down(struct nfc_dev *dev)
+static inline void nfc_llcp_mac_is_down(struct nfc_dev *dev)
 {
 }
 
-void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
                        u8 comm_mode, u8 rf_mode)
 {
 }
index b07c4fc4ae223363659592f91a9b6ff37ac42862..b3d3cf8931cb9a3c055df2e497943ec2500cfc51 100644 (file)
@@ -2390,6 +2390,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
        if (sinfo->filled & STATION_INFO_TX_FAILED)
                NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED,
                            sinfo->tx_failed);
+       if (sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT)
+               NLA_PUT_U32(msg, NL80211_STA_INFO_BEACON_LOSS,
+                           sinfo->beacon_loss_count);
        if (sinfo->filled & STATION_INFO_BSS_PARAM) {
                bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
                if (!bss_param)