]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Apr 2011 18:34:25 +0000 (14:34 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Apr 2011 18:34:25 +0000 (14:34 -0400)
Conflicts:
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h

192 files changed:
drivers/bluetooth/Kconfig
drivers/bluetooth/ath3k.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.h
drivers/bluetooth/hci_ath.c
drivers/bluetooth/hci_h4.c
drivers/bluetooth/hci_ldisc.c
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath5k/ahb.c
drivers/net/wireless/ath/ath5k/ath5k.h
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/base.h
drivers/net/wireless/ath/ath5k/caps.c
drivers/net/wireless/ath/ath5k/debug.c
drivers/net/wireless/ath/ath5k/debug.h
drivers/net/wireless/ath/ath5k/desc.c
drivers/net/wireless/ath/ath5k/eeprom.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath5k/pci.c
drivers/net/wireless/ath/ath5k/pcu.c
drivers/net/wireless/ath/ath5k/qcu.c
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/ahb.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9002_phy.h
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hif_usb.h
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_debug.c [new file with mode: 0644]
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/htc_hst.c
drivers/net/wireless/ath/ath9k/htc_hst.h
drivers/net/wireless/ath/ath9k/hw-ops.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/phy.h
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/wmi.c
drivers/net/wireless/ath/ath9k/wmi.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/key.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/ath/regd_common.h
drivers/net/wireless/iwlegacy/iwl-4965-rs.c
drivers/net/wireless/iwlegacy/iwl4965-base.c
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.h
drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
drivers/net/wireless/iwlwifi/iwl-agn-led.c [deleted file]
drivers/net/wireless/iwlwifi/iwl-agn-led.h [deleted file]
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.h
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-commands.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-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-helpers.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-led.h
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/11n.h
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/11n_rxreorder.h
drivers/net/wireless/mwifiex/README
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cfp.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/mwifiex/decl.h
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.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/sta_tx.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/mwifiex/wmm.h
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/Makefile
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00crypto.c
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rt2x00/rt2x00ht.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00link.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rt2x00/rt2x00usb.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/led.c
drivers/net/wireless/rtlwifi/rtl8192ce/led.h
drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
include/linux/nl80211.h
include/linux/rfkill-regulator.h [new file with mode: 0644]
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/mac80211.h
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/mac80211/cfg.c
net/mac80211/debugfs_sta.c
net/mac80211/driver-ops.h
net/mac80211/driver-trace.h
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/rfkill/Kconfig
net/rfkill/Makefile
net/rfkill/rfkill-regulator.c [new file with mode: 0644]
net/wireless/mesh.c
net/wireless/nl80211.c
net/wireless/nl80211.h

index 8e0de9a058673e401cf50ae06c1a2a7f97eb2be3..11b41fd40c275b0f61aa77120dfab5b14219564a 100644 (file)
@@ -188,7 +188,7 @@ config BT_MRVL
          The core driver to support Marvell Bluetooth devices.
 
          This driver is required if you want to support
-         Marvell Bluetooth devices, such as 8688.
+         Marvell Bluetooth devices, such as 8688/8787.
 
          Say Y here to compile Marvell Bluetooth driver
          into the kernel or say M to compile it as module.
@@ -201,7 +201,7 @@ config BT_MRVL_SDIO
          The driver for Marvell Bluetooth chipsets with SDIO interface.
 
          This driver is required if you want to use Marvell Bluetooth
-         devices with SDIO interface. Currently only SD8688 chipset is
+         devices with SDIO interface. Currently SD8688/SD8787 chipsets are
          supported.
 
          Say Y here to compile support for Marvell BT-over-SDIO driver
index 5577ed656e2f108e565e1d4fee1db4365eeef6e6..695d4414bd4c31f060fc0cef81daad90de36a1f9 100644 (file)
@@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev,
                count -= size;
        }
 
-       kfree(send_buf);
-       return 0;
-
 error:
        kfree(send_buf);
        return err;
index dcc2a6ec23f00eb191bda5047387de18eb71d923..7f521d4ac657e13764e9917fd45f393b0933eee3 100644 (file)
 static u8 user_rmmod;
 static u8 sdio_ireg;
 
+static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
+       .cfg = 0x03,
+       .host_int_mask = 0x04,
+       .host_intstatus = 0x05,
+       .card_status = 0x20,
+       .sq_read_base_addr_a0 = 0x10,
+       .sq_read_base_addr_a1 = 0x11,
+       .card_fw_status0 = 0x40,
+       .card_fw_status1 = 0x41,
+       .card_rx_len = 0x42,
+       .card_rx_unit = 0x43,
+       .io_port_0 = 0x00,
+       .io_port_1 = 0x01,
+       .io_port_2 = 0x02,
+};
+static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
+       .cfg = 0x00,
+       .host_int_mask = 0x02,
+       .host_intstatus = 0x03,
+       .card_status = 0x30,
+       .sq_read_base_addr_a0 = 0x40,
+       .sq_read_base_addr_a1 = 0x41,
+       .card_revision = 0x5c,
+       .card_fw_status0 = 0x60,
+       .card_fw_status1 = 0x61,
+       .card_rx_len = 0x62,
+       .card_rx_unit = 0x63,
+       .io_port_0 = 0x78,
+       .io_port_1 = 0x79,
+       .io_port_2 = 0x7a,
+};
+
 static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
        .helper         = "sd8688_helper.bin",
        .firmware       = "sd8688.bin",
+       .reg            = &btmrvl_reg_8688,
+       .sd_blksz_fw_dl = 64,
+};
+
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
+       .helper         = NULL,
+       .firmware       = "mrvl/sd8787_uapsta.bin",
+       .reg            = &btmrvl_reg_8787,
+       .sd_blksz_fw_dl = 256,
 };
 
 static const struct sdio_device_id btmrvl_sdio_ids[] = {
        /* Marvell SD8688 Bluetooth device */
        { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
                        .driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
+       /* Marvell SD8787 Bluetooth device */
+       { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
+                       .driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
 
        { }     /* Terminating entry */
 };
@@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
        u8 reg;
        int ret;
 
-       reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret);
+       reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
        if (!ret)
                card->rx_unit = reg;
 
@@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
 
        *dat = 0;
 
-       fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
+       fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
        if (ret)
                return -EIO;
 
-       fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
+       fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
        if (ret)
                return -EIO;
 
@@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
        u8 reg;
        int ret;
 
-       reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret);
+       reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
        if (!ret)
                *dat = (u16) reg << card->rx_unit;
 
@@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
 {
        int ret;
 
-       sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret);
+       sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
        if (ret) {
                BT_ERR("Unable to enable the host interrupt!");
                ret = -EIO;
@@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
        u8 host_int_mask;
        int ret;
 
-       host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret);
+       host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
        if (ret)
                return -EIO;
 
        host_int_mask &= ~mask;
 
-       sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret);
+       sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
        if (ret < 0) {
                BT_ERR("Unable to disable the host interrupt!");
                return -EIO;
@@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
        int ret;
 
        for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
-               status = sdio_readb(card->func, CARD_STATUS_REG, &ret);
+               status = sdio_readb(card->func, card->reg->card_status, &ret);
                if (ret)
                        goto failed;
                if ((status & bits) == bits)
@@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
        u8 base0, base1;
        void *tmpfwbuf = NULL;
        u8 *fwbuf;
-       u16 len;
+       u16 len, blksz_dl = card->sd_blksz_fw_dl;
        int txlen = 0, tx_blocks = 0, count = 0;
 
        ret = request_firmware(&fw_firmware, card->firmware,
@@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
 
                for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
                        base0 = sdio_readb(card->func,
-                                       SQ_READ_BASE_ADDRESS_A0_REG, &ret);
+                                       card->reg->sq_read_base_addr_a0, &ret);
                        if (ret) {
                                BT_ERR("BASE0 register read failed:"
                                        " base0 = 0x%04X(%d)."
@@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
                                goto done;
                        }
                        base1 = sdio_readb(card->func,
-                                       SQ_READ_BASE_ADDRESS_A1_REG, &ret);
+                                       card->reg->sq_read_base_addr_a1, &ret);
                        if (ret) {
                                BT_ERR("BASE1 register read failed:"
                                        " base1 = 0x%04X(%d)."
@@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
                        if (firmwarelen - offset < txlen)
                                txlen = firmwarelen - offset;
 
-                       tx_blocks =
-                           (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
+                       tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
 
                        memcpy(fwbuf, &firmware[offset], txlen);
                }
 
                ret = sdio_writesb(card->func, card->ioport, fwbuf,
-                                       tx_blocks * SDIO_BLOCK_SIZE);
+                                               tx_blocks * blksz_dl);
 
                if (ret < 0) {
                        BT_ERR("FW download, writesb(%d) failed @%d",
                                                        count, offset);
-                       sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
-                                                                       &ret);
+                       sdio_writeb(card->func, HOST_CMD53_FIN,
+                                               card->reg->cfg, &ret);
                        if (ret)
                                BT_ERR("writeb failed (CFG)");
                }
@@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
 
        priv = card->priv;
 
-       ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
+       ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
        if (ret) {
                BT_ERR("sdio_readb: read int status register failed");
                return;
@@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
 
                sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
                                        UP_LD_HOST_INT_STATUS),
-                               HOST_INTSTATUS_REG, &ret);
+                               card->reg->host_intstatus, &ret);
                if (ret) {
                        BT_ERR("sdio_writeb: clear int status register failed");
                        return;
@@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
                goto release_irq;
        }
 
-       reg = sdio_readb(func, IO_PORT_0_REG, &ret);
+       reg = sdio_readb(func, card->reg->io_port_0, &ret);
        if (ret < 0) {
                ret = -EIO;
                goto release_irq;
@@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 
        card->ioport = reg;
 
-       reg = sdio_readb(func, IO_PORT_1_REG, &ret);
+       reg = sdio_readb(func, card->reg->io_port_1, &ret);
        if (ret < 0) {
                ret = -EIO;
                goto release_irq;
@@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
 
        card->ioport |= (reg << 8);
 
-       reg = sdio_readb(func, IO_PORT_2_REG, &ret);
+       reg = sdio_readb(func, card->reg->io_port_2, &ret);
        if (ret < 0) {
                ret = -EIO;
                goto release_irq;
@@ -815,6 +858,8 @@ exit:
 static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
 {
        int ret = 0;
+       u8 fws0;
+       int pollnum = MAX_POLL_TRIES;
 
        if (!card || !card->func) {
                BT_ERR("card or function is NULL!");
@@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
                goto done;
        }
 
-       ret = btmrvl_sdio_download_helper(card);
+       /* Check if other function driver is downloading the firmware */
+       fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
        if (ret) {
-               BT_ERR("Failed to download helper!");
+               BT_ERR("Failed to read FW downloading status!");
                ret = -EIO;
                goto done;
        }
+       if (fws0) {
+               BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
+
+               /* Give other function more time to download the firmware */
+               pollnum *= 10;
+       } else {
+               if (card->helper) {
+                       ret = btmrvl_sdio_download_helper(card);
+                       if (ret) {
+                               BT_ERR("Failed to download helper!");
+                               ret = -EIO;
+                               goto done;
+                       }
+               }
 
-       if (btmrvl_sdio_download_fw_w_helper(card)) {
-               BT_ERR("Failed to download firmware!");
-               ret = -EIO;
-               goto done;
+               if (btmrvl_sdio_download_fw_w_helper(card)) {
+                       BT_ERR("Failed to download firmware!");
+                       ret = -EIO;
+                       goto done;
+               }
        }
 
-       if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) {
+       if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
                BT_ERR("FW failed to be active in time!");
                ret = -ETIMEDOUT;
                goto done;
@@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
 
        sdio_claim_host(card->func);
 
-       sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret);
+       sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
 
        sdio_release_host(card->func);
 
@@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 
        if (id->driver_data) {
                struct btmrvl_sdio_device *data = (void *) id->driver_data;
-               card->helper   = data->helper;
+               card->helper = data->helper;
                card->firmware = data->firmware;
+               card->reg = data->reg;
+               card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
        }
 
        if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL v2");
 MODULE_FIRMWARE("sd8688_helper.bin");
 MODULE_FIRMWARE("sd8688.bin");
+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
index 27329f107e5a26520aafd15d6f2fc7f5d2be3736..43d35a609ca9a94795afb731d230fa88ca109bef 100644 (file)
 /* Max retry number of CMD53 write */
 #define MAX_WRITE_IOMEM_RETRY          2
 
-/* Host Control Registers */
-#define IO_PORT_0_REG                  0x00
-#define IO_PORT_1_REG                  0x01
-#define IO_PORT_2_REG                  0x02
-
-#define CONFIG_REG                     0x03
-#define HOST_POWER_UP                  BIT(1)
-#define HOST_CMD53_FIN                 BIT(2)
-
-#define HOST_INT_MASK_REG              0x04
-#define HIM_DISABLE                    0xff
-#define HIM_ENABLE                     (BIT(0) | BIT(1))
-
-#define HOST_INTSTATUS_REG             0x05
-#define UP_LD_HOST_INT_STATUS          BIT(0)
-#define DN_LD_HOST_INT_STATUS          BIT(1)
-
-/* Card Control Registers */
-#define SQ_READ_BASE_ADDRESS_A0_REG    0x10
-#define SQ_READ_BASE_ADDRESS_A1_REG    0x11
-
-#define CARD_STATUS_REG                0x20
-#define DN_LD_CARD_RDY                 BIT(0)
-#define CARD_IO_READY                  BIT(3)
-
-#define CARD_FW_STATUS0_REG            0x40
-#define CARD_FW_STATUS1_REG            0x41
-#define FIRMWARE_READY                 0xfedc
-
-#define CARD_RX_LEN_REG                        0x42
-#define CARD_RX_UNIT_REG               0x43
-
+/* register bitmasks */
+#define HOST_POWER_UP                          BIT(1)
+#define HOST_CMD53_FIN                         BIT(2)
+
+#define HIM_DISABLE                            0xff
+#define HIM_ENABLE                             (BIT(0) | BIT(1))
+
+#define UP_LD_HOST_INT_STATUS                  BIT(0)
+#define DN_LD_HOST_INT_STATUS                  BIT(1)
+
+#define DN_LD_CARD_RDY                         BIT(0)
+#define CARD_IO_READY                          BIT(3)
+
+#define FIRMWARE_READY                         0xfedc
+
+
+struct btmrvl_sdio_card_reg {
+       u8 cfg;
+       u8 host_int_mask;
+       u8 host_intstatus;
+       u8 card_status;
+       u8 sq_read_base_addr_a0;
+       u8 sq_read_base_addr_a1;
+       u8 card_revision;
+       u8 card_fw_status0;
+       u8 card_fw_status1;
+       u8 card_rx_len;
+       u8 card_rx_unit;
+       u8 io_port_0;
+       u8 io_port_1;
+       u8 io_port_2;
+};
 
 struct btmrvl_sdio_card {
        struct sdio_func *func;
        u32 ioport;
        const char *helper;
        const char *firmware;
+       const struct btmrvl_sdio_card_reg *reg;
+       u16 sd_blksz_fw_dl;
        u8 rx_unit;
        struct btmrvl_private *priv;
 };
@@ -92,6 +94,8 @@ struct btmrvl_sdio_card {
 struct btmrvl_sdio_device {
        const char *helper;
        const char *firmware;
+       const struct btmrvl_sdio_card_reg *reg;
+       u16 sd_blksz_fw_dl;
 };
 
 
index bd34406faaae087f30eff8bc34b19a7ffb0204d9..4093935ddf42619e44fef9b87428c34454104fe8 100644 (file)
@@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
 /* Recv data */
 static int ath_recv(struct hci_uart *hu, void *data, int count)
 {
-       if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
+       int ret;
+
+       ret = hci_recv_stream_fragment(hu->hdev, data, count);
+       if (ret < 0) {
                BT_ERR("Frame Reassembly Failed");
+               return ret;
+       }
 
        return count;
 }
index 7b8ad93e2c367401e98eef5a38b2f51a3096ddac..2fcd8b387d694b74130956fe836b5c211dbee20a 100644 (file)
@@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
 /* Recv data */
 static int h4_recv(struct hci_uart *hu, void *data, int count)
 {
-       if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
+       int ret;
+
+       ret = hci_recv_stream_fragment(hu->hdev, data, count);
+       if (ret < 0) {
                BT_ERR("Frame Reassembly Failed");
+               return ret;
+       }
 
        return count;
 }
index 48ad2a7ab080ba9a58c425da7cc959dba0e1e3de..320f71803a2b397f75c77a930dac1bd8de8f496d 100644 (file)
@@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
  */
 static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
 {
+       int ret;
        struct hci_uart *hu = (void *)tty->disc_data;
 
        if (!hu || tty != hu->tty)
@@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
                return;
 
        spin_lock(&hu->rx_lock);
-       hu->proto->recv(hu, (void *) data, count);
-       hu->hdev->stat.byte_rx += count;
+       ret = hu->proto->recv(hu, (void *) data, count);
+       if (ret > 0)
+               hu->hdev->stat.byte_rx += count;
        spin_unlock(&hu->rx_lock);
 
        tty_unthrottle(tty);
index 6d7105b7e8f1686f48c5fec61e3c7edce635dc02..7cf4317a2a84b35dc8c19c277746aec8345220e1 100644 (file)
@@ -123,14 +123,7 @@ struct ath_ops {
 };
 
 struct ath_common;
-
-struct ath_bus_ops {
-       enum ath_bus_type ath_bus_type;
-       void (*read_cachesize)(struct ath_common *common, int *csz);
-       bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
-       void (*bt_coex_prep)(struct ath_common *common);
-       void (*extn_synch_en)(struct ath_common *common);
-};
+struct ath_bus_ops;
 
 struct ath_common {
        void *ah;
index 82324e98efefc0b669a6ea46de37b4c8f77776cb..ea99827815599e9028682de9b4c2276d2d7939f3 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
+#include <linux/etherdevice.h>
 #include <ar231x_platform.h>
 #include "ath5k.h"
 #include "debug.h"
@@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
        return 0;
 }
 
+static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+       struct ath5k_softc *sc = ah->ah_sc;
+       struct platform_device *pdev = to_platform_device(sc->dev);
+       struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+       u8 *cfg_mac;
+
+       if (to_platform_device(sc->dev)->id == 0)
+               cfg_mac = bcfg->config->wlan0_mac;
+       else
+               cfg_mac = bcfg->config->wlan1_mac;
+
+       memcpy(mac, cfg_mac, ETH_ALEN);
+       return 0;
+}
+
 static const struct ath_bus_ops ath_ahb_bus_ops = {
        .ath_bus_type = ATH_AHB,
        .read_cachesize = ath5k_ahb_read_cachesize,
        .eeprom_read = ath5k_ahb_eeprom_read,
+       .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
 };
 
 /*Initialization*/
@@ -142,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev)
                else
                        reg |= AR5K_AR5312_ENABLE_WLAN1;
                __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+
+               /*
+                * On a dual-band AR5312, the multiband radio is only
+                * used as pass-through. Disable 2 GHz support in the
+                * driver for it
+                */
+               if (to_platform_device(sc->dev)->id == 0 &&
+                   (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
+                    (BD_WLAN1|BD_WLAN0))
+                       __set_bit(ATH_STAT_2G_DISABLED, sc->status);
        }
 
        ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
index 8a06dbd39629459f8306839f3c309e41d528d4e8..bb50700436fe5f7ea318a553b8ddb309b99072a8 100644 (file)
 
 /* SIFS */
 #define        AR5K_INIT_SIFS_TURBO                    6
-/* XXX: 8 from initvals 10 from standard */
-#define        AR5K_INIT_SIFS_DEFAULT_BG               8
+#define        AR5K_INIT_SIFS_DEFAULT_BG               10
 #define        AR5K_INIT_SIFS_DEFAULT_A                16
 #define        AR5K_INIT_SIFS_HALF_RATE                32
 #define AR5K_INIT_SIFS_QUARTER_RATE            64
@@ -453,12 +452,10 @@ struct ath5k_tx_status {
        u16     ts_seqnum;
        u16     ts_tstamp;
        u8      ts_status;
-       u8      ts_rate[4];
-       u8      ts_retry[4];
        u8      ts_final_idx;
+       u8      ts_final_retry;
        s8      ts_rssi;
        u8      ts_shortretry;
-       u8      ts_longretry;
        u8      ts_virtcol;
        u8      ts_antenna;
 };
@@ -875,6 +872,19 @@ enum ath5k_int {
        AR5K_INT_QTRIG  =       0x40000000, /* Non common */
        AR5K_INT_GLOBAL =       0x80000000,
 
+       AR5K_INT_TX_ALL = AR5K_INT_TXOK
+               | AR5K_INT_TXDESC
+               | AR5K_INT_TXERR
+               | AR5K_INT_TXEOL
+               | AR5K_INT_TXURN,
+
+       AR5K_INT_RX_ALL = AR5K_INT_RXOK
+               | AR5K_INT_RXDESC
+               | AR5K_INT_RXERR
+               | AR5K_INT_RXNOFRM
+               | AR5K_INT_RXEOL
+               | AR5K_INT_RXORN,
+
        AR5K_INT_COMMON  = AR5K_INT_RXOK
                | AR5K_INT_RXDESC
                | AR5K_INT_RXERR
@@ -1058,6 +1068,7 @@ struct ath5k_hw {
        u8                      ah_coverage_class;
        bool                    ah_ack_bitrate_high;
        u8                      ah_bwmode;
+       bool                    ah_short_slot;
 
        /* Antenna Control */
        u32                     ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
@@ -1144,6 +1155,13 @@ struct ath5k_hw {
                struct ath5k_rx_status *);
 };
 
+struct ath_bus_ops {
+       enum ath_bus_type ath_bus_type;
+       void (*read_cachesize)(struct ath_common *common, int *csz);
+       bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+       int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac);
+};
+
 /*
  * Prototypes
  */
@@ -1227,13 +1245,12 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
 /* EEPROM access functions */
 int ath5k_eeprom_init(struct ath5k_hw *ah);
 void ath5k_eeprom_detach(struct ath5k_hw *ah);
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
 
 
 /* Protocol Control Unit Functions */
 /* Helpers */
 int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
-               int len, struct ieee80211_rate *rate);
+               int len, struct ieee80211_rate *rate, bool shortpre);
 unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
 unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
 extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
index bc82405604884dadfb293c60817b4f2a93d3a40b..1588401de3c45ba225e2094d1f287818b40c6bf6 100644 (file)
@@ -313,12 +313,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
                goto err;
        }
 
+       if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
+               __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
+               __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
+       }
+
        /* Crypto settings */
        common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
                          AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
 
        if (srev >= AR5K_SREV_AR5212_V4 &&
-           (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
+           (ee->ee_version < AR5K_EEPROM_VERSION_5_0 ||
            !AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
                common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
 
index 349a5963931b21a60d3f361878cd18022e425b52..203243bacc8919b264b3d05fa12cf33dfeaa9570 100644 (file)
@@ -1443,6 +1443,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
        return true;
 }
 
+static void
+ath5k_set_current_imask(struct ath5k_softc *sc)
+{
+       enum ath5k_int imask = sc->imask;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sc->irqlock, flags);
+       if (sc->rx_pending)
+               imask &= ~AR5K_INT_RX_ALL;
+       if (sc->tx_pending)
+               imask &= ~AR5K_INT_TX_ALL;
+       ath5k_hw_set_imr(sc->ah, imask);
+       spin_unlock_irqrestore(&sc->irqlock, flags);
+}
+
 static void
 ath5k_tasklet_rx(unsigned long data)
 {
@@ -1506,6 +1521,8 @@ next:
        } while (ath5k_rxbuf_setup(sc, bf) == 0);
 unlock:
        spin_unlock(&sc->rxbuflock);
+       sc->rx_pending = false;
+       ath5k_set_current_imask(sc);
 }
 
 
@@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
                         struct ath5k_txq *txq, struct ath5k_tx_status *ts)
 {
        struct ieee80211_tx_info *info;
+       u8 tries[3];
        int i;
 
        sc->stats.tx_all_count++;
        sc->stats.tx_bytes_count += skb->len;
        info = IEEE80211_SKB_CB(skb);
 
+       tries[0] = info->status.rates[0].count;
+       tries[1] = info->status.rates[1].count;
+       tries[2] = info->status.rates[2].count;
+
        ieee80211_tx_info_clear_status(info);
-       for (i = 0; i < 4; i++) {
+
+       for (i = 0; i < ts->ts_final_idx; i++) {
                struct ieee80211_tx_rate *r =
                        &info->status.rates[i];
 
-               if (ts->ts_rate[i]) {
-                       r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
-                       r->count = ts->ts_retry[i];
-               } else {
-                       r->idx = -1;
-                       r->count = 0;
-               }
+               r->count = tries[i];
        }
 
-       /* count the successful attempt as well */
-       info->status.rates[ts->ts_final_idx].count++;
+       info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
+       info->status.rates[ts->ts_final_idx + 1].idx = -1;
 
        if (unlikely(ts->ts_status)) {
                sc->stats.ack_fail++;
@@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
        } else {
                info->flags |= IEEE80211_TX_STAT_ACK;
                info->status.ack_signal = ts->ts_rssi;
+
+               /* count the successful attempt as well */
+               info->status.rates[ts->ts_final_idx].count++;
        }
 
        /*
@@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
        for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
                if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
                        ath5k_tx_processq(sc, &sc->txqs[i]);
+
+       sc->tx_pending = false;
+       ath5k_set_current_imask(sc);
 }
 
 
@@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
         * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
 }
 
+static void
+ath5k_schedule_rx(struct ath5k_softc *sc)
+{
+       sc->rx_pending = true;
+       tasklet_schedule(&sc->rxtq);
+}
+
+static void
+ath5k_schedule_tx(struct ath5k_softc *sc)
+{
+       sc->tx_pending = true;
+       tasklet_schedule(&sc->txtq);
+}
+
 irqreturn_t
 ath5k_intr(int irq, void *dev_id)
 {
@@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
                                ieee80211_queue_work(sc->hw, &sc->reset_work);
                        }
                        else
-                               tasklet_schedule(&sc->rxtq);
+                               ath5k_schedule_rx(sc);
                } else {
                        if (status & AR5K_INT_SWBA) {
                                tasklet_hi_schedule(&sc->beacontq);
@@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
                                ath5k_hw_update_tx_triglevel(ah, true);
                        }
                        if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
-                               tasklet_schedule(&sc->rxtq);
+                               ath5k_schedule_rx(sc);
                        if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
                                        | AR5K_INT_TXERR | AR5K_INT_TXEOL))
-                               tasklet_schedule(&sc->txtq);
+                               ath5k_schedule_tx(sc);
                        if (status & AR5K_INT_BMISS) {
                                /* TODO */
                        }
@@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
 
        } while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
 
+       if (sc->rx_pending || sc->tx_pending)
+               ath5k_set_current_imask(sc);
+
        if (unlikely(!counter))
                ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
 
@@ -2572,6 +2612,8 @@ done:
 
 static void stop_tasklets(struct ath5k_softc *sc)
 {
+       sc->rx_pending = false;
+       sc->tx_pending = false;
        tasklet_kill(&sc->rxtq);
        tasklet_kill(&sc->txtq);
        tasklet_kill(&sc->calib);
@@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
        INIT_WORK(&sc->reset_work, ath5k_reset_work);
        INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
 
-       ret = ath5k_eeprom_read_mac(ah, mac);
+       ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
        if (ret) {
                ATH5K_ERR(sc, "unable to read address from EEPROM\n");
                goto err_queues;
@@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
         * XXX: ??? detach ath5k_hw ???
         * Other than that, it's straightforward...
         */
-       ath5k_debug_finish_device(sc);
        ieee80211_unregister_hw(hw);
        ath5k_desc_free(sc);
        ath5k_txq_release(sc);
index 978f1f4ac2f33b89c92dd40652faca4fc75ecb8d..b294f3305011b4f122b5caeea490b937048e6d04 100644 (file)
@@ -193,12 +193,13 @@ struct ath5k_softc {
        dma_addr_t              desc_daddr;     /* DMA (physical) address */
        size_t                  desc_len;       /* size of TX/RX descriptors */
 
-       DECLARE_BITMAP(status, 5);
+       DECLARE_BITMAP(status, 6);
 #define ATH_STAT_INVALID       0               /* disable hardware accesses */
 #define ATH_STAT_MRRETRY       1               /* multi-rate retry support */
 #define ATH_STAT_PROMISC       2
 #define ATH_STAT_LEDSOFT       3               /* enable LED gpio status */
 #define ATH_STAT_STARTED       4               /* opened & irqs enabled */
+#define ATH_STAT_2G_DISABLED   5               /* multiband radio without 2G */
 
        unsigned int            filter_flags;   /* HW flags, AR5K_RX_FILTER_* */
        struct ieee80211_channel *curchan;      /* current h/w channel */
@@ -207,6 +208,10 @@ struct ath5k_softc {
 
        enum ath5k_int          imask;          /* interrupt mask copy */
 
+       spinlock_t              irqlock;
+       bool                    rx_pending;     /* rx tasklet pending */
+       bool                    tx_pending;     /* tx tasklet pending */
+
        u8                      lladdr[ETH_ALEN];
        u8                      bssidmask[ETH_ALEN];
 
index f77e8a703c5cbcd7212751509828db9efe46f74f..7dd88e1c3ff8c083ab87eeaaaa1b86b4a5988364 100644 (file)
@@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
                }
        }
 
+       if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
+               __clear_bit(AR5K_MODE_11A, caps->cap_mode);
+
        /* Set number of supported TX queues */
        if (ah->ah_version == AR5K_AR5210)
                caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
index 0230f30e9e9aac1fa59d8d1ddb4faa7012db3d89..0bf7313b8a17884d544a425357b9204cf3771975 100644 (file)
@@ -888,65 +888,38 @@ static const struct file_operations fops_queue = {
 void
 ath5k_debug_init_device(struct ath5k_softc *sc)
 {
-       sc->debug.level = ath5k_debug;
+       struct dentry *phydir;
 
-       sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
-                               sc->hw->wiphy->debugfsdir);
+       sc->debug.level = ath5k_debug;
 
-       sc->debug.debugfs_debug = debugfs_create_file("debug",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_debug);
+       phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
+       if (!phydir)
+           return;
 
-       sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_registers);
+       debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
+                           &fops_debug);
 
-       sc->debug.debugfs_beacon = debugfs_create_file("beacon",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_beacon);
+       debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
 
-       sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_reset);
+       debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
+                           &fops_beacon);
 
-       sc->debug.debugfs_antenna = debugfs_create_file("antenna",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_antenna);
+       debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
 
-       sc->debug.debugfs_misc = debugfs_create_file("misc",
-                               S_IRUSR,
-                               sc->debug.debugfs_phydir, sc, &fops_misc);
+       debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
+                           &fops_antenna);
 
-       sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc,
-                               &fops_frameerrors);
+       debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
 
-       sc->debug.debugfs_ani = debugfs_create_file("ani",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc,
-                               &fops_ani);
+       debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
+                           &fops_frameerrors);
 
-       sc->debug.debugfs_queue = debugfs_create_file("queue",
-                               S_IWUSR | S_IRUSR,
-                               sc->debug.debugfs_phydir, sc,
-                               &fops_queue);
-}
+       debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
 
-void
-ath5k_debug_finish_device(struct ath5k_softc *sc)
-{
-       debugfs_remove(sc->debug.debugfs_debug);
-       debugfs_remove(sc->debug.debugfs_registers);
-       debugfs_remove(sc->debug.debugfs_beacon);
-       debugfs_remove(sc->debug.debugfs_reset);
-       debugfs_remove(sc->debug.debugfs_antenna);
-       debugfs_remove(sc->debug.debugfs_misc);
-       debugfs_remove(sc->debug.debugfs_frameerrors);
-       debugfs_remove(sc->debug.debugfs_ani);
-       debugfs_remove(sc->debug.debugfs_queue);
-       debugfs_remove(sc->debug.debugfs_phydir);
+       debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
+                           &fops_queue);
 }
 
-
 /* functions used in other places */
 
 void
index b0355aef68d3f196394db308f4392d84273245dd..193dd2d4ea3c30e5cbc6c48b10ac2019ebbb00e6 100644 (file)
@@ -68,17 +68,6 @@ struct ath5k_buf;
 
 struct ath5k_dbg_info {
        unsigned int            level;          /* debug level */
-       /* debugfs entries */
-       struct dentry           *debugfs_phydir;
-       struct dentry           *debugfs_debug;
-       struct dentry           *debugfs_registers;
-       struct dentry           *debugfs_beacon;
-       struct dentry           *debugfs_reset;
-       struct dentry           *debugfs_antenna;
-       struct dentry           *debugfs_misc;
-       struct dentry           *debugfs_frameerrors;
-       struct dentry           *debugfs_ani;
-       struct dentry           *debugfs_queue;
 };
 
 /**
@@ -140,9 +129,6 @@ enum ath5k_debug_level {
 void
 ath5k_debug_init_device(struct ath5k_softc *sc);
 
-void
-ath5k_debug_finish_device(struct ath5k_softc *sc);
-
 void
 ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
 
@@ -166,9 +152,6 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
 static inline void
 ath5k_debug_init_device(struct ath5k_softc *sc) {}
 
-static inline void
-ath5k_debug_finish_device(struct ath5k_softc *sc) {}
-
 static inline void
 ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
 
index a8fcc94269f72e0e5bfdcbf9500b17b53123cb2f..62172d5857239549ba6fa233df721096773fd707 100644 (file)
@@ -185,6 +185,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
        struct ath5k_hw_4w_tx_ctl *tx_ctl;
        unsigned int frame_len;
 
+       /*
+        * Use local variables for these to reduce load/store access on
+        * uncached memory
+        */
+       u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0;
+
        tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
        /*
@@ -208,8 +214,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
        if (tx_power > AR5K_TUNE_MAX_TXPOWER)
                tx_power = AR5K_TUNE_MAX_TXPOWER;
 
-       /* Clear descriptor */
-       memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+       /* Clear descriptor status area */
+       memset(&desc->ud.ds_tx5212.tx_stat, 0,
+              sizeof(desc->ud.ds_tx5212.tx_stat));
 
        /* Setup control descriptor */
 
@@ -221,7 +228,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
        if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
                return -EINVAL;
 
-       tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+       txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
 
        /* Verify and set buffer length */
 
@@ -232,21 +239,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
        if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
                return -EINVAL;
 
-       tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+       txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
 
-       tx_ctl->tx_control_0 |=
-               AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
-               AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
-       tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
-                                       AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
-       tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0,
-                                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
-       tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+       txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+                 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+       txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+       txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+       txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 
 #define _TX_FLAGS(_c, _flag)                                   \
        if (flags & AR5K_TXDESC_##_flag) {                      \
-               tx_ctl->tx_control_##_c |=                      \
-                       AR5K_4W_TX_DESC_CTL##_c##_##_flag;      \
+               txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
        }
 
        _TX_FLAGS(0, CLRDMASK);
@@ -262,8 +265,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
         * WEP crap
         */
        if (key_index != AR5K_TXKEYIX_INVALID) {
-               tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-               tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
+               txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+               txctl1 |= AR5K_REG_SM(key_index,
                                AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
        }
 
@@ -274,12 +277,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
                if ((flags & AR5K_TXDESC_RTSENA) &&
                                (flags & AR5K_TXDESC_CTSENA))
                        return -EINVAL;
-               tx_ctl->tx_control_2 |= rtscts_duration &
-                               AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
-               tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+               txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+               txctl3 |= AR5K_REG_SM(rtscts_rate,
                                AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
        }
 
+       tx_ctl->tx_control_0 = txctl0;
+       tx_ctl->tx_control_1 = txctl1;
+       tx_ctl->tx_control_2 = txctl2;
+       tx_ctl->tx_control_3 = txctl3;
+
        return 0;
 }
 
@@ -364,7 +371,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
                AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
        ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-       ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+       ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,
                AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
        /*TODO: ts->ts_virtcol + test*/
        ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
@@ -373,9 +380,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
                AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
        ts->ts_antenna = 1;
        ts->ts_status = 0;
-       ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
-               AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
-       ts->ts_retry[0] = ts->ts_longretry;
        ts->ts_final_idx = 0;
 
        if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
@@ -401,81 +405,48 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 {
        struct ath5k_hw_4w_tx_ctl *tx_ctl;
        struct ath5k_hw_tx_status *tx_status;
+       u32 txstat0, txstat1;
 
        tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
        tx_status = &desc->ud.ds_tx5212.tx_stat;
 
+       txstat1 = ACCESS_ONCE(tx_status->tx_status_1);
+
        /* No frame has been send or error */
-       if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
+       if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))
                return -EINPROGRESS;
 
+       txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
+
        /*
         * Get descriptor status
         */
-       ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+       ts->ts_tstamp = AR5K_REG_MS(txstat0,
                AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-       ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+       ts->ts_shortretry = AR5K_REG_MS(txstat0,
                AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-       ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+       ts->ts_final_retry = AR5K_REG_MS(txstat0,
                AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-       ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+       ts->ts_seqnum = AR5K_REG_MS(txstat1,
                AR5K_DESC_TX_STATUS1_SEQ_NUM);
-       ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+       ts->ts_rssi = AR5K_REG_MS(txstat1,
                AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-       ts->ts_antenna = (tx_status->tx_status_1 &
+       ts->ts_antenna = (txstat1 &
                AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
        ts->ts_status = 0;
 
-       ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+       ts->ts_final_idx = AR5K_REG_MS(txstat1,
                        AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
 
-       /* The longretry counter has the number of un-acked retries
-        * for the final rate. To get the total number of retries
-        * we have to add the retry counters for the other rates
-        * as well
-        */
-       ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
-       switch (ts->ts_final_idx) {
-       case 3:
-               ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
-                       AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-
-               ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
-                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
-               ts->ts_longretry += ts->ts_retry[2];
-               /* fall through */
-       case 2:
-               ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
-                       AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-
-               ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
-                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
-               ts->ts_longretry += ts->ts_retry[1];
-               /* fall through */
-       case 1:
-               ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
-                       AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-
-               ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
-                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
-               ts->ts_longretry += ts->ts_retry[0];
-               /* fall through */
-       case 0:
-               ts->ts_rate[0] = tx_ctl->tx_control_3 &
-                       AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-               break;
-       }
-
        /* TX error */
-       if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
-               if (tx_status->tx_status_0 &
-                               AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+       if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+               if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
                        ts->ts_status |= AR5K_TXERR_XRETRY;
 
-               if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+               if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
                        ts->ts_status |= AR5K_TXERR_FIFO;
 
-               if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+               if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)
                        ts->ts_status |= AR5K_TXERR_FILT;
        }
 
@@ -609,37 +580,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
                                        struct ath5k_rx_status *rs)
 {
        struct ath5k_hw_rx_status *rx_status;
+       u32 rxstat0, rxstat1;
 
        rx_status = &desc->ud.ds_rx.rx_stat;
+       rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);
 
        /* No frame received / not ready */
-       if (unlikely(!(rx_status->rx_status_1 &
-                               AR5K_5212_RX_DESC_STATUS1_DONE)))
+       if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
                return -EINPROGRESS;
 
        memset(rs, 0, sizeof(struct ath5k_rx_status));
+       rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);
 
        /*
         * Frame receive status
         */
-       rs->rs_datalen = rx_status->rx_status_0 &
-               AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
-       rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+       rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+       rs->rs_rssi = AR5K_REG_MS(rxstat0,
                AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-       rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+       rs->rs_rate = AR5K_REG_MS(rxstat0,
                AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
-       rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+       rs->rs_antenna = AR5K_REG_MS(rxstat0,
                AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
-       rs->rs_more = !!(rx_status->rx_status_0 &
-               AR5K_5212_RX_DESC_STATUS0_MORE);
-       rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+       rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
+       rs->rs_tstamp = AR5K_REG_MS(rxstat1,
                AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 
        /*
         * Key table status
         */
-       if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
-               rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+       if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
+               rs->rs_keyix = AR5K_REG_MS(rxstat1,
                                           AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
        else
                rs->rs_keyix = AR5K_RXKEYIX_INVALID;
@@ -647,27 +618,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
        /*
         * Receive/descriptor errors
         */
-       if (!(rx_status->rx_status_1 &
-           AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
-               if (rx_status->rx_status_1 &
-                               AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+       if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+               if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
                        rs->rs_status |= AR5K_RXERR_CRC;
 
-               if (rx_status->rx_status_1 &
-                               AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+               if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
                        rs->rs_status |= AR5K_RXERR_PHY;
-                       rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
+                       rs->rs_phyerr = AR5K_REG_MS(rxstat1,
                                AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
                        if (!ah->ah_capabilities.cap_has_phyerr_counters)
                                ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
                }
 
-               if (rx_status->rx_status_1 &
-                               AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+               if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
                        rs->rs_status |= AR5K_RXERR_DECRYPT;
 
-               if (rx_status->rx_status_1 &
-                               AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+               if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
                        rs->rs_status |= AR5K_RXERR_MIC;
        }
        return 0;
index efb672cb31e49521c95b2207f8f49278db142a4f..1fef84f87c78f5196e57ff5c9a3ad78ca7fed50a 100644 (file)
@@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
                vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
 }
 
+static int
+ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
+{
+       struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+       struct ath5k_chan_pcal_info *chinfo;
+       u8 pier, pdg;
+
+       switch (mode) {
+       case AR5K_EEPROM_MODE_11A:
+               if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+                       return 0;
+               chinfo = ee->ee_pwr_cal_a;
+               break;
+       case AR5K_EEPROM_MODE_11B:
+               if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+                       return 0;
+               chinfo = ee->ee_pwr_cal_b;
+               break;
+       case AR5K_EEPROM_MODE_11G:
+               if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+                       return 0;
+               chinfo = ee->ee_pwr_cal_g;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+               if (!chinfo[pier].pd_curves)
+                       continue;
+
+               for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+                       struct ath5k_pdgain_info *pd =
+                                       &chinfo[pier].pd_curves[pdg];
+
+                       if (pd != NULL) {
+                               kfree(pd->pd_step);
+                               kfree(pd->pd_pwr);
+                       }
+               }
+
+               kfree(chinfo[pier].pd_curves);
+       }
+
+       return 0;
+}
+
 /* Convert RF5111 specific data to generic raw data
  * used by interpolation code */
 static int
@@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
                                GFP_KERNEL);
 
                if (!chinfo[pier].pd_curves)
-                       return -ENOMEM;
+                       goto err_out;
 
                /* Only one curve for RF5111
                 * find out which one and place
@@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
                pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
                                        sizeof(u8), GFP_KERNEL);
                if (!pd->pd_step)
-                       return -ENOMEM;
+                       goto err_out;
 
                pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
                                        sizeof(s16), GFP_KERNEL);
                if (!pd->pd_pwr)
-                       return -ENOMEM;
+                       goto err_out;
 
                /* Fill raw dataset
                 * (convert power to 0.25dB units
@@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
        }
 
        return 0;
+
+err_out:
+       ath5k_eeprom_free_pcal_info(ah, mode);
+       return -ENOMEM;
 }
 
 /* Parse EEPROM data */
@@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
                                        GFP_KERNEL);
 
                if (!chinfo[pier].pd_curves)
-                       return -ENOMEM;
+                       goto err_out;
 
                /* Fill pd_curves */
                for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
@@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
                                                sizeof(u8), GFP_KERNEL);
 
                                if (!pd->pd_step)
-                                       return -ENOMEM;
+                                       goto err_out;
 
                                pd->pd_pwr = kcalloc(pd->pd_points,
                                                sizeof(s16), GFP_KERNEL);
 
                                if (!pd->pd_pwr)
-                                       return -ENOMEM;
-
+                                       goto err_out;
 
                                /* Fill raw dataset
                                 * (all power levels are in 0.25dB units) */
@@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
                                                sizeof(u8), GFP_KERNEL);
 
                                if (!pd->pd_step)
-                                       return -ENOMEM;
+                                       goto err_out;
 
                                pd->pd_pwr = kcalloc(pd->pd_points,
                                                sizeof(s16), GFP_KERNEL);
 
                                if (!pd->pd_pwr)
-                                       return -ENOMEM;
+                                       goto err_out;
 
                                /* Fill raw dataset
                                 * (all power levels are in 0.25dB units) */
@@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
        }
 
        return 0;
+
+err_out:
+       ath5k_eeprom_free_pcal_info(ah, mode);
+       return -ENOMEM;
 }
 
 /* Parse EEPROM data */
@@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
                                        GFP_KERNEL);
 
                if (!chinfo[pier].pd_curves)
-                       return -ENOMEM;
+                       goto err_out;
 
                /* Fill pd_curves */
                for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
@@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
                                        sizeof(u8), GFP_KERNEL);
 
                        if (!pd->pd_step)
-                               return -ENOMEM;
+                               goto err_out;
 
                        pd->pd_pwr = kcalloc(pd->pd_points,
                                        sizeof(s16), GFP_KERNEL);
 
                        if (!pd->pd_pwr)
-                               return -ENOMEM;
+                               goto err_out;
 
                        /* Fill raw dataset
                         * convert all pwr levels to
@@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
        }
 
        return 0;
+
+err_out:
+       ath5k_eeprom_free_pcal_info(ah, mode);
+       return -ENOMEM;
 }
 
 /* Parse EEPROM data */
@@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
        return 0;
 }
 
-static int
-ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
-{
-       struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-       struct ath5k_chan_pcal_info *chinfo;
-       u8 pier, pdg;
-
-       switch (mode) {
-       case AR5K_EEPROM_MODE_11A:
-               if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
-                       return 0;
-               chinfo = ee->ee_pwr_cal_a;
-               break;
-       case AR5K_EEPROM_MODE_11B:
-               if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
-                       return 0;
-               chinfo = ee->ee_pwr_cal_b;
-               break;
-       case AR5K_EEPROM_MODE_11G:
-               if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
-                       return 0;
-               chinfo = ee->ee_pwr_cal_g;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
-               if (!chinfo[pier].pd_curves)
-                       continue;
-
-               for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-                       struct ath5k_pdgain_info *pd =
-                                       &chinfo[pier].pd_curves[pdg];
-
-                       if (pd != NULL) {
-                               kfree(pd->pd_step);
-                               kfree(pd->pd_pwr);
-                       }
-               }
-
-               kfree(chinfo[pier].pd_curves);
-       }
-
-       return 0;
-}
-
 /* Read conformance test limits used for regulatory control */
 static int
 ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
@@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
        return ret;
 }
 
-/*
- * Read the MAC address from eeprom
- */
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
-       u8 mac_d[ETH_ALEN] = {};
-       u32 total, offset;
-       u16 data;
-       int octet;
-
-       AR5K_EEPROM_READ(0x20, data);
-
-       for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
-               AR5K_EEPROM_READ(offset, data);
-
-               total += data;
-               mac_d[octet + 1] = data & 0xff;
-               mac_d[octet] = data >> 8;
-               octet += 2;
-       }
-
-       if (!total || total == 3 * 0xffff)
-               return -EINVAL;
-
-       memcpy(mac, mac_d, ETH_ALEN);
-
-       return 0;
-}
-
 
 /***********************\
 * Init/Detach functions *
index 9be29b728b1cffe2fdc5d9bf0977fe14e77fc562..807bd6440169b916435e554b9a00793811f84310 100644 (file)
@@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (changes & BSS_CHANGED_BEACON_INT)
                sc->bintval = bss_conf->beacon_int;
 
+       if (changes & BSS_CHANGED_ERP_SLOT) {
+               int slot_time;
+
+               ah->ah_short_slot = bss_conf->use_short_slot;
+               slot_time = ath5k_hw_get_default_slottime(ah) +
+                           3 * ah->ah_coverage_class;
+               ath5k_hw_set_ifs_intervals(ah, slot_time);
+       }
+
        if (changes & BSS_CHANGED_ASSOC) {
                avf->assoc = bss_conf->assoc;
                if (bss_conf->assoc)
index 3c44689a700b7b73030860e35ee941a4f66b6678..296c316a83412eaa64bd4c6bd47b264dc4910822 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/nl80211.h>
 #include <linux/pci.h>
 #include <linux/pci-aspm.h>
+#include <linux/etherdevice.h>
 #include "../ath.h"
 #include "ath5k.h"
 #include "debug.h"
@@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
        return 0;
 }
 
+/*
+ * Read the MAC address from eeprom or platform_data
+ */
+static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+       u8 mac_d[ETH_ALEN] = {};
+       u32 total, offset;
+       u16 data;
+       int octet;
+
+       AR5K_EEPROM_READ(0x20, data);
+
+       for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+               AR5K_EEPROM_READ(offset, data);
+
+               total += data;
+               mac_d[octet + 1] = data & 0xff;
+               mac_d[octet] = data >> 8;
+               octet += 2;
+       }
+
+       if (!total || total == 3 * 0xffff)
+               return -EINVAL;
+
+       memcpy(mac, mac_d, ETH_ALEN);
+
+       return 0;
+}
+
+
 /* Common ath_bus_opts structure */
 static const struct ath_bus_ops ath_pci_bus_ops = {
        .ath_bus_type = ATH_PCI,
        .read_cachesize = ath5k_pci_read_cachesize,
        .eeprom_read = ath5k_pci_eeprom_read,
+       .eeprom_read_mac = ath5k_pci_eeprom_read_mac,
 };
 
 /********************\
index d9b3f828455aeaf3fd19907aed1cd9030af6f54d..712a9ac4000e47d313ad9b29296bb5c940cc98ff 100644 (file)
@@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] =
  * bwmodes.
  */
 int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
-               int len, struct ieee80211_rate *rate)
+               int len, struct ieee80211_rate *rate, bool shortpre)
 {
        struct ath5k_softc *sc = ah->ah_sc;
        int sifs, preamble, plcp_bits, sym_time;
@@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
 
        /* Fallback */
        if (!ah->ah_bwmode) {
-               dur = ieee80211_generic_frame_duration(sc->hw,
-                                               NULL, len, rate);
-               return le16_to_cpu(dur);
+               __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
+                                       NULL, len, rate);
+
+               /* subtract difference between long and short preamble */
+               dur = le16_to_cpu(raw_dur);
+               if (shortpre)
+                       dur -= 96;
+
+               return dur;
        }
 
        bitrate = rate->bitrate;
@@ -145,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
                slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
                break;
        case AR5K_BWMODE_DEFAULT:
-               slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
        default:
-               if (channel->hw_value & CHANNEL_CCK)
+               slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
+               if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
                        slot_time = AR5K_INIT_SLOT_TIME_B;
                break;
        }
@@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
                 * actual rate for this rate. See mac80211 tx.c
                 * ieee80211_duration() for a brief description of
                 * what rate we should choose to TX ACKs. */
-               tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+               tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
 
                ath5k_hw_reg_write(ah, tx_time, reg);
 
                if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
                        continue;
 
-               /*
-                * We're not distinguishing short preamble here,
-                * This is true, all we'll get is a longer value here
-                * which is not necessarilly bad. We could use
-                * export ieee80211_frame_duration() but that needs to be
-                * fixed first to be properly used by mac802111 drivers:
-                *
-                *  - remove erp stuff and let the routine figure ofdm
-                *    erp rates
-                *  - remove passing argument ieee80211_local as
-                *    drivers don't have access to it
-                *  - move drivers using ieee80211_generic_frame_duration()
-                *    to this
-                */
+               tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);
                ath5k_hw_reg_write(ah, tx_time,
                        reg + (AR5K_SET_SHORT_PREAMBLE << 2));
        }
index 3343fb9e4940f24012ed07020d7c99dc3dbad0e6..b18c5021aac36f826904787632ba8499d39d9f7e 100644 (file)
@@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
                return -EINVAL;
 
        sifs = ath5k_hw_get_default_sifs(ah);
-       sifs_clock = ath5k_hw_htoclock(ah, sifs);
+       sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
 
        /* EIFS
         * Txtime of ack at lowest rate + SIFS + DIFS
@@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
        else
                rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
 
-       ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+       ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
 
        /* ack_tx_time includes an SIFS already */
        eifs = ack_tx_time + sifs + 2 * slot_time;
index ad57a6d2311067cc798889fef2336f9e63949511..d9ff8413ab9af4e6e9634277cec7e58752c833b0 100644 (file)
@@ -5,7 +5,7 @@ config ATH9K_COMMON
 
 config ATH9K
        tristate "Atheros 802.11n wireless cards support"
-       depends on PCI && MAC80211
+       depends on MAC80211
        select ATH9K_HW
        select MAC80211_LEDS
        select LEDS_CLASS
@@ -23,6 +23,25 @@ config ATH9K
 
          If you choose to build a module, it'll be called ath9k.
 
+config ATH9K_PCI
+       bool "Atheros ath9k PCI/PCIe bus support"
+       depends on ATH9K && PCI
+       default PCI
+       ---help---
+         This option enables the PCI bus support in ath9k.
+
+         Say Y, if you have a compatible PCI/PCIe wireless card.
+
+config ATH9K_AHB
+       bool "Atheros ath9k AHB bus support"
+       depends on ATH9K
+       default n
+       ---help---
+         This option enables the AHB bus support in ath9k.
+
+         Say Y, if you have a SoC with a compatible built-in
+         wireless MAC. Say N if unsure.
+
 config ATH9K_DEBUGFS
        bool "Atheros ath9k debugging"
        depends on ATH9K && DEBUG_FS
index 4d66ca8042ebcd3bd242b7fe6c0dd8edaf684ce6..05a6fade7b1cea811402b5a7e95b3490f415936f 100644 (file)
@@ -6,8 +6,8 @@ ath9k-y +=      beacon.o \
                xmit.o \
 
 ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
-ath9k-$(CONFIG_PCI) += pci.o
-ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
+ath9k-$(CONFIG_ATH9K_PCI) += pci.o
+ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
@@ -48,4 +48,6 @@ ath9k_htc-y +=        htc_hst.o \
                htc_drv_init.o \
                htc_drv_gpio.o
 
+ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o
+
 obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
index 9cb0efa9b4c0873710c99d28d7dbd6ab5feee696..5193ed58a17b781516bd0a6773762b68fdb5f3f8 100644 (file)
 #include <linux/ath9k_platform.h>
 #include "ath9k.h"
 
+const struct platform_device_id ath9k_platform_id_table[] = {
+       {
+               .name = "ath9k",
+               .driver_data = AR5416_AR9100_DEVID,
+       },
+       {},
+};
+
 /* return bus cachesize in 4B word units */
 static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
 {
@@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
        struct ath_softc *sc;
        struct ieee80211_hw *hw;
        struct resource *res;
+       const struct platform_device_id *id = platform_get_device_id(pdev);
        int irq;
        int ret = 0;
        struct ath_hw *ah;
@@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
                goto err_free_hw;
        }
 
-       ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops);
+       ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops);
        if (ret) {
                dev_err(&pdev->dev, "failed to initialize device\n");
                goto err_irq;
@@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = {
                .name   = "ath9k",
                .owner  = THIS_MODULE,
        },
+       .id_table    = ath9k_platform_id_table,
 };
 
+MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
+
 int ath_ahb_init(void)
 {
        return platform_driver_register(&ath_ahb_driver);
index 8dd8f63085024680540df644fde89296f058f4e4..c338efbccf40c29931dfc69c39b9c918314ba1da 100644 (file)
@@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
                | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
                | SM(txPower, AR_XmitPower)
                | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-               | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
                | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
                | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
 
@@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
        }
 }
 
+static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+{
+       struct ar5416_desc *ads = AR5416DESC(ds);
+
+       if (val)
+               ads->ds_ctl0 |= AR_ClrDestMask;
+       else
+               ads->ds_ctl0 &= ~AR_ClrDestMask;
+}
+
 static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
                                          void *lastds,
                                          u32 durUpdateEn, u32 rtsctsRate,
@@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
        ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
        ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
        ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
+       ops->set_clrdmask = ar9002_hw_set_clrdmask;
 }
index 37663dbbcf57959f9b9afb15fe5b15e0efd613cd..47780ef1c892e56317d48e4fdc500bf34fc7c17f 100644 (file)
 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000
 #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19
 
+#define AR_PHY_TX_PWRCTRL8       0xa278
+
 #define AR_PHY_TX_PWRCTRL9       0xa27C
+
+#define AR_PHY_TX_PWRCTRL10       0xa394
 #define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00
 #define AR_PHY_TX_DESIRED_SCALE_CCK_S      10
 #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000
 
 #define AR_PHY_CH0_TX_PWRCTRL11  0xa398
 #define AR_PHY_CH1_TX_PWRCTRL11  0xb398
+#define AR_PHY_CH0_TX_PWRCTRL12  0xa3dc
+#define AR_PHY_CH0_TX_PWRCTRL13  0xa3e0
 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00
 #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
 
index 9ecca93392e8a563fc9775caa814b3ae64120917..f915a3dbfcad106737b4fc803c814a6ae63e067f 100644 (file)
@@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
 
 static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
-       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
-       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
@@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
        {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
        {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
        {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
-       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
-       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
-       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
-       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
-       {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
        {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
@@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
        {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
@@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
        {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
        {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
        {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
        {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
@@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
 
 static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
-       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
-       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
        {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
@@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
        {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
        {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
        {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
-       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
-       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
-       {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
-       {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
        {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
@@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
 
 static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
@@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
        {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
        {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
        {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
        {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
        {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
        {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
@@ -1361,45 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
        {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
        {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
        {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
-       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
-       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
-       {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
-       {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
-       {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
-       {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
-       {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
-       {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
-       {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
-       {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
-       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
-       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
-       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
-       {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
        {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
index 724ac2464ad59e62d1474a37be32d45cb96f2758..c1264d60c49925c07ffa58763dc3faad0ac7682a 100644 (file)
@@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
                | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
                | SM(txpower, AR_XmitPower)
                | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-               | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
                | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
                | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
 
@@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
        ads->ctl22 = 0;
 }
 
+static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+{
+       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
+
+       if (val)
+               ads->ctl11 |= AR_ClrDestMask;
+       else
+               ads->ctl11 &= ~AR_ClrDestMask;
+}
+
 static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
                                          void *lastds,
                                          u32 durUpdateEn, u32 rtsctsRate,
@@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
        ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
        ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
        ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
+       ops->set_clrdmask = ar9003_hw_set_clrdmask;
 }
 
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
index eb250d6b8038140f8729559f76760e3290910ff7..1bc33f51e4663c877fca5208d4c9fcee83df8481 100644 (file)
@@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
        freq = centers.synth_center;
 
        if (freq < 4800) {     /* 2 GHz, fractional mode */
-               if (AR_SREV_9485(ah))
-                       channelSel = CHANSEL_2G_9485(freq);
-               else
+               if (AR_SREV_9485(ah)) {
+                       u32 chan_frac;
+
+                       /*
+                        * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
+                        * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
+                        * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
+                        */
+                       channelSel = (freq * 4) / 120;
+                       chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
+                       channelSel = (channelSel << 17) | chan_frac;
+               } else
                        channelSel = CHANSEL_2G(freq);
                /* Set to 2G mode */
                bMode = 1;
@@ -401,7 +410,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
 
        ar9003_hw_spur_ofdm_clear(ah);
 
-       for (i = 0; spurChansPtr[i] && i < 5; i++) {
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
                freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
                if (abs(freq_offset) < range) {
                        ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
index f91f73e50d00b95cdee7216544a468608ff52b2a..fbdde29f0ab8d4e9349d3320e923eeef262d4432 100644 (file)
@@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
        {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
        {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
        {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
        {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
        {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
        {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
@@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
        {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
        {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
        {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
        {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
        {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
        {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
@@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
        {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
        {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
        {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
        {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
        {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
        {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
@@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
        {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
        {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
        {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
        {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
        {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
        {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
@@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
        {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
        {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
        {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
        {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
        {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
        {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
index 38835bc324b2a99b066754d6fa9691504987afa4..a6b538802251ae4108fd1ac4027bcf66c5b2da70 100644 (file)
@@ -200,6 +200,7 @@ struct ath_atx_ac {
        int sched;
        struct list_head list;
        struct list_head tid_q;
+       bool clear_ps_filter;
 };
 
 struct ath_frame_info {
@@ -255,8 +256,12 @@ struct ath_node {
 #endif
        struct ath_atx_tid tid[WME_NUM_TID];
        struct ath_atx_ac ac[WME_NUM_AC];
+       int ps_key;
+
        u16 maxampdu;
        u8 mpdudensity;
+
+       bool sleeping;
 };
 
 #define AGGR_CLEANUP         BIT(1)
@@ -338,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 
+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
+bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
+
 /********/
 /* VIFs */
 /********/
@@ -665,7 +673,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
 bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
 bool ath9k_uses_beacons(int type);
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_ATH9K_PCI
 int ath_pci_init(void);
 void ath_pci_exit(void);
 #else
@@ -673,7 +681,7 @@ static inline int ath_pci_init(void) { return 0; };
 static inline void ath_pci_exit(void) {};
 #endif
 
-#ifdef CONFIG_ATHEROS_AR71XX
+#ifdef CONFIG_ATH9K_AHB
 int ath_ahb_init(void);
 void ath_ahb_exit(void);
 #else
index eccb0ec87adbca404416863f0b6193e54980d783..24f565ba9988a4a0726aec7dbf0f2434479172b0 100644 (file)
@@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
        if (avp->av_bcbuf != NULL) {
                struct ath_buf *bf;
 
+               avp->is_bslot_active = false;
                if (avp->av_bslot != -1) {
                        sc->beacon.bslot[avp->av_bslot] = NULL;
                        sc->nbcnvifs--;
@@ -743,9 +744,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
                cur_conf->dtim_period = 1;
 
        ath_set_beacon(sc);
-       sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
 }
 
+static bool ath_has_valid_bslot(struct ath_softc *sc)
+{
+       struct ath_vif *avp;
+       int slot;
+       bool found = false;
+
+       for (slot = 0; slot < ATH_BCBUF; slot++) {
+               if (sc->beacon.bslot[slot]) {
+                       avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+                       if (avp->is_bslot_active) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+       return found;
+}
+
+
 void ath_set_beacon(struct ath_softc *sc)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -753,7 +772,8 @@ void ath_set_beacon(struct ath_softc *sc)
 
        switch (sc->sc_ah->opmode) {
        case NL80211_IFTYPE_AP:
-               ath_beacon_config_ap(sc, cur_conf);
+               if (ath_has_valid_bslot(sc))
+                       ath_beacon_config_ap(sc, cur_conf);
                break;
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_MESH_POINT:
@@ -761,6 +781,12 @@ void ath_set_beacon(struct ath_softc *sc)
                break;
        case NL80211_IFTYPE_STATION:
                ath_beacon_config_sta(sc, cur_conf);
+               /*
+                * Request a re-configuration of Beacon related timers
+                * on the receipt of the first Beacon frame (i.e.,
+                * after time sync with the AP).
+                */
+               sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
                break;
        default:
                ath_dbg(common, ATH_DBG_CONFIG,
@@ -774,20 +800,8 @@ void ath_set_beacon(struct ath_softc *sc)
 void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
 {
        struct ath_hw *ah = sc->sc_ah;
-       struct ath_vif *avp;
-       int slot;
-       bool found = false;
 
-       for (slot = 0; slot < ATH_BCBUF; slot++) {
-               if (sc->beacon.bslot[slot]) {
-                       avp = (void *)sc->beacon.bslot[slot]->drv_priv;
-                       if (avp->is_bslot_active) {
-                               found = true;
-                               break;
-                       }
-               }
-       }
-       if (!found)
+       if (!ath_has_valid_bslot(sc))
                return;
 
        ath9k_ps_wakeup(sc);
index a762cadb3ab754c4621b7973a8b3af1bc0535b2d..34f191ec8e8cab2b3a043dcf1640fb69984a35d7 100644 (file)
@@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
 
        struct ath_softc *sc = file->private_data;
        char *buf;
-       unsigned int len = 0, size = 1152;
+       unsigned int len = 0, size = 1400;
        ssize_t retval = 0;
 
        buf = kzalloc(size, GFP_KERNEL);
@@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
                        "%18s : %10u\n", "DECRYPT BUSY ERR",
                        sc->debug.stats.rxstats.decrypt_busy_err);
 
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-CTL0",
+                       sc->debug.stats.rxstats.rs_rssi_ctl0);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-CTL1",
+                       sc->debug.stats.rxstats.rs_rssi_ctl1);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-CTL2",
+                       sc->debug.stats.rxstats.rs_rssi_ctl2);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-EXT0",
+                       sc->debug.stats.rxstats.rs_rssi_ext0);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-EXT1",
+                       sc->debug.stats.rxstats.rs_rssi_ext1);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "RSSI-EXT2",
+                       sc->debug.stats.rxstats.rs_rssi_ext2);
+
+       len += snprintf(buf + len, size - len,
+                       "%18s : %10d\n", "Rx Antenna",
+                       sc->debug.stats.rxstats.rs_antenna);
+
        PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
        PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
        PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
@@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
                RX_PHY_ERR_INC(phyerr);
        }
 
+       sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
+       sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
+       sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
+
+       sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
+       sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
+       sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
+
+       sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
+
 #undef RX_STAT_INC
 #undef RX_PHY_ERR_INC
 }
index 59338de0ce19bdaef71d4a0a4c5b1a7594628eb6..1f9f8eada465d88331e46a334aeaa31c7da05e55 100644 (file)
@@ -157,6 +157,13 @@ struct ath_rx_stats {
        u32 post_delim_crc_err;
        u32 decrypt_busy_err;
        u32 phy_err_stats[ATH9K_PHYERR_MAX];
+       int8_t rs_rssi_ctl0;
+       int8_t rs_rssi_ctl1;
+       int8_t rs_rssi_ctl2;
+       int8_t rs_rssi_ext0;
+       int8_t rs_rssi_ext1;
+       int8_t rs_rssi_ext2;
+       u8 rs_antenna;
 };
 
 struct ath_stats {
index bd82447f5b780b26df88c138191610c34e2a582b..3e316133f114c9b6765b9002d168e157fbccdaba 100644 (file)
@@ -436,7 +436,11 @@ struct modal_eep_4k_header {
        u8 db2_2:4, db2_3:4;
        u8 db2_4:4, reserved:4;
 #endif
-       u8 futureModal[4];
+       u8 tx_diversity;
+       u8 flc_pwr_thresh;
+       u8 bb_scale_smrt_antenna;
+#define EEP_4K_BB_DESIRED_SCALE_MASK   0x1f
+       u8 futureModal[1];
        struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
 } __packed;
 
index bc77a308c901eaf8ccd4c111f2600a754d0774b9..6f714dd723653032c0622b8821852749b4254f38 100644 (file)
@@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 {
        struct modal_eep_4k_header *pModal;
        struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+       struct base_eep_header_4k *pBase = &eep->baseEepHeader;
        u8 txRxAttenLocal;
        u8 ob[5], db1[5], db2[5];
        u8 ant_div_control1, ant_div_control2;
@@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
                                      AR_PHY_SETTLING_SWITCH,
                                      pModal->swSettleHt40);
        }
+       if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
+               u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
+                               EEP_4K_BB_DESIRED_SCALE_MASK);
+               if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
+                       u32 pwrctrl, mask, clr;
+
+                       mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+                       mask = BIT(0)|BIT(5)|BIT(15);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
+
+                       mask = BIT(0)|BIT(5);
+                       pwrctrl = mask * bb_desired_scale;
+                       clr = mask * 0x1f;
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+                       REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+               }
+       }
 }
 
 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
index 2f0712ea49a69c97287888ecc53dc84e7d8b51f4..13579752a3006c9ccf883ed0cb55c19d818285c5 100644 (file)
@@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
 {
        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
        struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
-       u16 antWrites[AR9287_ANT_16S];
        u32 regChainOffset, regval;
        u8 txRxAttenLocal;
-       int i, j, offset_num;
+       int i;
 
        pModal = &eep->modalHeader;
 
-       antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
-       antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
-       antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
-       antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
-       antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
-       antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
-       antWrites[6] = (u16)((pModal->antCtrlCommon >> 4)  & 0xF);
-       antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
-
-       offset_num = 8;
-
-       for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
-               antWrites[j++] = 0;
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
-               antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
-               antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
-       }
-
        REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
 
        for (i = 0; i < AR9287_MAX_CHAINS; i++) {
index 2d10239ce8295e2633699c6680a9f1b7072703e1..2e3a33a53406a85d08c4266d90e33462a1a8208b 100644 (file)
 #include "htc.h"
 
 /* identify firmware images */
-#define FIRMWARE_AR7010                "ar7010.fw"
-#define FIRMWARE_AR7010_1_1    "ar7010_1_1.fw"
-#define FIRMWARE_AR9271                "ar9271.fw"
+#define FIRMWARE_AR7010_1_1     "htc_7010.fw"
+#define FIRMWARE_AR9271         "htc_9271.fw"
 
-MODULE_FIRMWARE(FIRMWARE_AR7010);
 MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
 MODULE_FIRMWARE(FIRMWARE_AR9271);
 
@@ -80,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb)
 
        if (cmd) {
                ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
-                                         cmd->skb, 1);
+                                         cmd->skb, true);
                kfree(cmd);
        }
 
@@ -126,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
        return ret;
 }
 
+static void hif_usb_mgmt_cb(struct urb *urb)
+{
+       struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
+       struct hif_device_usb *hif_dev = cmd->hif_dev;
+       bool txok = true;
+
+       if (!cmd || !cmd->skb || !cmd->hif_dev)
+               return;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ENODEV:
+       case -ESHUTDOWN:
+               txok = false;
+
+               /*
+                * If the URBs are being flushed, no need to complete
+                * this packet.
+                */
+               spin_lock(&hif_dev->tx.tx_lock);
+               if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
+                       spin_unlock(&hif_dev->tx.tx_lock);
+                       dev_kfree_skb_any(cmd->skb);
+                       kfree(cmd);
+                       return;
+               }
+               spin_unlock(&hif_dev->tx.tx_lock);
+
+               break;
+       default:
+               txok = false;
+               break;
+       }
+
+       skb_pull(cmd->skb, 4);
+       ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
+                                 cmd->skb, txok);
+       kfree(cmd);
+}
+
+static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev,
+                            struct sk_buff *skb)
+{
+       struct urb *urb;
+       struct cmd_buf *cmd;
+       int ret = 0;
+       __le16 *hdr;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (urb == NULL)
+               return -ENOMEM;
+
+       cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+       if (cmd == NULL) {
+               usb_free_urb(urb);
+               return -ENOMEM;
+       }
+
+       cmd->skb = skb;
+       cmd->hif_dev = hif_dev;
+
+       hdr = (__le16 *) skb_push(skb, 4);
+       *hdr++ = cpu_to_le16(skb->len - 4);
+       *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG);
+
+       usb_fill_bulk_urb(urb, hif_dev->udev,
+                        usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE),
+                        skb->data, skb->len,
+                        hif_usb_mgmt_cb, cmd);
+
+       usb_anchor_urb(urb, &hif_dev->mgmt_submitted);
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret) {
+               usb_unanchor_urb(urb);
+               kfree(cmd);
+       }
+       usb_free_urb(urb);
+
+       return ret;
+}
+
 static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
                                         struct sk_buff_head *list)
 {
@@ -133,7 +215,22 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
 
        while ((skb = __skb_dequeue(list)) != NULL) {
                dev_kfree_skb_any(skb);
-               TX_STAT_INC(skb_dropped);
+       }
+}
+
+static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
+                                           struct sk_buff_head *queue,
+                                           bool txok)
+{
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(queue)) != NULL) {
+               ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
+                                         skb, txok);
+               if (txok)
+                       TX_STAT_INC(skb_success);
+               else
+                       TX_STAT_INC(skb_failed);
        }
 }
 
@@ -141,7 +238,7 @@ static void hif_usb_tx_cb(struct urb *urb)
 {
        struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
        struct hif_device_usb *hif_dev;
-       struct sk_buff *skb;
+       bool txok = true;
 
        if (!tx_buf || !tx_buf->hif_dev)
                return;
@@ -155,10 +252,7 @@ static void hif_usb_tx_cb(struct urb *urb)
        case -ECONNRESET:
        case -ENODEV:
        case -ESHUTDOWN:
-               /*
-                * The URB has been killed, free the SKBs.
-                */
-               ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
+               txok = false;
 
                /*
                 * If the URBs are being flushed, no need to add this
@@ -167,41 +261,19 @@ static void hif_usb_tx_cb(struct urb *urb)
                spin_lock(&hif_dev->tx.tx_lock);
                if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
                        spin_unlock(&hif_dev->tx.tx_lock);
+                       ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
                        return;
                }
                spin_unlock(&hif_dev->tx.tx_lock);
 
-               /*
-                * In the stop() case, this URB has to be added to
-                * the free list.
-                */
-               goto add_free;
+               break;
        default:
+               txok = false;
                break;
        }
 
-       /*
-        * Check if TX has been stopped, this is needed because
-        * this CB could have been invoked just after the TX lock
-        * was released in hif_stop() and kill_urb() hasn't been
-        * called yet.
-        */
-       spin_lock(&hif_dev->tx.tx_lock);
-       if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
-               spin_unlock(&hif_dev->tx.tx_lock);
-               ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
-               goto add_free;
-       }
-       spin_unlock(&hif_dev->tx.tx_lock);
-
-       /* Complete the queued SKBs. */
-       while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
-               ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
-                                         skb, 1);
-               TX_STAT_INC(skb_completed);
-       }
+       ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok);
 
-add_free:
        /* Re-initialize the SKB queue */
        tx_buf->len = tx_buf->offset = 0;
        __skb_queue_head_init(&tx_buf->skb_queue);
@@ -274,7 +346,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
        ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
        if (ret) {
                tx_buf->len = tx_buf->offset = 0;
-               ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
+               ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false);
                __skb_queue_head_init(&tx_buf->skb_queue);
                list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
                hif_dev->tx.tx_buf_cnt++;
@@ -286,10 +358,11 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
        return ret;
 }
 
-static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
-                          struct ath9k_htc_tx_ctl *tx_ctl)
+static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
 {
+       struct ath9k_htc_tx_ctl *tx_ctl;
        unsigned long flags;
+       int ret = 0;
 
        spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 
@@ -304,26 +377,36 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
                return -ENOMEM;
        }
 
-       __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
-       hif_dev->tx.tx_skb_cnt++;
+       spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
-       /* Send normal frames immediately */
-       if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL)))
-               __hif_usb_tx(hif_dev);
+       tx_ctl = HTC_SKB_CB(skb);
+
+       /* Mgmt/Beacon frames don't use the TX buffer pool */
+       if ((tx_ctl->type == ATH9K_HTC_MGMT) ||
+           (tx_ctl->type == ATH9K_HTC_BEACON)) {
+               ret = hif_usb_send_mgmt(hif_dev, skb);
+       }
+
+       spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+
+       if ((tx_ctl->type == ATH9K_HTC_NORMAL) ||
+           (tx_ctl->type == ATH9K_HTC_AMPDU)) {
+               __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
+               hif_dev->tx.tx_skb_cnt++;
+       }
 
        /* Check if AMPDUs have to be sent immediately */
-       if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) &&
-           (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
+       if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
            (hif_dev->tx.tx_skb_cnt < 2)) {
                __hif_usb_tx(hif_dev);
        }
 
        spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
-       return 0;
+       return ret;
 }
 
-static void hif_usb_start(void *hif_handle, u8 pipe_id)
+static void hif_usb_start(void *hif_handle)
 {
        struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
        unsigned long flags;
@@ -335,14 +418,14 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id)
        spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 }
 
-static void hif_usb_stop(void *hif_handle, u8 pipe_id)
+static void hif_usb_stop(void *hif_handle)
 {
        struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
        struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
-       ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue);
+       ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false);
        hif_dev->tx.tx_skb_cnt = 0;
        hif_dev->tx.flags |= HIF_USB_TX_STOP;
        spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
@@ -352,17 +435,18 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
                                 &hif_dev->tx.tx_pending, list) {
                usb_kill_urb(tx_buf->urb);
        }
+
+       usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
 }
 
-static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
-                       struct ath9k_htc_tx_ctl *tx_ctl)
+static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
 {
        struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
        int ret = 0;
 
        switch (pipe_id) {
        case USB_WLAN_TX_PIPE:
-               ret = hif_usb_send_tx(hif_dev, skb, tx_ctl);
+               ret = hif_usb_send_tx(hif_dev, skb);
                break;
        case USB_REG_OUT_PIPE:
                ret = hif_usb_send_regout(hif_dev, skb);
@@ -377,6 +461,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
        return ret;
 }
 
+static inline bool check_index(struct sk_buff *skb, u8 idx)
+{
+       struct ath9k_htc_tx_ctl *tx_ctl;
+
+       tx_ctl = HTC_SKB_CB(skb);
+
+       if ((tx_ctl->type == ATH9K_HTC_AMPDU) &&
+           (tx_ctl->sta_idx == idx))
+               return true;
+
+       return false;
+}
+
+static void hif_usb_sta_drain(void *hif_handle, u8 idx)
+{
+       struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
+       struct sk_buff *skb, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
+
+       skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) {
+               if (check_index(skb, idx)) {
+                       __skb_unlink(skb, &hif_dev->tx.tx_skb_queue);
+                       ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
+                                                 skb, false);
+                       hif_dev->tx.tx_skb_cnt--;
+                       TX_STAT_INC(skb_failed);
+               }
+       }
+
+       spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
+}
+
 static struct ath9k_htc_hif hif_usb = {
        .transport = ATH9K_HIF_USB,
        .name = "ath9k_hif_usb",
@@ -386,6 +504,7 @@ static struct ath9k_htc_hif hif_usb = {
 
        .start = hif_usb_start,
        .stop = hif_usb_stop,
+       .sta_drain = hif_usb_sta_drain,
        .send = hif_usb_send,
 };
 
@@ -567,6 +686,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
        case -ESHUTDOWN:
                goto free;
        default:
+               skb_reset_tail_pointer(skb);
+               skb_trim(skb, 0);
+
                goto resubmit;
        }
 
@@ -591,23 +713,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
                                                 USB_REG_IN_PIPE),
                                 nskb->data, MAX_REG_IN_BUF_SIZE,
                                 ath9k_hif_usb_reg_in_cb, nskb);
-
-               ret = usb_submit_urb(urb, GFP_ATOMIC);
-               if (ret) {
-                       kfree_skb(nskb);
-                       urb->context = NULL;
-               }
-
-               return;
        }
 
 resubmit:
-       skb_reset_tail_pointer(skb);
-       skb_trim(skb, 0);
-
+       usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
        ret = usb_submit_urb(urb, GFP_ATOMIC);
-       if (ret)
+       if (ret) {
+               usb_unanchor_urb(urb);
                goto free;
+       }
 
        return;
 free:
@@ -641,6 +755,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
                kfree(tx_buf->buf);
                kfree(tx_buf);
        }
+
+       usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
 }
 
 static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
@@ -652,6 +768,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
        INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
        spin_lock_init(&hif_dev->tx.tx_lock);
        __skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
+       init_usb_anchor(&hif_dev->mgmt_submitted);
 
        for (i = 0; i < MAX_TX_URB_NUM; i++) {
                tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
@@ -748,43 +865,67 @@ err_urb:
        return ret;
 }
 
-static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
+static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)
 {
-       if (hif_dev->reg_in_urb) {
-               usb_kill_urb(hif_dev->reg_in_urb);
-               if (hif_dev->reg_in_urb->context)
-                       kfree_skb((void *)hif_dev->reg_in_urb->context);
-               usb_free_urb(hif_dev->reg_in_urb);
-               hif_dev->reg_in_urb = NULL;
-       }
+       usb_kill_anchored_urbs(&hif_dev->reg_in_submitted);
 }
 
-static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
 {
-       struct sk_buff *skb;
+       struct urb *urb = NULL;
+       struct sk_buff *skb = NULL;
+       int i, ret;
 
-       hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (hif_dev->reg_in_urb == NULL)
-               return -ENOMEM;
+       init_usb_anchor(&hif_dev->reg_in_submitted);
 
-       skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
-       if (!skb)
-               goto err;
+       for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
 
-       usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev,
-                        usb_rcvbulkpipe(hif_dev->udev,
-                                        USB_REG_IN_PIPE),
-                        skb->data, MAX_REG_IN_BUF_SIZE,
-                        ath9k_hif_usb_reg_in_cb, skb);
+               /* Allocate URB */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (urb == NULL) {
+                       ret = -ENOMEM;
+                       goto err_urb;
+               }
 
-       if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
-               goto err;
+               /* Allocate buffer */
+               skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
+               if (!skb) {
+                       ret = -ENOMEM;
+                       goto err_skb;
+               }
+
+               usb_fill_bulk_urb(urb, hif_dev->udev,
+                                 usb_rcvbulkpipe(hif_dev->udev,
+                                                 USB_REG_IN_PIPE),
+                                 skb->data, MAX_REG_IN_BUF_SIZE,
+                                 ath9k_hif_usb_reg_in_cb, skb);
+
+               /* Anchor URB */
+               usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
+
+               /* Submit URB */
+               ret = usb_submit_urb(urb, GFP_KERNEL);
+               if (ret) {
+                       usb_unanchor_urb(urb);
+                       goto err_submit;
+               }
+
+               /*
+                * Drop reference count.
+                * This ensures that the URB is freed when killing them.
+                */
+               usb_free_urb(urb);
+       }
 
        return 0;
 
-err:
-       ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
-       return -ENOMEM;
+err_submit:
+       kfree_skb(skb);
+err_skb:
+       usb_free_urb(urb);
+err_urb:
+       ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
+       return ret;
 }
 
 static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
@@ -801,7 +942,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
                goto err_rx;
 
        /* Register Read */
-       if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
+       if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0)
                goto err_reg;
 
        return 0;
@@ -816,7 +957,7 @@ err:
 static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
 {
        usb_kill_anchored_urbs(&hif_dev->regout_submitted);
-       ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
+       ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
        ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
        ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
 }
@@ -1026,10 +1167,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
        /* Find out which firmware to load */
 
        if (IS_AR7010_DEVICE(id->driver_info))
-               if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
-                       hif_dev->fw_name = FIRMWARE_AR7010_1_1;
-               else
-                       hif_dev->fw_name = FIRMWARE_AR7010;
+               hif_dev->fw_name = FIRMWARE_AR7010_1_1;
        else
                hif_dev->fw_name = FIRMWARE_AR9271;
 
index 7b9d863d4035b278ba52215c4c4d49f388f98599..f59df48a86e22de3b160df5187ef7f989e9b0ef2 100644 (file)
@@ -31,7 +31,7 @@
 
 /* FIXME: Verify these numbers (with Windows) */
 #define MAX_TX_URB_NUM  8
-#define MAX_TX_BUF_NUM  1024
+#define MAX_TX_BUF_NUM  256
 #define MAX_TX_BUF_SIZE 32768
 #define MAX_TX_AGGR_NUM 20
 
@@ -40,7 +40,7 @@
 #define MAX_PKT_NUM_IN_TRANSFER 10
 
 #define MAX_REG_OUT_URB_NUM  1
-#define MAX_REG_OUT_BUF_NUM  8
+#define MAX_REG_IN_URB_NUM   64
 
 #define MAX_REG_IN_BUF_SIZE 64
 
@@ -90,9 +90,10 @@ struct hif_device_usb {
        const struct firmware *firmware;
        struct htc_target *htc_handle;
        struct hif_usb_tx tx;
-       struct urb *reg_in_urb;
        struct usb_anchor regout_submitted;
        struct usb_anchor rx_submitted;
+       struct usb_anchor reg_in_submitted;
+       struct usb_anchor mgmt_submitted;
        struct sk_buff *remain_skb;
        const char *fw_name;
        int rx_remain_len;
index ec47be94b74fa712b04c477ffddf16987ca76239..48a885575085286bd0aae8539071152ff3e72638 100644 (file)
@@ -67,8 +67,11 @@ enum htc_opmode {
 };
 
 #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr)
-#define ATH9K_HTC_AMPDU        1
+
+#define ATH9K_HTC_AMPDU  1
 #define ATH9K_HTC_NORMAL 2
+#define ATH9K_HTC_BEACON 3
+#define ATH9K_HTC_MGMT   4
 
 #define ATH9K_HTC_TX_CTSONLY      0x1
 #define ATH9K_HTC_TX_RTSCTS       0x2
@@ -82,7 +85,8 @@ struct tx_frame_hdr {
        __be32 flags; /* ATH9K_HTC_TX_* */
        u8 key_type;
        u8 keyix;
-       u8 reserved[26];
+       u8 cookie;
+       u8 pad;
 } __packed;
 
 struct tx_mgmt_hdr {
@@ -92,26 +96,16 @@ struct tx_mgmt_hdr {
        u8 flags;
        u8 key_type;
        u8 keyix;
-       u16 reserved;
+       u8 cookie;
+       u8 pad;
 } __packed;
 
 struct tx_beacon_header {
-       u8 len_changed;
        u8 vif_index;
+       u8 len_changed;
        u16 rev;
 } __packed;
 
-struct ath9k_htc_target_hw {
-       u32 flags;
-       u32 flags_ext;
-       u32 ampdu_limit;
-       u8 ampdu_subframes;
-       u8 tx_chainmask;
-       u8 tx_chainmask_legacy;
-       u8 rtscts_ratecode;
-       u8 protmode;
-} __packed;
-
 struct ath9k_htc_cap_target {
        u32 flags;
        u32 flags_ext;
@@ -121,21 +115,16 @@ struct ath9k_htc_cap_target {
        u8 tx_chainmask_legacy;
        u8 rtscts_ratecode;
        u8 protmode;
+       u8 pad;
 } __packed;
 
 struct ath9k_htc_target_vif {
        u8 index;
-       u8 des_bssid[ETH_ALEN];
-       __be32 opmode;
+       u8 opmode;
        u8 myaddr[ETH_ALEN];
-       u8 bssid[ETH_ALEN];
-       u32 flags;
-       u32 flags_ext;
-       u16 ps_sta;
-       __be16 rtsthreshold;
        u8 ath_cap;
-       u8 node;
-       s8 mcast_rate;
+       __be16 rtsthreshold;
+       u8 pad;
 } __packed;
 
 #define ATH_HTC_STA_AUTH  0x0001
@@ -143,27 +132,16 @@ struct ath9k_htc_target_vif {
 #define ATH_HTC_STA_ERP   0x0004
 #define ATH_HTC_STA_HT    0x0008
 
-/* FIXME: UAPSD variables */
 struct ath9k_htc_target_sta {
-       u16 associd;
-       u16 txpower;
-       u32 ucastkey;
        u8 macaddr[ETH_ALEN];
        u8 bssid[ETH_ALEN];
        u8 sta_index;
        u8 vif_index;
-       u8 vif_sta;
-       __be16 flags; /* ATH_HTC_STA_* */
-       u16 htcap;
-       u8 valid;
-       u16 capinfo;
-       struct ath9k_htc_target_hw *hw;
-       struct ath9k_htc_target_vif *vif;
-       u16 txseqmgmt;
        u8 is_vif_sta;
-       u16 maxampdu;
-       u16 iv16;
-       u32 iv32;
+       __be16 flags; /* ATH_HTC_STA_* */
+       __be16 htcap;
+       __be16 maxampdu;
+       u8 pad;
 } __packed;
 
 struct ath9k_htc_target_aggr {
@@ -197,12 +175,31 @@ struct ath9k_htc_target_rate {
        struct ath9k_htc_rate rates;
 };
 
-struct ath9k_htc_target_stats {
-       __be32 tx_shortretry;
-       __be32 tx_longretry;
-       __be32 tx_xretries;
-       __be32 ht_txunaggr_xretry;
-       __be32 ht_tx_xretries;
+struct ath9k_htc_target_int_stats {
+       __be32 rx;
+       __be32 rxorn;
+       __be32 rxeol;
+       __be32 txurn;
+       __be32 txto;
+       __be32 cst;
+} __packed;
+
+struct ath9k_htc_target_tx_stats {
+       __be32 xretries;
+       __be32 fifoerr;
+       __be32 filtered;
+       __be32 timer_exp;
+       __be32 shortretries;
+       __be32 longretries;
+       __be32 qnull;
+       __be32 encap_fail;
+       __be32 nobuf;
+} __packed;
+
+struct ath9k_htc_target_rx_stats {
+       __be32 nobuf;
+       __be32 host_send;
+       __be32 host_done;
 } __packed;
 
 #define ATH9K_HTC_MAX_VIF 2
@@ -244,6 +241,8 @@ struct ath9k_htc_vif {
        u8 index;
        u16 seq_no;
        bool beacon_configured;
+       int bslot;
+       __le64 tsfadjust;
 };
 
 struct ath9k_vif_iter_data {
@@ -282,23 +281,65 @@ struct ath9k_htc_rx {
        spinlock_t rxbuflock;
 };
 
+#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */
+#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */
+#define ATH9K_HTC_TX_RESERVE 10
+#define ATH9K_HTC_TX_TIMEOUT_COUNT 20
+#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE)
+
+#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0)
+#define ATH9K_HTC_OP_TX_DRAIN       BIT(1)
+
+struct ath9k_htc_tx {
+       u8 flags;
+       int queued_cnt;
+       struct sk_buff_head mgmt_ep_queue;
+       struct sk_buff_head cab_ep_queue;
+       struct sk_buff_head data_be_queue;
+       struct sk_buff_head data_bk_queue;
+       struct sk_buff_head data_vi_queue;
+       struct sk_buff_head data_vo_queue;
+       struct sk_buff_head tx_failed;
+       DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
+       struct timer_list cleanup_timer;
+       spinlock_t tx_lock;
+};
+
 struct ath9k_htc_tx_ctl {
        u8 type; /* ATH9K_HTC_* */
+       u8 epid;
+       u8 txok;
+       u8 sta_idx;
+       unsigned long timestamp;
 };
 
+static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+       BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) >
+                    IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
+       return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data;
+}
+
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
 
 #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
 #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
+#define CAB_STAT_INC   priv->debug.tx_stats.cab_queued++
 
 #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
 
+void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
+                          struct ath_htc_rx_status *rxs);
+
 struct ath_tx_stats {
        u32 buf_queued;
        u32 buf_completed;
        u32 skb_queued;
-       u32 skb_completed;
-       u32 skb_dropped;
+       u32 skb_success;
+       u32 skb_failed;
+       u32 cab_queued;
        u32 queue_stats[WME_NUM_AC];
 };
 
@@ -306,25 +347,35 @@ struct ath_rx_stats {
        u32 skb_allocated;
        u32 skb_completed;
        u32 skb_dropped;
+       u32 err_crc;
+       u32 err_decrypt_crc;
+       u32 err_mic;
+       u32 err_pre_delim;
+       u32 err_post_delim;
+       u32 err_decrypt_busy;
+       u32 err_phy;
+       u32 err_phy_stats[ATH9K_PHYERR_MAX];
 };
 
 struct ath9k_debug {
        struct dentry *debugfs_phy;
-       struct dentry *debugfs_tgt_stats;
-       struct dentry *debugfs_xmit;
-       struct dentry *debugfs_recv;
        struct ath_tx_stats tx_stats;
        struct ath_rx_stats rx_stats;
-       u32 txrate;
 };
 
 #else
 
 #define TX_STAT_INC(c) do { } while (0)
 #define RX_STAT_INC(c) do { } while (0)
+#define CAB_STAT_INC   do { } while (0)
 
 #define TX_QSTAT_INC(c) do { } while (0)
 
+static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
+                                        struct ath_htc_rx_status *rxs)
+{
+}
+
 #endif /* CONFIG_ATH9K_HTC_DEBUGFS */
 
 #define ATH_LED_PIN_DEF             1
@@ -351,10 +402,21 @@ struct ath_led {
        int brightness;
 };
 
+#define BSTUCK_THRESHOLD 10
+
+/*
+ * Adjust these when the max. no of beaconing interfaces is
+ * increased.
+ */
+#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */
+#define MIN_SWBA_RESPONSE     10 /* in TUs */
+
 struct htc_beacon_config {
+       struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF];
        u16 beacon_interval;
        u16 dtim_period;
        u16 bmiss_timeout;
+       u32 bmiss_cnt;
 };
 
 struct ath_btcoex {
@@ -388,6 +450,9 @@ struct ath9k_htc_priv {
        struct htc_target *htc;
        struct wmi *wmi;
 
+       u16 fw_version_major;
+       u16 fw_version_minor;
+
        enum htc_endpoint_id wmi_cmd_ep;
        enum htc_endpoint_id beacon_ep;
        enum htc_endpoint_id cab_ep;
@@ -411,27 +476,23 @@ struct ath9k_htc_priv {
        u16 txpowlimit;
        u16 nvifs;
        u16 nstations;
-       u32 bmiss_cnt;
        bool rearm_ani;
        bool reconfig_beacon;
+       unsigned int rxfilter;
 
        struct ath9k_hw_cal_data caldata;
+       struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 
        spinlock_t beacon_lock;
+       struct htc_beacon_config cur_beacon_conf;
 
-       bool tx_queues_stop;
-       spinlock_t tx_lock;
+       struct ath9k_htc_rx rx;
+       struct ath9k_htc_tx tx;
 
-       struct ieee80211_vif *vif;
-       struct htc_beacon_config cur_beacon_conf;
-       unsigned int rxfilter;
        struct tasklet_struct swba_tasklet;
        struct tasklet_struct rx_tasklet;
-       struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-       struct ath9k_htc_rx rx;
-       struct tasklet_struct tx_tasklet;
-       struct sk_buff_head tx_queue;
        struct delayed_work ani_work;
+       struct tasklet_struct tx_failed_tasklet;
        struct work_struct ps_work;
        struct work_struct fatal_work;
 
@@ -470,11 +531,18 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 
 void ath9k_htc_reset(struct ath9k_htc_priv *priv);
 
+void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
+                           struct ieee80211_vif *vif);
+void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
+                           struct ieee80211_vif *vif);
+void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
+                            struct ieee80211_vif *vif);
 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
                             struct ieee80211_vif *vif);
 void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
-void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
+void ath9k_htc_swba(struct ath9k_htc_priv *priv,
+                   struct wmi_event_swba *swba);
 
 void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
                    enum htc_endpoint_id ep_id);
@@ -491,14 +559,23 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
 void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv);
-void ath9k_tx_tasklet(unsigned long data);
-int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb);
+int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
+                      struct sk_buff *skb, u8 slot, bool is_cab);
 void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
 bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype);
 int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);
 int get_hw_qnum(u16 queue, int *hwq_map);
 int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
                       struct ath9k_tx_queue_info *qinfo);
+void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv);
+void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv);
+int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
+void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
+void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
+void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
+void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv);
+void ath9k_tx_failed_tasklet(unsigned long data);
+void ath9k_htc_tx_cleanup_timer(unsigned long data);
 
 int ath9k_rx_init(struct ath9k_htc_priv *priv);
 void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
@@ -528,15 +605,9 @@ void ath9k_htc_suspend(struct htc_target *htc_handle);
 int ath9k_htc_resume(struct htc_target *htc_handle);
 #endif
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
-int ath9k_htc_debug_create_root(void);
-void ath9k_htc_debug_remove_root(void);
 int ath9k_htc_init_debug(struct ath_hw *ah);
-void ath9k_htc_exit_debug(struct ath_hw *ah);
 #else
-static inline int ath9k_htc_debug_create_root(void) { return 0; };
-static inline void ath9k_htc_debug_remove_root(void) {};
 static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; };
-static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {};
 #endif /* CONFIG_ATH9K_HTC_DEBUGFS */
 
 #endif /* HTC_H */
index 8f56158e5887a49ebc23c018ecfc1105a93d3931..a157107b3f3b894d39779f59205a1382770d3f91 100644 (file)
 
 #define FUDGE 2
 
+void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
+{
+       struct ath_hw *ah = priv->ah;
+       struct ath9k_tx_queue_info qi, qi_be;
+
+       memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
+       memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info));
+
+       ath9k_hw_get_txq_props(ah, priv->beaconq, &qi);
+
+       if (priv->ah->opmode == NL80211_IFTYPE_AP) {
+               qi.tqi_aifs = 1;
+               qi.tqi_cwmin = 0;
+               qi.tqi_cwmax = 0;
+       } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
+               int qnum = priv->hwq_map[WME_AC_BE];
+
+               ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+
+               qi.tqi_aifs = qi_be.tqi_aifs;
+
+               /*
+                * For WIFI Beacon Distribution
+                * Long slot time  : 2x cwmin
+                * Short slot time : 4x cwmin
+                */
+               if (ah->slottime == ATH9K_SLOT_TIME_20)
+                       qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
+               else
+                       qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
+
+               qi.tqi_cwmax = qi_be.tqi_cwmax;
+
+       }
+
+       if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
+               ath_err(ath9k_hw_common(ah),
+                       "Unable to update beacon queue %u!\n", priv->beaconq);
+       } else {
+               ath9k_hw_resettxqueue(ah, priv->beaconq);
+       }
+}
+
+
 static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
                                        struct htc_beacon_config *bss_conf)
 {
@@ -154,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
        intval /= ATH9K_HTC_MAX_BCN_VIF;
        nexttbtt = intval;
 
+       /*
+        * To reduce beacon misses under heavy TX load,
+        * set the beacon response time to a larger value.
+        */
+       if (intval > DEFAULT_SWBA_RESPONSE)
+               priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE;
+       else
+               priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
+
        if (priv->op_flags & OP_TSF_RESET) {
                ath9k_hw_reset_tsf(priv->ah);
                priv->op_flags &= ~OP_TSF_RESET;
@@ -172,12 +225,16 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
                imask |= ATH9K_INT_SWBA;
 
        ath_dbg(common, ATH_DBG_CONFIG,
-               "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
-               bss_conf->beacon_interval, nexttbtt, imask);
+               "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);
+
+       ath9k_htc_beaconq_config(priv);
 
        WMI_CMD(WMI_DISABLE_INTR_CMDID);
        ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
-       priv->bmiss_cnt = 0;
+       priv->cur_beacon_conf.bmiss_cnt = 0;
        htc_imask = cpu_to_be32(imask);
        WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
 }
@@ -205,16 +262,26 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
                nexttbtt += intval;
        } while (nexttbtt < tsftu);
 
+       /*
+        * Only one IBSS interfce is allowed.
+        */
+       if (intval > DEFAULT_SWBA_RESPONSE)
+               priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE;
+       else
+               priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
+
        if (priv->op_flags & OP_ENABLE_BEACON)
                imask |= ATH9K_INT_SWBA;
 
        ath_dbg(common, ATH_DBG_CONFIG,
-               "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n",
-               bss_conf->beacon_interval, nexttbtt, imask);
+               "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);
 
        WMI_CMD(WMI_DISABLE_INTR_CMDID);
        ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
-       priv->bmiss_cnt = 0;
+       priv->cur_beacon_conf.bmiss_cnt = 0;
        htc_imask = cpu_to_be32(imask);
        WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
 }
@@ -225,38 +292,101 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
        dev_kfree_skb_any(skb);
 }
 
-void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
+static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
+                                   int slot)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ieee80211_vif *vif;
+       struct sk_buff *skb;
+       struct ieee80211_hdr *hdr;
+       int padpos, padsize, ret, tx_slot;
+
+       spin_lock_bh(&priv->beacon_lock);
+
+       vif = priv->cur_beacon_conf.bslot[slot];
+
+       skb = ieee80211_get_buffered_bc(priv->hw, vif);
+
+       while(skb) {
+               hdr = (struct ieee80211_hdr *) skb->data;
+
+               padpos = ath9k_cmn_padpos(hdr->frame_control);
+               padsize = padpos & 3;
+               if (padsize && skb->len > padpos) {
+                       if (skb_headroom(skb) < padsize) {
+                               dev_kfree_skb_any(skb);
+                               goto next;
+                       }
+                       skb_push(skb, padsize);
+                       memmove(skb->data, skb->data + padsize, padpos);
+               }
+
+               tx_slot = ath9k_htc_tx_get_slot(priv);
+               if (tx_slot < 0) {
+                       ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n");
+                       dev_kfree_skb_any(skb);
+                       goto next;
+               }
+
+               ret = ath9k_htc_tx_start(priv, skb, tx_slot, true);
+               if (ret != 0) {
+                       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");
+               } else {
+                       spin_lock_bh(&priv->tx.tx_lock);
+                       priv->tx.queued_cnt++;
+                       spin_unlock_bh(&priv->tx.tx_lock);
+               }
+       next:
+               skb = ieee80211_get_buffered_bc(priv->hw, vif);
+       }
+
+       spin_unlock_bh(&priv->beacon_lock);
+}
+
+static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
+                                 int slot)
 {
-       struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ieee80211_vif *vif;
+       struct ath9k_htc_vif *avp;
        struct tx_beacon_header beacon_hdr;
-       struct ath9k_htc_tx_ctl tx_ctl;
+       struct ath9k_htc_tx_ctl *tx_ctl;
        struct ieee80211_tx_info *info;
+       struct ieee80211_mgmt *mgmt;
        struct sk_buff *beacon;
        u8 *tx_fhdr;
+       int ret;
 
        memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
-       memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
-
-       /* FIXME: Handle BMISS */
-       if (beacon_pending != 0) {
-               priv->bmiss_cnt++;
-               return;
-       }
 
        spin_lock_bh(&priv->beacon_lock);
 
+       vif = priv->cur_beacon_conf.bslot[slot];
+       avp = (struct ath9k_htc_vif *)vif->drv_priv;
+
        if (unlikely(priv->op_flags & OP_SCANNING)) {
                spin_unlock_bh(&priv->beacon_lock);
                return;
        }
 
        /* Get a new beacon */
-       beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+       beacon = ieee80211_beacon_get(priv->hw, vif);
        if (!beacon) {
                spin_unlock_bh(&priv->beacon_lock);
                return;
        }
 
+       /*
+        * Update the TSF adjust value here, the HW will
+        * add this value for every beacon.
+        */
+       mgmt = (struct ieee80211_mgmt *)beacon->data;
+       mgmt->u.beacon.timestamp = avp->tsfadjust;
+
        info = IEEE80211_SKB_CB(beacon);
        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
                struct ieee80211_hdr *hdr =
@@ -266,45 +396,149 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
                hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
        }
 
-       tx_ctl.type = ATH9K_HTC_NORMAL;
+       tx_ctl = HTC_SKB_CB(beacon);
+       memset(tx_ctl, 0, sizeof(*tx_ctl));
+
+       tx_ctl->type = ATH9K_HTC_BEACON;
+       tx_ctl->epid = priv->beacon_ep;
+
        beacon_hdr.vif_index = avp->index;
        tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
        memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr));
 
-       htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl);
+       ret = htc_send(priv->htc, beacon);
+       if (ret != 0) {
+               if (ret == -ENOMEM) {
+                       ath_dbg(common, ATH_DBG_BSTUCK,
+                               "Failed to send beacon, no free TX buffer\n");
+               }
+               dev_kfree_skb_any(beacon);
+       }
+
+       spin_unlock_bh(&priv->beacon_lock);
+}
+
+static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
+                                 struct wmi_event_swba *swba)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       u64 tsf;
+       u32 tsftu;
+       u16 intval;
+       int slot;
+
+       intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
 
+       tsf = be64_to_cpu(swba->tsf);
+       tsftu = TSF_TO_TU(tsf >> 32, tsf);
+       slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval;
+       slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1;
+
+       ath_dbg(common, ATH_DBG_BEACON,
+               "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n",
+               slot, tsf, tsftu, intval);
+
+       return slot;
+}
+
+void ath9k_htc_swba(struct ath9k_htc_priv *priv,
+                   struct wmi_event_swba *swba)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       int slot;
+
+       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");
+                       ieee80211_queue_work(priv->hw,
+                                            &priv->fatal_work);
+               }
+               return;
+       }
+
+       if (priv->cur_beacon_conf.bmiss_cnt) {
+               ath_dbg(common, ATH_DBG_BSTUCK,
+                       "Resuming beacon xmit after %u misses\n",
+                       priv->cur_beacon_conf.bmiss_cnt);
+               priv->cur_beacon_conf.bmiss_cnt = 0;
+       }
+
+       slot = ath9k_htc_choose_bslot(priv, swba);
+       spin_lock_bh(&priv->beacon_lock);
+       if (priv->cur_beacon_conf.bslot[slot] == NULL) {
+               spin_unlock_bh(&priv->beacon_lock);
+               return;
+       }
        spin_unlock_bh(&priv->beacon_lock);
+
+       ath9k_htc_send_buffered(priv, slot);
+       ath9k_htc_send_beacon(priv, slot);
 }
 
-/* Currently, only for IBSS */
-void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
+void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv,
+                           struct ieee80211_vif *vif)
 {
-       struct ath_hw *ah = priv->ah;
-       struct ath9k_tx_queue_info qi, qi_be;
-       int qnum = priv->hwq_map[WME_AC_BE];
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
+       int i = 0;
 
-       memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
-       memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info));
+       spin_lock_bh(&priv->beacon_lock);
+       for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) {
+               if (priv->cur_beacon_conf.bslot[i] == NULL) {
+                       avp->bslot = i;
+                       break;
+               }
+       }
+
+       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);
+}
+
+void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv,
+                           struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
+
+       spin_lock_bh(&priv->beacon_lock);
+       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);
+}
 
-       ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+/*
+ * Calculate the TSF adjustment value for all slots
+ * other than zero.
+ */
+void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv,
+                            struct ieee80211_vif *vif)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv;
+       struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
+       u64 tsfadjust;
+
+       if (avp->bslot == 0)
+               return;
 
-       qi.tqi_aifs = qi_be.tqi_aifs;
-       /* For WIFI Beacon Distribution
-        * Long slot time  : 2x cwmin
-        * Short slot time : 4x cwmin
+       /*
+        * The beacon interval cannot be different for multi-AP mode,
+        * and we reach here only for VIF slots greater than zero,
+        * so beacon_interval is guaranteed to be set in cur_conf.
         */
-       if (ah->slottime == ATH9K_SLOT_TIME_20)
-               qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
-       else
-               qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
-       qi.tqi_cwmax = qi_be.tqi_cwmax;
+       tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF;
+       avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
 
-       if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
-               ath_err(ath9k_hw_common(ah),
-                       "Unable to update beacon queue %u!\n", qnum);
-       } else {
-               ath9k_hw_resettxqueue(ah, priv->beaconq);
-       }
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "tsfadjust is: %llu for bslot: %d\n",
+               (unsigned long long)tsfadjust, avp->bslot);
 }
 
 static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
new file mode 100644 (file)
index 0000000..eca7774
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2010-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 "htc.h"
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       struct ath9k_htc_target_int_stats cmd_rsp;
+       char buf[512];
+       unsigned int len = 0;
+       int ret = 0;
+
+       memset(&cmd_rsp, 0, sizeof(cmd_rsp));
+
+       WMI_CMD(WMI_INT_STATS_CMDID);
+       if (ret)
+               return -EINVAL;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "RX",
+                       be32_to_cpu(cmd_rsp.rx));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "RXORN",
+                       be32_to_cpu(cmd_rsp.rxorn));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "RXEOL",
+                       be32_to_cpu(cmd_rsp.rxeol));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "TXURN",
+                       be32_to_cpu(cmd_rsp.txurn));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "TXTO",
+                       be32_to_cpu(cmd_rsp.txto));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "CST",
+                       be32_to_cpu(cmd_rsp.cst));
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tgt_int_stats = {
+       .read = read_file_tgt_int_stats,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       struct ath9k_htc_target_tx_stats cmd_rsp;
+       char buf[512];
+       unsigned int len = 0;
+       int ret = 0;
+
+       memset(&cmd_rsp, 0, sizeof(cmd_rsp));
+
+       WMI_CMD(WMI_TX_STATS_CMDID);
+       if (ret)
+               return -EINVAL;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "Xretries",
+                       be32_to_cpu(cmd_rsp.xretries));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "FifoErr",
+                       be32_to_cpu(cmd_rsp.fifoerr));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "Filtered",
+                       be32_to_cpu(cmd_rsp.filtered));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "TimerExp",
+                       be32_to_cpu(cmd_rsp.timer_exp));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "ShortRetries",
+                       be32_to_cpu(cmd_rsp.shortretries));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "LongRetries",
+                       be32_to_cpu(cmd_rsp.longretries));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "QueueNull",
+                       be32_to_cpu(cmd_rsp.qnull));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "EncapFail",
+                       be32_to_cpu(cmd_rsp.encap_fail));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "NoBuf",
+                       be32_to_cpu(cmd_rsp.nobuf));
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tgt_tx_stats = {
+       .read = read_file_tgt_tx_stats,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       struct ath9k_htc_target_rx_stats cmd_rsp;
+       char buf[512];
+       unsigned int len = 0;
+       int ret = 0;
+
+       memset(&cmd_rsp, 0, sizeof(cmd_rsp));
+
+       WMI_CMD(WMI_RX_STATS_CMDID);
+       if (ret)
+               return -EINVAL;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "NoBuf",
+                       be32_to_cpu(cmd_rsp.nobuf));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "HostSend",
+                       be32_to_cpu(cmd_rsp.host_send));
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "HostDone",
+                       be32_to_cpu(cmd_rsp.host_done));
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_tgt_rx_stats = {
+       .read = read_file_tgt_rx_stats,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       char buf[512];
+       unsigned int len = 0;
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "Buffers queued",
+                       priv->debug.tx_stats.buf_queued);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "Buffers completed",
+                       priv->debug.tx_stats.buf_completed);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "SKBs queued",
+                       priv->debug.tx_stats.skb_queued);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "SKBs success",
+                       priv->debug.tx_stats.skb_success);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "SKBs failed",
+                       priv->debug.tx_stats.skb_failed);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "CAB queued",
+                       priv->debug.tx_stats.cab_queued);
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "BE queued",
+                       priv->debug.tx_stats.queue_stats[WME_AC_BE]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "BK queued",
+                       priv->debug.tx_stats.queue_stats[WME_AC_BK]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "VI queued",
+                       priv->debug.tx_stats.queue_stats[WME_AC_VI]);
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "%20s : %10u\n", "VO queued",
+                       priv->debug.tx_stats.queue_stats[WME_AC_VO]);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_xmit = {
+       .read = read_file_xmit,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
+                          struct ath_htc_rx_status *rxs)
+{
+#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++
+
+       if (rxs->rs_status & ATH9K_RXERR_CRC)
+               priv->debug.rx_stats.err_crc++;
+       if (rxs->rs_status & ATH9K_RXERR_DECRYPT)
+               priv->debug.rx_stats.err_decrypt_crc++;
+       if (rxs->rs_status & ATH9K_RXERR_MIC)
+               priv->debug.rx_stats.err_mic++;
+       if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
+               priv->debug.rx_stats.err_pre_delim++;
+       if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST)
+               priv->debug.rx_stats.err_post_delim++;
+       if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY)
+               priv->debug.rx_stats.err_decrypt_busy++;
+
+       if (rxs->rs_status & ATH9K_RXERR_PHY) {
+               priv->debug.rx_stats.err_phy++;
+               if (rxs->rs_phyerr < ATH9K_PHYERR_MAX)
+                       RX_PHY_ERR_INC(rxs->rs_phyerr);
+       }
+
+#undef RX_PHY_ERR_INC
+}
+
+static ssize_t read_file_recv(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+#define PHY_ERR(s, p)                                                  \
+       len += snprintf(buf + len, size - len, "%20s : %10u\n", s,      \
+                       priv->debug.rx_stats.err_phy_stats[p]);
+
+       struct ath9k_htc_priv *priv = file->private_data;
+       char *buf;
+       unsigned int len = 0, size = 1500;
+       ssize_t retval = 0;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "SKBs allocated",
+                       priv->debug.rx_stats.skb_allocated);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "SKBs completed",
+                       priv->debug.rx_stats.skb_completed);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "SKBs Dropped",
+                       priv->debug.rx_stats.skb_dropped);
+
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "CRC ERR",
+                       priv->debug.rx_stats.err_crc);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "DECRYPT CRC ERR",
+                       priv->debug.rx_stats.err_decrypt_crc);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "MIC ERR",
+                       priv->debug.rx_stats.err_mic);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "PRE-DELIM CRC ERR",
+                       priv->debug.rx_stats.err_pre_delim);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "POST-DELIM CRC ERR",
+                       priv->debug.rx_stats.err_post_delim);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "DECRYPT BUSY ERR",
+                       priv->debug.rx_stats.err_decrypt_busy);
+       len += snprintf(buf + len, size - len,
+                       "%20s : %10u\n", "TOTAL PHY ERR",
+                       priv->debug.rx_stats.err_phy);
+
+
+       PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
+       PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
+       PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
+       PHY_ERR("RATE", ATH9K_PHYERR_RATE);
+       PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
+       PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
+       PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
+       PHY_ERR("TOR", ATH9K_PHYERR_TOR);
+       PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
+       PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
+       PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
+       PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
+       PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
+       PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
+       PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
+       PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
+       PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
+       PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
+       PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
+       PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
+       PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
+       PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
+       PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
+       PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
+       PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
+       PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+
+#undef PHY_ERR
+}
+
+static const struct file_operations fops_recv = {
+       .read = read_file_recv,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_slot(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       char buf[512];
+       unsigned int len = 0;
+
+       spin_lock_bh(&priv->tx.tx_lock);
+
+       len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : ");
+
+       len += bitmap_scnprintf(buf + len, sizeof(buf) - len,
+                              priv->tx.tx_slot, MAX_TX_BUF_NUM);
+
+       len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+       len += snprintf(buf + len, sizeof(buf) - len,
+                       "Used slots     : %d\n",
+                       bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
+
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_slot = {
+       .read = read_file_slot,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_queue(struct file *file, char __user *user_buf,
+                              size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       char buf[512];
+       unsigned int len = 0;
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
+
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Failed queue", skb_queue_len(&priv->tx.tx_failed));
+
+       spin_lock_bh(&priv->tx.tx_lock);
+       len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+                       "Queued count", priv->tx.queued_cnt);
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+}
+
+static const struct file_operations fops_queue = {
+       .read = read_file_queue,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+                              size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "0x%08x\n", common->debug_mask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       struct ath9k_htc_priv *priv = file->private_data;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       buf[len] = '\0';
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+
+       common->debug_mask = mask;
+       return count;
+}
+
+static const struct file_operations fops_debug = {
+       .read = read_file_debug,
+       .write = write_file_debug,
+       .open = ath9k_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+int ath9k_htc_init_debug(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+
+       priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
+                                            priv->hw->wiphy->debugfsdir);
+       if (!priv->debug.debugfs_phy)
+               return -ENOMEM;
+
+       debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_tgt_int_stats);
+       debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_tgt_tx_stats);
+       debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_tgt_rx_stats);
+       debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_xmit);
+       debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_recv);
+       debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_slot);
+       debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy,
+                               priv, &fops_queue);
+       debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
+                               priv, &fops_debug);
+
+       return 0;
+}
index 7e630a81b4536e9f1786f6126577978b999a3d30..dc0b33d012104f5ee610217910c7a8cf4eca88b1 100644 (file)
@@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
 
        /* Start TX */
        htc_start(priv->htc);
-       spin_lock_bh(&priv->tx_lock);
-       priv->tx_queues_stop = false;
-       spin_unlock_bh(&priv->tx_lock);
+       spin_lock_bh(&priv->tx.tx_lock);
+       priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
+       spin_unlock_bh(&priv->tx.tx_lock);
        ieee80211_wake_queues(hw);
 
        WMI_CMD(WMI_ENABLE_INTR_CMDID);
@@ -429,13 +429,15 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
 
        /* Stop TX */
        ieee80211_stop_queues(hw);
-       htc_stop(priv->htc);
+       ath9k_htc_tx_drain(priv);
        WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
-       skb_queue_purge(&priv->tx_queue);
 
        /* Stop RX */
        WMI_CMD(WMI_STOP_RECV_CMDID);
 
+       /* Clear the WMI event queue */
+       ath9k_wmi_event_drain(priv);
+
        /*
         * The MIB counters have to be disabled here,
         * since the target doesn't do it.
index 8303b34bdc904c3fc3cc7f7eaa6b01aef3269f57..06e043bffaf45c72376e965257aa13002bf1d887 100644 (file)
@@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
 
 static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
 {
-       ath9k_htc_exit_debug(priv->ah);
        ath9k_hw_deinit(priv->ah);
        kfree(priv->ah);
        priv->ah = NULL;
@@ -643,7 +642,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 {
        struct ath_hw *ah = NULL;
        struct ath_common *common;
-       int ret = 0, csz = 0;
+       int i, ret = 0, csz = 0;
 
        priv->op_flags |= OP_INVALID;
 
@@ -671,20 +670,19 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
        common->priv = priv;
        common->debug_mask = ath9k_debug;
 
-       spin_lock_init(&priv->wmi->wmi_lock);
        spin_lock_init(&priv->beacon_lock);
-       spin_lock_init(&priv->tx_lock);
+       spin_lock_init(&priv->tx.tx_lock);
        mutex_init(&priv->mutex);
        mutex_init(&priv->htc_pm_lock);
-       tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
-                    (unsigned long)priv);
        tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
                     (unsigned long)priv);
-       tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+       tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
                     (unsigned long)priv);
        INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
        INIT_WORK(&priv->ps_work, ath9k_ps_work);
        INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
+       setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
+                   (unsigned long)priv);
 
        /*
         * Cache line size is used to size and align various
@@ -701,16 +699,13 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
                goto err_hw;
        }
 
-       ret = ath9k_htc_init_debug(ah);
-       if (ret) {
-               ath_err(common, "Unable to create debugfs files\n");
-               goto err_debug;
-       }
-
        ret = ath9k_init_queues(priv);
        if (ret)
                goto err_queues;
 
+       for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
+               priv->cur_beacon_conf.bslot[i] = NULL;
+
        ath9k_init_crypto(priv);
        ath9k_init_channels_rates(priv);
        ath9k_init_misc(priv);
@@ -723,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
        return 0;
 
 err_queues:
-       ath9k_htc_exit_debug(ah);
-err_debug:
        ath9k_hw_deinit(ah);
 err_hw:
 
@@ -745,11 +738,15 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
                IEEE80211_HW_HAS_RATE_CONTROL |
                IEEE80211_HW_RX_INCLUDES_FCS |
                IEEE80211_HW_SUPPORTS_PS |
-               IEEE80211_HW_PS_NULLFUNC_STACK;
+               IEEE80211_HW_PS_NULLFUNC_STACK |
+               IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC);
+               BIT(NL80211_IFTYPE_ADHOC) |
+               BIT(NL80211_IFTYPE_AP) |
+               BIT(NL80211_IFTYPE_P2P_GO) |
+               BIT(NL80211_IFTYPE_P2P_CLIENT);
 
        hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
@@ -782,6 +779,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
 }
 
+static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
+{
+       struct ieee80211_hw *hw = priv->hw;
+       struct wmi_fw_version cmd_rsp;
+       int ret;
+
+       memset(&cmd_rsp, 0, sizeof(cmd_rsp));
+
+       WMI_CMD(WMI_GET_FW_VERSION);
+       if (ret)
+               return -EINVAL;
+
+       priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
+       priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
+
+       snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
+                priv->fw_version_major,
+                priv->fw_version_minor);
+
+       dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
+                priv->fw_version_major,
+                priv->fw_version_minor);
+
+       return 0;
+}
+
 static int ath9k_init_device(struct ath9k_htc_priv *priv,
                             u16 devid, char *product, u32 drv_info)
 {
@@ -801,6 +824,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
        common = ath9k_hw_common(ah);
        ath9k_set_hw_capab(priv, hw);
 
+       error = ath9k_init_firmware_version(priv);
+       if (error != 0)
+               goto err_fw;
+
        /* Initialize regulatory */
        error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
                              ath9k_reg_notifier);
@@ -831,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
                        goto err_world;
        }
 
+       error = ath9k_htc_init_debug(priv->ah);
+       if (error) {
+               ath_err(common, "Unable to create debugfs files\n");
+               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",
@@ -861,6 +894,8 @@ err_rx:
 err_tx:
        /* Nothing */
 err_regd:
+       /* Nothing */
+err_fw:
        ath9k_deinit_priv(priv);
 err_init:
        return error;
@@ -949,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
 
 static int __init ath9k_htc_init(void)
 {
-       int error;
-
-       error = ath9k_htc_debug_create_root();
-       if (error < 0) {
-               printk(KERN_ERR
-                       "ath9k_htc: Unable to create debugfs root: %d\n",
-                       error);
-               goto err_dbg;
-       }
-
-       error = ath9k_hif_usb_init();
-       if (error < 0) {
+       if (ath9k_hif_usb_init() < 0) {
                printk(KERN_ERR
                        "ath9k_htc: No USB devices found,"
                        " driver not installed.\n");
-               error = -ENODEV;
-               goto err_usb;
+               return -ENODEV;
        }
 
        return 0;
-
-err_usb:
-       ath9k_htc_debug_remove_root();
-err_dbg:
-       return error;
 }
 module_init(ath9k_htc_init);
 
 static void __exit ath9k_htc_exit(void)
 {
        ath9k_hif_usb_exit();
-       ath9k_htc_debug_remove_root();
        printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
 }
 module_exit(ath9k_htc_exit);
index db8c0c044e9e8498a97dc4788906624b7087c531..4de38643cb5311429abe06716b8e993a7d654e72 100644 (file)
 
 #include "htc.h"
 
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-static struct dentry *ath9k_debugfs_root;
-#endif
-
 /*************/
 /* Utilities */
 /*************/
@@ -197,11 +193,16 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 
        ath9k_htc_stop_ani(priv);
        ieee80211_stop_queues(priv->hw);
-       htc_stop(priv->htc);
+
+       del_timer_sync(&priv->tx.cleanup_timer);
+       ath9k_htc_tx_drain(priv);
+
        WMI_CMD(WMI_DISABLE_INTR_CMDID);
        WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
        WMI_CMD(WMI_STOP_RECV_CMDID);
 
+       ath9k_wmi_event_drain(priv);
+
        caldata = &priv->caldata;
        ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
        if (ret) {
@@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
        ath9k_htc_vif_reconfig(priv);
        ieee80211_wake_queues(priv->hw);
 
+       mod_timer(&priv->tx.cleanup_timer,
+                 jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
+
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
 }
@@ -250,11 +254,16 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
        fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
 
        ath9k_htc_ps_wakeup(priv);
-       htc_stop(priv->htc);
+
+       del_timer_sync(&priv->tx.cleanup_timer);
+       ath9k_htc_tx_drain(priv);
+
        WMI_CMD(WMI_DISABLE_INTR_CMDID);
        WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
        WMI_CMD(WMI_STOP_RECV_CMDID);
 
+       ath9k_wmi_event_drain(priv);
+
        ath_dbg(common, ATH_DBG_CONFIG,
                "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
                priv->ah->curchan->channel,
@@ -263,6 +272,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 
        if (!fastcc)
                caldata = &priv->caldata;
+
        ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
        if (ret) {
                ath_err(common,
@@ -296,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
            !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
                ath9k_htc_vif_reconfig(priv);
 
+       mod_timer(&priv->tx.cleanup_timer,
+                 jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
+
 err:
        ath9k_htc_ps_restore(priv);
        return ret;
@@ -349,7 +362,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
        memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
        memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
 
-       hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
+       hvif.opmode = HTC_M_MONITOR;
        hvif.index = ffz(priv->vif_slot);
 
        WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
@@ -382,7 +395,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
        tsta.is_vif_sta = 1;
        tsta.sta_index = sta_idx;
        tsta.vif_index = hvif.index;
-       tsta.maxampdu = 0xffff;
+       tsta.maxampdu = cpu_to_be16(0xffff);
 
        WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
        if (ret) {
@@ -463,9 +476,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
                ista = (struct ath9k_htc_sta *) sta->drv_priv;
                memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
                memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
-               tsta.associd = common->curaid;
                tsta.is_vif_sta = 0;
-               tsta.valid = true;
                ista->index = sta_idx;
        } else {
                memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
@@ -474,7 +485,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 
        tsta.sta_index = sta_idx;
        tsta.vif_index = avp->index;
-       tsta.maxampdu = 0xffff;
+       tsta.maxampdu = cpu_to_be16(0xffff);
        if (sta && sta->ht_cap.ht_supported)
                tsta.flags = cpu_to_be16(ATH_HTC_STA_HT);
 
@@ -709,218 +720,13 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
                        (aggr.aggr_enable) ? "Starting" : "Stopping",
                        sta->addr, tid);
 
-       spin_lock_bh(&priv->tx_lock);
+       spin_lock_bh(&priv->tx.tx_lock);
        ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP;
-       spin_unlock_bh(&priv->tx_lock);
+       spin_unlock_bh(&priv->tx.tx_lock);
 
        return ret;
 }
 
-/*********/
-/* DEBUG */
-/*********/
-
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
-                                  size_t count, loff_t *ppos)
-{
-       struct ath9k_htc_priv *priv = file->private_data;
-       struct ath9k_htc_target_stats cmd_rsp;
-       char buf[512];
-       unsigned int len = 0;
-       int ret = 0;
-
-       memset(&cmd_rsp, 0, sizeof(cmd_rsp));
-
-       WMI_CMD(WMI_TGT_STATS_CMDID);
-       if (ret)
-               return -EINVAL;
-
-
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Short Retries",
-                       be32_to_cpu(cmd_rsp.tx_shortretry));
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Long Retries",
-                       be32_to_cpu(cmd_rsp.tx_longretry));
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Xretries",
-                       be32_to_cpu(cmd_rsp.tx_xretries));
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Unaggr. Xretries",
-                       be32_to_cpu(cmd_rsp.ht_txunaggr_xretry));
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Xretries (HT)",
-                       be32_to_cpu(cmd_rsp.ht_tx_xretries));
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%19s : %10u\n", "TX Rate", priv->debug.txrate);
-
-       if (len > sizeof(buf))
-               len = sizeof(buf);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_tgt_stats = {
-       .read = read_file_tgt_stats,
-       .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
-                             size_t count, loff_t *ppos)
-{
-       struct ath9k_htc_priv *priv = file->private_data;
-       char buf[512];
-       unsigned int len = 0;
-
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "Buffers queued",
-                       priv->debug.tx_stats.buf_queued);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "Buffers completed",
-                       priv->debug.tx_stats.buf_completed);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs queued",
-                       priv->debug.tx_stats.skb_queued);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs completed",
-                       priv->debug.tx_stats.skb_completed);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs dropped",
-                       priv->debug.tx_stats.skb_dropped);
-
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "BE queued",
-                       priv->debug.tx_stats.queue_stats[WME_AC_BE]);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "BK queued",
-                       priv->debug.tx_stats.queue_stats[WME_AC_BK]);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "VI queued",
-                       priv->debug.tx_stats.queue_stats[WME_AC_VI]);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "VO queued",
-                       priv->debug.tx_stats.queue_stats[WME_AC_VO]);
-
-       if (len > sizeof(buf))
-               len = sizeof(buf);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_xmit = {
-       .read = read_file_xmit,
-       .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_recv(struct file *file, char __user *user_buf,
-                             size_t count, loff_t *ppos)
-{
-       struct ath9k_htc_priv *priv = file->private_data;
-       char buf[512];
-       unsigned int len = 0;
-
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs allocated",
-                       priv->debug.rx_stats.skb_allocated);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs completed",
-                       priv->debug.rx_stats.skb_completed);
-       len += snprintf(buf + len, sizeof(buf) - len,
-                       "%20s : %10u\n", "SKBs Dropped",
-                       priv->debug.rx_stats.skb_dropped);
-
-       if (len > sizeof(buf))
-               len = sizeof(buf);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_recv = {
-       .read = read_file_recv,
-       .open = ath9k_debugfs_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-int ath9k_htc_init_debug(struct ath_hw *ah)
-{
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-
-       if (!ath9k_debugfs_root)
-               return -ENOENT;
-
-       priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy),
-                                                    ath9k_debugfs_root);
-       if (!priv->debug.debugfs_phy)
-               goto err;
-
-       priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR,
-                                                   priv->debug.debugfs_phy,
-                                                   priv, &fops_tgt_stats);
-       if (!priv->debug.debugfs_tgt_stats)
-               goto err;
-
-
-       priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR,
-                                                      priv->debug.debugfs_phy,
-                                                      priv, &fops_xmit);
-       if (!priv->debug.debugfs_xmit)
-               goto err;
-
-       priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR,
-                                                      priv->debug.debugfs_phy,
-                                                      priv, &fops_recv);
-       if (!priv->debug.debugfs_recv)
-               goto err;
-
-       return 0;
-
-err:
-       ath9k_htc_exit_debug(ah);
-       return -ENOMEM;
-}
-
-void ath9k_htc_exit_debug(struct ath_hw *ah)
-{
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-
-       debugfs_remove(priv->debug.debugfs_recv);
-       debugfs_remove(priv->debug.debugfs_xmit);
-       debugfs_remove(priv->debug.debugfs_tgt_stats);
-       debugfs_remove(priv->debug.debugfs_phy);
-}
-
-int ath9k_htc_debug_create_root(void)
-{
-       ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-       if (!ath9k_debugfs_root)
-               return -ENOENT;
-
-       return 0;
-}
-
-void ath9k_htc_debug_remove_root(void)
-{
-       debugfs_remove(ath9k_debugfs_root);
-       ath9k_debugfs_root = NULL;
-}
-
-#endif /* CONFIG_ATH9K_HTC_DEBUGFS */
-
 /*******/
 /* ANI */
 /*******/
@@ -1040,7 +846,8 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr;
        struct ath9k_htc_priv *priv = hw->priv;
-       int padpos, padsize, ret;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       int padpos, padsize, ret, slot;
 
        hdr = (struct ieee80211_hdr *) skb->data;
 
@@ -1048,30 +855,32 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        padpos = ath9k_cmn_padpos(hdr->frame_control);
        padsize = padpos & 3;
        if (padsize && skb->len > padpos) {
-               if (skb_headroom(skb) < padsize)
+               if (skb_headroom(skb) < padsize) {
+                       ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n");
                        goto fail_tx;
+               }
                skb_push(skb, padsize);
                memmove(skb->data, skb->data + padsize, padpos);
        }
 
-       ret = ath9k_htc_tx_start(priv, skb);
-       if (ret != 0) {
-               if (ret == -ENOMEM) {
-                       ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-                               "Stopping TX queues\n");
-                       ieee80211_stop_queues(hw);
-                       spin_lock_bh(&priv->tx_lock);
-                       priv->tx_queues_stop = true;
-                       spin_unlock_bh(&priv->tx_lock);
-               } else {
-                       ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-                               "Tx failed\n");
-               }
+       slot = ath9k_htc_tx_get_slot(priv);
+       if (slot < 0) {
+               ath_dbg(common, ATH_DBG_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");
+               goto clear_slot;
+       }
+
+       ath9k_htc_check_stop_queues(priv);
+
        return;
 
+clear_slot:
+       ath9k_htc_tx_clear_slot(priv, slot);
 fail_tx:
        dev_kfree_skb_any(skb);
 }
@@ -1130,12 +939,15 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
        priv->op_flags &= ~OP_INVALID;
        htc_start(priv->htc);
 
-       spin_lock_bh(&priv->tx_lock);
-       priv->tx_queues_stop = false;
-       spin_unlock_bh(&priv->tx_lock);
+       spin_lock_bh(&priv->tx.tx_lock);
+       priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
+       spin_unlock_bh(&priv->tx.tx_lock);
 
        ieee80211_wake_queues(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) {
                ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
                                           AR_STOMP_LOW_WLAN_WGHT);
@@ -1164,16 +976,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
        }
 
        ath9k_htc_ps_wakeup(priv);
-       htc_stop(priv->htc);
+
        WMI_CMD(WMI_DISABLE_INTR_CMDID);
        WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
        WMI_CMD(WMI_STOP_RECV_CMDID);
 
-       tasklet_kill(&priv->swba_tasklet);
        tasklet_kill(&priv->rx_tasklet);
-       tasklet_kill(&priv->tx_tasklet);
 
-       skb_queue_purge(&priv->tx_queue);
+       del_timer_sync(&priv->tx.cleanup_timer);
+       ath9k_htc_tx_drain(priv);
+       ath9k_wmi_event_drain(priv);
 
        mutex_unlock(&priv->mutex);
 
@@ -1245,13 +1057,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
-               hvif.opmode = cpu_to_be32(HTC_M_STA);
+               hvif.opmode = HTC_M_STA;
                break;
        case NL80211_IFTYPE_ADHOC:
-               hvif.opmode = cpu_to_be32(HTC_M_IBSS);
+               hvif.opmode = HTC_M_IBSS;
                break;
        case NL80211_IFTYPE_AP:
-               hvif.opmode = cpu_to_be32(HTC_M_HOSTAP);
+               hvif.opmode = HTC_M_HOSTAP;
                break;
        default:
                ath_err(common,
@@ -1281,14 +1093,20 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
-       priv->vif = vif;
 
        INC_VIF(priv, vif->type);
+
+       if ((vif->type == NL80211_IFTYPE_AP) ||
+           (vif->type == NL80211_IFTYPE_ADHOC))
+               ath9k_htc_assign_bslot(priv, vif);
+
        ath9k_htc_set_opmode(priv);
 
        if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
-           !(priv->op_flags & OP_ANI_RUNNING))
+           !(priv->op_flags & OP_ANI_RUNNING)) {
+               ath9k_hw_set_tsfadjust(priv->ah, 1);
                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);
@@ -1321,9 +1139,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
        priv->vif_slot &= ~(1 << avp->index);
 
        ath9k_htc_remove_station(priv, vif, NULL);
-       priv->vif = NULL;
 
        DEC_VIF(priv, vif->type);
+
+       if ((vif->type == NL80211_IFTYPE_AP) ||
+           (vif->type == NL80211_IFTYPE_ADHOC))
+               ath9k_htc_remove_bslot(priv, vif);
+
        ath9k_htc_set_opmode(priv);
 
        /*
@@ -1493,10 +1315,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
                                struct ieee80211_sta *sta)
 {
        struct ath9k_htc_priv *priv = hw->priv;
+       struct ath9k_htc_sta *ista;
        int ret;
 
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
+       ista = (struct ath9k_htc_sta *) sta->drv_priv;
+       htc_sta_drain(priv->htc, ista->index);
        ret = ath9k_htc_remove_station(priv, vif, sta);
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
@@ -1644,6 +1469,7 @@ 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);
+               ath9k_htc_set_tsfadjust(priv, vif);
                priv->op_flags |= OP_ENABLE_BEACON;
                ath9k_htc_beacon_config(priv, vif);
        }
@@ -1758,9 +1584,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
                ista = (struct ath9k_htc_sta *) sta->drv_priv;
-               spin_lock_bh(&priv->tx_lock);
+               spin_lock_bh(&priv->tx.tx_lock);
                ista->tid_state[tid] = AGGR_OPERATIONAL;
-               spin_unlock_bh(&priv->tx_lock);
+               spin_unlock_bh(&priv->tx.tx_lock);
                break;
        default:
                ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
index 4a4f27ba96afdbbba1f47632203464815122e316..723a3a9c5cd91426262ee1770149a40a85981c64 100644 (file)
@@ -53,6 +53,138 @@ int get_hw_qnum(u16 queue, int *hwq_map)
        }
 }
 
+void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv)
+{
+       spin_lock_bh(&priv->tx.tx_lock);
+       priv->tx.queued_cnt++;
+       if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) &&
+           !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) {
+               priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP;
+               ieee80211_stop_queues(priv->hw);
+       }
+       spin_unlock_bh(&priv->tx.tx_lock);
+}
+
+void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv)
+{
+       spin_lock_bh(&priv->tx.tx_lock);
+       if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) &&
+           (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) {
+               priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
+               ieee80211_wake_queues(priv->hw);
+       }
+       spin_unlock_bh(&priv->tx.tx_lock);
+}
+
+int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv)
+{
+       int slot;
+
+       spin_lock_bh(&priv->tx.tx_lock);
+       slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM);
+       if (slot >= MAX_TX_BUF_NUM) {
+               spin_unlock_bh(&priv->tx.tx_lock);
+               return -ENOBUFS;
+       }
+       __set_bit(slot, priv->tx.tx_slot);
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       return slot;
+}
+
+void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot)
+{
+       spin_lock_bh(&priv->tx.tx_lock);
+       __clear_bit(slot, priv->tx.tx_slot);
+       spin_unlock_bh(&priv->tx.tx_lock);
+}
+
+static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
+                                               u16 qnum)
+{
+       enum htc_endpoint_id epid;
+
+       switch (qnum) {
+       case 0:
+               TX_QSTAT_INC(WME_AC_VO);
+               epid = priv->data_vo_ep;
+               break;
+       case 1:
+               TX_QSTAT_INC(WME_AC_VI);
+               epid = priv->data_vi_ep;
+               break;
+       case 2:
+               TX_QSTAT_INC(WME_AC_BE);
+               epid = priv->data_be_ep;
+               break;
+       case 3:
+       default:
+               TX_QSTAT_INC(WME_AC_BK);
+               epid = priv->data_bk_ep;
+               break;
+       }
+
+       return epid;
+}
+
+static inline struct sk_buff_head*
+get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct sk_buff_head *epid_queue = NULL;
+
+       if (epid == priv->mgmt_ep)
+               epid_queue = &priv->tx.mgmt_ep_queue;
+       else if (epid == priv->cab_ep)
+               epid_queue = &priv->tx.cab_ep_queue;
+       else if (epid == priv->data_be_ep)
+               epid_queue = &priv->tx.data_be_queue;
+       else if (epid == priv->data_bk_ep)
+               epid_queue = &priv->tx.data_bk_queue;
+       else if (epid == priv->data_vi_ep)
+               epid_queue = &priv->tx.data_vi_queue;
+       else if (epid == priv->data_vo_ep)
+               epid_queue = &priv->tx.data_vo_queue;
+       else
+               ath_err(common, "Invalid EPID: %d\n", epid);
+
+       return epid_queue;
+}
+
+/*
+ * Removes the driver header and returns the TX slot number
+ */
+static inline int strip_drv_header(struct ath9k_htc_priv *priv,
+                                  struct sk_buff *skb)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_tx_ctl *tx_ctl;
+       int slot;
+
+       tx_ctl = HTC_SKB_CB(skb);
+
+       if (tx_ctl->epid == priv->mgmt_ep) {
+               struct tx_mgmt_hdr *tx_mhdr =
+                       (struct tx_mgmt_hdr *)skb->data;
+               slot = tx_mhdr->cookie;
+               skb_pull(skb, sizeof(struct tx_mgmt_hdr));
+       } else if ((tx_ctl->epid == priv->data_bk_ep) ||
+                  (tx_ctl->epid == priv->data_be_ep) ||
+                  (tx_ctl->epid == priv->data_vi_ep) ||
+                  (tx_ctl->epid == priv->data_vo_ep) ||
+                  (tx_ctl->epid == priv->cab_ep)) {
+               struct tx_frame_hdr *tx_fhdr =
+                       (struct tx_frame_hdr *)skb->data;
+               slot = tx_fhdr->cookie;
+               skb_pull(skb, sizeof(struct tx_frame_hdr));
+       } else {
+               ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid);
+               slot = -EINVAL;
+       }
+
+       return slot;
+}
+
 int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
                       struct ath9k_tx_queue_info *qinfo)
 {
@@ -79,23 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
        return error;
 }
 
-int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
+static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv,
+                             struct ath9k_htc_vif *avp,
+                             struct sk_buff *skb,
+                             u8 sta_idx, u8 vif_idx, u8 slot)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_mgmt *mgmt;
+       struct ieee80211_hdr *hdr;
+       struct tx_mgmt_hdr mgmt_hdr;
+       struct ath9k_htc_tx_ctl *tx_ctl;
+       u8 *tx_fhdr;
+
+       tx_ctl = HTC_SKB_CB(skb);
+       hdr = (struct ieee80211_hdr *) skb->data;
+
+       memset(tx_ctl, 0, sizeof(*tx_ctl));
+       memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));
+
+       /*
+        * Set the TSF adjust value for probe response
+        * frame also.
+        */
+       if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) {
+               mgmt = (struct ieee80211_mgmt *)skb->data;
+               mgmt->u.probe_resp.timestamp = avp->tsfadjust;
+       }
+
+       tx_ctl->type = ATH9K_HTC_MGMT;
+
+       mgmt_hdr.node_idx = sta_idx;
+       mgmt_hdr.vif_idx = vif_idx;
+       mgmt_hdr.tidno = 0;
+       mgmt_hdr.flags = 0;
+       mgmt_hdr.cookie = slot;
+
+       mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
+       if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
+               mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
+       else
+               mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx;
+
+       tx_fhdr = skb_push(skb, sizeof(mgmt_hdr));
+       memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr));
+       tx_ctl->epid = priv->mgmt_ep;
+}
+
+static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv,
+                             struct ieee80211_vif *vif,
+                             struct sk_buff *skb,
+                             u8 sta_idx, u8 vif_idx, u8 slot,
+                             bool is_cab)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr;
+       struct ath9k_htc_tx_ctl *tx_ctl;
+       struct tx_frame_hdr tx_hdr;
+       u32 flags = 0;
+       u8 *qc, *tx_fhdr;
+       u16 qnum;
+
+       tx_ctl = HTC_SKB_CB(skb);
+       hdr = (struct ieee80211_hdr *) skb->data;
+
+       memset(tx_ctl, 0, sizeof(*tx_ctl));
+       memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));
+
+       tx_hdr.node_idx = sta_idx;
+       tx_hdr.vif_idx = vif_idx;
+       tx_hdr.cookie = slot;
+
+       /*
+        * This is a bit redundant but it helps to get
+        * the per-packet index quickly when draining the
+        * TX queue in the HIF layer. Otherwise we would
+        * have to parse the packet contents ...
+        */
+       tx_ctl->sta_idx = sta_idx;
+
+       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+               tx_ctl->type = ATH9K_HTC_AMPDU;
+               tx_hdr.data_type = ATH9K_HTC_AMPDU;
+       } else {
+               tx_ctl->type = ATH9K_HTC_NORMAL;
+               tx_hdr.data_type = ATH9K_HTC_NORMAL;
+       }
+
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+       }
+
+       /* Check for RTS protection */
+       if (priv->hw->wiphy->rts_threshold != (u32) -1)
+               if (skb->len > priv->hw->wiphy->rts_threshold)
+                       flags |= ATH9K_HTC_TX_RTSCTS;
+
+       /* CTS-to-self */
+       if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
+           (vif && vif->bss_conf.use_cts_prot))
+               flags |= ATH9K_HTC_TX_CTSONLY;
+
+       tx_hdr.flags = cpu_to_be32(flags);
+       tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
+       if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
+               tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
+       else
+               tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx;
+
+       tx_fhdr = skb_push(skb, sizeof(tx_hdr));
+       memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
+
+       if (is_cab) {
+               CAB_STAT_INC;
+               tx_ctl->epid = priv->cab_ep;
+               return;
+       }
+
+       qnum = skb_get_queue_mapping(skb);
+       tx_ctl->epid = get_htc_epid(priv, qnum);
+}
+
+int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
+                      struct sk_buff *skb,
+                      u8 slot, bool is_cab)
 {
        struct ieee80211_hdr *hdr;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_sta *sta = tx_info->control.sta;
        struct ieee80211_vif *vif = tx_info->control.vif;
        struct ath9k_htc_sta *ista;
-       struct ath9k_htc_vif *avp;
-       struct ath9k_htc_tx_ctl tx_ctl;
-       enum htc_endpoint_id epid;
-       u16 qnum;
-       __le16 fc;
-       u8 *tx_fhdr;
+       struct ath9k_htc_vif *avp = NULL;
        u8 sta_idx, vif_idx;
 
        hdr = (struct ieee80211_hdr *) skb->data;
-       fc = hdr->frame_control;
 
        /*
         * Find out on which interface this packet has to be
@@ -124,218 +373,432 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
                sta_idx = priv->vif_sta_pos[vif_idx];
        }
 
-       memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
+       if (ieee80211_is_data(hdr->frame_control))
+               ath9k_htc_tx_data(priv, vif, skb,
+                                 sta_idx, vif_idx, slot, is_cab);
+       else
+               ath9k_htc_tx_mgmt(priv, avp, skb,
+                                 sta_idx, vif_idx, slot);
 
-       if (ieee80211_is_data(fc)) {
-               struct tx_frame_hdr tx_hdr;
-               u32 flags = 0;
-               u8 *qc;
 
-               memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));
+       return htc_send(priv->htc, skb);
+}
 
-               tx_hdr.node_idx = sta_idx;
-               tx_hdr.vif_idx = vif_idx;
+static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
+                                            struct ath9k_htc_sta *ista, u8 tid)
+{
+       bool ret = false;
 
-               if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-                       tx_ctl.type = ATH9K_HTC_AMPDU;
-                       tx_hdr.data_type = ATH9K_HTC_AMPDU;
-               } else {
-                       tx_ctl.type = ATH9K_HTC_NORMAL;
-                       tx_hdr.data_type = ATH9K_HTC_NORMAL;
-               }
+       spin_lock_bh(&priv->tx.tx_lock);
+       if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP))
+               ret = true;
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       return ret;
+}
+
+static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
+                                   struct ieee80211_vif *vif,
+                                   struct sk_buff *skb)
+{
+       struct ieee80211_sta *sta;
+       struct ieee80211_hdr *hdr;
+       __le16 fc;
+
+       hdr = (struct ieee80211_hdr *) skb->data;
+       fc = hdr->frame_control;
+
+       rcu_read_lock();
+
+       sta = ieee80211_find_sta(vif, hdr->addr1);
+       if (!sta) {
+               rcu_read_unlock();
+               return;
+       }
 
+       if (sta && conf_is_ht(&priv->hw->conf) &&
+           !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
                if (ieee80211_is_data_qos(fc)) {
+                       u8 *qc, tid;
+                       struct ath9k_htc_sta *ista;
+
                        qc = ieee80211_get_qos_ctl(hdr);
-                       tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+                       tid = qc[0] & 0xf;
+                       ista = (struct ath9k_htc_sta *)sta->drv_priv;
+                       if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) {
+                               ieee80211_start_tx_ba_session(sta, tid, 0);
+                               spin_lock_bh(&priv->tx.tx_lock);
+                               ista->tid_state[tid] = AGGR_PROGRESS;
+                               spin_unlock_bh(&priv->tx.tx_lock);
+                       }
                }
+       }
 
-               /* Check for RTS protection */
-               if (priv->hw->wiphy->rts_threshold != (u32) -1)
-                       if (skb->len > priv->hw->wiphy->rts_threshold)
-                               flags |= ATH9K_HTC_TX_RTSCTS;
+       rcu_read_unlock();
+}
 
-               /* CTS-to-self */
-               if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
-                   (vif && vif->bss_conf.use_cts_prot))
-                       flags |= ATH9K_HTC_TX_CTSONLY;
+static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
+                                struct sk_buff *skb,
+                                struct __wmi_event_txstatus *txs)
+{
+       struct ieee80211_vif *vif;
+       struct ath9k_htc_tx_ctl *tx_ctl;
+       struct ieee80211_tx_info *tx_info;
+       struct ieee80211_tx_rate *rate;
+       struct ieee80211_conf *cur_conf = &priv->hw->conf;
+       struct ieee80211_supported_band *sband;
+       bool txok;
+       int slot;
 
-               tx_hdr.flags = cpu_to_be32(flags);
-               tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
-               if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
-                       tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
-               else
-                       tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx;
+       slot = strip_drv_header(priv, skb);
+       if (slot < 0) {
+               dev_kfree_skb_any(skb);
+               return;
+       }
 
-               tx_fhdr = skb_push(skb, sizeof(tx_hdr));
-               memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
+       tx_ctl = HTC_SKB_CB(skb);
+       txok = tx_ctl->txok;
+       tx_info = IEEE80211_SKB_CB(skb);
+       vif = tx_info->control.vif;
+       rate = &tx_info->status.rates[0];
+       sband = priv->hw->wiphy->bands[cur_conf->channel->band];
 
-               qnum = skb_get_queue_mapping(skb);
+       memset(&tx_info->status, 0, sizeof(tx_info->status));
 
-               switch (qnum) {
-               case 0:
-                       TX_QSTAT_INC(WME_AC_VO);
-                       epid = priv->data_vo_ep;
-                       break;
-               case 1:
-                       TX_QSTAT_INC(WME_AC_VI);
-                       epid = priv->data_vi_ep;
-                       break;
-               case 2:
-                       TX_QSTAT_INC(WME_AC_BE);
-                       epid = priv->data_be_ep;
-                       break;
-               case 3:
-               default:
-                       TX_QSTAT_INC(WME_AC_BK);
-                       epid = priv->data_bk_ep;
-                       break;
-               }
-       } else {
-               struct tx_mgmt_hdr mgmt_hdr;
+       /*
+        * URB submission failed for this frame, it never reached
+        * the target.
+        */
+       if (!txok || !vif || !txs)
+               goto send_mac80211;
 
-               memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));
+       if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK)
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
+       if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT)
+               tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
 
-               tx_ctl.type = ATH9K_HTC_NORMAL;
+       if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS)
+               rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
 
-               mgmt_hdr.node_idx = sta_idx;
-               mgmt_hdr.vif_idx = vif_idx;
-               mgmt_hdr.tidno = 0;
-               mgmt_hdr.flags = 0;
+       rate->count = 1;
+       rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE);
 
-               mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
-               if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
-                       mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
-               else
-                       mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx;
+       if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) {
+               rate->flags |= IEEE80211_TX_RC_MCS;
 
-               tx_fhdr = skb_push(skb, sizeof(mgmt_hdr));
-               memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr));
-               epid = priv->mgmt_ep;
+               if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40)
+                       rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+               if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
+                       rate->flags |= IEEE80211_TX_RC_SHORT_GI;
+       } else {
+               if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
+                       rate->idx += 4; /* No CCK rates */
        }
 
-       return htc_send(priv->htc, skb, epid, &tx_ctl);
+       ath9k_htc_check_tx_aggr(priv, vif, skb);
+
+send_mac80211:
+       spin_lock_bh(&priv->tx.tx_lock);
+       if (WARN_ON(--priv->tx.queued_cnt < 0))
+               priv->tx.queued_cnt = 0;
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       ath9k_htc_tx_clear_slot(priv, slot);
+
+       /* Send status to mac80211 */
+       ieee80211_tx_status(priv->hw, skb);
 }
 
-static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
-                                   struct ath9k_htc_sta *ista, u8 tid)
+static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv,
+                                      struct sk_buff_head *queue)
 {
-       bool ret = false;
+       struct sk_buff *skb;
 
-       spin_lock_bh(&priv->tx_lock);
-       if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP))
-               ret = true;
-       spin_unlock_bh(&priv->tx_lock);
+       while ((skb = skb_dequeue(queue)) != NULL) {
+               ath9k_htc_tx_process(priv, skb, NULL);
+       }
+}
 
-       return ret;
+void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv)
+{
+       struct ath9k_htc_tx_event *event, *tmp;
+
+       spin_lock_bh(&priv->tx.tx_lock);
+       priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN;
+       spin_unlock_bh(&priv->tx.tx_lock);
+
+       /*
+        * Ensure that all pending TX frames are flushed,
+        * and that the TX completion/failed tasklets is killed.
+        */
+       htc_stop(priv->htc);
+       tasklet_kill(&priv->wmi->wmi_event_tasklet);
+       tasklet_kill(&priv->tx_failed_tasklet);
+
+       ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue);
+       ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
+
+       /*
+        * The TX cleanup timer has already been killed.
+        */
+       spin_lock_bh(&priv->wmi->event_lock);
+       list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) {
+               list_del(&event->list);
+               kfree(event);
+       }
+       spin_unlock_bh(&priv->wmi->event_lock);
+
+       spin_lock_bh(&priv->tx.tx_lock);
+       priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN;
+       spin_unlock_bh(&priv->tx.tx_lock);
 }
 
-void ath9k_tx_tasklet(unsigned long data)
+void ath9k_tx_failed_tasklet(unsigned long data)
 {
        struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
-       struct ieee80211_vif *vif;
-       struct ieee80211_sta *sta;
-       struct ieee80211_hdr *hdr;
-       struct ieee80211_tx_info *tx_info;
-       struct sk_buff *skb = NULL;
-       __le16 fc;
 
-       while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) {
+       spin_lock_bh(&priv->tx.tx_lock);
+       if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
+               spin_unlock_bh(&priv->tx.tx_lock);
+               return;
+       }
+       spin_unlock_bh(&priv->tx.tx_lock);
 
-               hdr = (struct ieee80211_hdr *) skb->data;
-               fc = hdr->frame_control;
-               tx_info = IEEE80211_SKB_CB(skb);
-               vif = tx_info->control.vif;
+       ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
+}
 
-               memset(&tx_info->status, 0, sizeof(tx_info->status));
+static inline bool check_cookie(struct ath9k_htc_priv *priv,
+                               struct sk_buff *skb,
+                               u8 cookie, u8 epid)
+{
+       u8 fcookie = 0;
+
+       if (epid == priv->mgmt_ep) {
+               struct tx_mgmt_hdr *hdr;
+               hdr = (struct tx_mgmt_hdr *) skb->data;
+               fcookie = hdr->cookie;
+       } else if ((epid == priv->data_bk_ep) ||
+                  (epid == priv->data_be_ep) ||
+                  (epid == priv->data_vi_ep) ||
+                  (epid == priv->data_vo_ep) ||
+                  (epid == priv->cab_ep)) {
+               struct tx_frame_hdr *hdr;
+               hdr = (struct tx_frame_hdr *) skb->data;
+               fcookie = hdr->cookie;
+       }
 
-               if (!vif)
-                       goto send_mac80211;
+       if (fcookie == cookie)
+               return true;
 
-               rcu_read_lock();
+       return false;
+}
 
-               sta = ieee80211_find_sta(vif, hdr->addr1);
-               if (!sta) {
-                       rcu_read_unlock();
-                       ieee80211_tx_status(priv->hw, skb);
-                       continue;
+static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv,
+                                              struct __wmi_event_txstatus *txs)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct sk_buff_head *epid_queue;
+       struct sk_buff *skb, *tmp;
+       unsigned long flags;
+       u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID);
+
+       epid_queue = get_htc_epid_queue(priv, epid);
+       if (!epid_queue)
+               return NULL;
+
+       spin_lock_irqsave(&epid_queue->lock, flags);
+       skb_queue_walk_safe(epid_queue, skb, tmp) {
+               if (check_cookie(priv, skb, txs->cookie, epid)) {
+                       __skb_unlink(skb, epid_queue);
+                       spin_unlock_irqrestore(&epid_queue->lock, flags);
+                       return skb;
                }
+       }
+       spin_unlock_irqrestore(&epid_queue->lock, flags);
 
-               /* Check if we need to start aggregation */
+       ath_dbg(common, ATH_DBG_XMIT,
+               "No matching packet for cookie: %d, epid: %d\n",
+               txs->cookie, epid);
 
-               if (sta && conf_is_ht(&priv->hw->conf) &&
-                   !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-                       if (ieee80211_is_data_qos(fc)) {
-                               u8 *qc, tid;
-                               struct ath9k_htc_sta *ista;
+       return NULL;
+}
 
-                               qc = ieee80211_get_qos_ctl(hdr);
-                               tid = qc[0] & 0xf;
-                               ista = (struct ath9k_htc_sta *)sta->drv_priv;
+void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event)
+{
+       struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event;
+       struct __wmi_event_txstatus *__txs;
+       struct sk_buff *skb;
+       struct ath9k_htc_tx_event *tx_pend;
+       int i;
 
-                               if (ath9k_htc_check_tx_aggr(priv, ista, tid)) {
-                                       ieee80211_start_tx_ba_session(sta, tid, 0);
-                                       spin_lock_bh(&priv->tx_lock);
-                                       ista->tid_state[tid] = AGGR_PROGRESS;
-                                       spin_unlock_bh(&priv->tx_lock);
-                               }
-                       }
-               }
+       for (i = 0; i < txs->cnt; i++) {
+               WARN_ON(txs->cnt > HTC_MAX_TX_STATUS);
 
-               rcu_read_unlock();
+               __txs = &txs->txstatus[i];
+
+               skb = ath9k_htc_tx_get_packet(priv, __txs);
+               if (!skb) {
+                       /*
+                        * Store this event, so that the TX cleanup
+                        * routine can check later for the needed packet.
+                        */
+                       tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event),
+                                         GFP_ATOMIC);
+                       if (!tx_pend)
+                               continue;
+
+                       memcpy(&tx_pend->txs, __txs,
+                              sizeof(struct __wmi_event_txstatus));
+
+                       spin_lock(&priv->wmi->event_lock);
+                       list_add_tail(&tx_pend->list,
+                                     &priv->wmi->pending_tx_events);
+                       spin_unlock(&priv->wmi->event_lock);
 
-       send_mac80211:
-               /* Send status to mac80211 */
-               ieee80211_tx_status(priv->hw, skb);
+                       continue;
+               }
+
+               ath9k_htc_tx_process(priv, skb, __txs);
        }
 
        /* Wake TX queues if needed */
-       spin_lock_bh(&priv->tx_lock);
-       if (priv->tx_queues_stop) {
-               priv->tx_queues_stop = false;
-               spin_unlock_bh(&priv->tx_lock);
-               ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
-                       "Waking up TX queues\n");
-               ieee80211_wake_queues(priv->hw);
-               return;
-       }
-       spin_unlock_bh(&priv->tx_lock);
+       ath9k_htc_check_wake_queues(priv);
 }
 
 void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
                    enum htc_endpoint_id ep_id, bool txok)
 {
        struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
-       struct ath_common *common = ath9k_hw_common(priv->ah);
-       struct ieee80211_tx_info *tx_info;
+       struct ath9k_htc_tx_ctl *tx_ctl;
+       struct sk_buff_head *epid_queue;
 
-       if (!skb)
+       tx_ctl = HTC_SKB_CB(skb);
+       tx_ctl->txok = txok;
+       tx_ctl->timestamp = jiffies;
+
+       if (!txok) {
+               skb_queue_tail(&priv->tx.tx_failed, skb);
+               tasklet_schedule(&priv->tx_failed_tasklet);
                return;
+       }
 
-       if (ep_id == priv->mgmt_ep) {
-               skb_pull(skb, sizeof(struct tx_mgmt_hdr));
-       } else if ((ep_id == priv->data_bk_ep) ||
-                  (ep_id == priv->data_be_ep) ||
-                  (ep_id == priv->data_vi_ep) ||
-                  (ep_id == priv->data_vo_ep)) {
-               skb_pull(skb, sizeof(struct tx_frame_hdr));
-       } else {
-               ath_err(common, "Unsupported TX EPID: %d\n", ep_id);
+       epid_queue = get_htc_epid_queue(priv, ep_id);
+       if (!epid_queue) {
                dev_kfree_skb_any(skb);
                return;
        }
 
-       tx_info = IEEE80211_SKB_CB(skb);
+       skb_queue_tail(epid_queue, skb);
+}
 
-       if (txok)
-               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_tx_ctl *tx_ctl;
 
-       skb_queue_tail(&priv->tx_queue, skb);
-       tasklet_schedule(&priv->tx_tasklet);
+       tx_ctl = HTC_SKB_CB(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");
+               return true;
+       }
+
+       return false;
+}
+
+static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv,
+                                      struct sk_buff_head *epid_queue)
+{
+       bool process = false;
+       unsigned long flags;
+       struct sk_buff *skb, *tmp;
+       struct sk_buff_head queue;
+
+       skb_queue_head_init(&queue);
+
+       spin_lock_irqsave(&epid_queue->lock, flags);
+       skb_queue_walk_safe(epid_queue, skb, tmp) {
+               if (check_packet(priv, skb)) {
+                       __skb_unlink(skb, epid_queue);
+                       __skb_queue_tail(&queue, skb);
+                       process = true;
+               }
+       }
+       spin_unlock_irqrestore(&epid_queue->lock, flags);
+
+       if (process) {
+               skb_queue_walk_safe(&queue, skb, tmp) {
+                       __skb_unlink(skb, &queue);
+                       ath9k_htc_tx_process(priv, skb, NULL);
+               }
+       }
+}
+
+void ath9k_htc_tx_cleanup_timer(unsigned long data)
+{
+       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_tx_event *event, *tmp;
+       struct sk_buff *skb;
+
+       spin_lock(&priv->wmi->event_lock);
+       list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) {
+
+               skb = ath9k_htc_tx_get_packet(priv, &event->txs);
+               if (skb) {
+                       ath_dbg(common, ATH_DBG_XMIT,
+                               "Found packet for cookie: %d, epid: %d\n",
+                               event->txs.cookie,
+                               MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID));
+
+                       ath9k_htc_tx_process(priv, skb, &event->txs);
+                       list_del(&event->list);
+                       kfree(event);
+                       continue;
+               }
+
+               if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) {
+                       list_del(&event->list);
+                       kfree(event);
+               }
+       }
+       spin_unlock(&priv->wmi->event_lock);
+
+       /*
+        * Check if status-pending packets have to be cleaned up.
+        */
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue);
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue);
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue);
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue);
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue);
+       ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue);
+
+       /* Wake TX queues if needed */
+       ath9k_htc_check_wake_queues(priv);
+
+       mod_timer(&priv->tx.cleanup_timer,
+                 jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
 }
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv)
 {
-       skb_queue_head_init(&priv->tx_queue);
+       skb_queue_head_init(&priv->tx.mgmt_ep_queue);
+       skb_queue_head_init(&priv->tx.cab_ep_queue);
+       skb_queue_head_init(&priv->tx.data_be_queue);
+       skb_queue_head_init(&priv->tx.data_bk_queue);
+       skb_queue_head_init(&priv->tx.data_vi_queue);
+       skb_queue_head_init(&priv->tx.data_vo_queue);
+       skb_queue_head_init(&priv->tx.tx_failed);
        return 0;
 }
 
@@ -507,8 +970,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
        int last_rssi = ATH_RSSI_DUMMY_MARKER;
        __le16 fc;
 
-       if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) {
-               ath_err(common, "Corrupted RX frame, dropping\n");
+       if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
+               ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
+                       skb->len);
                goto rx_next;
        }
 
@@ -522,6 +986,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
                goto rx_next;
        }
 
+       ath9k_htc_err_stat_rx(priv, rxstatus);
+
        /* Get the RX status information */
        memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
        skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
index 62e139a30a74d9b05f6ffeae825c15bd13c0ce0b..cee970fdf65256c5124d358b674b977d9201c9b5 100644 (file)
@@ -17,8 +17,8 @@
 #include "htc.h"
 
 static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
-                         u16 len, u8 flags, u8 epid,
-                         struct ath9k_htc_tx_ctl *tx_ctl)
+                         u16 len, u8 flags, u8 epid)
+
 {
        struct htc_frame_hdr *hdr;
        struct htc_endpoint *endpoint = &target->endpoint[epid];
@@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
        hdr->flags = flags;
        hdr->payload_len = cpu_to_be16(len);
 
-       status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
-                                  tx_ctl);
+       status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
+
        return status;
 }
 
@@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
 
        target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
 
-       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
+       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
        if (ret)
                goto err;
 
@@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target)
 
        target->htc_flags |= HTC_OP_START_WAIT;
 
-       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
+       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
        if (ret)
                goto err;
 
@@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target,
        conn_msg->dl_pipeid = endpoint->dl_pipeid;
        conn_msg->ul_pipeid = endpoint->ul_pipeid;
 
-       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
+       ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
        if (ret)
                goto err;
 
@@ -286,35 +286,33 @@ err:
        return ret;
 }
 
-int htc_send(struct htc_target *target, struct sk_buff *skb,
-            enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
+int htc_send(struct htc_target *target, struct sk_buff *skb)
 {
-       return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl);
+       struct ath9k_htc_tx_ctl *tx_ctl;
+
+       tx_ctl = HTC_SKB_CB(skb);
+       return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid);
 }
 
-void htc_stop(struct htc_target *target)
+int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
+                 enum htc_endpoint_id epid)
 {
-       enum htc_endpoint_id epid;
-       struct htc_endpoint *endpoint;
+       return htc_issue_send(target, skb, skb->len, 0, epid);
+}
 
-       for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
-               endpoint = &target->endpoint[epid];
-               if (endpoint->service_id != 0)
-                       target->hif->stop(target->hif_dev, endpoint->ul_pipeid);
-       }
+void htc_stop(struct htc_target *target)
+{
+       target->hif->stop(target->hif_dev);
 }
 
 void htc_start(struct htc_target *target)
 {
-       enum htc_endpoint_id epid;
-       struct htc_endpoint *endpoint;
+       target->hif->start(target->hif_dev);
+}
 
-       for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
-               endpoint = &target->endpoint[epid];
-               if (endpoint->service_id != 0)
-                       target->hif->start(target->hif_dev,
-                                          endpoint->ul_pipeid);
-       }
+void htc_sta_drain(struct htc_target *target, u8 idx)
+{
+       target->hif->sta_drain(target->hif_dev, idx);
 }
 
 void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
index ecd018798c4721d6d62c8802b53c87d28673a66d..cb9174ade53ee83445fa9656a3d094e68ddf2c70 100644 (file)
@@ -33,10 +33,10 @@ struct ath9k_htc_hif {
        u8 control_dl_pipe;
        u8 control_ul_pipe;
 
-       void (*start) (void *hif_handle, u8 pipe);
-       void (*stop) (void *hif_handle, u8 pipe);
-       int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf,
-                    struct ath9k_htc_tx_ctl *tx_ctl);
+       void (*start) (void *hif_handle);
+       void (*stop) (void *hif_handle);
+       void (*sta_drain) (void *hif_handle, u8 idx);
+       int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf);
 };
 
 enum htc_endpoint_id {
@@ -205,10 +205,12 @@ int htc_init(struct htc_target *target);
 int htc_connect_service(struct htc_target *target,
                          struct htc_service_connreq *service_connreq,
                          enum htc_endpoint_id *conn_rsp_eid);
-int htc_send(struct htc_target *target, struct sk_buff *skb,
-            enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl);
+int htc_send(struct htc_target *target, struct sk_buff *skb);
+int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
+                 enum htc_endpoint_id epid);
 void htc_stop(struct htc_target *target);
 void htc_start(struct htc_target *target);
+void htc_sta_drain(struct htc_target *target, u8 idx);
 
 void ath9k_htc_rx_msg(struct htc_target *htc_handle,
                      struct sk_buff *skb, u32 len, u8 pipe_id);
index 22ee888b0baf269fd254cc9decf734193868da82..9dd90a85ad63eb5a7c8f447a0976668c14269820 100644 (file)
@@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
        ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
 }
 
+static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
+{
+       ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
+}
+
 /* Private hardware call ops */
 
 /* PHY ops */
index c8a2d0dae7964de2a50a57b8b076ad54c131ba62..045abd5578407b2a2cf5645ebaaa232ea2cfaed1 100644 (file)
@@ -676,42 +676,55 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
 
-#define DPLL2_KD_VAL            0x3D
-#define DPLL2_KI_VAL            0x06
-#define DPLL3_PHASE_SHIFT_VAL   0x1
-
+#define DPLL3_PHASE_SHIFT_VAL 0x1
 static void ath9k_hw_init_pll(struct ath_hw *ah,
                              struct ath9k_channel *chan)
 {
        u32 pll;
 
        if (AR_SREV_9485(ah)) {
-               REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
-               REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01);
-
-               REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
-                             AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
 
-               REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
-               udelay(1000);
+               /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_PLL_PWD, 0x1);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_DPLL2_KD, 0x40);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_DPLL2_KI, 0x4);
 
-               REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_REFDIV, 0x5);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_NINI, 0x58);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1,
+                             AR_CH0_BB_DPLL1_NFRAC, 0x0);
 
                REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
-                             AR_CH0_DPLL2_KD, DPLL2_KD_VAL);
+                             AR_CH0_BB_DPLL2_OUTDIV, 0x1);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1);
                REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
-                             AR_CH0_DPLL2_KI, DPLL2_KI_VAL);
+                             AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1);
 
+               /* program BB PLL phase_shift to 0x6 */
                REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
-                             AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
-               REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
+                             AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6);
+
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+                             AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
                udelay(1000);
+
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+                             AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
        }
 
        pll = ath9k_hw_compute_pll_control(ah, chan);
 
        REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
+       if (AR_SREV_9485(ah))
+               udelay(1000);
+
        /* Switch the core clock for ar9271 to 117Mhz */
        if (AR_SREV_9271(ah)) {
                udelay(500);
index a778b66f44380726ddb88e40bb45f97176f3be45..1018d6cbd5301bf1d5a779ef85ae960f1cb57699 100644 (file)
@@ -626,6 +626,7 @@ struct ath_hw_ops {
        void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
        void (*set11n_burstduration)(struct ath_hw *ah, void *ds,
                                     u32 burstDuration);
+       void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
 };
 
 struct ath_nf_limits {
@@ -846,6 +847,14 @@ struct ath_hw {
        u32 ent_mode;
 };
 
+struct ath_bus_ops {
+       enum ath_bus_type ath_bus_type;
+       void (*read_cachesize)(struct ath_common *common, int *csz);
+       bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+       void (*bt_coex_prep)(struct ath_common *common);
+       void (*extn_synch_en)(struct ath_common *common);
+};
+
 static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
 {
        return &ah->common;
index c2a59386fb9cf05a7eabb12214e613103e0c08b0..b60c130917f7e959a356381757c852934c2ada17 100644 (file)
@@ -239,7 +239,6 @@ struct ath_desc {
        void *ds_vdata;
 } __packed __aligned(4);
 
-#define ATH9K_TXDESC_CLRDMASK          0x0001
 #define ATH9K_TXDESC_NOACK             0x0002
 #define ATH9K_TXDESC_RTSENA            0x0004
 #define ATH9K_TXDESC_CTSENA            0x0008
index 4c5c9997dac6e18f178ba7684889f2cc1f21ddc1..a8d9009a76d5a183f4a20527c187779a859c4030 100644 (file)
@@ -1373,6 +1373,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
        if ((iter_data.naps + iter_data.nadhocs) > 0) {
                sc->sc_flags |= SC_OP_ANI_RUN;
                ath_start_ani(common);
+       } else {
+               sc->sc_flags &= ~SC_OP_ANI_RUN;
+               del_timer_sync(&common->ani.timer);
        }
 }
 
@@ -1733,23 +1736,63 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
                         struct ieee80211_sta *sta)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+       struct ieee80211_key_conf ps_key = { };
 
        ath_node_attach(sc, sta);
+       an->ps_key = ath_key_config(common, vif, sta, &ps_key);
 
        return 0;
 }
 
+static void ath9k_del_ps_key(struct ath_softc *sc,
+                            struct ieee80211_vif *vif,
+                            struct ieee80211_sta *sta)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+       struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
+
+       if (!an->ps_key)
+           return;
+
+       ath_key_delete(common, &ps_key);
+}
+
 static int ath9k_sta_remove(struct ieee80211_hw *hw,
                            struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta)
 {
        struct ath_softc *sc = hw->priv;
 
+       ath9k_del_ps_key(sc, vif, sta);
        ath_node_detach(sc, sta);
 
        return 0;
 }
 
+static void ath9k_sta_notify(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif,
+                        enum sta_notify_cmd cmd,
+                        struct ieee80211_sta *sta)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+
+       switch (cmd) {
+       case STA_NOTIFY_SLEEP:
+               an->sleeping = true;
+               if (ath_tx_aggr_sleep(sc, an))
+                       ieee80211_sta_set_tim(sta);
+               break;
+       case STA_NOTIFY_AWAKE:
+               an->sleeping = false;
+               ath_tx_aggr_wakeup(sc, an);
+               break;
+       }
+}
+
 static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
                         const struct ieee80211_tx_queue_params *params)
 {
@@ -1826,6 +1869,9 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 
        switch (cmd) {
        case SET_KEY:
+               if (sta)
+                       ath9k_del_ps_key(sc, vif, sta);
+
                ret = ath_key_config(common, vif, sta, key);
                if (ret >= 0) {
                        key->hw_key_idx = ret;
@@ -2209,6 +2255,21 @@ out:
        ath9k_ps_restore(sc);
 }
 
+static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       int i;
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+
+               if (ath9k_has_pending_frames(sc, &sc->tx.txq[i]))
+                       return true;
+       }
+       return false;
+}
+
 struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -2220,6 +2281,7 @@ struct ieee80211_ops ath9k_ops = {
        .configure_filter   = ath9k_configure_filter,
        .sta_add            = ath9k_sta_add,
        .sta_remove         = ath9k_sta_remove,
+       .sta_notify         = ath9k_sta_notify,
        .conf_tx            = ath9k_conf_tx,
        .bss_info_changed   = ath9k_bss_info_changed,
        .set_key            = ath9k_set_key,
@@ -2231,4 +2293,5 @@ struct ieee80211_ops ath9k_ops = {
        .rfkill_poll        = ath9k_rfkill_poll_state,
        .set_coverage_class = ath9k_set_coverage_class,
        .flush              = ath9k_flush,
+       .tx_frames_pending  = ath9k_tx_frames_pending,
 };
index f50e2c29f71e0a52b88aaa578e462bf30dba9436..8e5fe9d7f1749066c9aa3b481fba98fff7bd3705 100644 (file)
@@ -19,7 +19,6 @@
 
 #define CHANSEL_DIV            15
 #define CHANSEL_2G(_freq)      (((_freq) * 0x10000) / CHANSEL_DIV)
-#define CHANSEL_2G_9485(_freq) ((((_freq) * 0x10000) - 215) / CHANSEL_DIV)
 #define CHANSEL_5G(_freq)      (((_freq) * 0x8000) / CHANSEL_DIV)
 
 #define AR_PHY_BASE     0x9800
index 4c0d36a6980f5e319ce2a40b9782a53a4d8c22d6..18094094b298fd9e055fa422feb331b4820ce938 100644 (file)
@@ -1092,8 +1092,7 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
        if (!(rate->flags & IEEE80211_TX_RC_MCS))
                return rate->idx;
 
-       while (rate->idx > mcs_rix_off[i] &&
-              i < ARRAY_SIZE(mcs_rix_off)) {
+       while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
                rix++; i++;
        }
 
index cfaf0a48b93998464719cfe0c5e1ef19bf700dea..642504f9638ca79fd018756378a32c9d3a295c0d 100644 (file)
@@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
                *sc->rx.rxlink = bf->bf_daddr;
 
        sc->rx.rxlink = &ds->ds_link;
-       ath9k_hw_rxena(ah);
 }
 
 static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
@@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
        else
                rfilt |= ATH9K_RX_FILTER_BEACON;
 
-       if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
-           AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
-           (sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
+       if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
            (sc->rx.rxfilter & FIF_PSPOLL))
                rfilt |= ATH9K_RX_FILTER_PSPOLL;
 
@@ -1767,6 +1764,7 @@ requeue:
                } else {
                        list_move_tail(&bf->list, &sc->rx.rxbuf);
                        ath_rx_buf_link(sc, bf);
+                       ath9k_hw_rxena(ah);
                }
        } while (1);
 
index 693d543937b599d0e311383db220a007bfc3dd21..6acbf0e2240b9182e98714e1795ac90d96f0d1bf 100644 (file)
 #define AR_SREV_9300(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
 #define AR_SREV_9300_20_OR_LATER(_ah) \
-       (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \
-        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
-         ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20)))
+       ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
 
 #define AR_SREV_9485(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
@@ -1088,14 +1086,35 @@ enum {
 #define AR_ENT_OTP               0x40d8
 #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
 #define AR_ENT_OTP_MPSD                0x00800000
-#define AR_CH0_BB_DPLL2          0x16184
+
+#define AR_CH0_BB_DPLL1                 0x16180
+#define AR_CH0_BB_DPLL1_REFDIV  0xF8000000
+#define AR_CH0_BB_DPLL1_REFDIV_S 27
+#define AR_CH0_BB_DPLL1_NINI    0x07FC0000
+#define AR_CH0_BB_DPLL1_NINI_S  18
+#define AR_CH0_BB_DPLL1_NFRAC   0x0003FFFF
+#define AR_CH0_BB_DPLL1_NFRAC_S         0
+
+#define AR_CH0_BB_DPLL2                     0x16184
+#define AR_CH0_BB_DPLL2_LOCAL_PLL       0x40000000
+#define AR_CH0_BB_DPLL2_LOCAL_PLL_S     30
+#define AR_CH0_DPLL2_KI              0x3C000000
+#define AR_CH0_DPLL2_KI_S            26
+#define AR_CH0_DPLL2_KD              0x03F80000
+#define AR_CH0_DPLL2_KD_S            19
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG   0x00040000
+#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18
+#define AR_CH0_BB_DPLL2_PLL_PWD             0x00010000
+#define AR_CH0_BB_DPLL2_PLL_PWD_S    16
+#define AR_CH0_BB_DPLL2_OUTDIV      0x0000E000
+#define AR_CH0_BB_DPLL2_OUTDIV_S     13
+
 #define AR_CH0_BB_DPLL3          0x16188
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT    0x3F800000
+#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S  23
+
 #define AR_CH0_DDR_DPLL2         0x16244
 #define AR_CH0_DDR_DPLL3         0x16248
-#define AR_CH0_DPLL2_KD              0x03F80000
-#define AR_CH0_DPLL2_KD_S            19
-#define AR_CH0_DPLL2_KI              0x3C000000
-#define AR_CH0_DPLL2_KI_S            26
 #define AR_CH0_DPLL3_PHASE_SHIFT     0x3F800000
 #define AR_CH0_DPLL3_PHASE_SHIFT_S   23
 #define AR_PHY_CCA_NOM_VAL_2GHZ      -118
index d3d24904f62f89d46ff270914f7946b9f43bdf5e..8f095ad0a3db146f59b44f922fa7179a5737fe7f 100644 (file)
@@ -23,20 +23,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
                return "WMI_ECHO_CMDID";
        case WMI_ACCESS_MEMORY_CMDID:
                return "WMI_ACCESS_MEMORY_CMDID";
+       case WMI_GET_FW_VERSION:
+               return "WMI_GET_FW_VERSION";
        case WMI_DISABLE_INTR_CMDID:
                return "WMI_DISABLE_INTR_CMDID";
        case WMI_ENABLE_INTR_CMDID:
                return "WMI_ENABLE_INTR_CMDID";
-       case WMI_RX_LINK_CMDID:
-               return "WMI_RX_LINK_CMDID";
        case WMI_ATH_INIT_CMDID:
                return "WMI_ATH_INIT_CMDID";
        case WMI_ABORT_TXQ_CMDID:
                return "WMI_ABORT_TXQ_CMDID";
        case WMI_STOP_TX_DMA_CMDID:
                return "WMI_STOP_TX_DMA_CMDID";
-       case WMI_STOP_DMA_RECV_CMDID:
-               return "WMI_STOP_DMA_RECV_CMDID";
        case WMI_ABORT_TX_DMA_CMDID:
                return "WMI_ABORT_TX_DMA_CMDID";
        case WMI_DRAIN_TXQ_CMDID:
@@ -51,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
                return "WMI_FLUSH_RECV_CMDID";
        case WMI_SET_MODE_CMDID:
                return "WMI_SET_MODE_CMDID";
-       case WMI_RESET_CMDID:
-               return "WMI_RESET_CMDID";
        case WMI_NODE_CREATE_CMDID:
                return "WMI_NODE_CREATE_CMDID";
        case WMI_NODE_REMOVE_CMDID:
@@ -61,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
                return "WMI_VAP_REMOVE_CMDID";
        case WMI_VAP_CREATE_CMDID:
                return "WMI_VAP_CREATE_CMDID";
-       case WMI_BEACON_UPDATE_CMDID:
-               return "WMI_BEACON_UPDATE_CMDID";
        case WMI_REG_READ_CMDID:
                return "WMI_REG_READ_CMDID";
        case WMI_REG_WRITE_CMDID:
@@ -71,20 +65,20 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
                return "WMI_RC_STATE_CHANGE_CMDID";
        case WMI_RC_RATE_UPDATE_CMDID:
                return "WMI_RC_RATE_UPDATE_CMDID";
-       case WMI_DEBUG_INFO_CMDID:
-               return "WMI_DEBUG_INFO_CMDID";
-       case WMI_HOST_ATTACH:
-               return "WMI_HOST_ATTACH";
        case WMI_TARGET_IC_UPDATE_CMDID:
                return "WMI_TARGET_IC_UPDATE_CMDID";
-       case WMI_TGT_STATS_CMDID:
-               return "WMI_TGT_STATS_CMDID";
        case WMI_TX_AGGR_ENABLE_CMDID:
                return "WMI_TX_AGGR_ENABLE_CMDID";
        case WMI_TGT_DETACH_CMDID:
                return "WMI_TGT_DETACH_CMDID";
-       case WMI_TGT_TXQ_ENABLE_CMDID:
-               return "WMI_TGT_TXQ_ENABLE_CMDID";
+       case WMI_NODE_UPDATE_CMDID:
+               return "WMI_NODE_UPDATE_CMDID";
+       case WMI_INT_STATS_CMDID:
+               return "WMI_INT_STATS_CMDID";
+       case WMI_TX_STATS_CMDID:
+               return "WMI_TX_STATS_CMDID";
+       case WMI_RX_STATS_CMDID:
+               return "WMI_RX_STATS_CMDID";
        case WMI_AGGR_LIMIT_CMD:
                return "WMI_AGGR_LIMIT_CMD";
        }
@@ -102,9 +96,15 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
 
        wmi->drv_priv = priv;
        wmi->stopped = false;
+       skb_queue_head_init(&wmi->wmi_event_queue);
+       spin_lock_init(&wmi->wmi_lock);
+       spin_lock_init(&wmi->event_lock);
        mutex_init(&wmi->op_mutex);
        mutex_init(&wmi->multi_write_mutex);
        init_completion(&wmi->cmd_wait);
+       INIT_LIST_HEAD(&wmi->pending_tx_events);
+       tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet,
+                    (unsigned long)wmi);
 
        return wmi;
 }
@@ -120,11 +120,65 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
        kfree(priv->wmi);
 }
 
-void ath9k_swba_tasklet(unsigned long data)
+void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
 {
-       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
+       unsigned long flags;
 
-       ath9k_htc_swba(priv, priv->wmi->beacon_pending);
+       tasklet_kill(&priv->wmi->wmi_event_tasklet);
+       spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
+       __skb_queue_purge(&priv->wmi->wmi_event_queue);
+       spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
+}
+
+void ath9k_wmi_event_tasklet(unsigned long data)
+{
+       struct wmi *wmi = (struct wmi *)data;
+       struct ath9k_htc_priv *priv = wmi->drv_priv;
+       struct wmi_cmd_hdr *hdr;
+       void *wmi_event;
+       struct wmi_event_swba *swba;
+       struct sk_buff *skb = NULL;
+       unsigned long flags;
+       u16 cmd_id;
+
+       do {
+               spin_lock_irqsave(&wmi->wmi_lock, flags);
+               skb = __skb_dequeue(&wmi->wmi_event_queue);
+               if (!skb) {
+                       spin_unlock_irqrestore(&wmi->wmi_lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&wmi->wmi_lock, flags);
+
+               hdr = (struct wmi_cmd_hdr *) skb->data;
+               cmd_id = be16_to_cpu(hdr->command_id);
+               wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+
+               switch (cmd_id) {
+               case WMI_SWBA_EVENTID:
+                       swba = (struct wmi_event_swba *) wmi_event;
+                       ath9k_htc_swba(priv, swba);
+                       break;
+               case WMI_FATAL_EVENTID:
+                       ieee80211_queue_work(wmi->drv_priv->hw,
+                                            &wmi->drv_priv->fatal_work);
+                       break;
+               case WMI_TXSTATUS_EVENTID:
+                       spin_lock_bh(&priv->tx.tx_lock);
+                       if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
+                               spin_unlock_bh(&priv->tx.tx_lock);
+                               break;
+                       }
+                       spin_unlock_bh(&priv->tx.tx_lock);
+
+                       ath9k_htc_txstatus(priv, wmi_event);
+                       break;
+               default:
+                       break;
+               }
+
+               kfree_skb(skb);
+       } while (1);
 }
 
 void ath9k_fatal_work(struct work_struct *work)
@@ -153,10 +207,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
        struct wmi *wmi = (struct wmi *) priv;
        struct wmi_cmd_hdr *hdr;
        u16 cmd_id;
-       void *wmi_event;
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-       __be32 txrate;
-#endif
 
        if (unlikely(wmi->stopped))
                goto free_skb;
@@ -165,26 +215,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
        cmd_id = be16_to_cpu(hdr->command_id);
 
        if (cmd_id & 0x1000) {
-               wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
-               switch (cmd_id) {
-               case WMI_SWBA_EVENTID:
-                       wmi->beacon_pending = *(u8 *)wmi_event;
-                       tasklet_schedule(&wmi->drv_priv->swba_tasklet);
-                       break;
-               case WMI_FATAL_EVENTID:
-                       ieee80211_queue_work(wmi->drv_priv->hw,
-                                            &wmi->drv_priv->fatal_work);
-                       break;
-               case WMI_TXRATE_EVENTID:
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
-                       txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
-                       wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
-#endif
-                       break;
-               default:
-                       break;
-               }
-               kfree_skb(skb);
+               spin_lock(&wmi->wmi_lock);
+               __skb_queue_tail(&wmi->wmi_event_queue, skb);
+               spin_unlock(&wmi->wmi_lock);
+               tasklet_schedule(&wmi->wmi_event_tasklet);
                return;
        }
 
@@ -243,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
        hdr->command_id = cpu_to_be16(cmd);
        hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
 
-       return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL);
+       return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid);
 }
 
 int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
index 42084277522dc15441a9d5ff953e028bf172a8d9..02ecb9f06db02dd03d6f93801d4daee3a1082c8e 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef WMI_H
 #define WMI_H
 
-
 struct wmi_event_txrate {
        __be32 txrate;
        struct {
@@ -31,18 +30,65 @@ struct wmi_cmd_hdr {
        __be16 seq_no;
 } __packed;
 
+struct wmi_fw_version {
+       __be16 major;
+       __be16 minor;
+
+} __packed;
+
+struct wmi_event_swba {
+       __be64 tsf;
+       u8 beacon_pending;
+};
+
+/*
+ * 64 - HTC header - WMI header - 1 / txstatus
+ * And some other hdr. space is also accounted for.
+ * 12 seems to be the magic number.
+ */
+#define HTC_MAX_TX_STATUS 12
+
+#define ATH9K_HTC_TXSTAT_ACK        BIT(0)
+#define ATH9K_HTC_TXSTAT_FILT       BIT(1)
+#define ATH9K_HTC_TXSTAT_RTC_CTS    BIT(2)
+#define ATH9K_HTC_TXSTAT_MCS        BIT(3)
+#define ATH9K_HTC_TXSTAT_CW40       BIT(4)
+#define ATH9K_HTC_TXSTAT_SGI        BIT(5)
+
+/*
+ * Legacy rates are indicated as indices.
+ * HT rates are indicated as dot11 numbers.
+ * This allows us to resrict the rate field
+ * to 4 bits.
+ */
+#define ATH9K_HTC_TXSTAT_RATE       0x0f
+#define ATH9K_HTC_TXSTAT_RATE_S     0
+
+#define ATH9K_HTC_TXSTAT_EPID       0xf0
+#define ATH9K_HTC_TXSTAT_EPID_S     4
+
+struct __wmi_event_txstatus {
+       u8 cookie;
+       u8 ts_rate; /* Also holds EP ID */
+       u8 ts_flags;
+};
+
+struct wmi_event_txstatus {
+       u8 cnt;
+       struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS];
+} __packed;
+
 enum wmi_cmd_id {
        WMI_ECHO_CMDID = 0x0001,
        WMI_ACCESS_MEMORY_CMDID,
 
        /* Commands to Target */
+       WMI_GET_FW_VERSION,
        WMI_DISABLE_INTR_CMDID,
        WMI_ENABLE_INTR_CMDID,
-       WMI_RX_LINK_CMDID,
        WMI_ATH_INIT_CMDID,
        WMI_ABORT_TXQ_CMDID,
        WMI_STOP_TX_DMA_CMDID,
-       WMI_STOP_DMA_RECV_CMDID,
        WMI_ABORT_TX_DMA_CMDID,
        WMI_DRAIN_TXQ_CMDID,
        WMI_DRAIN_TXQ_ALL_CMDID,
@@ -50,23 +96,21 @@ enum wmi_cmd_id {
        WMI_STOP_RECV_CMDID,
        WMI_FLUSH_RECV_CMDID,
        WMI_SET_MODE_CMDID,
-       WMI_RESET_CMDID,
        WMI_NODE_CREATE_CMDID,
        WMI_NODE_REMOVE_CMDID,
        WMI_VAP_REMOVE_CMDID,
        WMI_VAP_CREATE_CMDID,
-       WMI_BEACON_UPDATE_CMDID,
        WMI_REG_READ_CMDID,
        WMI_REG_WRITE_CMDID,
        WMI_RC_STATE_CHANGE_CMDID,
        WMI_RC_RATE_UPDATE_CMDID,
-       WMI_DEBUG_INFO_CMDID,
-       WMI_HOST_ATTACH,
        WMI_TARGET_IC_UPDATE_CMDID,
-       WMI_TGT_STATS_CMDID,
        WMI_TX_AGGR_ENABLE_CMDID,
        WMI_TGT_DETACH_CMDID,
-       WMI_TGT_TXQ_ENABLE_CMDID,
+       WMI_NODE_UPDATE_CMDID,
+       WMI_INT_STATS_CMDID,
+       WMI_TX_STATS_CMDID,
+       WMI_RX_STATS_CMDID,
        WMI_AGGR_LIMIT_CMD = 0x0026,
 };
 
@@ -76,9 +120,8 @@ enum wmi_event_id {
        WMI_FATAL_EVENTID,
        WMI_TXTO_EVENTID,
        WMI_BMISS_EVENTID,
-       WMI_WLAN_TXCOMP_EVENTID,
        WMI_DELBA_EVENTID,
-       WMI_TXRATE_EVENTID,
+       WMI_TXSTATUS_EVENTID,
 };
 
 #define MAX_CMD_NUMBER 62
@@ -88,6 +131,12 @@ struct register_write {
        __be32 val;
 };
 
+struct ath9k_htc_tx_event {
+       int count;
+       struct __wmi_event_txstatus txs;
+       struct list_head list;
+};
+
 struct wmi {
        struct ath9k_htc_priv *drv_priv;
        struct htc_target *htc;
@@ -95,12 +144,16 @@ struct wmi {
        struct mutex op_mutex;
        struct completion cmd_wait;
        enum wmi_cmd_id last_cmd_id;
+       struct sk_buff_head wmi_event_queue;
+       struct tasklet_struct wmi_event_tasklet;
        u16 tx_seq_id;
        u8 *cmd_rsp_buf;
        u32 cmd_rsp_len;
        bool stopped;
 
-       u8 beacon_pending;
+       struct list_head pending_tx_events;
+       spinlock_t event_lock;
+
        spinlock_t wmi_lock;
 
        atomic_t mwrite_cnt;
@@ -117,8 +170,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
                  u8 *cmd_buf, u32 cmd_len,
                  u8 *rsp_buf, u32 rsp_len,
                  u32 timeout);
-void ath9k_swba_tasklet(unsigned long data);
+void ath9k_wmi_event_tasklet(unsigned long data);
 void ath9k_fatal_work(struct work_struct *work);
+void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
 
 #define WMI_CMD(_wmi_cmd)                                              \
        do {                                                            \
index 3cea3f76e37351d4c80e8985861391e14b50de72..e9e99f730ca8ee2827f2f8e27094149bd6024065 100644 (file)
@@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        struct ath_frame_info *fi;
        int nframes;
        u8 tidno;
+       bool clear_filter;
 
        skb = bf->bf_mpdu;
        hdr = (struct ieee80211_hdr *)skb->data;
@@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                        /* transmit completion */
                        acked_cnt++;
                } else {
-                       if (!(tid->state & AGGR_CLEANUP) && retry) {
-                               if (fi->retries < ATH_MAX_SW_RETRIES) {
-                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu);
-                                       txpending = 1;
-                               } else {
-                                       bf->bf_state.bf_type |= BUF_XRETRY;
-                                       txfail = 1;
-                                       sendbar = 1;
-                                       txfail_cnt++;
-                               }
-                       } else {
+                       if ((tid->state & AGGR_CLEANUP) || !retry) {
                                /*
                                 * cleanup in progress, just fail
                                 * the un-acked sub-frames
                                 */
                                txfail = 1;
+                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+                               if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
+                                   !an->sleeping)
+                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu);
+
+                               clear_filter = true;
+                               txpending = 1;
+                       } else {
+                               bf->bf_state.bf_type |= BUF_XRETRY;
+                               txfail = 1;
+                               sendbar = 1;
+                               txfail_cnt++;
                        }
                }
 
@@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                                !txfail, sendbar);
                } else {
                        /* retry the un-acked ones */
+                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
                        if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
                                if (bf->bf_next == NULL && bf_last->bf_stale) {
                                        struct ath_buf *tbf;
@@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
        /* prepend un-acked frames to the beginning of the pending frame queue */
        if (!list_empty(&bf_pending)) {
+               if (an->sleeping)
+                       ieee80211_sta_set_tim(sta);
+
                spin_lock_bh(&txq->axq_lock);
+               if (clear_filter)
+                       tid->ac->clear_ps_filter = true;
                list_splice(&bf_pending, &tid->buf_q);
                ath_tx_queue_tid(txq, tid);
                spin_unlock_bh(&txq->axq_lock);
@@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
                bf = list_first_entry(&bf_q, struct ath_buf, list);
                bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
 
+               if (tid->ac->clear_ps_filter) {
+                       tid->ac->clear_ps_filter = false;
+                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+               }
+
                /* if only one frame, send as non-aggregate */
                if (bf == bf->bf_lastbf) {
                        fi = get_frame_info(bf->bf_mpdu);
@@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
        ath_tx_flush_tid(sc, txtid);
 }
 
+bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
+{
+       struct ath_atx_tid *tid;
+       struct ath_atx_ac *ac;
+       struct ath_txq *txq;
+       bool buffered = false;
+       int tidno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID; tidno++, tid++) {
+
+               if (!tid->sched)
+                       continue;
+
+               ac = tid->ac;
+               txq = ac->txq;
+
+               spin_lock_bh(&txq->axq_lock);
+
+               if (!list_empty(&tid->buf_q))
+                       buffered = true;
+
+               tid->sched = false;
+               list_del(&tid->list);
+
+               if (ac->sched) {
+                       ac->sched = false;
+                       list_del(&ac->list);
+               }
+
+               spin_unlock_bh(&txq->axq_lock);
+       }
+
+       return buffered;
+}
+
+void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
+{
+       struct ath_atx_tid *tid;
+       struct ath_atx_ac *ac;
+       struct ath_txq *txq;
+       int tidno;
+
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < WME_NUM_TID; tidno++, tid++) {
+
+               ac = tid->ac;
+               txq = ac->txq;
+
+               spin_lock_bh(&txq->axq_lock);
+               ac->clear_ps_filter = true;
+
+               if (!list_empty(&tid->buf_q) && !tid->paused) {
+                       ath_tx_queue_tid(txq, tid);
+                       ath_txq_schedule(sc, txq);
+               }
+
+               spin_unlock_bh(&txq->axq_lock);
+       }
+}
+
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 {
        struct ath_atx_tid *txtid;
@@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
        struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
        struct ieee80211_hdr *hdr;
        struct ath_frame_info *fi = get_frame_info(skb);
-       struct ath_node *an;
+       struct ath_node *an = NULL;
        struct ath_atx_tid *tid;
        enum ath9k_key_type keytype;
        u16 seqno = 0;
@@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
 
+       if (sta)
+               an = (struct ath_node *) sta->drv_priv;
+
        hdr = (struct ieee80211_hdr *)skb->data;
-       if (sta && ieee80211_is_data_qos(hdr->frame_control) &&
+       if (an && ieee80211_is_data_qos(hdr->frame_control) &&
                conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
 
-               an = (struct ath_node *) sta->drv_priv;
                tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
 
                /*
@@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
        memset(fi, 0, sizeof(*fi));
        if (hw_key)
                fi->keyix = hw_key->hw_key_idx;
+       else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
+               fi->keyix = an->ps_key;
        else
                fi->keyix = ATH9K_TXKEYIX_INVALID;
        fi->keytype = keytype;
@@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb)
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        int flags = 0;
 
-       flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
        flags |= ATH9K_TXDESC_INTREQ;
 
        if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
@@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
                if (txctl->paprd)
                        bf->bf_state.bfs_paprd_timestamp = jiffies;
 
+               if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+
                ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
        }
 
index 0d4f39cbdcabfef96fe9ccc6ca5dcfe3fa6d591a..a61ef3d6d89c7ee50da52b9602071dd88bb9eb5b 100644 (file)
@@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *common,
        memset(&hk, 0, sizeof(hk));
 
        switch (key->cipher) {
+       case 0:
+               hk.kv_type = ATH_CIPHER_CLR;
+               break;
        case WLAN_CIPHER_SUITE_WEP40:
        case WLAN_CIPHER_SUITE_WEP104:
                hk.kv_type = ATH_CIPHER_WEP;
@@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *common,
        }
 
        hk.kv_len = key->keylen;
-       memcpy(hk.kv_val, key->key, key->keylen);
+       if (key->keylen)
+               memcpy(hk.kv_val, key->key, key->keylen);
 
        if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
                switch (vif->type) {
index 0e1b8793c8641012617070e7d97ef0bfb8060a4f..028310f263c81c01060f5d551496cca88519b3b9 100644 (file)
@@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
        }
 };
 
-/* Can be used by 0x67, 0x6A and 0x68 */
-static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
+/* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
        .n_reg_rules = 4,
        .alpha2 =  "99",
        .reg_rules = {
@@ -151,7 +151,8 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
        case 0x67:
        case 0x68:
        case 0x6A:
-               return &ath_world_regdom_67_68_6A;
+       case 0x6C:
+               return &ath_world_regdom_67_68_6A_6C;
        default:
                WARN_ON(1);
                return ath_default_world_regdomain();
@@ -333,6 +334,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
        case 0x63:
        case 0x66:
        case 0x67:
+       case 0x6C:
                ath_reg_apply_beaconing_flags(wiphy, initiator);
                break;
        case 0x68:
index 5c2cfe6941524ccd7b05525a147b5ce6854c3133..24b53839fc3ae43176743739c510f2902f0c4aa2 100644 (file)
@@ -86,6 +86,7 @@ enum EnumRd {
        WOR9_WORLD = 0x69,
        WORA_WORLD = 0x6A,
        WORB_WORLD = 0x6B,
+       WORC_WORLD = 0x6C,
 
        MKK3_MKKB = 0x80,
        MKK3_MKKA2 = 0x81,
@@ -282,6 +283,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
        {WOR9_WORLD, NO_CTL, NO_CTL},
        {WORA_WORLD, NO_CTL, NO_CTL},
        {WORB_WORLD, NO_CTL, NO_CTL},
+       {WORC_WORLD, NO_CTL, NO_CTL},
 };
 
 static struct country_code_to_enum_rd allCountries[] = {
index 31ac672b64e11b11d2d91fd026d19026f6c42545..89509392ef5d9b7f968365bbe0873f6cea8dc062 100644 (file)
@@ -2860,7 +2860,6 @@ static struct rate_control_ops rs_4965_ops = {
 
 int iwl4965_rate_control_register(void)
 {
-       pr_err("Registering 4965 rate control operations\n");
        return ieee80211_rate_control_register(&rs_4965_ops);
 }
 
index d484c3678163f9191570f59dade85c9d642e018e..f8870543d68f8555025c1a26d094dfa91d4c3a8d 100644 (file)
@@ -3173,7 +3173,7 @@ static void iwl4965_hw_detect(struct iwl_priv *priv)
 {
        priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
        priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG);
-       pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+       priv->rev_id = priv->pci_dev->revision;
        IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
 }
 
index 3652931753e08f046d616197dcb0776ea60d44cf..bb6a737de61fbd656abd534c464d72733c89affe 100644 (file)
@@ -1,6 +1,6 @@
 # AGN
 obj-$(CONFIG_IWLAGN)   += iwlagn.o
-iwlagn-objs            := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
+iwlagn-objs            := iwl-agn.o iwl-agn-rs.o
 iwlagn-objs            += iwl-agn-ucode.o iwl-agn-tx.o
 iwlagn-objs            += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
 iwlagn-objs            += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
index 1b27992918342701ac403ce515b0f62961917995..baf80111efaf7bfa6efcd47aad23b80996efd58b 100644 (file)
@@ -45,7 +45,6 @@
 #include "iwl-agn.h"
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
-#include "iwl-agn-led.h"
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
 #define IWL100_UCODE_API_MIN 5
 
 #define IWL1000_FW_PRE "iwlwifi-1000-"
-#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
-#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
+#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
 
 #define IWL100_FW_PRE "iwlwifi-100-"
-#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
-#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api)
+#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
 
 
 /*
@@ -184,10 +181,6 @@ static struct iwl_lib_ops iwl1000_lib = {
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
-       .dump_fh = iwl_dump_fh,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .apm_ops = {
@@ -202,7 +195,7 @@ static struct iwl_lib_ops iwl1000_lib = {
                        EEPROM_REG_BAND_4_CHANNELS,
                        EEPROM_REG_BAND_5_CHANNELS,
                        EEPROM_REG_BAND_24_HT40_CHANNELS,
-                       EEPROM_REG_BAND_52_HT40_CHANNELS
+                       EEPROM_REGULATORY_BAND_NO_HT40,
                },
                .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
                .release_semaphore = iwlcore_eeprom_release_semaphore,
@@ -221,19 +214,12 @@ static struct iwl_lib_ops iwl1000_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static const struct iwl_ops iwl1000_ops = {
        .lib = &iwl1000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl1000_base_params = {
@@ -241,7 +227,6 @@ static struct iwl_base_params iwl1000_base_params = {
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .eeprom_size = OTP_LOW_IMAGE_SIZE,
        .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_1000,
        .shadow_ram_support = false,
        .led_compensation = 51,
@@ -251,9 +236,6 @@ static struct iwl_base_params iwl1000_base_params = {
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
        .max_event_log_size = 128,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
 };
 static struct iwl_ht_params iwl1000_ht_params = {
        .ht_greenfield_support = true,
index f602af4b9408631bb54b9fdcf3c21a36f0eb59b0..e76e02c28928afe0b4b046c2c2c24b5bba942884 100644 (file)
@@ -46,7 +46,6 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-6000-hw.h"
-#include "iwl-agn-led.h"
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
 #define IWL200_UCODE_API_MIN 5
 
 #define IWL2030_FW_PRE "iwlwifi-2030-"
-#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"
-#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api)
+#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"
 
 #define IWL2000_FW_PRE "iwlwifi-2000-"
-#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"
-#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api)
+#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"
 
 #define IWL200_FW_PRE "iwlwifi-200-"
-#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"
-#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api)
+#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"
 
 static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -101,6 +97,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
                iwl_set_bit(priv, CSR_GP_DRIVER_REG,
                            CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
 
+       if (priv->cfg->disable_otp_refresh)
+               iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010);
 }
 
 static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
@@ -265,10 +263,6 @@ static struct iwl_lib_ops iwl2000_lib = {
        .setup_deferred_work = iwlagn_bt_setup_deferred_work,
        .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
-       .dump_fh = iwl_dump_fh,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .set_channel_switch = iwl2030_hw_channel_switch,
@@ -284,7 +278,7 @@ static struct iwl_lib_ops iwl2000_lib = {
                        EEPROM_REG_BAND_4_CHANNELS,
                        EEPROM_REG_BAND_5_CHANNELS,
                        EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
-                       EEPROM_REG_BAND_52_HT40_CHANNELS
+                       EEPROM_REGULATORY_BAND_NO_HT40,
                },
                .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
                .release_semaphore = iwlcore_eeprom_release_semaphore,
@@ -304,43 +298,30 @@ static struct iwl_lib_ops iwl2000_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static const struct iwl_ops iwl2000_ops = {
        .lib = &iwl2000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl2030_ops = {
        .lib = &iwl2000_lib,
        .hcmd = &iwlagn_bt_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl200_ops = {
        .lib = &iwl2000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl230_ops = {
        .lib = &iwl2000_lib,
        .hcmd = &iwlagn_bt_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl2000_base_params = {
@@ -348,7 +329,6 @@ static struct iwl_base_params iwl2000_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = 0,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_2x00,
        .shadow_ram_support = true,
        .led_compensation = 51,
@@ -359,9 +339,6 @@ static struct iwl_base_params iwl2000_base_params = {
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
        .max_event_log_size = 512,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
        .shadow_reg_enable = true,
 };
 
@@ -371,7 +348,6 @@ static struct iwl_base_params iwl2030_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = 0,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_2x00,
        .shadow_ram_support = true,
        .led_compensation = 57,
@@ -382,9 +358,6 @@ static struct iwl_base_params iwl2030_base_params = {
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_LONG_WD_TIMEOUT,
        .max_event_log_size = 512,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
        .shadow_reg_enable = true,
 };
 
@@ -394,7 +367,6 @@ static struct iwl_ht_params iwl2000_ht_params = {
 };
 
 static struct iwl_bt_params iwl2030_bt_params = {
-       .bt_statistics = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .advanced_bt_coexist = true,
        .agg_time_limit = BT_AGG_THRESHOLD_DEF,
@@ -416,7 +388,8 @@ static struct iwl_bt_params iwl2030_bt_params = {
        .need_dc_calib = true,                                  \
        .need_temp_offset_calib = true,                         \
        .led_mode = IWL_LED_RF_STATE,                           \
-       .iq_invert = true                                       \
+       .iq_invert = true,                                      \
+       .disable_otp_refresh = true                             \
 
 struct iwl_cfg iwl2000_2bgn_cfg = {
        .name = "2000 Series 2x2 BGN",
index 66f5fe8fe1ac186bfac5763dcd405371709dc7e2..655afc19f68fa1c024767a9ed810a7f03b0d3411 100644 (file)
@@ -45,7 +45,6 @@
 #include "iwl-sta.h"
 #include "iwl-helpers.h"
 #include "iwl-agn.h"
-#include "iwl-agn-led.h"
 #include "iwl-agn-hw.h"
 #include "iwl-5000-hw.h"
 #include "iwl-agn-debugfs.h"
 #define IWL5150_UCODE_API_MIN 1
 
 #define IWL5000_FW_PRE "iwlwifi-5000-"
-#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
-#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)
+#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
 
 #define IWL5150_FW_PRE "iwlwifi-5150-"
-#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
-#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
+#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
 
 /* NIC configuration for 5000 series */
 static void iwl5000_nic_config(struct iwl_priv *priv)
@@ -261,7 +258,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
        u32 vt = 0;
        s32 offset =  iwl_temp_calib_to_offset(priv);
 
-       vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature);
+       vt = le32_to_cpu(priv->statistics.common.temperature);
        vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
        /* now vt hold the temperature in Kelvin */
        priv->temperature = KELVIN_TO_CELSIUS(vt);
@@ -352,10 +349,6 @@ static struct iwl_lib_ops iwl5000_lib = {
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
-       .dump_fh = iwl_dump_fh,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .set_channel_switch = iwl5000_hw_channel_switch,
@@ -390,11 +383,6 @@ static struct iwl_lib_ops iwl5000_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static struct iwl_lib_ops iwl5150_lib = {
@@ -408,9 +396,6 @@ static struct iwl_lib_ops iwl5150_lib = {
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .set_channel_switch = iwl5000_hw_channel_switch,
@@ -445,27 +430,18 @@ static struct iwl_lib_ops iwl5150_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static const struct iwl_ops iwl5000_ops = {
        .lib = &iwl5000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl5150_ops = {
        .lib = &iwl5150_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl5000_base_params = {
@@ -473,16 +449,12 @@ static struct iwl_base_params iwl5000_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
-       .set_l0s = true,
        .led_compensation = 51,
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_LONG_WD_TIMEOUT,
        .max_event_log_size = 512,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
 };
 static struct iwl_ht_params iwl5000_ht_params = {
        .ht_greenfield_support = true,
index 24d105b29aec9318f9672c4ae9e144bf17504a8a..905eb57f7cab14433aa35c5e1f56dd688a2d1915 100644 (file)
@@ -46,7 +46,6 @@
 #include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-6000-hw.h"
-#include "iwl-agn-led.h"
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
 #define IWL6000G2_UCODE_API_MIN 4
 
 #define IWL6000_FW_PRE "iwlwifi-6000-"
-#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
-#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api)
+#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
 
 #define IWL6050_FW_PRE "iwlwifi-6050-"
-#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
-#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
+#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
 
 #define IWL6005_FW_PRE "iwlwifi-6000g2a-"
-#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
-#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api)
+#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
 
 #define IWL6030_FW_PRE "iwlwifi-6000g2b-"
-#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
-#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api)
+#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
 
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -293,10 +288,6 @@ static struct iwl_lib_ops iwl6000_lib = {
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
-       .dump_fh = iwl_dump_fh,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .set_channel_switch = iwl6000_hw_channel_switch,
@@ -332,11 +323,6 @@ static struct iwl_lib_ops iwl6000_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static struct iwl_lib_ops iwl6030_lib = {
@@ -351,10 +337,6 @@ static struct iwl_lib_ops iwl6030_lib = {
        .setup_deferred_work = iwlagn_bt_setup_deferred_work,
        .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-       .dump_nic_event_log = iwl_dump_nic_event_log,
-       .dump_nic_error_log = iwl_dump_nic_error_log,
-       .dump_csr = iwl_dump_csr,
-       .dump_fh = iwl_dump_fh,
        .send_tx_power = iwlagn_send_tx_power,
        .update_chain_flags = iwl_update_chain_flags,
        .set_channel_switch = iwl6000_hw_channel_switch,
@@ -390,11 +372,6 @@ static struct iwl_lib_ops iwl6030_lib = {
        },
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
-       .tt_ops = {
-               .lower_power_detection = iwl_tt_is_low_power_state,
-               .tt_power_mode = iwl_tt_current_power_mode,
-               .ct_kill_check = iwl_check_for_ct_kill,
-       }
 };
 
 static struct iwl_nic_ops iwl6050_nic_ops = {
@@ -409,34 +386,26 @@ static const struct iwl_ops iwl6000_ops = {
        .lib = &iwl6000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6050_ops = {
        .lib = &iwl6000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
        .nic = &iwl6050_nic_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6150_ops = {
        .lib = &iwl6000_lib,
        .hcmd = &iwlagn_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
        .nic = &iwl6150_nic_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static const struct iwl_ops iwl6030_ops = {
        .lib = &iwl6030_lib,
        .hcmd = &iwlagn_bt_hcmd,
        .utils = &iwlagn_hcmd_utils,
-       .led = &iwlagn_led_ops,
-       .ieee80211_ops = &iwlagn_hw_ops,
 };
 
 static struct iwl_base_params iwl6000_base_params = {
@@ -444,7 +413,6 @@ static struct iwl_base_params iwl6000_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = 0,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
        .shadow_ram_support = true,
        .led_compensation = 51,
@@ -455,9 +423,6 @@ static struct iwl_base_params iwl6000_base_params = {
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
        .max_event_log_size = 512,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
        .shadow_reg_enable = true,
 };
 
@@ -466,7 +431,6 @@ static struct iwl_base_params iwl6050_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = 0,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
        .shadow_ram_support = true,
        .led_compensation = 51,
@@ -477,9 +441,6 @@ static struct iwl_base_params iwl6050_base_params = {
        .chain_noise_scale = 1500,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
        .max_event_log_size = 1024,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
        .shadow_reg_enable = true,
 };
 static struct iwl_base_params iwl6000_g2_base_params = {
@@ -487,7 +448,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
        .num_of_queues = IWLAGN_NUM_QUEUES,
        .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
        .pll_cfg_val = 0,
-       .set_l0s = true,
        .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
        .shadow_ram_support = true,
        .led_compensation = 57,
@@ -498,9 +458,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
        .chain_noise_scale = 1000,
        .wd_timeout = IWL_LONG_WD_TIMEOUT,
        .max_event_log_size = 512,
-       .ucode_tracing = true,
-       .sensitivity_calib_by_driver = true,
-       .chain_noise_calib_by_driver = true,
        .shadow_reg_enable = true,
 };
 
@@ -510,7 +467,6 @@ static struct iwl_ht_params iwl6000_ht_params = {
 };
 
 static struct iwl_bt_params iwl6000_bt_params = {
-       .bt_statistics = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .advanced_bt_coexist = true,
        .agg_time_limit = BT_AGG_THRESHOLD_DEF,
index 7b761de77b0abdb2d9189eecfb0d165237ad8439..0f6bb9b2e642610a56e260812be037d18b1bd34b 100644 (file)
@@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
        IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
 }
 
-void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
+void iwl_sensitivity_calibration(struct iwl_priv *priv)
 {
        u32 rx_enable_time;
        u32 fa_cck;
@@ -631,16 +631,9 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       if (iwl_bt_statistics(priv)) {
-               rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
-                             rx.general.common);
-               ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
-               cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck);
-       } else {
-               rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general);
-               ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm);
-               cck = &(((struct iwl_notif_statistics *)resp)->rx.cck);
-       }
+       rx_info = &priv->statistics.rx_non_phy;
+       ofdm = &priv->statistics.rx_ofdm;
+       cck = &priv->statistics.rx_cck;
        if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
                IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -851,7 +844,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
  * 1)  Which antennas are connected.
  * 2)  Differential rx gain settings to balance the 3 receivers.
  */
-void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
+void iwl_chain_noise_calibration(struct iwl_priv *priv)
 {
        struct iwl_chain_noise_data *data = NULL;
 
@@ -896,13 +889,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       if (iwl_bt_statistics(priv)) {
-               rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
-                             rx.general.common);
-       } else {
-               rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
-                             rx.general);
-       }
+
+       rx_info = &priv->statistics.rx_non_phy;
+
        if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
                IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -911,19 +900,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 
        rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
        rxon_chnum = le16_to_cpu(ctx->staging.channel);
-       if (iwl_bt_statistics(priv)) {
-               stat_band24 = !!(((struct iwl_bt_notif_statistics *)
-                                stat_resp)->flag &
-                                STATISTICS_REPLY_FLG_BAND_24G_MSK);
-               stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *)
-                                        stat_resp)->flag) >> 16;
-       } else {
-               stat_band24 = !!(((struct iwl_notif_statistics *)
-                                stat_resp)->flag &
-                                STATISTICS_REPLY_FLG_BAND_24G_MSK);
-               stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *)
-                                        stat_resp)->flag) >> 16;
-       }
+       stat_band24 =
+               !!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
+       stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16;
 
        /* Make sure we accumulate data for just the associated channel
         *   (even if scanning). */
index ef4d5079a7ed136ea808e95064ea4670dca8fa61..4ef4dd934254e57a2dfbab0847c4bed25cd6bd99 100644 (file)
@@ -66,8 +66,8 @@
 #include "iwl-core.h"
 #include "iwl-commands.h"
 
-void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
-void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp);
+void iwl_chain_noise_calibration(struct iwl_priv *priv);
+void iwl_sensitivity_calibration(struct iwl_priv *priv);
 
 void iwl_init_sensitivity(struct iwl_priv *priv);
 void iwl_reset_run_time_calib(struct iwl_priv *priv);
index d1834aa7edf01328beedd1b27dd62b62b1cdf101..71a5f31cd7cc403ed5638cd5efdbea8805263201 100644 (file)
@@ -39,10 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
        int p = 0;
        u32 flag;
 
-       if (iwl_bt_statistics(priv))
-               flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
-       else
-               flag = le32_to_cpu(priv->_agn.statistics.flag);
+       flag = le32_to_cpu(priv->statistics.flag);
 
        p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
        if (flag & UCODE_STATISTICS_CLEAR_MSK)
@@ -88,43 +85,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
         * the last statistics notification from uCode
         * might not reflect the current uCode activity
         */
-       if (iwl_bt_statistics(priv)) {
-               ofdm = &priv->_agn.statistics_bt.rx.ofdm;
-               cck = &priv->_agn.statistics_bt.rx.cck;
-               general = &priv->_agn.statistics_bt.rx.general.common;
-               ht = &priv->_agn.statistics_bt.rx.ofdm_ht;
-               accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm;
-               accum_cck = &priv->_agn.accum_statistics_bt.rx.cck;
-               accum_general =
-                       &priv->_agn.accum_statistics_bt.rx.general.common;
-               accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht;
-               delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm;
-               delta_cck = &priv->_agn.delta_statistics_bt.rx.cck;
-               delta_general =
-                       &priv->_agn.delta_statistics_bt.rx.general.common;
-               delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht;
-               max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm;
-               max_cck = &priv->_agn.max_delta_bt.rx.cck;
-               max_general = &priv->_agn.max_delta_bt.rx.general.common;
-               max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht;
-       } else {
-               ofdm = &priv->_agn.statistics.rx.ofdm;
-               cck = &priv->_agn.statistics.rx.cck;
-               general = &priv->_agn.statistics.rx.general;
-               ht = &priv->_agn.statistics.rx.ofdm_ht;
-               accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
-               accum_cck = &priv->_agn.accum_statistics.rx.cck;
-               accum_general = &priv->_agn.accum_statistics.rx.general;
-               accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
-               delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
-               delta_cck = &priv->_agn.delta_statistics.rx.cck;
-               delta_general = &priv->_agn.delta_statistics.rx.general;
-               delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
-               max_ofdm = &priv->_agn.max_delta.rx.ofdm;
-               max_cck = &priv->_agn.max_delta.rx.cck;
-               max_general = &priv->_agn.max_delta.rx.general;
-               max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
-       }
+       ofdm = &priv->statistics.rx_ofdm;
+       cck = &priv->statistics.rx_cck;
+       general = &priv->statistics.rx_non_phy;
+       ht = &priv->statistics.rx_ofdm_ht;
+       accum_ofdm = &priv->accum_stats.rx_ofdm;
+       accum_cck = &priv->accum_stats.rx_cck;
+       accum_general = &priv->accum_stats.rx_non_phy;
+       accum_ht = &priv->accum_stats.rx_ofdm_ht;
+       delta_ofdm = &priv->delta_stats.rx_ofdm;
+       delta_cck = &priv->delta_stats.rx_cck;
+       delta_general = &priv->delta_stats.rx_non_phy;
+       delta_ht = &priv->delta_stats.rx_ofdm_ht;
+       max_ofdm = &priv->max_delta_stats.rx_ofdm;
+       max_cck = &priv->max_delta_stats.rx_cck;
+       max_general = &priv->max_delta_stats.rx_non_phy;
+       max_ht = &priv->max_delta_stats.rx_ofdm_ht;
 
        pos += iwl_statistics_flag(priv, buf, bufsz);
        pos += scnprintf(buf + pos, bufsz - pos,
@@ -531,20 +507,13 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
        }
 
        /* the statistic information display here is based on
-         * the last statistics notification from uCode
-         * might not reflect the current uCode activity
-         */
-       if (iwl_bt_statistics(priv)) {
-               tx = &priv->_agn.statistics_bt.tx;
-               accum_tx = &priv->_agn.accum_statistics_bt.tx;
-               delta_tx = &priv->_agn.delta_statistics_bt.tx;
-               max_tx = &priv->_agn.max_delta_bt.tx;
-       } else {
-               tx = &priv->_agn.statistics.tx;
-               accum_tx = &priv->_agn.accum_statistics.tx;
-               delta_tx = &priv->_agn.delta_statistics.tx;
-               max_tx = &priv->_agn.max_delta.tx;
-       }
+        * the last statistics notification from uCode
+        * might not reflect the current uCode activity
+        */
+       tx = &priv->statistics.tx;
+       accum_tx = &priv->accum_stats.tx;
+       delta_tx = &priv->delta_stats.tx;
+       max_tx = &priv->max_delta_stats.tx;
 
        pos += iwl_statistics_flag(priv, buf, bufsz);
        pos += scnprintf(buf + pos, bufsz - pos,
@@ -731,36 +700,21 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
        }
 
        /* the statistic information display here is based on
-         * the last statistics notification from uCode
-         * might not reflect the current uCode activity
-         */
-       if (iwl_bt_statistics(priv)) {
-               general = &priv->_agn.statistics_bt.general.common;
-               dbg = &priv->_agn.statistics_bt.general.common.dbg;
-               div = &priv->_agn.statistics_bt.general.common.div;
-               accum_general = &priv->_agn.accum_statistics_bt.general.common;
-               accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg;
-               accum_div = &priv->_agn.accum_statistics_bt.general.common.div;
-               delta_general = &priv->_agn.delta_statistics_bt.general.common;
-               max_general = &priv->_agn.max_delta_bt.general.common;
-               delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg;
-               max_dbg = &priv->_agn.max_delta_bt.general.common.dbg;
-               delta_div = &priv->_agn.delta_statistics_bt.general.common.div;
-               max_div = &priv->_agn.max_delta_bt.general.common.div;
-       } else {
-               general = &priv->_agn.statistics.general.common;
-               dbg = &priv->_agn.statistics.general.common.dbg;
-               div = &priv->_agn.statistics.general.common.div;
-               accum_general = &priv->_agn.accum_statistics.general.common;
-               accum_dbg = &priv->_agn.accum_statistics.general.common.dbg;
-               accum_div = &priv->_agn.accum_statistics.general.common.div;
-               delta_general = &priv->_agn.delta_statistics.general.common;
-               max_general = &priv->_agn.max_delta.general.common;
-               delta_dbg = &priv->_agn.delta_statistics.general.common.dbg;
-               max_dbg = &priv->_agn.max_delta.general.common.dbg;
-               delta_div = &priv->_agn.delta_statistics.general.common.div;
-               max_div = &priv->_agn.max_delta.general.common.div;
-       }
+        * the last statistics notification from uCode
+        * might not reflect the current uCode activity
+        */
+       general = &priv->statistics.common;
+       dbg = &priv->statistics.common.dbg;
+       div = &priv->statistics.common.div;
+       accum_general = &priv->accum_stats.common;
+       accum_dbg = &priv->accum_stats.common.dbg;
+       accum_div = &priv->accum_stats.common.div;
+       delta_general = &priv->delta_stats.common;
+       max_general = &priv->max_delta_stats.common;
+       delta_dbg = &priv->delta_stats.common.dbg;
+       max_dbg = &priv->max_delta_stats.common.dbg;
+       delta_div = &priv->delta_stats.common.div;
+       max_div = &priv->max_delta_stats.common.div;
 
        pos += iwl_statistics_flag(priv, buf, bufsz);
        pos += scnprintf(buf + pos, bufsz - pos,
@@ -876,8 +830,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
         * the last statistics notification from uCode
         * might not reflect the current uCode activity
         */
-       bt = &priv->_agn.statistics_bt.general.activity;
-       accum_bt = &priv->_agn.accum_statistics_bt.general.activity;
+       bt = &priv->statistics.bt_activity;
+       accum_bt = &priv->accum_stats.bt_activity;
 
        pos += iwl_statistics_flag(priv, buf, bufsz);
        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
@@ -918,10 +872,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
 
        pos += scnprintf(buf + pos, bufsz - pos,
                         "(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
-                        le32_to_cpu(priv->_agn.statistics_bt.rx.
-                               general.num_bt_kills),
-                        priv->_agn.accum_statistics_bt.rx.
-                               general.num_bt_kills);
+                        le32_to_cpu(priv->statistics.num_bt_kills),
+                        priv->statistics.accum_num_bt_kills);
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
        kfree(buf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
deleted file mode 100644 (file)
index 4bb877e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-commands.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-agn-led.h"
-
-/* Send led command */
-static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl_led_cmd),
-               .data = led_cmd,
-               .flags = CMD_ASYNC,
-               .callback = NULL,
-       };
-       u32 reg;
-
-       reg = iwl_read32(priv, CSR_LED_REG);
-       if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
-               iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
-
-       return iwl_send_cmd(priv, &cmd);
-}
-
-/* Set led register off */
-void iwlagn_led_enable(struct iwl_priv *priv)
-{
-       iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
-}
-
-const struct iwl_led_ops iwlagn_led_ops = {
-       .cmd = iwl_send_led_cmd,
-};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
deleted file mode 100644 (file)
index c0b7611..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 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.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_agn_led_h__
-#define __iwl_agn_led_h__
-
-extern const struct iwl_led_ops iwlagn_led_ops;
-void iwlagn_led_enable(struct iwl_priv *priv);
-
-#endif /* __iwl_agn_led_h__ */
index 9e47be6a7393cf203fed83cf14168ca12fd529a9..e741128842bb25fb629ab416ed3ab5d58b26b7b2 100644 (file)
@@ -172,6 +172,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
 
 static void iwlagn_set_tx_status(struct iwl_priv *priv,
                                 struct ieee80211_tx_info *info,
+                                struct iwl_rxon_context *ctx,
                                 struct iwlagn_tx_resp *tx_resp,
                                 int txq_id, bool is_agg)
 {
@@ -186,6 +187,13 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv,
        if (!iwl_is_tx_success(status))
                iwlagn_count_tx_err_status(priv, status);
 
+       if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
+           iwl_is_associated_ctx(ctx) && ctx->vif &&
+           ctx->vif->type == NL80211_IFTYPE_STATION) {
+               ctx->last_tx_rejected = true;
+               iwl_stop_queue(priv, &priv->txq[txq_id]);
+       }
+
        IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
                           "0x%x retries %d\n",
                           txq_id,
@@ -242,15 +250,16 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
 
        /* # frames attempted by Tx command */
        if (agg->frame_count == 1) {
+               struct iwl_tx_info *txb;
+
                /* Only one frame was attempted; no block-ack will arrive */
                idx = start_idx;
 
                IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
                                   agg->frame_count, agg->start_idx, idx);
-               iwlagn_set_tx_status(priv,
-                                    IEEE80211_SKB_CB(
-                                       priv->txq[txq_id].txb[idx].skb),
-                                    tx_resp, txq_id, true);
+               txb = &priv->txq[txq_id].txb[idx];
+               iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb),
+                                    txb->ctx, tx_resp, txq_id, true);
                agg->wait_for_ba = 0;
        } else {
                /* Two or more frames were attempted; expect block-ack */
@@ -391,7 +400,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
        struct iwl_tx_queue *txq = &priv->txq[txq_id];
        struct ieee80211_tx_info *info;
        struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-       u32  status = le16_to_cpu(tx_resp->status.status);
+       struct iwl_tx_info *txb;
+       u32 status = le16_to_cpu(tx_resp->status.status);
        int tid;
        int sta_id;
        int freed;
@@ -406,7 +416,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
        }
 
        txq->time_stamp = jiffies;
-       info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+       txb = &txq->txb[txq->q.read_ptr];
+       info = IEEE80211_SKB_CB(txb->skb);
        memset(&info->status, 0, sizeof(info->status));
 
        tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
@@ -450,12 +461,14 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
                                iwl_wake_queue(priv, txq);
                }
        } else {
-               iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false);
+               iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp,
+                                    txq_id, false);
                freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
                iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
                if (priv->mac80211_registered &&
-                   (iwl_queue_space(&txq->q) > txq->q.low_mark))
+                   iwl_queue_space(&txq->q) > txq->q.low_mark &&
+                   status != TX_STATUS_FAIL_PASSIVE_NO_RX)
                        iwl_wake_queue(priv, txq);
        }
 
@@ -482,8 +495,10 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
 
 void iwlagn_setup_deferred_work(struct iwl_priv *priv)
 {
-       /* in agn, the tx power calibration is done in uCode */
-       priv->disable_tx_power_cal = 1;
+       /*
+        * nothing need to be done here anymore
+        * still keep for future use if needed
+        */
 }
 
 int iwlagn_hw_valid_rtc_data_addr(u32 addr)
@@ -534,9 +549,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 void iwlagn_temperature(struct iwl_priv *priv)
 {
        /* store temperature from correct statistics (in Celsius) */
-       priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ?
-               priv->_agn.statistics_bt.general.common.temperature :
-               priv->_agn.statistics.general.common.temperature);
+       priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
        iwl_tt_handler(priv);
 }
 
index 69a29932babcf41fc27bda3cfc3b6d9909a70eda..bdae82e7fa904e5a3decefd6c85cfdb4760fa2a3 100644 (file)
@@ -83,7 +83,6 @@ enum {
 
 enum {
        IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
-       IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
        IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
        IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
        IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
index c335ee6883eefa2ddb0aa831089a2edf733c5e18..56f46ee3bacd26d9313d45ee7d85a79ca69b1f69 100644 (file)
@@ -29,6 +29,7 @@
 #include "iwl-sta.h"
 #include "iwl-core.h"
 #include "iwl-agn-calib.h"
+#include "iwl-helpers.h"
 
 static int iwlagn_disable_bss(struct iwl_priv *priv,
                              struct iwl_rxon_context *ctx,
@@ -600,6 +601,18 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
                        priv->timestamp = bss_conf->timestamp;
                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
                } else {
+                       /*
+                        * If we disassociate while there are pending
+                        * frames, just wake up the queues and let the
+                        * frames "escape" ... This shouldn't really
+                        * be happening to start with, but we should
+                        * not get stuck in this case either since it
+                        * can happen if userspace gets confused.
+                        */
+                       if (ctx->last_tx_rejected) {
+                               ctx->last_tx_rejected = false;
+                               iwl_wake_any_queue(priv, ctx);
+                       }
                        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                }
        }
index 01a6d2fc795c56c6ec7062f8d66c26138763c2bf..5c30f6b19a7f00b7fd5e803b654088f0feb1ffe8 100644 (file)
@@ -428,6 +428,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
 int iwlagn_alive_notify(struct iwl_priv *priv)
 {
        const struct queue_to_fifo_ac *queue_to_fifo;
+       struct iwl_rxon_context *ctx;
        u32 a;
        unsigned long flags;
        int i, chan;
@@ -501,6 +502,8 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
        memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
        for (i = 0; i < 4; i++)
                atomic_set(&priv->queue_stop_count[i], 0);
+       for_each_context(priv, ctx)
+               ctx->last_tx_rejected = false;
 
        /* reset to 0 to enable all the queue first */
        priv->txq_ctx_active_msk = 0;
index 60bfde75ce87016604d56d880e054c2c9ec03b12..cdeb09eee7396cfb87447ed517d6d1840c3afb21 100644 (file)
@@ -59,7 +59,6 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
-#include "iwl-agn-led.h"
 
 
 /******************************************************************************
@@ -254,6 +253,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        struct iwl_frame *frame;
        unsigned int frame_size;
        int rc;
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_TX_BEACON,
+               .flags = CMD_SIZE_HUGE,
+       };
 
        frame = iwl_get_free_frame(priv);
        if (!frame) {
@@ -269,8 +272,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
                return -EINVAL;
        }
 
-       rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-                             &frame->u.cmd[0]);
+       cmd.len = frame_size;
+       cmd.data = &frame->u.cmd[0];
+
+       rc = iwl_send_cmd_sync(priv, &cmd);
 
        iwl_free_frame(priv, frame);
 
@@ -395,7 +400,9 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
                return -EINVAL;
        }
 
-       BUG_ON(addr & ~DMA_BIT_MASK(36));
+       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+               return -EINVAL;
+
        if (unlikely(addr & ~IWL_TX_DMA_MASK))
                IWL_ERR(priv, "Unaligned address = %llx\n",
                          (unsigned long long)addr);
@@ -719,7 +726,10 @@ static void iwl_rx_handle(struct iwl_priv *priv)
                /* If an RXB doesn't have a Rx queue slot associated with it,
                 * then a bug has been introduced in the queue refilling
                 * routines -- catch it here */
-               BUG_ON(rxb == NULL);
+               if (WARN_ON(rxb == NULL)) {
+                       i = (i + 1) & RX_QUEUE_MASK;
+                       continue;
+               }
 
                rxq->queue[i] = NULL;
 
@@ -1481,7 +1491,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
                                        le32_to_cpup((__le32 *)tlv_data);
                        break;
                default:
-                       IWL_WARN(priv, "unknown TLV: %d\n", tlv_type);
+                       IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
                        break;
                }
        }
@@ -1705,10 +1715,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        else
                priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
 
-       if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS ||
-           (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics))
-               priv->bt_statistics = true;
-
        /* Copy images into buffers for card's bus-master reads ... */
 
        /* Runtime instructions (first block of data in file) */
@@ -2626,17 +2632,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        }
 
        if (priv->start_calib) {
-               if (iwl_bt_statistics(priv)) {
-                       iwl_chain_noise_calibration(priv,
-                                       (void *)&priv->_agn.statistics_bt);
-                       iwl_sensitivity_calibration(priv,
-                                       (void *)&priv->_agn.statistics_bt);
-               } else {
-                       iwl_chain_noise_calibration(priv,
-                                       (void *)&priv->_agn.statistics);
-                       iwl_sensitivity_calibration(priv,
-                                       (void *)&priv->_agn.statistics);
-               }
+               iwl_chain_noise_calibration(priv);
+               iwl_sensitivity_calibration(priv);
        }
 
        mutex_unlock(&priv->mutex);
@@ -2828,9 +2825,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 
        hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 
-       if (!priv->cfg->base_params->broken_powersave)
-               hw->flags |= IEEE80211_HW_SUPPORTS_PS |
-                            IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+       hw->flags |= IEEE80211_HW_SUPPORTS_PS |
+                    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
        if (priv->cfg->sku & IWL_SKU_N)
                hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
@@ -3732,6 +3728,28 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
        7, 6, 5, 4,
 };
 
+/* This function both allocates and initializes hw and priv. */
+static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
+{
+       struct iwl_priv *priv;
+       /* mac80211 allocates memory for this device instance, including
+        *   space for this driver's private structure */
+       struct ieee80211_hw *hw;
+
+       hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops);
+       if (hw == NULL) {
+               pr_err("%s: Can not allocate network device\n",
+                      cfg->name);
+               goto out;
+       }
+
+       priv = hw->priv;
+       priv->hw = hw;
+
+out:
+       return hw;
+}
+
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = 0, i;
index 016b79e4421e59c2287ea7ed2aff92f21156efdb..078a23e5d99decfd05cd0a0081fcebe5a507a1a8 100644 (file)
@@ -173,8 +173,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv);
 int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
 int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
-void iwl_dump_csr(struct iwl_priv *priv);
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
 
 /* rx */
 void iwlagn_rx_queue_restock(struct iwl_priv *priv);
@@ -222,6 +220,7 @@ static inline u32 iwl_tx_status_to_mac80211(u32 status)
        case TX_STATUS_DIRECT_DONE:
                return IEEE80211_TX_STAT_ACK;
        case TX_STATUS_FAIL_DEST_PS:
+       case TX_STATUS_FAIL_PASSIVE_NO_RX:
                return IEEE80211_TX_STAT_TX_FILTERED;
        default:
                return 0;
index a1a5c1b23096442141829cb867e682183a3212dc..0edba8a6419b315d7cd5f3ecff04bddc3bc9cd23 100644 (file)
@@ -2535,53 +2535,6 @@ struct rate_histogram {
 
 /* statistics command response */
 
-struct iwl39_statistics_rx_phy {
-       __le32 ina_cnt;
-       __le32 fina_cnt;
-       __le32 plcp_err;
-       __le32 crc32_err;
-       __le32 overrun_err;
-       __le32 early_overrun_err;
-       __le32 crc32_good;
-       __le32 false_alarm_cnt;
-       __le32 fina_sync_err_cnt;
-       __le32 sfd_timeout;
-       __le32 fina_timeout;
-       __le32 unresponded_rts;
-       __le32 rxe_frame_limit_overrun;
-       __le32 sent_ack_cnt;
-       __le32 sent_cts_cnt;
-} __packed;
-
-struct iwl39_statistics_rx_non_phy {
-       __le32 bogus_cts;       /* CTS received when not expecting CTS */
-       __le32 bogus_ack;       /* ACK received when not expecting ACK */
-       __le32 non_bssid_frames;        /* number of frames with BSSID that
-                                        * doesn't belong to the STA BSSID */
-       __le32 filtered_frames; /* count frames that were dumped in the
-                                * filtering process */
-       __le32 non_channel_beacons;     /* beacons with our bss id but not on
-                                        * our serving channel */
-} __packed;
-
-struct iwl39_statistics_rx {
-       struct iwl39_statistics_rx_phy ofdm;
-       struct iwl39_statistics_rx_phy cck;
-       struct iwl39_statistics_rx_non_phy general;
-} __packed;
-
-struct iwl39_statistics_tx {
-       __le32 preamble_cnt;
-       __le32 rx_detected_cnt;
-       __le32 bt_prio_defer_cnt;
-       __le32 bt_prio_kill_cnt;
-       __le32 few_bytes_cnt;
-       __le32 cts_timeout;
-       __le32 ack_timeout;
-       __le32 expected_ack_cnt;
-       __le32 actual_ack_cnt;
-} __packed;
-
 struct statistics_dbg {
        __le32 burst_check;
        __le32 burst_count;
@@ -2589,23 +2542,6 @@ struct statistics_dbg {
        __le32 reserved[3];
 } __packed;
 
-struct iwl39_statistics_div {
-       __le32 tx_on_a;
-       __le32 tx_on_b;
-       __le32 exec_time;
-       __le32 probe_time;
-} __packed;
-
-struct iwl39_statistics_general {
-       __le32 temperature;
-       struct statistics_dbg dbg;
-       __le32 sleep_time;
-       __le32 slots_out;
-       __le32 slots_idle;
-       __le32 ttl_timestamp;
-       struct iwl39_statistics_div div;
-} __packed;
-
 struct statistics_rx_phy {
        __le32 ina_cnt;
        __le32 fina_cnt;
index 45ec5cfe3fcf5aa2469c9b8b6a8cdf291f21f770..885167f8168d7b23aa5993d88acdfdc96850e0b8 100644 (file)
@@ -67,30 +67,6 @@ u32 iwl_debug_level;
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
-
-/* This function both allocates and initializes hw and priv. */
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
-{
-       struct iwl_priv *priv;
-       /* mac80211 allocates memory for this device instance, including
-        *   space for this driver's private structure */
-       struct ieee80211_hw *hw;
-
-       hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
-                               cfg->ops->ieee80211_ops);
-       if (hw == NULL) {
-               pr_err("%s: Can not allocate network device\n",
-                      cfg->name);
-               goto out;
-       }
-
-       priv = hw->priv;
-       priv->hw = hw;
-
-out:
-       return hw;
-}
-
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
 static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
@@ -965,12 +941,10 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
        IWL_ERR(priv, "Loaded firmware version: %s\n",
                priv->hw->wiphy->fw_version);
 
-       priv->cfg->ops->lib->dump_nic_error_log(priv);
-       if (priv->cfg->ops->lib->dump_csr)
-               priv->cfg->ops->lib->dump_csr(priv);
-       if (priv->cfg->ops->lib->dump_fh)
-               priv->cfg->ops->lib->dump_fh(priv, NULL, false);
-       priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
+       iwl_dump_nic_error_log(priv);
+       iwl_dump_csr(priv);
+       iwl_dump_fh(priv, NULL, false);
+       iwl_dump_nic_event_log(priv, false, NULL, false);
 #ifdef CONFIG_IWLWIFI_DEBUG
        if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
                iwl_print_rx_config_cmd(priv,
@@ -1051,7 +1025,6 @@ int iwl_apm_init(struct iwl_priv *priv)
        /*
         * Enable HAP INTA (interrupt from management bus) to
         * wake device's PCI Express link L1a -> L0s
-        * NOTE:  This is no-op for 3945 (non-existent bit)
         */
        iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                                    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
@@ -1064,20 +1037,18 @@ int iwl_apm_init(struct iwl_priv *priv)
         * If not (unlikely), enable L0S, so there is at least some
         *    power savings, even without L1.
         */
-       if (priv->cfg->base_params->set_l0s) {
-               lctl = iwl_pcie_link_ctl(priv);
-               if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                                       PCI_CFG_LINK_CTRL_VAL_L1_EN) {
-                       /* L1-ASPM enabled; disable(!) L0S  */
-                       iwl_set_bit(priv, CSR_GIO_REG,
-                                       CSR_GIO_REG_VAL_L0S_ENABLED);
-                       IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
-               } else {
-                       /* L1-ASPM disabled; enable(!) L0S */
-                       iwl_clear_bit(priv, CSR_GIO_REG,
-                                       CSR_GIO_REG_VAL_L0S_ENABLED);
-                       IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
-               }
+       lctl = iwl_pcie_link_ctl(priv);
+       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+               /* L1-ASPM enabled; disable(!) L0S  */
+               iwl_set_bit(priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
+       } else {
+               /* L1-ASPM disabled; enable(!) L0S */
+               iwl_clear_bit(priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
        }
 
        /* Configure analog phase-lock-loop before activating to D0A */
@@ -1777,6 +1748,15 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
        mutex_lock(&priv->mutex);
 
+       if (!ctx->vif || !iwl_is_ready_rf(priv)) {
+               /*
+                * Huh? But wait ... this can maybe happen when
+                * we're in the middle of a firmware restart!
+                */
+               err = -EBUSY;
+               goto out;
+       }
+
        interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
 
        if (!(interface_modes & BIT(newtype))) {
@@ -1804,6 +1784,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        /* success */
        iwl_teardown_interface(priv, vif, true);
        vif->type = newtype;
+       vif->p2p = newp2p;
        err = iwl_setup_interface(priv, ctx);
        WARN_ON(err);
        /*
index 82939f851eb9f40559a26fbc3a8ebc77063d3f39..32a990ff09ae1c32a8552ddfc2887d982c0c42b3 100644 (file)
@@ -139,12 +139,6 @@ struct iwl_temp_ops {
        void (*temperature)(struct iwl_priv *priv);
 };
 
-struct iwl_tt_ops {
-       bool (*lower_power_detection)(struct iwl_priv *priv);
-       u8 (*tt_power_mode)(struct iwl_priv *priv);
-       bool (*ct_kill_check)(struct iwl_priv *priv);
-};
-
 struct iwl_lib_ops {
        /* set hw dependent parameters */
        int (*set_hw_params)(struct iwl_priv *priv);
@@ -171,12 +165,6 @@ struct iwl_lib_ops {
        void (*cancel_deferred_work)(struct iwl_priv *priv);
        /* check validity of rtc data address */
        int (*is_valid_rtc_data_addr)(u32 addr);
-
-       int (*dump_nic_event_log)(struct iwl_priv *priv,
-                                 bool full_log, char **buf, bool display);
-       void (*dump_nic_error_log)(struct iwl_priv *priv);
-       void (*dump_csr)(struct iwl_priv *priv);
-       int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
        int (*set_channel_switch)(struct iwl_priv *priv,
                                  struct ieee80211_channel_switch *ch_switch);
        /* power management */
@@ -196,13 +184,6 @@ struct iwl_lib_ops {
        void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 
        struct iwl_debugfs_ops debugfs_ops;
-
-       /* thermal throttling */
-       struct iwl_tt_ops tt_ops;
-};
-
-struct iwl_led_ops {
-       int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
 };
 
 /* NIC specific ops */
@@ -210,23 +191,11 @@ struct iwl_nic_ops {
        void (*additional_nic_config)(struct iwl_priv *priv);
 };
 
-struct iwl_legacy_ops {
-       void (*post_associate)(struct iwl_priv *priv);
-       void (*config_ap)(struct iwl_priv *priv);
-       /* station management */
-       int (*update_bcast_stations)(struct iwl_priv *priv);
-       int (*manage_ibss_station)(struct iwl_priv *priv,
-                                  struct ieee80211_vif *vif, bool add);
-};
-
 struct iwl_ops {
        const struct iwl_lib_ops *lib;
        const struct iwl_hcmd_ops *hcmd;
        const struct iwl_hcmd_utils_ops *utils;
-       const struct iwl_led_ops *led;
        const struct iwl_nic_ops *nic;
-       const struct iwl_legacy_ops *legacy;
-       const struct ieee80211_ops *ieee80211_ops;
 };
 
 struct iwl_mod_params {
@@ -256,13 +225,6 @@ struct iwl_mod_params {
  * @wd_timeout: TX queues watchdog timeout
  * @temperature_kelvin: temperature report by uCode in kelvin
  * @max_event_log_size: size of event log buffer size for ucode event logging
- * @tx_power_by_driver: tx power calibration performed by driver
- *     instead of uCode
- * @ucode_tracing: support ucode continuous tracing
- * @sensitivity_calib_by_driver: driver has the capability to perform
- *     sensitivity calibration operation
- * @chain_noise_calib_by_driver: driver has the capability to perform
- *     chain noise calibration operation
  * @shadow_reg_enable: HW shadhow register bit
  */
 struct iwl_base_params {
@@ -271,12 +233,10 @@ struct iwl_base_params {
        int num_of_ampdu_queues;/* def: HW dependent */
        /* for iwl_apm_init() */
        u32 pll_cfg_val;
-       bool set_l0s;
 
        const u16 max_ll_items;
        const bool shadow_ram_support;
        u16 led_compensation;
-       const bool broken_powersave;
        int chain_noise_num_beacons;
        bool adv_thermal_throttle;
        bool support_ct_kill_exit;
@@ -286,17 +246,12 @@ struct iwl_base_params {
        unsigned int wd_timeout;
        bool temperature_kelvin;
        u32 max_event_log_size;
-       const bool tx_power_by_driver;
-       const bool ucode_tracing;
-       const bool sensitivity_calib_by_driver;
-       const bool chain_noise_calib_by_driver;
        const bool shadow_reg_enable;
 };
 /*
  * @advanced_bt_coexist: support advanced bt coexist
  * @bt_init_traffic_load: specify initial bt traffic load
  * @bt_prio_boost: default bt priority boost value
- * @bt_statistics: use BT version of statistics notification
  * @agg_time_limit: maximum number of uSec in aggregation
  * @ampdu_factor: Maximum A-MPDU length factor
  * @ampdu_density: Minimum A-MPDU spacing
@@ -306,7 +261,6 @@ struct iwl_bt_params {
        bool advanced_bt_coexist;
        u8 bt_init_traffic_load;
        u8 bt_prio_boost;
-       const bool bt_statistics;
        u16 agg_time_limit;
        u8 ampdu_factor;
        u8 ampdu_density;
@@ -337,6 +291,7 @@ struct iwl_ht_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @iq_invert: I/Q inversion
+ * @disable_otp_refresh: disable OTP refresh current limit
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -387,13 +342,13 @@ struct iwl_cfg {
        const bool rx_with_siso_diversity;
        const bool internal_wimax_coex;
        const bool iq_invert;
+       const bool disable_otp_refresh;
 };
 
 /***************************
  *   L i b                 *
  ***************************/
 
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                    const struct ieee80211_tx_queue_params *params);
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
@@ -598,6 +553,8 @@ extern const struct dev_pm_ops iwl_pm_ops;
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 int iwl_dump_nic_event_log(struct iwl_priv *priv,
                           bool full_log, char **buf, bool display);
+void iwl_dump_csr(struct iwl_priv *priv);
+int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
 #ifdef CONFIG_IWLWIFI_DEBUG
 void iwl_print_rx_config_cmd(struct iwl_priv *priv,
                             struct iwl_rxon_context *ctx);
@@ -709,11 +666,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
               priv->cfg->bt_params->advanced_bt_coexist;
 }
 
-static inline bool iwl_bt_statistics(struct iwl_priv *priv)
-{
-       return priv->bt_statistics;
-}
-
 extern bool bt_coex_active;
 extern bool bt_siso_mode;
 
index 92f6efd2c73f4c443d2f087617bb16d4b7ecb201..c272204fccffe319c5118000e4a04d9091d68d0d 100644 (file)
@@ -437,8 +437,7 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file,
        int pos = 0;
        ssize_t ret = -ENOMEM;
 
-       ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
-                                       priv, true, &buf, true);
+       ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
        if (buf) {
                ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
                kfree(buf);
@@ -462,8 +461,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
        if (sscanf(buf, "%d", &event_log_flag) != 1)
                return -EFAULT;
        if (event_log_flag == 1)
-               priv->cfg->ops->lib->dump_nic_event_log(priv, true,
-                                                       NULL, false);
+               iwl_dump_nic_event_log(priv, true, NULL, false);
 
        return count;
 }
@@ -1268,8 +1266,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
        if (sscanf(buf, "%d", &csr) != 1)
                return -EFAULT;
 
-       if (priv->cfg->ops->lib->dump_csr)
-               priv->cfg->ops->lib->dump_csr(priv);
+       iwl_dump_csr(priv);
 
        return count;
 }
@@ -1359,13 +1356,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
        int pos = 0;
        ssize_t ret = -EFAULT;
 
-       if (priv->cfg->ops->lib->dump_fh) {
-               ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
-               if (buf) {
-                       ret = simple_read_from_buffer(user_buf,
-                                                     count, ppos, buf, pos);
-                       kfree(buf);
-               }
+       ret = pos = iwl_dump_fh(priv, &buf, true);
+       if (buf) {
+               ret = simple_read_from_buffer(user_buf,
+                                             count, ppos, buf, pos);
+               kfree(buf);
        }
 
        return ret;
@@ -1728,11 +1723,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
-       if (!priv->cfg->base_params->broken_powersave) {
-               DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
-                                S_IWUSR | S_IRUSR);
-               DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
-       }
+       DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
@@ -1755,29 +1747,20 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
                DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
 
-       if (priv->cfg->base_params->sensitivity_calib_by_driver)
-               DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
-       if (priv->cfg->base_params->chain_noise_calib_by_driver)
-               DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
-       if (priv->cfg->base_params->ucode_tracing)
-               DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
-       if (iwl_bt_statistics(priv))
-               DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
+       DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
        if (iwl_advanced_bt_coexist(priv))
                DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
-       if (priv->cfg->base_params->sensitivity_calib_by_driver)
-               DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
-                                &priv->disable_sens_cal);
-       if (priv->cfg->base_params->chain_noise_calib_by_driver)
-               DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
-                                &priv->disable_chain_noise_cal);
-       if (priv->cfg->base_params->tx_power_by_driver)
-               DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
-                               &priv->disable_tx_power_cal);
+       DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
+                        &priv->disable_sens_cal);
+       DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
+                        &priv->disable_chain_noise_cal);
        return 0;
 
 err:
index 72133368c1f53f53baa19a217a3c56cbf6254593..e84534c4d9560b7374bc00f7605580604a512f75 100644 (file)
@@ -543,13 +543,12 @@ enum iwl_ucode_tlv_type {
  * enum iwl_ucode_tlv_flag - ucode API flags
  * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
  *     was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_BTSTATS: This uCode image uses BT statistics, which
- *     may be true even if the device doesn't have BT.
+ * @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved
  * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
  */
 enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_PAN         = BIT(0),
-       IWL_UCODE_TLV_FLAGS_BTSTATS     = BIT(1),
+       IWL_UCODE_TLV_FLAGS_RESERVED_1  = BIT(1),
        IWL_UCODE_TLV_FLAGS_MFP         = BIT(2),
 };
 
@@ -1170,6 +1169,8 @@ struct iwl_rxon_context {
                bool enabled, is_40mhz;
                u8 extension_chan_offset;
        } ht;
+
+       bool last_tx_rejected;
 };
 
 enum iwl_scan_type {
@@ -1354,6 +1355,31 @@ struct iwl_priv {
        /* Last Rx'd beacon timestamp */
        u64 timestamp;
 
+       struct {
+               __le32 flag;
+               struct statistics_general_common common;
+               struct statistics_rx_non_phy rx_non_phy;
+               struct statistics_rx_phy rx_ofdm;
+               struct statistics_rx_ht_phy rx_ofdm_ht;
+               struct statistics_rx_phy rx_cck;
+               struct statistics_tx tx;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+               struct statistics_bt_activity bt_activity;
+               __le32 num_bt_kills, accum_num_bt_kills;
+#endif
+       } statistics;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+       struct {
+               struct statistics_general_common common;
+               struct statistics_rx_non_phy rx_non_phy;
+               struct statistics_rx_phy rx_ofdm;
+               struct statistics_rx_ht_phy rx_ofdm_ht;
+               struct statistics_rx_phy rx_cck;
+               struct statistics_tx tx;
+               struct statistics_bt_activity bt_activity;
+       } accum_stats, delta_stats, max_delta_stats;
+#endif
+
        struct {
                /* INT ICT Table */
                __le32 *ict_tbl;
@@ -1385,19 +1411,9 @@ struct iwl_priv {
                u8 phy_calib_chain_noise_reset_cmd;
                u8 phy_calib_chain_noise_gain_cmd;
 
-               struct iwl_notif_statistics statistics;
-               struct iwl_bt_notif_statistics statistics_bt;
                /* counts reply_tx error */
                struct reply_tx_error_statistics reply_tx_stats;
                struct reply_agg_tx_error_statistics reply_agg_tx_stats;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-               struct iwl_notif_statistics accum_statistics;
-               struct iwl_notif_statistics delta_statistics;
-               struct iwl_notif_statistics max_delta;
-               struct iwl_bt_notif_statistics accum_statistics_bt;
-               struct iwl_bt_notif_statistics delta_statistics_bt;
-               struct iwl_bt_notif_statistics max_delta_bt;
-#endif
                /* notification wait support */
                struct list_head notif_waits;
                spinlock_t notif_wait_lock;
@@ -1422,7 +1438,6 @@ struct iwl_priv {
        bool bt_ch_announce;
        bool bt_full_concurrent;
        bool bt_ant_couple_ok;
-       bool bt_statistics;
        __le32 kill_ack_mask;
        __le32 kill_cts_mask;
        __le16 bt_valid;
@@ -1487,7 +1502,6 @@ struct iwl_priv {
        struct work_struct txpower_work;
        u32 disable_sens_cal;
        u32 disable_chain_noise_cal;
-       u32 disable_tx_power_cal;
        struct work_struct run_time_calib_work;
        struct timer_list statistics_periodic;
        struct timer_list ucode_trace;
index 859b94a1229779a0b4ebb12b1a02a22fd715f598..402733638f50719907e6bbd4727203bf6182f5a5 100644 (file)
@@ -215,12 +215,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
        return  nvm_type;
 }
 
-const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
-       BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
-       return &priv->eeprom[offset];
-}
-
 static int iwl_init_otp_access(struct iwl_priv *priv)
 {
        int ret;
index 0e9d9703636accb3fbf5c26adb0ae1468037a0f5..9ce052573c6afb1d967159fbfef1f29b1c6b941e 100644 (file)
@@ -309,7 +309,6 @@ int  iwl_eeprom_check_sku(struct iwl_priv *priv);
 const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
 int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
-const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
 int iwl_init_channel_map(struct iwl_priv *priv);
 void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
index e7a1bc6b76fd6073e8782f9d646084ffe92569cd..6dfa806aefecf2695198b596c3dd49a8891fa507 100644 (file)
 /**
  * Keep-Warm (KW) buffer base address.
  *
- * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
+ * Driver must allocate a 4KByte buffer that is for keeping the
  * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
- * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host
+ * DRAM access when doing Txing or Rxing.  The dummy accesses prevent host
  * from going into a power-savings mode that would cause higher DRAM latency,
  * and possible data over/under-runs, before all Tx/Rx is complete.
  *
  * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
- * of the buffer, which must be 4K aligned.  Once this is set up, the 4965
+ * of the buffer, which must be 4K aligned.  Once this is set up, the device
  * automatically invokes keep-warm accesses when normal accesses might not
  * be sufficient to maintain fast DRAM response.
  *
@@ -97,7 +97,7 @@
 /**
  * TFD Circular Buffers Base (CBBC) addresses
  *
- * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
+ * Device has 16 base pointer registers, one for each of 16 host-DRAM-resident
  * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
  * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04
  * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
 /**
  * Rx SRAM Control and Status Registers (RSCSR)
  *
- * These registers provide handshake between driver and 4965 for the Rx queue
+ * These registers provide handshake between driver and device for the Rx queue
  * (this queue handles *all* command responses, notifications, Rx data, etc.
- * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx
+ * sent from uCode to host driver).  Unlike Tx, there is only one Rx
  * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can
  * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
  * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
  * mapping between RBDs and RBs.
  *
  * Driver must allocate host DRAM memory for the following, and set the
- * physical address of each into 4965 registers:
+ * physical address of each into device registers:
  *
  * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
  *     entries (although any power of 2, up to 4096, is selectable by driver).
  *     Driver sets physical address [35:8] of base of RBD circular buffer
  *     into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
  *
- * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
+ * 2)  Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers
  *     (RBs) have been filled, via a "write pointer", actually the index of
  *     the RB's corresponding RBD within the circular buffer.  Driver sets
  *     physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
  *
  *     Bit fields in lower dword of Rx status buffer (upper dword not used
- *     by driver; see struct iwl4965_shared, val0):
+ *     by driver:
  *     31-12:  Not used by driver
  *     11- 0:  Index of last filled Rx buffer descriptor
- *             (4965 writes, driver reads this value)
+ *             (device writes, driver reads this value)
  *
- * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
+ * As the driver prepares Receive Buffers (RBs) for device to fill, driver must
  * enter pointers to these RBs into contiguous RBD circular buffer entries,
- * and update the 4965's "write" index register,
+ * and update the device's "write" index register,
  * FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
  *
  * This "write" index corresponds to the *next* RBD that the driver will make
  * RBs), should be 8 after preparing the first 8 RBs (for example), and must
  * wrap back to 0 at the end of the circular buffer (but don't wrap before
  * "read" index has advanced past 1!  See below).
- * NOTE:  4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
+ * NOTE:  DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
  *
- * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
+ * As the device fills RBs (referenced from contiguous RBDs within the circular
  * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
  * to tell the driver the index of the latest filled RBD.  The driver must
- * read this "read" index from DRAM after receiving an Rx interrupt from 4965.
+ * read this "read" index from DRAM after receiving an Rx interrupt from device
  *
  * The driver must also internally keep track of a third index, which is the
  * next RBD to process.  When receiving an Rx interrupt, driver should process
  * driver may process the RB pointed to by RBD 0.  Depending on volume of
  * traffic, there may be many RBs to process.
  *
- * If read index == write index, 4965 thinks there is no room to put new data.
+ * If read index == write index, device thinks there is no room to put new data.
  * Due to this, the maximum number of filled RBs is 255, instead of 256.  To
  * be safe, make sure that there is a gap of at least 2 RBDs between "write"
  * and "read" indexes; that is, make sure that there are no more than 254
 /**
  * Transmit DMA Channel Control/Status Registers (TCSR)
  *
- * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
+ * Device has one configuration register for each of 8 Tx DMA/FIFO channels
  * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
  * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
  *
 #define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
 
 /* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH49_TCSR_CHNL_NUM                            (7)
 #define FH50_TCSR_CHNL_NUM                            (8)
 
 /* TCSR: tx_config register values */
 #define RX_LOW_WATERMARK 8
 
 /* Size of one Rx buffer in host DRAM */
-#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */
 #define IWL_RX_BUF_SIZE_4K (4 * 1024)
 #define IWL_RX_BUF_SIZE_8K (8 * 1024)
 
@@ -443,7 +441,7 @@ struct iwl_rb_status {
        __le16 closed_fr_num;
        __le16 finished_rb_num;
        __le16 finished_fr_nam;
-       __le32 __unused; /* 3945 only */
+       __le32 __unused;
 } __packed;
 
 
index 9177b553fe573cb77b14563ad9202fd468eeb1c0..8f0beb992ccfb3f0bcf11baa83d92f7cbcf0d431 100644 (file)
@@ -143,10 +143,12 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 {
        int ret;
 
-       BUG_ON(!(cmd->flags & CMD_ASYNC));
+       if (WARN_ON(!(cmd->flags & CMD_ASYNC)))
+               return -EINVAL;
 
        /* An asynchronous command can not expect an SKB to be set. */
-       BUG_ON(cmd->flags & CMD_WANT_SKB);
+       if (WARN_ON(cmd->flags & CMD_WANT_SKB))
+               return -EINVAL;
 
        /* Assign a generic callback if one is not provided */
        if (!cmd->callback)
@@ -169,10 +171,12 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        int cmd_idx;
        int ret;
 
-       lockdep_assert_held(&priv->mutex);
+       if (WARN_ON(cmd->flags & CMD_ASYNC))
+               return -EINVAL;
 
         /* A synchronous command can not have a callback set. */
-       BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback);
+       if (WARN_ON(cmd->callback))
+               return -EINVAL;
 
        IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
                        get_cmd_string(cmd->id));
index 5da5761c74b176f3705443de1d66ba116b13f12f..9309ff2df4c219e1b44fc882edab4e16c728300e 100644 (file)
@@ -131,6 +131,19 @@ static inline void iwl_stop_queue(struct iwl_priv *priv,
                        ieee80211_stop_queue(priv->hw, ac);
 }
 
+static inline void iwl_wake_any_queue(struct iwl_priv *priv,
+                                     struct iwl_rxon_context *ctx)
+{
+       u8 ac;
+
+       for (ac = 0; ac < AC_NUM; ac++) {
+               IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n",
+                       ac, (atomic_read(&priv->queue_stop_count[ac]) > 0)
+                             ? "stopped" : "awake");
+               iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]);
+       }
+}
+
 #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
 #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
 
index c2862d4e00e3270699b73c6dd998f2793b0fa278..d798c2a152d3062240edc34c96b5d2f8142837be 100644 (file)
@@ -61,10 +61,16 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
        { .throughput = 300 * 1024 - 1, .blink_time = 50 },
 };
 
+/* Set led register off */
+void iwlagn_led_enable(struct iwl_priv *priv)
+{
+       iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
+}
+
 /*
  * Adjust led blink rate to compensate on a MAC Clock difference on every HW
- * Led blink rate analysis showed an average deviation of 0% on 3945,
- * 5% on 4965 HW and 20% on 5000 series and up.
+ * Led blink rate analysis showed an average deviation of 20% on 5000 series
+ * and up.
  * Need to compensate on the led on/off time per HW according to the deviation
  * to achieve the desired led frequency
  * The calculation is: (100-averageDeviation)/100 * blinkTime
@@ -84,6 +90,24 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv,
        return (u8)((time * compensation) >> 6);
 }
 
+static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
+{
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_LEDS_CMD,
+               .len = sizeof(struct iwl_led_cmd),
+               .data = led_cmd,
+               .flags = CMD_ASYNC,
+               .callback = NULL,
+       };
+       u32 reg;
+
+       reg = iwl_read32(priv, CSR_LED_REG);
+       if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
+               iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
+
+       return iwl_send_cmd(priv, &cmd);
+}
+
 /* Set led pattern command */
 static int iwl_led_cmd(struct iwl_priv *priv,
                       unsigned long on,
@@ -108,7 +132,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
        led_cmd.off = iwl_blink_compensation(priv, off,
                                priv->cfg->base_params->led_compensation);
 
-       ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
+       ret = iwl_send_led_cmd(priv, &led_cmd);
        if (!ret) {
                priv->blink_on = on;
                priv->blink_off = off;
index 05b8e8f7dd4af36ea793ea3e9259ebb9f12540ec..1c93dfef6933b826c5a0c0187bfd88ae76606f39 100644 (file)
@@ -50,6 +50,7 @@ enum iwl_led_mode {
        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 c43c8e66de73cd9a1de0f9435b0fa59d68e5219b..595c930b28aebaf9bccd9ec50ab936190246345a 100644 (file)
@@ -188,9 +188,10 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
                        table = range_0;
        }
 
-       BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
-
-       *cmd = table[lvl].cmd;
+       if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM))
+               memset(cmd, 0, sizeof(*cmd));
+       else
+               *cmd = table[lvl].cmd;
 
        if (period == 0) {
                skip = 0;
@@ -354,16 +355,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
 
        dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
-       if (priv->cfg->base_params->broken_powersave)
-               iwl_power_sleep_cam_cmd(priv, cmd);
-       else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
+       if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
                iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
-       else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
-                priv->cfg->ops->lib->tt_ops.tt_power_mode &&
-                priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
+       else if (iwl_tt_is_low_power_state(priv)) {
                /* in thermal throttling low power state */
                iwl_static_sleep_cmd(priv, cmd,
-                   priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
+                   iwl_tt_current_power_mode(priv), dtimper);
        } else if (!enabled)
                iwl_power_sleep_cam_cmd(priv, cmd);
        else if (priv->power_data.debug_sleep_level_override >= 0)
index c960195df989f84d3765fc634e23de7788e56283..f00d188b2cfc7d7e008ea1c2f8296620d10e6e5d 100644 (file)
  * device.  A queue maps to only one (selectable by driver) Tx DMA channel,
  * but one DMA channel may take input from several queues.
  *
- * Tx DMA FIFOs have dedicated purposes.  For 4965, they are used as follows
- * (cf. default_queue_to_tx_fifo in iwl-4965.c):
- *
- * 0 -- EDCA BK (background) frames, lowest priority
- * 1 -- EDCA BE (best effort) frames, normal priority
- * 2 -- EDCA VI (video) frames, higher priority
- * 3 -- EDCA VO (voice) and management frames, highest priority
- * 4 -- Commands (e.g. RXON, etc.)
- * 5 -- unused (HCCA)
- * 6 -- unused (HCCA)
- * 7 -- not used by driver (device-internal only)
+ * Tx DMA FIFOs have dedicated purposes.
  *
  * For 5000 series and up, they are used differently
  * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
  *     Tx completion may end up being out-of-order).
  *
  *     The driver must maintain the queue's Byte Count table in host DRAM
- *     (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode.
+ *     for this mode.
  *     This mode does not support fragmentation.
  *
  * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
  *
  * Driver controls scheduler operation via 3 means:
  * 1)  Scheduler registers
- * 2)  Shared scheduler data base in internal 4956 SRAM
+ * 2)  Shared scheduler data base in internal SRAM
  * 3)  Shared data in host DRAM
  *
  * Initialization:
index c421f566982f6afd2195942f128535316f8db8af..b49819ca2cd68d7a1fcf9bb2e431dc3f4c4db1c4 100644 (file)
@@ -390,21 +390,16 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
  * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
  * operation state.
  */
-static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt)
+static bool iwl_good_ack_health(struct iwl_priv *priv,
+                               struct statistics_tx *cur)
 {
        int actual_delta, expected_delta, ba_timeout_delta;
-       struct statistics_tx *cur, *old;
+       struct statistics_tx *old;
 
        if (priv->_agn.agg_tids_count)
                return true;
 
-       if (iwl_bt_statistics(priv)) {
-               cur = &pkt->u.stats_bt.tx;
-               old = &priv->_agn.statistics_bt.tx;
-       } else {
-               cur = &pkt->u.stats.tx;
-               old = &priv->_agn.statistics.tx;
-       }
+       old = &priv->statistics.tx;
 
        actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
                       le32_to_cpu(old->actual_ack_cnt);
@@ -430,10 +425,10 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt
                 * DEBUG is not, these will just compile out.
                 */
                IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
-                               priv->_agn.delta_statistics.tx.rx_detected_cnt);
+                               priv->delta_stats.tx.rx_detected_cnt);
                IWL_DEBUG_RADIO(priv,
                                "ack_or_ba_timeout_collision delta %d\n",
-                               priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision);
+                               priv->delta_stats.tx.ack_or_ba_timeout_collision);
 #endif
 
                if (ba_timeout_delta >= BA_TIMEOUT_MAX)
@@ -450,7 +445,9 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt
  * to improve the throughput.
  */
 static bool iwl_good_plcp_health(struct iwl_priv *priv,
-                                struct iwl_rx_packet *pkt, unsigned int msecs)
+                                struct statistics_rx_phy *cur_ofdm,
+                                struct statistics_rx_ht_phy *cur_ofdm_ht,
+                                unsigned int msecs)
 {
        int delta;
        int threshold = priv->cfg->base_params->plcp_delta_threshold;
@@ -460,29 +457,12 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
                return true;
        }
 
-       if (iwl_bt_statistics(priv)) {
-               struct statistics_rx_bt *cur, *old;
-
-               cur = &pkt->u.stats_bt.rx;
-               old = &priv->_agn.statistics_bt.rx;
-
-               delta = le32_to_cpu(cur->ofdm.plcp_err) -
-                       le32_to_cpu(old->ofdm.plcp_err) +
-                       le32_to_cpu(cur->ofdm_ht.plcp_err) -
-                       le32_to_cpu(old->ofdm_ht.plcp_err);
-       } else {
-               struct statistics_rx *cur, *old;
-
-               cur = &pkt->u.stats.rx;
-               old = &priv->_agn.statistics.rx;
+       delta = le32_to_cpu(cur_ofdm->plcp_err) -
+               le32_to_cpu(priv->statistics.rx_ofdm.plcp_err) +
+               le32_to_cpu(cur_ofdm_ht->plcp_err) -
+               le32_to_cpu(priv->statistics.rx_ofdm_ht.plcp_err);
 
-               delta = le32_to_cpu(cur->ofdm.plcp_err) -
-                       le32_to_cpu(old->ofdm.plcp_err) +
-                       le32_to_cpu(cur->ofdm_ht.plcp_err) -
-                       le32_to_cpu(old->ofdm_ht.plcp_err);
-       }
-
-       /* Can be negative if firmware reseted statistics */
+       /* Can be negative if firmware reset statistics */
        if (delta <= 0)
                return true;
 
@@ -497,44 +477,36 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
 }
 
 static void iwl_recover_from_statistics(struct iwl_priv *priv,
-                                       struct iwl_rx_packet *pkt)
+                                       struct statistics_rx_phy *cur_ofdm,
+                                       struct statistics_rx_ht_phy *cur_ofdm_ht,
+                                       struct statistics_tx *tx,
+                                       unsigned long stamp)
 {
        const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
        unsigned int msecs;
-       unsigned long stamp;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       stamp = jiffies;
        msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
 
        /* Only gather statistics and update time stamp when not associated */
        if (!iwl_is_any_associated(priv))
-               goto out;
+               return;
 
        /* Do not check/recover when do not have enough statistics data */
        if (msecs < 99)
                return;
 
-       if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) {
+       if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) {
                IWL_ERR(priv, "low ack count detected, restart firmware\n");
                if (!iwl_force_reset(priv, IWL_FW_RESET, false))
                        return;
        }
 
-       if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs))
+       if (mod_params->plcp_check &&
+           !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
                iwl_force_reset(priv, IWL_RF_RESET, false);
-
-out:
-       if (iwl_bt_statistics(priv))
-               memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
-                       sizeof(priv->_agn.statistics_bt));
-       else
-               memcpy(&priv->_agn.statistics, &pkt->u.stats,
-                       sizeof(priv->_agn.statistics));
-
-       priv->rx_statistics_jiffies = stamp;
 }
 
 /* Calculate noise level, based on measurements during network silence just
@@ -548,10 +520,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
        int bcn_silence_a, bcn_silence_b, bcn_silence_c;
        int last_rx_noise;
 
-       if (iwl_bt_statistics(priv))
-               rx_info = &(priv->_agn.statistics_bt.rx.general.common);
-       else
-               rx_info = &(priv->_agn.statistics.rx.general);
+       rx_info = &priv->statistics.rx_non_phy;
+
        bcn_silence_a =
                le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
        bcn_silence_b =
@@ -583,105 +553,153 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
                        last_rx_noise);
 }
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
 /*
  *  based on the assumption of all statistics counter are in DWORD
  *  FIXME: This function is for debugging, do not deal with
  *  the case of counters roll-over.
  */
-static void iwl_accumulative_statistics(struct iwl_priv *priv,
-                                       __le32 *stats)
+static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta,
+                       __le32 *max_delta, __le32 *accum, int size)
 {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-       int i, size;
-       __le32 *prev_stats;
-       u32 *accum_stats;
-       u32 *delta, *max_delta;
-       struct statistics_general_common *general, *accum_general;
-       struct statistics_tx *tx, *accum_tx;
-
-       if (iwl_bt_statistics(priv)) {
-               prev_stats = (__le32 *)&priv->_agn.statistics_bt;
-               accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
-               size = sizeof(struct iwl_bt_notif_statistics);
-               general = &priv->_agn.statistics_bt.general.common;
-               accum_general = &priv->_agn.accum_statistics_bt.general.common;
-               tx = &priv->_agn.statistics_bt.tx;
-               accum_tx = &priv->_agn.accum_statistics_bt.tx;
-               delta = (u32 *)&priv->_agn.delta_statistics_bt;
-               max_delta = (u32 *)&priv->_agn.max_delta_bt;
-       } else {
-               prev_stats = (__le32 *)&priv->_agn.statistics;
-               accum_stats = (u32 *)&priv->_agn.accum_statistics;
-               size = sizeof(struct iwl_notif_statistics);
-               general = &priv->_agn.statistics.general.common;
-               accum_general = &priv->_agn.accum_statistics.general.common;
-               tx = &priv->_agn.statistics.tx;
-               accum_tx = &priv->_agn.accum_statistics.tx;
-               delta = (u32 *)&priv->_agn.delta_statistics;
-               max_delta = (u32 *)&priv->_agn.max_delta;
-       }
-       for (i = sizeof(__le32); i < size;
-            i += sizeof(__le32), stats++, prev_stats++, delta++,
-            max_delta++, accum_stats++) {
-               if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-                       *delta = (le32_to_cpu(*stats) -
-                               le32_to_cpu(*prev_stats));
-                       *accum_stats += *delta;
-                       if (*delta > *max_delta)
+       int i;
+
+       for (i = 0;
+            i < size / sizeof(__le32);
+            i++, prev++, cur++, delta++, max_delta++, accum++) {
+               if (le32_to_cpu(*cur) > le32_to_cpu(*prev)) {
+                       *delta = cpu_to_le32(
+                               le32_to_cpu(*cur) - le32_to_cpu(*prev));
+                       le32_add_cpu(accum, le32_to_cpu(*delta));
+                       if (le32_to_cpu(*delta) > le32_to_cpu(*max_delta))
                                *max_delta = *delta;
                }
        }
+}
 
-       /* reset accumulative statistics for "no-counter" type statistics */
-       accum_general->temperature = general->temperature;
-       accum_general->temperature_m = general->temperature_m;
-       accum_general->ttl_timestamp = general->ttl_timestamp;
-       accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
-       accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
-       accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
-#endif
+static void
+iwl_accumulative_statistics(struct iwl_priv *priv,
+                           struct statistics_general_common *common,
+                           struct statistics_rx_non_phy *rx_non_phy,
+                           struct statistics_rx_phy *rx_ofdm,
+                           struct statistics_rx_ht_phy *rx_ofdm_ht,
+                           struct statistics_rx_phy *rx_cck,
+                           struct statistics_tx *tx,
+                           struct statistics_bt_activity *bt_activity)
+{
+#define ACCUM(_name)   \
+       accum_stats((__le32 *)&priv->statistics._name,          \
+                   (__le32 *)_name,                            \
+                   (__le32 *)&priv->delta_stats._name,         \
+                   (__le32 *)&priv->max_delta_stats._name,     \
+                   (__le32 *)&priv->accum_stats._name,         \
+                   sizeof(*_name));
+
+       ACCUM(common);
+       ACCUM(rx_non_phy);
+       ACCUM(rx_ofdm);
+       ACCUM(rx_ofdm_ht);
+       ACCUM(rx_cck);
+       ACCUM(tx);
+       if (bt_activity)
+               ACCUM(bt_activity);
+#undef ACCUM
+}
+#else
+static inline void
+iwl_accumulative_statistics(struct iwl_priv *priv,
+                           struct statistics_general_common *common,
+                           struct statistics_rx_non_phy *rx_non_phy,
+                           struct statistics_rx_phy *rx_ofdm,
+                           struct statistics_rx_ht_phy *rx_ofdm_ht,
+                           struct statistics_rx_phy *rx_cck,
+                           struct statistics_tx *tx,
+                           struct statistics_bt_activity *bt_activity)
+{
 }
+#endif
 
 static void iwl_rx_statistics(struct iwl_priv *priv,
                              struct iwl_rx_mem_buffer *rxb)
 {
+       unsigned long stamp = jiffies;
        const int reg_recalib_period = 60;
        int change;
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+       __le32 *flag;
+       struct statistics_general_common *common;
+       struct statistics_rx_non_phy *rx_non_phy;
+       struct statistics_rx_phy *rx_ofdm;
+       struct statistics_rx_ht_phy *rx_ofdm_ht;
+       struct statistics_rx_phy *rx_cck;
+       struct statistics_tx *tx;
+       struct statistics_bt_activity *bt_activity;
+
+       len -= sizeof(struct iwl_cmd_header); /* skip header */
+
+       IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
+                    len);
+
+       if (len == sizeof(struct iwl_bt_notif_statistics)) {
+               struct iwl_bt_notif_statistics *stats;
+               stats = &pkt->u.stats_bt;
+               flag = &stats->flag;
+               common = &stats->general.common;
+               rx_non_phy = &stats->rx.general.common;
+               rx_ofdm = &stats->rx.ofdm;
+               rx_ofdm_ht = &stats->rx.ofdm_ht;
+               rx_cck = &stats->rx.cck;
+               tx = &stats->tx;
+               bt_activity = &stats->general.activity;
 
-       if (iwl_bt_statistics(priv)) {
-               IWL_DEBUG_RX(priv,
-                            "Statistics notification received (%d vs %d).\n",
-                            (int)sizeof(struct iwl_bt_notif_statistics),
-                            le32_to_cpu(pkt->len_n_flags) &
-                            FH_RSCSR_FRAME_SIZE_MSK);
-
-               change = ((priv->_agn.statistics_bt.general.common.temperature !=
-                          pkt->u.stats_bt.general.common.temperature) ||
-                          ((priv->_agn.statistics_bt.flag &
-                          STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-                          (pkt->u.stats_bt.flag &
-                          STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-
-               iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+               /* handle this exception directly */
+               priv->statistics.num_bt_kills = stats->rx.general.num_bt_kills;
+               le32_add_cpu(&priv->statistics.accum_num_bt_kills,
+                            le32_to_cpu(stats->rx.general.num_bt_kills));
+#endif
+       } else if (len == sizeof(struct iwl_notif_statistics)) {
+               struct iwl_notif_statistics *stats;
+               stats = &pkt->u.stats;
+               flag = &stats->flag;
+               common = &stats->general.common;
+               rx_non_phy = &stats->rx.general;
+               rx_ofdm = &stats->rx.ofdm;
+               rx_ofdm_ht = &stats->rx.ofdm_ht;
+               rx_cck = &stats->rx.cck;
+               tx = &stats->tx;
+               bt_activity = NULL;
        } else {
-               IWL_DEBUG_RX(priv,
-                            "Statistics notification received (%d vs %d).\n",
-                            (int)sizeof(struct iwl_notif_statistics),
-                            le32_to_cpu(pkt->len_n_flags) &
-                            FH_RSCSR_FRAME_SIZE_MSK);
-
-               change = ((priv->_agn.statistics.general.common.temperature !=
-                          pkt->u.stats.general.common.temperature) ||
-                          ((priv->_agn.statistics.flag &
-                          STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-                          (pkt->u.stats.flag &
-                          STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-
-               iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+               WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
+                         len, sizeof(struct iwl_bt_notif_statistics),
+                         sizeof(struct iwl_notif_statistics));
+               return;
        }
 
-       iwl_recover_from_statistics(priv, pkt);
+       change = common->temperature != priv->statistics.common.temperature ||
+                (*flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+                (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK);
+
+       iwl_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm,
+                                   rx_ofdm_ht, rx_cck, tx, bt_activity);
+
+       iwl_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp);
+
+       priv->statistics.flag = *flag;
+       memcpy(&priv->statistics.common, common, sizeof(*common));
+       memcpy(&priv->statistics.rx_non_phy, rx_non_phy, sizeof(*rx_non_phy));
+       memcpy(&priv->statistics.rx_ofdm, rx_ofdm, sizeof(*rx_ofdm));
+       memcpy(&priv->statistics.rx_ofdm_ht, rx_ofdm_ht, sizeof(*rx_ofdm_ht));
+       memcpy(&priv->statistics.rx_cck, rx_cck, sizeof(*rx_cck));
+       memcpy(&priv->statistics.tx, tx, sizeof(*tx));
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+       if (bt_activity)
+               memcpy(&priv->statistics.bt_activity, bt_activity,
+                       sizeof(*bt_activity));
+#endif
+
+       priv->rx_statistics_jiffies = stamp;
 
        set_bit(STATUS_STATISTICS, &priv->status);
 
@@ -708,18 +726,12 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,
 
        if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-               memset(&priv->_agn.accum_statistics, 0,
-                       sizeof(struct iwl_notif_statistics));
-               memset(&priv->_agn.delta_statistics, 0,
-                       sizeof(struct iwl_notif_statistics));
-               memset(&priv->_agn.max_delta, 0,
-                       sizeof(struct iwl_notif_statistics));
-               memset(&priv->_agn.accum_statistics_bt, 0,
-                       sizeof(struct iwl_bt_notif_statistics));
-               memset(&priv->_agn.delta_statistics_bt, 0,
-                       sizeof(struct iwl_bt_notif_statistics));
-               memset(&priv->_agn.max_delta_bt, 0,
-                       sizeof(struct iwl_bt_notif_statistics));
+               memset(&priv->accum_stats, 0,
+                       sizeof(priv->accum_stats));
+               memset(&priv->delta_stats, 0,
+                       sizeof(priv->delta_stats));
+               memset(&priv->max_delta_stats, 0,
+                       sizeof(priv->max_delta_stats));
 #endif
                IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
        }
@@ -873,6 +885,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
 {
        struct sk_buff *skb;
        __le16 fc = hdr->frame_control;
+       struct iwl_rxon_context *ctx;
 
        /* We only process data packets if the interface is open */
        if (unlikely(!priv->is_open)) {
@@ -895,6 +908,26 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
        skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
 
        iwl_update_stats(priv, false, fc, len);
+
+       /*
+       * Wake any queues that were stopped due to a passive channel tx
+       * failure. This can happen because the regulatory enforcement in
+       * the device waits for a beacon before allowing transmission,
+       * sometimes even after already having transmitted frames for the
+       * association because the new RXON may reset the information.
+       */
+       if (unlikely(ieee80211_is_beacon(fc))) {
+               for_each_context(priv, ctx) {
+                       if (!ctx->last_tx_rejected)
+                               continue;
+                       if (compare_ether_addr(hdr->addr3,
+                                              ctx->active.bssid_addr))
+                               continue;
+                       ctx->last_tx_rejected = false;
+                       iwl_wake_any_queue(priv, ctx);
+               }
+       }
+
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
        ieee80211_rx(priv->hw, skb);
index c21515640077c1ebccb4356e3f00e69d304032c7..3c8cebde16cc6608facbf2d28dd0b97100b6b637 100644 (file)
@@ -494,7 +494,8 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 
        priv->num_stations--;
 
-       BUG_ON(priv->num_stations < 0);
+       if (WARN_ON(priv->num_stations < 0))
+               priv->num_stations = 0;
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
@@ -679,7 +680,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 
                priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
                priv->num_stations--;
-               BUG_ON(priv->num_stations < 0);
+               if (WARN_ON(priv->num_stations < 0))
+                       priv->num_stations = 0;
                kfree(priv->stations[i].lq);
                priv->stations[i].lq = NULL;
        }
@@ -775,7 +777,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
        spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
        iwl_dump_lq_cmd(priv, lq);
-       BUG_ON(init && (cmd.flags & CMD_ASYNC));
+       if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
+               return -EINVAL;
 
        if (is_lq_table_valid(priv, ctx, lq))
                ret = iwl_send_cmd(priv, &cmd);
index 565980fbb591fd319c4a684d4fae2dbcc5eb722c..80c3565a66ae5361810d87de034f1284b3ed94d8 100644 (file)
@@ -232,7 +232,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
  * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
  * Tx queue resumed.
  *
- * See more detailed info in iwl-4965-hw.h.
  ***************************************************/
 
 int iwl_queue_space(const struct iwl_queue *q)
@@ -264,11 +263,13 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
 
        /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
         * and iwl_queue_dec_wrap are broken. */
-       BUG_ON(!is_power_of_2(count));
+       if (WARN_ON(!is_power_of_2(count)))
+               return -EINVAL;
 
        /* slots_num must be power-of-two size, otherwise
         * get_cmd_index is broken. */
-       BUG_ON(!is_power_of_2(slots_num));
+       if (WARN_ON(!is_power_of_2(slots_num)))
+               return -EINVAL;
 
        q->low_mark = q->n_window / 4;
        if (q->low_mark < 4)
@@ -385,7 +386,9 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
        BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
 
        /* Initialize queue's high/low-water marks, and head/tail indexes */
-       iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+       ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+       if (ret)
+               return ret;
 
        /* Tell device where to find queue */
        priv->cfg->ops->lib->txq_init(priv, txq);
@@ -447,14 +450,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
        fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
 
-       /* If any of the command structures end up being larger than
+       /*
+        * If any of the command structures end up being larger than
         * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
         * we will need to increase the size of the TFD entries
         * Also, check to see if command buffer should not exceed the size
-        * of device_cmd and max_cmd_size. */
-       BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
-              !(cmd->flags & CMD_SIZE_HUGE));
-       BUG_ON(fix_size > IWL_MAX_CMD_SIZE);
+        * of device_cmd and max_cmd_size.
+        */
+       if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+                   !(cmd->flags & CMD_SIZE_HUGE)))
+               return -EINVAL;
+
+       if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE))
+               return -EINVAL;
 
        if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
                IWL_WARN(priv, "Not sending command - %s KILL\n",
@@ -462,16 +470,21 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                return -EIO;
        }
 
+       /*
+        * As we only have a single huge buffer, check that the command
+        * is synchronous (otherwise buffers could end up being reused).
+        */
+
+       if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE)))
+               return -EINVAL;
+
        spin_lock_irqsave(&priv->hcmd_lock, flags);
 
        if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
                spin_unlock_irqrestore(&priv->hcmd_lock, flags);
 
                IWL_ERR(priv, "No space in command queue\n");
-               if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
-                       is_ct_kill =
-                               priv->cfg->ops->lib->tt_ops.ct_kill_check(priv);
-               }
+               is_ct_kill = iwl_check_for_ct_kill(priv);
                if (!is_ct_kill) {
                        IWL_ERR(priv, "Restarting adapter due to queue full\n");
                        iwlagn_fw_error(priv, false);
index 73a6e62f568093a480572c8f93e8fe85b219b2db..e22d761f2ef22f560fcc4c08696e94afbddda768 100644 (file)
@@ -115,7 +115,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv,
                SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);
 
        /* Clear RD responder bit */
-       RESETHT_EXTCAP_RDG(ht_ext_cap);
+       ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;
 
        ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info);
        ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
@@ -242,9 +242,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
  *
  * Handling includes changing the header fields into CPU format.
  */
-int mwifiex_ret_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *resp,
-                       void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
 {
        struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL;
        struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
@@ -298,8 +296,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
  *      - Setting AMSDU control parameters (for SET only)
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
+int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
                                int cmd_action, void *data_buf)
 {
        struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
@@ -331,8 +328,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,
  *
  * Handling includes changing the header fields into CPU format.
  */
-int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *resp,
+int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
                                void *data_buf)
 {
        struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL;
@@ -357,8 +353,7 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,
  *      - Setting HT Tx capability and HT Tx information fields
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd,
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
                        u16 cmd_action, void *data_buf)
 {
        struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
@@ -541,11 +536,8 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv,
        else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K)
                curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K;
        if (curr_tx_buf_size != tx_buf)
-               mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
-                       HostCmd_ACT_GEN_SET, 0,
-                       NULL, &tx_buf);
-
-       return;
+               mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
+                                      HostCmd_ACT_GEN_SET, 0, &tx_buf);
 }
 
 /*
@@ -583,8 +575,6 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
        list_del(&tx_ba_tsr_tbl->list);
 
        kfree(tx_ba_tsr_tbl);
-
-       return;
 }
 
 /*
@@ -663,8 +653,6 @@ void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv,
                list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
                spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
        }
-
-       return;
 }
 
 /*
@@ -694,8 +682,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
        memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);
 
        /* We don't wait for the response of this command */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ,
-                                 0, 0, NULL, &add_ba_req);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ,
+                                    0, 0, &add_ba_req);
 
        return ret;
 }
@@ -722,8 +710,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
        memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
 
        /* We don't wait for the response of this command */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA,
-                                 HostCmd_ACT_GEN_SET, 0, NULL, &delba);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA,
+                                    HostCmd_ACT_GEN_SET, 0, &delba);
 
        return ret;
 }
index 71a853e61b6127c7ee22055f159b01b0bb109360..02602ff30cbf2ac6a7d474d5967d4e04edac94cc 100644 (file)
@@ -28,15 +28,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
                          struct host_cmd_ds_command *resp);
 int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                              struct host_cmd_ds_command *resp);
-int mwifiex_ret_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *resp,
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
                        void *data_buf);
-int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd,
-                       u16 cmd_action, void *data_buf);
-
-int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
-                       struct host_cmd_ds_command *cmd,
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
                        u16 cmd_action, void *data_buf);
 
 int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
@@ -67,24 +61,19 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
                              struct mwifiex_ds_rx_reorder_tbl *buf);
 int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
                               struct mwifiex_ds_tx_ba_stream_tbl *buf);
-int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command
-                               *resp,
+int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
                                void *data_buf);
 int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
                             struct host_cmd_ds_command *cmd,
                             int cmd_action, void *data_buf);
-int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd,
-                               int cmd_action,
-                               void *data_buf);
+int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
+                               int cmd_action, void *data_buf);
 
 /*
  * This function checks whether AMPDU is allowed or not for a particular TID.
  */
 static inline u8
-mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
-                        struct mwifiex_ra_list_tbl *ptr, int tid)
+mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid)
 {
        return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
                ? true : false);
@@ -94,8 +83,7 @@ mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
  * This function checks whether AMSDU is allowed or not for a particular TID.
  */
 static inline u8
-mwifiex_is_amsdu_allowed(struct mwifiex_private *priv,
-                        struct mwifiex_ra_list_tbl *ptr, int tid)
+mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)
 {
        return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)
                        && ((priv->is_data_rate_auto)
@@ -104,23 +92,21 @@ mwifiex_is_amsdu_allowed(struct mwifiex_private *priv,
 }
 
 /*
- * This function checks whether a BA stream is available or not.
+ * This function checks whether a space is available for new BA stream or not.
  */
-static inline u8
-mwifiex_is_ba_stream_avail(struct mwifiex_private *priv)
+static inline u8 mwifiex_space_avail_for_new_ba_stream(
+                                       struct mwifiex_adapter *adapter)
 {
-       struct mwifiex_private *pmpriv = NULL;
-       u8 i = 0;
+       struct mwifiex_private *priv;
+       u8 i;
        u32 ba_stream_num = 0;
 
-       for (i = 0; i < priv->adapter->priv_num; i++) {
-               pmpriv = priv->adapter->priv[i];
-               if (pmpriv)
-                       ba_stream_num +=
-                               mwifiex_wmm_list_len(priv->adapter,
-                                                    (struct list_head
-                                                     *) &pmpriv->
-                                                    tx_ba_stream_tbl_ptr);
+       for (i = 0; i < adapter->priv_num; i++) {
+               priv = adapter->priv[i];
+               if (priv)
+                       ba_stream_num += mwifiex_wmm_list_len(
+                                               (struct list_head *)
+                                               &priv->tx_ba_stream_tbl_ptr);
        }
 
        return ((ba_stream_num <
@@ -133,8 +119,7 @@ mwifiex_is_ba_stream_avail(struct mwifiex_private *priv)
  * Upon successfully locating, both the TID and the RA are returned.
  */
 static inline u8
-mwifiex_find_stream_to_delete(struct mwifiex_private *priv,
-                             struct mwifiex_ra_list_tbl *ptr, int ptr_tid,
+mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,
                              int *ptid, u8 *ra)
 {
        int tid;
index c2abced66957a0ee2516fcf8964e0740292785af..c9fb0627de436e31b1e7ba2e9b00770927aa146b 100644 (file)
@@ -44,8 +44,7 @@
  * MSDU => |DA|SA|Length|SNAP|......   ..|
  */
 static int
-mwifiex_11n_form_amsdu_pkt(struct mwifiex_adapter *adapter,
-                          struct sk_buff *skb_aggr,
+mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
                           struct sk_buff *skb_src, int *pad)
 
 {
@@ -324,7 +323,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
-               mwifiex_11n_form_amsdu_pkt(adapter, skb_aggr, skb_src, &pad);
+               mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
 
                mwifiex_write_data_complete(adapter, skb_src, 0);
 
index 8e94e620e6f47f2c42ae6671cb7c5db803477f21..a93c03fdea8258d16d8b4427fa65f37b45ace374 100644 (file)
 #include "11n.h"
 #include "11n_rxreorder.h"
 
-/*
- * This function processes a received packet and forwards
- * it to the kernel/upper layer.
- */
-static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
-{
-       int ret = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
-
-       ret = mwifiex_process_rx_packet(adapter, (struct sk_buff *) payload);
-       return ret;
-}
-
 /*
  * This function dispatches all packets in the Rx reorder table.
  *
@@ -51,7 +38,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
                                         struct mwifiex_rx_reorder_tbl
                                         *rx_reor_tbl_ptr, int start_win)
 {
-       int no_pkt_to_send, i, xchg;
+       int no_pkt_to_send, i;
        void *rx_tmp_ptr = NULL;
        unsigned long flags;
 
@@ -68,7 +55,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
                }
                spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
                if (rx_tmp_ptr)
-                       mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
+                       mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
        }
 
        spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -76,8 +63,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
         * We don't have a circular buffer, hence use rotation to simulate
         * circular buffer
         */
-       xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send;
-       for (i = 0; i < xchg; ++i) {
+       for (i = 0; i < rx_reor_tbl_ptr->win_size - no_pkt_to_send; ++i) {
                rx_reor_tbl_ptr->rx_reorder_ptr[i] =
                        rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];
                rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL;
@@ -114,7 +100,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
                rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];
                rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL;
                spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-               mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr);
+               mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
        }
 
        spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -309,8 +295,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
        spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
        list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);
        spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
-
-       return;
 }
 
 /*
@@ -321,8 +305,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
  *      - Setting add BA request buffer
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
 {
        struct host_cmd_ds_11n_addba_req *add_ba_req =
                (struct host_cmd_ds_11n_addba_req *)
@@ -393,8 +376,7 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
  *      - Setting del BA request buffer
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_11n_delba(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf)
 {
        struct host_cmd_ds_11n_delba *del_ba = (struct host_cmd_ds_11n_delba *)
                &cmd->params.del_ba;
@@ -433,7 +415,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                                                tid, ta);
        if (!rx_reor_tbl_ptr) {
                if (pkt_type != PKT_TYPE_BAR)
-                       mwifiex_11n_dispatch_pkt(priv, payload);
+                       mwifiex_process_rx_packet(priv->adapter, payload);
                return 0;
        }
        start_win = rx_reor_tbl_ptr->start_win;
@@ -609,9 +591,7 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
        delba.del_ba_param_set |= cpu_to_le16(
                (u16) event->origninator << DELBA_INITIATOR_POS);
        delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
-       mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, NULL, &delba);
-
-       return;
+       mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba);
 }
 
 /*
index 42f569035745d4b12b828522030f01a2e0969962..f3ca8c8c18f9d95c35642fecd5bdec6bf9d13a60 100644 (file)
@@ -49,14 +49,12 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
 int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
                               struct host_cmd_ds_command
                               *resp);
-int mwifiex_cmd_11n_delba(struct mwifiex_private *priv,
-                         struct host_cmd_ds_command *cmd,
+int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
                          void *data_buf);
 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
                                  struct host_cmd_ds_command
                                  *cmd, void *data_buf);
-int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *cmd,
+int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
                              void *data_buf);
 void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
 struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
index 338377f7093b7a3c595070d76cd72057e0d272af..b55badef4660431fff9c18139e3ec29368d6bb42 100644 (file)
@@ -157,7 +157,7 @@ info
        mp_wr_bitmap = <SDIO multi-port write bitmap>
        cmd_resp_received = <0/1, no cmd response to process/response received and yet to process>
        event_received = <0/1, no event to process/event received and yet to process>
-       ioctl_pending = <number of ioctl pending>
+       cmd_pending = <number of cmd pending>
        tx_pending = <number of Tx packet pending>
        rx_pending = <number of Rx packet pending>
 
index ec0895f4e8d34863c90486f3eb1738ce2bd8f39b..b99ae2677d78982266105f73ba873df02a9d6723 100644 (file)
@@ -34,22 +34,17 @@ static int
 mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type
                                                  channel_type)
 {
-       int channel;
        switch (channel_type) {
        case NL80211_CHAN_NO_HT:
        case NL80211_CHAN_HT20:
-               channel = NO_SEC_CHANNEL;
-               break;
+               return NO_SEC_CHANNEL;
        case NL80211_CHAN_HT40PLUS:
-               channel = SEC_CHANNEL_ABOVE;
-               break;
+               return SEC_CHANNEL_ABOVE;
        case NL80211_CHAN_HT40MINUS:
-               channel = SEC_CHANNEL_BELOW;
-               break;
+               return SEC_CHANNEL_BELOW;
        default:
-               channel = NO_SEC_CHANNEL;
+               return NO_SEC_CHANNEL;
        }
-       return channel;
 }
 
 /*
@@ -64,21 +59,16 @@ mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type
 static enum nl80211_channel_type
 mwifiex_channels_to_cfg80211_channel_type(int channel_type)
 {
-       int channel;
        switch (channel_type) {
        case NO_SEC_CHANNEL:
-               channel = NL80211_CHAN_HT20;
-               break;
+               return NL80211_CHAN_HT20;
        case SEC_CHANNEL_ABOVE:
-               channel = NL80211_CHAN_HT40PLUS;
-               break;
+               return NL80211_CHAN_HT40PLUS;
        case SEC_CHANNEL_BELOW:
-               channel = NL80211_CHAN_HT40MINUS;
-               break;
+               return NL80211_CHAN_HT40MINUS;
        default:
-               channel = NL80211_CHAN_HT20;
+               return NL80211_CHAN_HT20;
        }
-       return channel;
 }
 
 /*
@@ -117,10 +107,8 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
                         u8 key_index, bool pairwise, const u8 *mac_addr)
 {
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
-       int ret = 0;
 
-       ret = mwifiex_set_encode(priv, NULL, 0, key_index, 1);
-       if (ret) {
+       if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) {
                wiphy_err(wiphy, "deleting the crypto keys\n");
                return -EFAULT;
        }
@@ -137,12 +125,17 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
                              enum nl80211_tx_power_setting type,
                              int dbm)
 {
-       int ret = 0;
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+       struct mwifiex_power_cfg power_cfg;
 
-       ret = mwifiex_set_tx_power(priv, type, dbm);
+       if (type == NL80211_TX_POWER_FIXED) {
+               power_cfg.is_power_auto = 0;
+               power_cfg.power_level = dbm;
+       } else {
+               power_cfg.is_power_auto = 1;
+       }
 
-       return ret;
+       return mwifiex_set_tx_power(priv, &power_cfg);
 }
 
 /*
@@ -155,17 +148,17 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
                                struct net_device *dev,
                                bool enabled, int timeout)
 {
-       int ret = 0;
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
+       u32 ps_mode;
 
        if (timeout)
                wiphy_dbg(wiphy,
                        "info: ignoring the timeout value"
                        " for IEEE power save\n");
 
-       ret = mwifiex_drv_set_power(priv, enabled);
+       ps_mode = enabled;
 
-       return ret;
+       return mwifiex_drv_set_power(priv, &ps_mode);
 }
 
 /*
@@ -177,18 +170,15 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
                                 bool multicast)
 {
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
-       int ret;
 
        /* Return if WEP key not configured */
        if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED)
                return 0;
 
-       ret = mwifiex_set_encode(priv, NULL, 0, key_index, 0);
-
-       wiphy_dbg(wiphy, "info: set default Tx key index\n");
-
-       if (ret)
+       if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) {
+               wiphy_err(wiphy, "set default Tx key index\n");
                return -EFAULT;
+       }
 
        return 0;
 }
@@ -202,15 +192,12 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
                         struct key_params *params)
 {
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
-       int ret = 0;
 
-       ret = mwifiex_set_encode(priv, params->key, params->key_len,
-                                                               key_index, 0);
-
-       wiphy_dbg(wiphy, "info: crypto keys added\n");
-
-       if (ret)
+       if (mwifiex_set_encode(priv, params->key, params->key_len,
+                                                       key_index, 0)) {
+               wiphy_err(wiphy, "crypto keys added\n");
                return -EFAULT;
+       }
 
        return 0;
 }
@@ -235,7 +222,6 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
        struct mwifiex_adapter *adapter = priv->adapter;
        struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
-       int ret = 0;
 
        /* Set country code */
        domain_info->country_code[0] = priv->country_code[0];
@@ -290,13 +276,14 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
        }
 
        domain_info->no_of_triplet = no_of_triplet;
-       /* Send cmd to FW to set domain info */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
-                                 HostCmd_ACT_GEN_SET, 0, NULL, NULL);
-       if (ret)
+
+       if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+                                    HostCmd_ACT_GEN_SET, 0, NULL)) {
                wiphy_err(wiphy, "11D: setting domain info in FW\n");
+               return -1;
+       }
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -346,8 +333,6 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
                       enum nl80211_channel_type channel_type)
 {
        struct mwifiex_chan_freq_power cfp;
-       int ret = 0;
-       int status = 0;
        struct mwifiex_ds_band_cfg band_cfg;
        u32 config_bands = 0;
        struct wiphy *wiphy = priv->wdev->wiphy;
@@ -366,15 +351,14 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
                        band_cfg.config_bands = config_bands;
                        band_cfg.adhoc_start_band = config_bands;
                }
-               /* Set channel offset */
+
                band_cfg.sec_chan_offset =
                        mwifiex_cfg80211_channel_type_to_mwifiex_channels
                        (channel_type);
-               status = mwifiex_radio_ioctl_band_cfg(priv, HostCmd_ACT_GEN_SET,
-                                                     &band_cfg);
 
-               if (status)
+               if (mwifiex_set_radio_band_cfg(priv, &band_cfg))
                        return -EFAULT;
+
                mwifiex_send_domain_info_cmd_fw(wiphy);
        }
 
@@ -382,20 +366,16 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,
                "mode %d\n", config_bands, band_cfg.sec_chan_offset,
                priv->bss_mode);
        if (!chan)
-               return ret;
+               return 0;
 
        memset(&cfp, 0, sizeof(cfp));
        cfp.freq = chan->center_freq;
-       /* Convert frequency to channel */
        cfp.channel = ieee80211_frequency_to_channel(chan->center_freq);
 
-       status = mwifiex_bss_ioctl_channel(priv, HostCmd_ACT_GEN_SET, &cfp);
-       if (status)
+       if (mwifiex_bss_set_channel(priv, &cfp))
                return -EFAULT;
 
-       ret = mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
-
-       return ret;
+       return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
 }
 
 /*
@@ -422,67 +402,41 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
 /*
  * This function sets the fragmentation threshold.
  *
- * This function creates an IOCTL request, populates it accordingly
- * and issues an IOCTL.
- *
- * The fragmentation threshold value must lies between MWIFIEX_FRAG_MIN_VALUE
+ * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
  * and MWIFIEX_FRAG_MAX_VALUE.
  */
 static int
 mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
 {
        int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
 
        if (frag_thr < MWIFIEX_FRAG_MIN_VALUE
            || frag_thr > MWIFIEX_FRAG_MAX_VALUE)
                return -EINVAL;
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_snmp_mib_ioctl(priv, wait, FRAG_THRESH_I,
-                                       HostCmd_ACT_GEN_SET, &frag_thr);
-
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option))
-               ret = -EFAULT;
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                                   HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
+                                   &frag_thr);
 
-       kfree(wait);
        return ret;
 }
 
 /*
  * This function sets the RTS threshold.
- *
- * This function creates an IOCTL request, populates it accordingly
- * and issues an IOCTL.
+
+ * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
+ * and MWIFIEX_RTS_MAX_VALUE.
  */
 static int
 mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
 {
-       int ret = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
-
        if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
                rts_thr = MWIFIEX_RTS_MAX_VALUE;
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_snmp_mib_ioctl(priv, wait, RTS_THRESH_I,
-                                       HostCmd_ACT_GEN_SET, &rts_thr);
-
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option))
-               ret = -EFAULT;
-
-       kfree(wait);
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                                   HostCmd_ACT_GEN_SET, RTS_THRESH_I,
+                                   &rts_thr);
 }
 
 /*
@@ -498,8 +452,11 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 
        int ret = 0;
 
-       if (changed & WIPHY_PARAM_RTS_THRESHOLD)
+       if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
                ret = mwifiex_set_rts(priv, wiphy->rts_threshold);
+               if (ret)
+                       return ret;
+       }
 
        if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
                ret = mwifiex_set_frag(priv, wiphy->frag_threshold);
@@ -518,7 +475,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
 {
        int ret = 0;
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct mwifiex_wait_queue *wait = NULL;
 
        if (priv->bss_mode == type) {
                wiphy_warn(wiphy, "already set to required type\n");
@@ -545,24 +501,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                return -EINVAL;
        }
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
-       mwifiex_deauthenticate(priv, wait, NULL);
+       mwifiex_deauthenticate(priv, NULL);
 
        priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
-                                 HostCmd_ACT_GEN_SET, 0, wait, NULL);
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       ret = mwifiex_request_ioctl(priv, wait, ret, MWIFIEX_IOCTL_WAIT);
-       if (ret)
-               ret = -EFAULT;
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE,
+                                   HostCmd_ACT_GEN_SET, 0, NULL);
 
-       kfree(wait);
        return ret;
 }
 
@@ -592,7 +537,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
 
        /* Get signal information from the firmware */
        memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal));
-       if (mwifiex_get_signal_info(priv, MWIFIEX_IOCTL_WAIT, &signal)) {
+       if (mwifiex_get_signal_info(priv, &signal)) {
                dev_err(priv->adapter->dev, "getting signal information\n");
                ret = -EFAULT;
        }
@@ -623,7 +568,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                             u8 *mac, struct station_info *sinfo)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       int ret = 0;
 
        mwifiex_dump_station_info(priv, sinfo);
 
@@ -632,10 +576,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
                return -ENOENT;
 
-
-       ret = mwifiex_dump_station_info(priv, sinfo);
-
-       return ret;
+       return mwifiex_dump_station_info(priv, sinfo);
 }
 
 /* Supported rates to be advertised to the cfg80211 */
@@ -750,7 +691,7 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
                return -EBUSY;
 
        priv->disconnect = 1;
-       if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL))
+       if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
        wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
@@ -774,15 +715,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
  */
 static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
 {
-       int ret = 0;
        struct ieee80211_channel *chan;
        struct mwifiex_bss_info bss_info;
        int ie_len = 0;
        u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
 
-       ret = mwifiex_get_bss_info(priv, &bss_info);
-       if (ret)
-               return ret;
+       if (mwifiex_get_bss_info(priv, &bss_info))
+               return -1;
 
        ie_buf[0] = WLAN_EID_SSID;
        ie_buf[1] = bss_info.ssid.ssid_len;
@@ -801,7 +740,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
                0, ie_buf, ie_len, 0, GFP_KERNEL);
        memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -830,16 +769,15 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
        struct mwifiex_bssdescriptor *scan_table;
        int i, j;
        struct ieee80211_channel *chan;
-       u8 *ie, *tmp, *ie_buf;
+       u8 *ie, *ie_buf;
        u32 ie_len;
-       u64 ts = 0;
        u8 *beacon;
        int beacon_size;
        u8 element_id, element_len;
 
        memset(&scan_resp, 0, sizeof(scan_resp));
-       if (mwifiex_get_scan_table(priv, MWIFIEX_IOCTL_WAIT, &scan_resp))
-               return -EFAULT;
+       scan_resp.scan_table = (u8 *) priv->adapter->scan_table;
+       scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table;
 
 #define MAX_IE_BUF     2048
        ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
@@ -914,9 +852,9 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
                        case WLAN_EID_BSS_AC_ACCESS_DELAY:
                                ie[0] = element_id;
                                ie[1] = element_len;
-                               tmp = (u8 *) beacon;
                                memcpy(&ie[sizeof(struct ieee_types_header)],
-                                      tmp + sizeof(struct ieee_types_header),
+                                      (u8 *) beacon
+                                      + sizeof(struct ieee_types_header),
                                       element_len);
                                ie_len += ie[1] +
                                        sizeof(struct ieee_types_header);
@@ -933,7 +871,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
                                                scan_table[i].freq);
                cfg80211_inform_bss(priv->wdev->wiphy, chan,
                                        scan_table[i].mac_address,
-                                       ts, scan_table[i].cap_info_bitmap,
+                                       0, scan_table[i].cap_info_bitmap,
                                        scan_table[i].beacon_period,
                                        ie_buf, ie_len,
                                        scan_table[i].rssi, GFP_KERNEL);
@@ -966,9 +904,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
        struct mwifiex_802_11_ssid req_ssid;
        struct mwifiex_ssid_bssid ssid_bssid;
        int ret = 0;
-       int auth_type = 0, pairwise_encrypt_mode = 0;
-       int group_encrypt_mode = 0;
-       int alg_is_wep = 0;
+       int auth_type = 0;
 
        memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
        memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
@@ -986,7 +922,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
        }
 
        /* disconnect before try to associate */
-       mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL);
+       mwifiex_deauthenticate(priv, NULL);
 
        if (channel)
                ret = mwifiex_set_rf_channel(priv, channel,
@@ -1034,9 +970,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
                ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
 
        if (sme->key) {
-               alg_is_wep = mwifiex_is_alg_wep(pairwise_encrypt_mode)
-                       | mwifiex_is_alg_wep(group_encrypt_mode);
-               if (alg_is_wep) {
+               if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) {
                        dev_dbg(priv->adapter->dev,
                                "info: setting wep encryption"
                                " with key len %d\n", sme->key_len);
@@ -1046,7 +980,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
        }
 done:
        /* Do specific SSID scanning */
-       if (mwifiex_request_scan(priv, MWIFIEX_IOCTL_WAIT, &req_ssid)) {
+       if (mwifiex_request_scan(priv, &req_ssid)) {
                dev_err(priv->adapter->dev, "scan error\n");
                return -EFAULT;
        }
@@ -1055,8 +989,7 @@ done:
        memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid));
 
        if (mode != NL80211_IFTYPE_ADHOC) {
-               if (mwifiex_find_best_bss(priv, MWIFIEX_IOCTL_WAIT,
-                                         &ssid_bssid))
+               if (mwifiex_find_best_bss(priv, &ssid_bssid))
                        return -EFAULT;
                /* Inform the BSS information to kernel, otherwise
                 * kernel will give a panic after successful assoc */
@@ -1072,7 +1005,10 @@ done:
        /* Connect to BSS by ESSID */
        memset(&ssid_bssid.bssid, 0, ETH_ALEN);
 
-       if (mwifiex_bss_start(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid))
+       if (!netif_queue_stopped(priv->netdev))
+               netif_stop_queue(priv->netdev);
+
+       if (mwifiex_bss_start(priv, &ssid_bssid))
                return -EFAULT;
 
        if (mode == NL80211_IFTYPE_ADHOC) {
@@ -1176,7 +1112,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 
        wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
                        priv->cfg_bssid);
-       if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL))
+       if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
        queue_work(priv->workqueue, &priv->cfg_workqueue);
@@ -1451,6 +1387,4 @@ done:
                memset(priv->cfg_bssid, 0, ETH_ALEN);
                priv->disconnect = 0;
        }
-
-       return;
 }
index 07187a405fee6831435e0e99be69f03702881e60..d0cada5a29a0e9cf0f67e4cc70efc048b6ebf036 100644 (file)
@@ -75,8 +75,7 @@ u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
  * This function maps an index in supported rates table into
  * the corresponding data rate.
  */
-u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,
-                              u8 ht_info)
+u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info)
 {
        u16 mcs_rate[4][8] = {
                {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e}
@@ -126,7 +125,7 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,
  * This function maps a data rate value into corresponding index in supported
  * rates table.
  */
-u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate)
+u8 mwifiex_data_rate_to_index(u32 rate)
 {
        u16 *ptr;
 
@@ -146,16 +145,12 @@ u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate)
  */
 u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)
 {
-       u32 k;
-
        if (!priv->media_connected)
-               k = mwifiex_get_supported_rates(priv, rates);
+               return mwifiex_get_supported_rates(priv, rates);
        else
-               k = mwifiex_copy_rates(rates, 0,
+               return mwifiex_copy_rates(rates, 0,
                                       priv->curr_bss_params.data_rates,
                                       priv->curr_bss_params.num_of_rates);
-
-       return k;
 }
 
 /*
@@ -265,9 +260,7 @@ mwifiex_is_rate_auto(struct mwifiex_private *priv)
 /*
  * This function converts rate bitmap into rate index.
  */
-int
-mwifiex_get_rate_index(struct mwifiex_adapter *adapter, u16 *rate_bitmap,
-                      int size)
+int mwifiex_get_rate_index(u16 *rate_bitmap, int size)
 {
        int i;
 
index a9aeb31af45529dd71b4f61bdecf424dcbe77dee..776146a104ec966144adb504b7e244e65ef801ee 100644 (file)
 static void
 mwifiex_init_cmd_node(struct mwifiex_private *priv,
                      struct cmd_ctrl_node *cmd_node,
-                     u32 cmd_oid, void *wait_queue, void *data_buf)
+                     u32 cmd_oid, void *data_buf)
 {
        cmd_node->priv = priv;
        cmd_node->cmd_oid = cmd_oid;
-       cmd_node->wq_buf = wait_queue;
+       cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
+       priv->adapter->cmd_wait_q_required = false;
        cmd_node->data_buf = data_buf;
        cmd_node->cmd_skb = cmd_node->skb;
 }
@@ -86,39 +87,13 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
 {
        cmd_node->cmd_oid = 0;
        cmd_node->cmd_flag = 0;
-       cmd_node->wq_buf = NULL;
        cmd_node->data_buf = NULL;
+       cmd_node->wait_q_enabled = false;
 
        if (cmd_node->resp_skb) {
                mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0);
                cmd_node->resp_skb = NULL;
        }
-
-       return;
-}
-
-/*
- * This function returns a command node from the pending queue which
- * matches the given IOCTL request.
- */
-static struct cmd_ctrl_node *
-mwifiex_get_pending_ioctl_cmd(struct mwifiex_adapter *adapter,
-                             struct mwifiex_wait_queue *wait_queue)
-{
-       unsigned long flags;
-       struct cmd_ctrl_node *cmd_node;
-
-       spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
-       list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
-               if (cmd_node->wq_buf == wait_queue) {
-                       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                                              flags);
-                       return cmd_node;
-               }
-       }
-       spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
-
-       return NULL;
 }
 
 /*
@@ -155,7 +130,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        struct mwifiex_adapter *adapter = priv->adapter;
        int ret = 0;
        struct host_cmd_ds_command *host_cmd;
-       struct mwifiex_wait_queue *wait_queue = NULL;
        uint16_t cmd_code;
        uint16_t cmd_size;
        struct timeval tstamp;
@@ -165,15 +139,13 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
                return -1;
 
        host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data);
-       if (cmd_node->wq_buf)
-               wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf;
 
        /* Sanity test */
        if (host_cmd == NULL || host_cmd->size == 0) {
                dev_err(adapter->dev, "DNLD_CMD: host_cmd is null"
                        " or cmd size is 0, not sending\n");
-               if (wait_queue)
-                       wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL;
+               if (cmd_node->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
                return -1;
        }
@@ -206,10 +178,12 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
                                             cmd_node->cmd_skb->data,
                                             cmd_node->cmd_skb->len, NULL);
 
+       skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN);
+
        if (ret == -1) {
                dev_err(adapter->dev, "DNLD_CMD: host to card failed\n");
-               if (wait_queue)
-                       wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL;
+               if (cmd_node->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
                mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
 
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
@@ -435,7 +409,31 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
 }
 
 /*
- * This function prepares a command before sending it to the firmware.
+ * This function is used to send synchronous command to the firmware.
+ *
+ * it allocates a wait queue for the command and wait for the command
+ * response.
+ */
+int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
+                         u16 cmd_action, u32 cmd_oid, void *data_buf)
+{
+       int ret = 0;
+       struct mwifiex_adapter *adapter = priv->adapter;
+
+       adapter->cmd_wait_q_required = true;
+       adapter->cmd_wait_q.condition = false;
+
+       ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
+                                    data_buf);
+       if (!ret)
+               ret = mwifiex_wait_queue_complete(adapter);
+
+       return ret;
+}
+
+
+/*
+ * This function prepares a command and asynchronously send it to the firmware.
  *
  * Preparation includes -
  *      - Sanity tests to make sure the card is still present or the FW
@@ -445,9 +443,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
  *      - Fill up the non-default parameters and buffer pointers
  *      - Add the command to pending queue
  */
-int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
-                       u16 cmd_action, u32 cmd_oid,
-                       void *wait_queue, void *data_buf)
+int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
+                          u16 cmd_action, u32 cmd_oid, void *data_buf)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -485,7 +482,7 @@ int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
        }
 
        /* Initialize the command node */
-       mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, wait_queue, data_buf);
+       mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf);
 
        if (!cmd_node->cmd_skb) {
                dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n");
@@ -535,18 +532,13 @@ void
 mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
                             struct cmd_ctrl_node *cmd_node)
 {
-       struct mwifiex_wait_queue *wait_queue = NULL;
        unsigned long flags;
 
-       if (cmd_node == NULL)
+       if (!cmd_node)
                return;
-       if (cmd_node->wq_buf) {
-               wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf;
-               if (wait_queue->status != MWIFIEX_ERROR_NO_ERROR)
-                       mwifiex_ioctl_complete(adapter, wait_queue, -1);
-               else
-                       mwifiex_ioctl_complete(adapter, wait_queue, 0);
-       }
+
+       if (cmd_node->wait_q_enabled)
+               mwifiex_complete_cmd(adapter);
        /* Clean the node */
        mwifiex_clean_cmd_node(adapter, cmd_node);
 
@@ -554,8 +546,6 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
        spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);
        list_add_tail(&cmd_node->list, &adapter->cmd_free_q);
        spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags);
-
-       return;
 }
 
 /*
@@ -600,8 +590,6 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
        spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 
        dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command);
-
-       return;
 }
 
 /*
@@ -692,7 +680,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
        uint16_t orig_cmdresp_no;
        uint16_t cmdresp_no;
        uint16_t cmdresp_result;
-       struct mwifiex_wait_queue *wait_queue = NULL;
        struct timeval tstamp;
        unsigned long flags;
 
@@ -706,10 +693,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
                return -1;
        }
 
-       if (adapter->curr_cmd->wq_buf)
-               wait_queue = (struct mwifiex_wait_queue *)
-                               adapter->curr_cmd->wq_buf;
-
        adapter->num_cmd_timeout = 0;
 
        resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data;
@@ -764,8 +747,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 
        if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
                dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
-               if (wait_queue)
-                       wait_queue->status = MWIFIEX_ERROR_FW_CMDRESP;
+               if (adapter->curr_cmd->wait_q_enabled)
+                       adapter->cmd_wait_q.status = -1;
 
                mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
@@ -781,8 +764,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
                        ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
        } else {
                /* handle response */
-               ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp,
-                                                 wait_queue);
+               ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp);
        }
 
        /* Check init command response */
@@ -797,10 +779,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
        }
 
        if (adapter->curr_cmd) {
-               if (wait_queue && (!ret))
-                       wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
-               else if (wait_queue && (ret == -1))
-                       wait_queue->status = MWIFIEX_ERROR_CMD_RESP_FAIL;
+               if (adapter->curr_cmd->wait_q_enabled && (!ret))
+                       adapter->cmd_wait_q.status = 0;
+               else if (adapter->curr_cmd->wait_q_enabled && (ret == -1))
+                       adapter->cmd_wait_q.status = -1;
 
                /* Clean up and put current command back to cmd_free_q */
                mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
@@ -824,7 +806,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
        struct mwifiex_adapter *adapter =
                (struct mwifiex_adapter *) function_context;
        struct cmd_ctrl_node *cmd_node = NULL;
-       struct mwifiex_wait_queue *wait_queue = NULL;
        struct timeval tstamp;
 
        adapter->num_cmd_timeout++;
@@ -834,10 +815,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
                return;
        }
        cmd_node = adapter->curr_cmd;
-       if (cmd_node->wq_buf) {
-               wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf;
-               wait_queue->status = MWIFIEX_ERROR_CMD_TIMEOUT;
-       }
+       if (cmd_node->wait_q_enabled)
+               adapter->cmd_wait_q.status = -ETIMEDOUT;
 
        if (cmd_node) {
                adapter->dbg.timeout_cmd_id =
@@ -886,8 +865,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
        }
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
                mwifiex_init_fw_complete(adapter);
-
-       return;
 }
 
 /*
@@ -901,18 +878,15 @@ void
 mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
 {
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
-       struct mwifiex_wait_queue *wait_queue = NULL;
        unsigned long flags;
 
        /* Cancel current cmd */
-       if ((adapter->curr_cmd) && (adapter->curr_cmd->wq_buf)) {
-               wait_queue =
-                       (struct mwifiex_wait_queue *) adapter->curr_cmd->wq_buf;
+       if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-               adapter->curr_cmd->wq_buf = NULL;
+               adapter->curr_cmd->wait_q_enabled = false;
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-               wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL;
-               mwifiex_ioctl_complete(adapter, wait_queue, -1);
+               adapter->cmd_wait_q.status = -1;
+               mwifiex_complete_cmd(adapter);
        }
        /* Cancel all pending command */
        spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
@@ -921,12 +895,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
                list_del(&cmd_node->list);
                spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
 
-               if (cmd_node->wq_buf) {
-                       wait_queue =
-                               (struct mwifiex_wait_queue *) cmd_node->wq_buf;
-                       wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL;
-                       mwifiex_ioctl_complete(adapter, wait_queue, -1);
-                       cmd_node->wq_buf = NULL;
+               if (cmd_node->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = -1;
+                       mwifiex_complete_cmd(adapter);
+                       cmd_node->wait_q_enabled = false;
                }
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
                spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
@@ -940,7 +912,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
                list_del(&cmd_node->list);
                spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
 
-               cmd_node->wq_buf = NULL;
+               cmd_node->wait_q_enabled = false;
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
                spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
        }
@@ -962,8 +934,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
  * are cancelled.
  */
 void
-mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,
-                            struct mwifiex_wait_queue *wait_queue)
+mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
 {
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
        unsigned long cmd_flags;
@@ -972,45 +943,33 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,
        uint16_t cancel_scan_cmd = false;
 
        if ((adapter->curr_cmd) &&
-           (adapter->curr_cmd->wq_buf == wait_queue)) {
+            (adapter->curr_cmd->wait_q_enabled)) {
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
                cmd_node = adapter->curr_cmd;
-               cmd_node->wq_buf = NULL;
+               cmd_node->wait_q_enabled = false;
                cmd_node->cmd_flag |= CMD_F_CANCELED;
-               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
-       }
-
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
-       while (1) {
-               cmd_node = mwifiex_get_pending_ioctl_cmd(adapter, wait_queue);
-               if (!cmd_node)
-                       break;
-
                spin_lock_irqsave(&adapter->cmd_pending_q_lock,
                                  cmd_pending_q_flags);
                list_del(&cmd_node->list);
                spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
                                       cmd_pending_q_flags);
-
-               cmd_node->wq_buf = NULL;
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
        }
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+
        /* Cancel all pending scan command */
        spin_lock_irqsave(&adapter->scan_pending_q_lock,
                          scan_pending_q_flags);
        list_for_each_entry_safe(cmd_node, tmp_node,
                                 &adapter->scan_pending_q, list) {
-               if (cmd_node->wq_buf == wait_queue) {
-                       list_del(&cmd_node->list);
-                       spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
-                                              scan_pending_q_flags);
-                       cmd_node->wq_buf = NULL;
-                       mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-                       spin_lock_irqsave(&adapter->scan_pending_q_lock,
-                                         scan_pending_q_flags);
-                       cancel_scan_cmd = true;
-               }
+               list_del(&cmd_node->list);
+               spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
+                                      scan_pending_q_flags);
+               cmd_node->wait_q_enabled = false;
+               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               spin_lock_irqsave(&adapter->scan_pending_q_lock,
+                                 scan_pending_q_flags);
+               cancel_scan_cmd = true;
        }
        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                               scan_pending_q_flags);
@@ -1020,10 +979,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,
                adapter->scan_processing = false;
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
        }
-       wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL;
-       mwifiex_ioctl_complete(adapter, wait_queue, -1);
-
-       return;
+       adapter->cmd_wait_q.status = -1;
+       mwifiex_complete_cmd(adapter);
 }
 
 /*
@@ -1127,7 +1084,6 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
        adapter->is_hs_configured = false;
        mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
                                   MWIFIEX_BSS_ROLE_ANY), false);
-       return;
 }
 
 /*
index 63b09692f27d8fd42277613779012a017fb25b04..7ddcb062f1037684fa9d3f176dba18d5c571e5e7 100644 (file)
@@ -129,8 +129,8 @@ static struct mwifiex_debug_data items[] = {
         item_addr(event_received), 1},
 
        /* variables defined in struct mwifiex_adapter */
-       {"ioctl_pending", adapter_item_size(ioctl_pending),
-        adapter_item_addr(ioctl_pending), 1},
+       {"cmd_pending", adapter_item_size(cmd_pending),
+        adapter_item_addr(cmd_pending), 1},
        {"tx_pending", adapter_item_size(tx_pending),
         adapter_item_addr(tx_pending), 1},
        {"rx_pending", adapter_item_size(rx_pending),
@@ -735,8 +735,6 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
        MWIFIEX_DFS_ADD_FILE(getlog);
        MWIFIEX_DFS_ADD_FILE(regrdwr);
        MWIFIEX_DFS_ADD_FILE(rdeeprom);
-
-       return;
 }
 
 /*
@@ -749,7 +747,6 @@ mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)
                return;
 
        debugfs_remove_recursive(priv->dfs_dev_dir);
-       return;
 }
 
 /*
index c3c15f9e757e94dbbe0bad677d7d39143acae95a..0e90b0986ed8880bb8c3f2d0bccde22ab19ec52d 100644 (file)
 
 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
 
-enum mwifiex_error_code {
-       MWIFIEX_ERROR_NO_ERROR = 0,
-       MWIFIEX_ERROR_FW_NOT_READY = 0x00000001,
-       MWIFIEX_ERROR_FW_BUSY,
-       MWIFIEX_ERROR_FW_CMDRESP,
-       MWIFIEX_ERROR_PKT_SIZE_INVALID = 0x80000001,
-       MWIFIEX_ERROR_PKT_TIMEOUT,
-       MWIFIEX_ERROR_CMD_INVALID,
-       MWIFIEX_ERROR_CMD_TIMEOUT,
-       MWIFIEX_ERROR_CMD_DNLD_FAIL,
-       MWIFIEX_ERROR_CMD_CANCEL,
-       MWIFIEX_ERROR_CMD_RESP_FAIL,
-       MWIFIEX_ERROR_ASSOC_FAIL,
-       MWIFIEX_ERROR_EVENT_UNKNOWN,
-       MWIFIEX_ERROR_INVALID_PARAMETER,
-};
-
 enum mwifiex_bss_type {
        MWIFIEX_BSS_TYPE_STA = 0,
        MWIFIEX_BSS_TYPE_UAP = 1,
@@ -112,12 +95,9 @@ struct mwifiex_802_11_ssid {
 };
 
 struct mwifiex_wait_queue {
-       u32 bss_index;
-       wait_queue_head_t *wait;
-       u16 *condition;
-       u32 start_time;
+       wait_queue_head_t wait;
+       u16 condition;
        int status;
-       u32 enabled;
 };
 
 struct mwifiex_rxinfo {
@@ -133,11 +113,11 @@ struct mwifiex_txinfo {
 };
 
 struct mwifiex_bss_attr {
-       u32 bss_type;
-       u32 frame_type;
-       u32 active;
-       u32 bss_priority;
-       u32 bss_num;
+       u8 bss_type;
+       u8 frame_type;
+       u8 active;
+       u8 bss_priority;
+       u8 bss_num;
 };
 
 enum mwifiex_wmm_ac_e {
@@ -146,8 +126,4 @@ enum mwifiex_wmm_ac_e {
        WMM_AC_VI,
        WMM_AC_VO
 } __packed;
-
-struct mwifiex_device {
-       struct mwifiex_bss_attr bss_attr[MWIFIEX_MAX_BSS_NUM];
-};
 #endif /* !_MWIFIEX_DECL_H_ */
index 2b938115b26a72fdcadfa0e2d64b48b1acde9137..6d1c4545eda6129c57de5da53198bceac0eb7a81 100644 (file)
@@ -72,33 +72,12 @@ enum KEY_TYPE_ID {
        KEY_TYPE_ID_AES,
        KEY_TYPE_ID_WAPI,
 };
-
-enum KEY_INFO_WEP {
-       KEY_INFO_WEP_MCAST = 0x01,
-       KEY_INFO_WEP_UNICAST = 0x02,
-       KEY_INFO_WEP_ENABLED = 0x04
-};
-
-enum KEY_INFO_TKIP {
-       KEY_INFO_TKIP_MCAST = 0x01,
-       KEY_INFO_TKIP_UNICAST = 0x02,
-       KEY_INFO_TKIP_ENABLED = 0x04
-};
-
-enum KEY_INFO_AES {
-       KEY_INFO_AES_MCAST = 0x01,
-       KEY_INFO_AES_UNICAST = 0x02,
-       KEY_INFO_AES_ENABLED = 0x04
-};
+#define KEY_MCAST      BIT(0)
+#define KEY_UNICAST    BIT(1)
+#define KEY_ENABLED    BIT(2)
 
 #define WAPI_KEY_LEN                   50
 
-enum KEY_INFO_WAPI {
-       KEY_INFO_WAPI_MCAST = 0x01,
-       KEY_INFO_WAPI_UNICAST = 0x02,
-       KEY_INFO_WAPI_ENABLED = 0x04
-};
-
 #define MAX_POLL_TRIES                 100
 
 #define MAX_MULTI_INTERFACE_POLL_TRIES  1000
@@ -155,7 +134,6 @@ enum MWIFIEX_802_11_WEP_STATUS {
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_4K        4096
 #define MWIFIEX_TX_DATA_BUF_SIZE_8K        8192
-#define NON_GREENFIELD_STAS     0x04
 
 #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
 
@@ -180,7 +158,6 @@ enum MWIFIEX_802_11_WEP_STATUS {
 #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))
 
 #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)
-#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~BIT(11))
 #define SETHT_MCS32(x) (x[4] |= 1)
 
 #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4))
index 8189862da1f9deceada4be6b6b4299a4bf3f3d9b..fc2c0c5728d975f30087e7c3c9b26eb4f6d247e9 100644 (file)
@@ -35,7 +35,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct mwifiex_bss_prio_node *bss_prio;
-       int status = 0;
        unsigned long flags;
 
        bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL);
@@ -59,7 +58,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
        spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority]
                        .bss_prio_lock, flags);
 
-       return status;
+       return 0;
 }
 
 /*
@@ -72,7 +71,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
 static int mwifiex_init_priv(struct mwifiex_private *priv)
 {
        u32 i;
-       int ret = 0;
 
        priv->media_connected = false;
        memset(priv->curr_addr, 0xff, ETH_ALEN);
@@ -140,9 +138,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
 
        priv->scan_block = false;
 
-       ret = mwifiex_add_bss_prio_tbl(priv);
-
-       return ret;
+       return mwifiex_add_bss_prio_tbl(priv);
 }
 
 /*
@@ -300,8 +296,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
        adapter->adhoc_awake_period = 0;
        memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
        adapter->arp_filter_size = 0;
-
-       return;
 }
 
 /*
@@ -340,8 +334,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
        adapter->if_ops.cleanup_if(adapter);
 
        dev_kfree_skb_any(adapter->sleep_cfm);
-
-       return;
 }
 
 /*
@@ -429,8 +421,6 @@ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
                        list_del(&priv->rx_reorder_tbl_ptr);
                }
        }
-
-       return;
 }
 
 /*
index 703a6d12ebf37ee3001c39894304d7745217a489..5488e111fd2c69f46d6618a11e4072683724247a 100644 (file)
@@ -268,14 +268,13 @@ struct mwifiex_debug_info {
 };
 
 #define MWIFIEX_KEY_INDEX_UNICAST      0x40000000
-#define MWIFIEX_MAX_KEY_LENGTH         32
 #define WAPI_RXPN_LEN                  16
 
 struct mwifiex_ds_encrypt_key {
        u32 key_disable;
        u32 key_index;
        u32 key_len;
-       u8 key_material[MWIFIEX_MAX_KEY_LENGTH];
+       u8 key_material[WLAN_MAX_KEY_LEN];
        u8 mac_addr[ETH_ALEN];
        u32 is_wapi_key;
        u8 wapi_rxpn[WAPI_RXPN_LEN];
index 7a9e0b5962eddd668f04cba887fedc8a291a8be0..23d2d0b9a52784531fafb86e4e8d72a6befaa7cf 100644 (file)
@@ -590,11 +590,10 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
  * an association success (0) or failure (non-zero).
  */
 int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
-                            struct host_cmd_ds_command *resp, void *wq_buf)
+                            struct host_cmd_ds_command *resp)
 {
+       struct mwifiex_adapter *adapter = priv->adapter;
        int ret = 0;
-       struct mwifiex_wait_queue *wait_queue =
-               (struct mwifiex_wait_queue *) wq_buf;
        struct ieee_types_assoc_rsp *assoc_rsp;
        struct mwifiex_bssdescriptor *bss_desc;
        u8 enable_data = true;
@@ -718,16 +717,11 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 
 done:
        /* Need to indicate IOCTL complete */
-       if (wait_queue) {
-               if (ret) {
-                       if (assoc_rsp->status_code)
-                               wait_queue->status =
-                                       le16_to_cpu(assoc_rsp->status_code);
-                       else
-                               wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL;
-               } else {
-                       wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
-               }
+       if (adapter->curr_cmd->wait_q_enabled) {
+               if (ret)
+                       adapter->cmd_wait_q.status = -1;
+               else
+                       adapter->cmd_wait_q.status = 0;
        }
 
        return ret;
@@ -755,7 +749,7 @@ int
 mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                                struct host_cmd_ds_command *cmd, void *data_buf)
 {
-       int ret = 0, rsn_ie_len = 0;
+       int rsn_ie_len = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start =
                &cmd->params.adhoc_start;
@@ -885,11 +879,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
        mwifiex_get_active_data_rates(priv, adhoc_start->DataRate);
        if ((adapter->adhoc_start_band & BAND_G) &&
            (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) {
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                         HostCmd_ACT_GEN_SET,
-                                         0, NULL, &priv->curr_pkt_filter);
-
-               if (ret) {
+               if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
+                                            HostCmd_ACT_GEN_SET, 0,
+                                            &priv->curr_pkt_filter)) {
                        dev_err(adapter->dev,
                               "ADHOC_S_CMD: G Protection config failed\n");
                        return -1;
@@ -1003,7 +995,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                                        IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
                        }
                        ht_info->ht_info.operation_mode =
-                               cpu_to_le16(NON_GREENFIELD_STAS);
+                            cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
                        ht_info->ht_info.basic_set[0] = 0xff;
                        pos += sizeof(struct mwifiex_ie_types_htinfo);
                        cmd_append_size +=
@@ -1045,7 +1037,7 @@ int
 mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *cmd, void *data_buf)
 {
-       int ret = 0, rsn_ie_len = 0;
+       int rsn_ie_len = 0;
        struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
                &cmd->params.adhoc_join;
        struct mwifiex_bssdescriptor *bss_desc =
@@ -1066,10 +1058,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                        priv->
                        curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON;
 
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                         HostCmd_ACT_GEN_SET, 0, NULL,
-                                         &curr_pkt_filter);
-               if (ret) {
+               if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
+                                            HostCmd_ACT_GEN_SET, 0,
+                                            &curr_pkt_filter)) {
                        dev_err(priv->adapter->dev,
                               "ADHOC_J_CMD: G Protection config failed\n");
                        return -1;
@@ -1180,7 +1171,7 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
 
        adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap);
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1192,22 +1183,19 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
  * saves the beacon buffer.
  */
 int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp, void *wq_buf)
+                             struct host_cmd_ds_command *resp)
 {
        int ret = 0;
-       struct mwifiex_wait_queue *wait_queue =
-               (struct mwifiex_wait_queue *) wq_buf;
+       struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
        struct mwifiex_bssdescriptor *bss_desc;
-       u16 command = le16_to_cpu(resp->command);
-       u16 result = le16_to_cpu(resp->result);
 
        adhoc_result = &resp->params.adhoc_result;
 
        bss_desc = priv->attempted_bss_desc;
 
        /* Join result code 0 --> SUCCESS */
-       if (result) {
+       if (le16_to_cpu(resp->result)) {
                dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n");
                if (priv->media_connected)
                        mwifiex_reset_connect_state(priv);
@@ -1222,7 +1210,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
        /* Send a Media Connected event, according to the Spec */
        priv->media_connected = true;
 
-       if (command == HostCmd_CMD_802_11_AD_HOC_START) {
+       if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
                dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n",
                                bss_desc->ssid.ssid);
 
@@ -1264,11 +1252,11 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
 
 done:
        /* Need to indicate IOCTL complete */
-       if (wait_queue) {
+       if (adapter->curr_cmd->wait_q_enabled) {
                if (ret)
-                       wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL;
+                       adapter->cmd_wait_q.status = -1;
                else
-                       wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
+                       adapter->cmd_wait_q.status = 0;
 
        }
 
@@ -1283,9 +1271,8 @@ done:
  * command to firmware.
  */
 int mwifiex_associate(struct mwifiex_private *priv,
-                     void *wait_queue, struct mwifiex_bssdescriptor *bss_desc)
+                     struct mwifiex_bssdescriptor *bss_desc)
 {
-       int ret = 0;
        u8 current_bssid[ETH_ALEN];
 
        /* Return error if the adapter or table entry is not marked as infra */
@@ -1301,11 +1288,8 @@ int mwifiex_associate(struct mwifiex_private *priv,
           retrieval */
        priv->assoc_rsp_size = 0;
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE,
-                                 HostCmd_ACT_GEN_SET, 0, wait_queue,
-                                 bss_desc);
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE,
+                                   HostCmd_ACT_GEN_SET, 0, bss_desc);
 }
 
 /*
@@ -1315,10 +1299,8 @@ int mwifiex_associate(struct mwifiex_private *priv,
  */
 int
 mwifiex_adhoc_start(struct mwifiex_private *priv,
-                   void *wait_queue, struct mwifiex_802_11_ssid *adhoc_ssid)
+                   struct mwifiex_802_11_ssid *adhoc_ssid)
 {
-       int ret = 0;
-
        dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",
                priv->adhoc_channel);
        dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n",
@@ -1326,11 +1308,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
        dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",
               priv->curr_bss_params.band);
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START,
-                                 HostCmd_ACT_GEN_SET, 0, wait_queue,
-                                 adhoc_ssid);
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START,
+                                   HostCmd_ACT_GEN_SET, 0, adhoc_ssid);
 }
 
 /*
@@ -1340,10 +1319,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,
  * if already not connected to the requested SSID.
  */
 int mwifiex_adhoc_join(struct mwifiex_private *priv,
-                      void *wait_queue, struct mwifiex_bssdescriptor *bss_desc)
+                      struct mwifiex_bssdescriptor *bss_desc)
 {
-       int ret = 0;
-
        dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n",
               priv->curr_bss_params.bss_descriptor.ssid.ssid);
        dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n",
@@ -1369,20 +1346,15 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
        dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",
               priv->curr_bss_params.band);
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
-                                 HostCmd_ACT_GEN_SET, 0, wait_queue,
-                                 bss_desc);
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
+                                   HostCmd_ACT_GEN_SET, 0, bss_desc);
 }
 
 /*
  * This function deauthenticates/disconnects from infra network by sending
  * deauthentication request.
  */
-static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv,
-                                       struct mwifiex_wait_queue *wait,
-                                       u8 *mac)
+static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)
 {
        u8 mac_address[ETH_ALEN];
        int ret = 0;
@@ -1400,11 +1372,8 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv,
                       bss_descriptor.mac_address, ETH_ALEN);
        }
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
-                                 HostCmd_ACT_GEN_SET, 0, wait, &mac_address);
-
-       if (!ret && wait)
-               ret = -EINPROGRESS;
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
+                                   HostCmd_ACT_GEN_SET, 0, &mac_address);
 
        return ret;
 }
@@ -1415,26 +1384,23 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv,
  * In case of infra made, it sends deauthentication request, and
  * in case of ad-hoc mode, a stop network request is sent to the firmware.
  */
-int mwifiex_deauthenticate(struct mwifiex_private *priv,
-                          struct mwifiex_wait_queue *wait, u8 *mac)
+int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
 {
        int ret = 0;
 
        if (priv->media_connected) {
                if (priv->bss_mode == NL80211_IFTYPE_STATION) {
-                       ret = mwifiex_deauthenticate_infra(priv, wait, mac);
+                       ret = mwifiex_deauthenticate_infra(priv, mac);
                } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
-                       ret = mwifiex_prepare_cmd(priv,
-                                       HostCmd_CMD_802_11_AD_HOC_STOP,
-                                       HostCmd_ACT_GEN_SET, 0, wait, NULL);
-
-                       if (!ret && wait)
-                               ret = -EINPROGRESS;
+                       ret = mwifiex_send_cmd_sync(priv,
+                                               HostCmd_CMD_802_11_AD_HOC_STOP,
+                                               HostCmd_ACT_GEN_SET, 0, NULL);
                }
        }
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);
 
 /*
  * This function converts band to radio type used in channel TLV.
@@ -1442,21 +1408,15 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv,
 u8
 mwifiex_band_to_radio_type(u8 band)
 {
-       u8 ret_radio_type;
-
        switch (band) {
        case BAND_A:
        case BAND_AN:
        case BAND_A | BAND_AN:
-               ret_radio_type = HostCmd_SCAN_RADIO_TYPE_A;
-               break;
+               return HostCmd_SCAN_RADIO_TYPE_A;
        case BAND_B:
        case BAND_G:
        case BAND_B | BAND_G:
        default:
-               ret_radio_type = HostCmd_SCAN_RADIO_TYPE_BG;
-               break;
+               return HostCmd_SCAN_RADIO_TYPE_BG;
        }
-
-       return ret_radio_type;
 }
index ed89ca41a9022709172e04910a5c1c8cce51a813..c5971880e7b37e4a01f3c80bb5660de851aaecfc 100644 (file)
@@ -40,14 +40,10 @@ static char fw_name[32] = DEFAULT_FW_NAME;
 /* Supported drv_mode table */
 static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
        {
-        /* drv_mode */
-        .drv_mode = DRV_MODE_STA,
-        /* intf number */
-        .intf_num = ARRAY_SIZE(mwifiex_bss_sta),
-        /* bss_attr */
-        .bss_attr = mwifiex_bss_sta,
-        }
-       ,
+               .drv_mode = DRV_MODE_STA,
+               .intf_num = ARRAY_SIZE(mwifiex_bss_sta),
+               .bss_attr = mwifiex_bss_sta,
+       },
 };
 
 /*
@@ -66,14 +62,12 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
  * proper cleanup before exiting.
  */
 static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
-                           struct mwifiex_device *mdevice, void **padapter)
+                           struct mwifiex_drv_mode *drv_mode_ptr)
 {
-       int ret = 0;
-       struct mwifiex_adapter *adapter = NULL;
-       u8 i = 0;
+       struct mwifiex_adapter *adapter;
+       int i;
 
        adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL);
-       /* Allocate memory for adapter structure */
        if (!adapter)
                return -1;
 
@@ -84,19 +78,17 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
        memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
 
        /* card specific initialization has been deferred until now .. */
-       ret = adapter->if_ops.init_if(adapter);
-       if (ret)
+       if (adapter->if_ops.init_if(adapter))
                goto error;
 
        adapter->priv_num = 0;
-       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
+       for (i = 0; i < drv_mode_ptr->intf_num; i++) {
                adapter->priv[i] = NULL;
 
-               if (!mdevice->bss_attr[i].active)
+               if (!drv_mode_ptr->bss_attr[i].active)
                        continue;
 
-               /* For valid bss_attr,
-                  allocate memory for private structure */
+               /* Allocate memory for private structure */
                adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private),
                                GFP_KERNEL);
                if (!adapter->priv[i]) {
@@ -106,26 +98,26 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
                }
 
                adapter->priv_num++;
-               memset(adapter->priv[i], 0,
-                      sizeof(struct mwifiex_private));
                adapter->priv[i]->adapter = adapter;
                /* Save bss_type, frame_type & bss_priority */
-               adapter->priv[i]->bss_type = (u8) mdevice->bss_attr[i].bss_type;
+               adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type;
                adapter->priv[i]->frame_type =
-                       (u8) mdevice->bss_attr[i].frame_type;
+                                       drv_mode_ptr->bss_attr[i].frame_type;
                adapter->priv[i]->bss_priority =
-                       (u8) mdevice->bss_attr[i].bss_priority;
-               if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA)
+                                       drv_mode_ptr->bss_attr[i].bss_priority;
+
+               if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA)
                        adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA;
-               else if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_UAP)
+               else if (drv_mode_ptr->bss_attr[i].bss_type ==
+                                                       MWIFIEX_BSS_TYPE_UAP)
                        adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP;
 
                /* Save bss_index & bss_num */
                adapter->priv[i]->bss_index = i;
-               adapter->priv[i]->bss_num = mdevice->bss_attr[i].bss_num;
+               adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num;
        }
+       adapter->drv_mode = drv_mode_ptr;
 
-       /* Initialize lock variables */
        if (mwifiex_init_lock_list(adapter))
                goto error;
 
@@ -133,16 +125,13 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
        adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
        adapter->cmd_timer.data = (unsigned long) adapter;
 
-       /* Return pointer of struct mwifiex_adapter */
-       *padapter = adapter;
        return 0;
 
 error:
        dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
 
-       /* Free lock variables */
        mwifiex_free_lock_list(adapter);
-       for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++)
+       for (i = 0; i < drv_mode_ptr->intf_num; i++)
                kfree(adapter->priv[i]);
        kfree(adapter);
 
@@ -337,10 +326,9 @@ exit_main_proc:
  * and initializing the private structures.
  */
 static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex)
+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
 {
        int i;
-       struct mwifiex_device device;
        struct mwifiex_drv_mode *drv_mode_ptr;
 
        /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */
@@ -357,20 +345,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex)
                return -1;
        }
 
-       memset(&device, 0, sizeof(struct mwifiex_device));
-
-       for (i = 0; i < drv_mode_ptr->intf_num; i++) {
-               device.bss_attr[i].bss_type =
-                       drv_mode_ptr->bss_attr[i].bss_type;
-               device.bss_attr[i].frame_type =
-                       drv_mode_ptr->bss_attr[i].frame_type;
-               device.bss_attr[i].active = drv_mode_ptr->bss_attr[i].active;
-               device.bss_attr[i].bss_priority =
-                       drv_mode_ptr->bss_attr[i].bss_priority;
-               device.bss_attr[i].bss_num = drv_mode_ptr->bss_attr[i].bss_num;
-       }
-
-       if (mwifiex_register(card, if_ops, &device, pmwifiex))
+       if (mwifiex_register(card, if_ops, drv_mode_ptr))
                return -1;
 
        return 0;
@@ -505,7 +480,6 @@ mwifiex_fill_buffer(struct sk_buff *skb)
         */
        do_gettimeofday(&tv);
        skb->tstamp = timeval_to_ktime(tv);
-       return;
 }
 
 /*
@@ -597,16 +571,23 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        struct sockaddr *hw_addr = (struct sockaddr *) addr;
+       int ret = 0;
 
        memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
 
-       if (mwifiex_request_set_mac_address(priv)) {
-               dev_err(priv->adapter->dev, "set MAC address failed\n");
-               return -EFAULT;
-       }
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
+                                   HostCmd_ACT_GEN_SET, 0, NULL);
+
+       if (!ret)
+               memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
+       else
+               dev_err(priv->adapter->dev, "set mac address failed: ret=%d"
+                                           "\n", ret);
+
        memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -615,7 +596,20 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr)
 static void mwifiex_set_multicast_list(struct net_device *dev)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       mwifiex_request_set_multicast_list(priv, dev);
+       struct mwifiex_multicast_list mcast_list;
+
+       if (dev->flags & IFF_PROMISC) {
+               mcast_list.mode = MWIFIEX_PROMISC_MODE;
+       } else if (dev->flags & IFF_ALLMULTI ||
+                  netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
+               mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
+       } else {
+               mcast_list.mode = MWIFIEX_MULTICAST_MODE;
+               if (netdev_mc_count(dev))
+                       mcast_list.num_multicast_addr =
+                               mwifiex_copy_mcast_addr(&mcast_list, dev);
+       }
+       mwifiex_request_set_multicast_list(priv, &mcast_list);
 }
 
 /*
@@ -677,9 +671,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)
 {
        dev->netdev_ops = &mwifiex_netdev_ops;
        /* Initialize private structure */
-       init_waitqueue_head(&priv->ioctl_wait_q);
-       init_waitqueue_head(&priv->cmd_wait_q);
-       init_waitqueue_head(&priv->w_stats_wait_q);
        priv->current_key_index = 0;
        priv->media_connected = false;
        memset(&priv->nick_name, 0, sizeof(priv->nick_name));
@@ -803,36 +794,8 @@ mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index)
        wiphy_unregister(priv->wdev->wiphy);
        wiphy_free(priv->wdev->wiphy);
        kfree(priv->wdev);
-
-       return;
 }
 
-/*
- * Sends IOCTL request to shutdown firmware.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_shutdown_fw(struct mwifiex_private *priv, u8 wait_option)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-
-       /* Allocate an IOCTL request buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_misc_ioctl_init_shutdown(priv->adapter, wait,
-                                                 MWIFIEX_FUNC_SHUTDOWN);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-
-       kfree(wait);
-       return status;
-}
-EXPORT_SYMBOL_GPL(mwifiex_shutdown_fw);
-
 /*
  * This function check if command is pending.
  */
@@ -905,30 +868,30 @@ int
 mwifiex_add_card(void *card, struct semaphore *sem,
                 struct mwifiex_if_ops *if_ops)
 {
-       int status = 0;
        int i;
-       struct mwifiex_adapter *adapter = NULL;
-       struct mwifiex_drv_mode *drv_mode_info = &mwifiex_drv_mode_tbl[0];
+       struct mwifiex_adapter *adapter;
 
        if (down_interruptible(sem))
                goto exit_sem_err;
 
-       if (mwifiex_init_sw(card, if_ops, (void **) &adapter)) {
+       if (mwifiex_init_sw(card, if_ops)) {
                pr_err("%s: software init failed\n", __func__);
                goto err_init_sw;
        }
 
-       adapter->drv_mode = drv_mode_info;
+       adapter = g_adapter;
 
        adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
-       /* PnP and power profile */
        adapter->surprise_removed = false;
        init_waitqueue_head(&adapter->init_wait_q);
        adapter->is_suspended = false;
        adapter->hs_activated = false;
        init_waitqueue_head(&adapter->hs_activate_wait_q);
+       adapter->cmd_wait_q_required = false;
+       init_waitqueue_head(&adapter->cmd_wait_q.wait);
+       adapter->cmd_wait_q.condition = false;
+       adapter->cmd_wait_q.status = 0;
 
-       /* Create workqueue */
        adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
        if (!adapter->workqueue)
                goto err_kmalloc;
@@ -942,21 +905,18 @@ mwifiex_add_card(void *card, struct semaphore *sem,
                goto err_registerdev;
        }
 
-       /* Init FW and HW */
        if (mwifiex_init_hw_fw(adapter)) {
                pr_err("%s: firmware init failed\n", __func__);
                goto err_init_fw;
        }
+
        /* Add interfaces */
-       for (i = 0; i < drv_mode_info->intf_num; i++) {
+       for (i = 0; i < adapter->drv_mode->intf_num; i++) {
                if (!mwifiex_add_interface(adapter, i,
                                adapter->drv_mode->bss_attr[i].bss_type)) {
-                       status = -1;
-                       break;
+                       goto err_add_intf;
                }
        }
-       if (status)
-               goto err_add_intf;
 
        up(sem);
 
@@ -966,7 +926,6 @@ err_add_intf:
        for (i = 0; i < adapter->priv_num; i++)
                mwifiex_remove_interface(adapter, i);
 err_init_fw:
-       /* Unregister device */
        pr_debug("info: %s: unregister device\n", __func__);
        adapter->if_ops.unregister_dev(adapter);
 err_registerdev:
@@ -977,8 +936,8 @@ err_kmalloc:
            (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
                pr_debug("info: %s: shutdown mwifiex\n", __func__);
                adapter->init_wait_q_woken = false;
-               status = mwifiex_shutdown_drv(adapter);
-               if (status == -EINPROGRESS)
+
+               if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
                        wait_event_interruptible(adapter->init_wait_q,
                                                 adapter->init_wait_q_woken);
        }
@@ -1007,7 +966,6 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card);
 int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 {
        struct mwifiex_private *priv = NULL;
-       int status;
        int i;
 
        if (down_interruptible(sem))
@@ -1031,19 +989,19 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 
        dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
        adapter->init_wait_q_woken = false;
-       status = mwifiex_shutdown_drv(adapter);
-       if (status == -EINPROGRESS)
+
+       if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
                wait_event_interruptible(adapter->init_wait_q,
                                         adapter->init_wait_q_woken);
        dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
        if (atomic_read(&adapter->rx_pending) ||
            atomic_read(&adapter->tx_pending) ||
-           atomic_read(&adapter->ioctl_pending)) {
+           atomic_read(&adapter->cmd_pending)) {
                dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
-                      "ioctl_pending=%d\n",
+                      "cmd_pending=%d\n",
                       atomic_read(&adapter->rx_pending),
                       atomic_read(&adapter->tx_pending),
-                      atomic_read(&adapter->ioctl_pending));
+                      atomic_read(&adapter->cmd_pending));
        }
 
        /* Remove interface */
index 43ff149de9db969577f9f8a163ed1f23cf25a62b..1b503038270e4aa96ccc08263bd5c152fff5eeb8 100644 (file)
@@ -42,11 +42,8 @@ extern const char driver_version[];
 extern struct mwifiex_adapter *g_adapter;
 
 enum {
-       MWIFIEX_NO_WAIT,
-       MWIFIEX_IOCTL_WAIT,
-       MWIFIEX_CMD_WAIT,
-       MWIFIEX_PROC_WAIT,
-       MWIFIEX_WSTATS_WAIT
+       MWIFIEX_ASYNC_CMD,
+       MWIFIEX_SYNC_CMD
 };
 
 #define DRV_MODE_STA       0x1
@@ -468,10 +465,6 @@ struct mwifiex_private {
        u32 curr_bcn_size;
        /* spin lock for beacon buffer */
        spinlock_t curr_bcn_buf_lock;
-       u16 ioctl_wait_q_woken;
-       wait_queue_head_t ioctl_wait_q;
-       u16 cmd_wait_q_woken;
-       wait_queue_head_t cmd_wait_q;
        struct wireless_dev *wdev;
        struct mwifiex_chan_freq_power cfp;
        char version_str[128];
@@ -480,8 +473,6 @@ struct mwifiex_private {
 #endif
        u8 nick_name[16];
        struct iw_statistics w_stats;
-       u16 w_stats_wait_q_woken;
-       wait_queue_head_t w_stats_wait_q;
        u16 current_key_index;
        struct semaphore async_sem;
        u8 scan_pending_on_block;
@@ -552,7 +543,7 @@ struct cmd_ctrl_node {
        struct sk_buff *cmd_skb;
        struct sk_buff *resp_skb;
        void *data_buf;
-       void *wq_buf;
+       u32 wait_q_enabled;
        struct sk_buff *skb;
 };
 
@@ -590,7 +581,7 @@ struct mwifiex_adapter {
        struct mwifiex_if_ops if_ops;
        atomic_t rx_pending;
        atomic_t tx_pending;
-       atomic_t ioctl_pending;
+       atomic_t cmd_pending;
        struct workqueue_struct *workqueue;
        struct work_struct main_work;
        struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
@@ -684,6 +675,8 @@ struct mwifiex_adapter {
        struct mwifiex_dbg dbg;
        u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
        u32 arp_filter_size;
+       u16 cmd_wait_q_required;
+       struct mwifiex_wait_queue cmd_wait_q;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -707,29 +700,23 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
 
 int mwifiex_process_event(struct mwifiex_adapter *adapter);
 
-int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter,
-                          struct mwifiex_wait_queue *ioctl_wq,
-                          int status);
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter);
 
-int mwifiex_prepare_cmd(struct mwifiex_private *priv,
-                       uint16_t cmd_no,
-                       u16 cmd_action,
-                       u32 cmd_oid,
-                       void *wait_queue, void *data_buf);
+int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
+                          u16 cmd_action, u32 cmd_oid, void *data_buf);
+
+int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
+                         u16 cmd_action, u32 cmd_oid, void *data_buf);
 
 void mwifiex_cmd_timeout_func(unsigned long function_context);
 
-int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter,
-                                    struct mwifiex_wait_queue *wait_queue,
-                                    u32 func_init_shutdown);
 int mwifiex_get_debug_info(struct mwifiex_private *,
                           struct mwifiex_debug_info *);
 
 int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);
 int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);
 void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter);
-void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,
-                                 struct mwifiex_wait_queue *ioctl_wq);
+void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);
 
 void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
                                  struct cmd_ctrl_node *cmd_node);
@@ -772,24 +759,20 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
                            u16 cmd_action, u32 cmd_oid,
                            void *data_buf, void *cmd_buf);
 int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
-                               void *cmd_buf, void *ioctl);
+                               void *cmd_buf);
 int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
                                  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
 void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
 int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
-int mwifiex_scan_networks(struct mwifiex_private *priv, void *wait_queue,
-                         u16 action,
-                         const struct mwifiex_user_scan_cfg
-                         *user_scan_in, struct mwifiex_scan_resp *);
-int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *cmd,
+int mwifiex_scan_networks(struct mwifiex_private *priv,
+                         const struct mwifiex_user_scan_cfg *user_scan_in);
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
                            void *data_buf);
 void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
                            struct cmd_ctrl_node *cmd_node);
 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp,
-                           void *wait_queue);
+                           struct host_cmd_ds_command *resp);
 s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
                                struct mwifiex_802_11_ssid *ssid, u8 *bssid,
                                u32 mode);
@@ -799,23 +782,20 @@ int mwifiex_find_best_network(struct mwifiex_private *priv,
                              struct mwifiex_ssid_bssid *req_ssid_bssid);
 s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
                       struct mwifiex_802_11_ssid *ssid2);
-int mwifiex_associate(struct mwifiex_private *priv, void *wait_queue,
+int mwifiex_associate(struct mwifiex_private *priv,
                      struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
                                 struct host_cmd_ds_command
                                 *cmd, void *data_buf);
 int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command *resp,
-                                void *wait_queue);
+                                struct host_cmd_ds_command *resp);
 void mwifiex_reset_connect_state(struct mwifiex_private *priv);
 void mwifiex_2040_coex_event(struct mwifiex_private *priv);
 u8 mwifiex_band_to_radio_type(u8 band);
-int mwifiex_deauthenticate(struct mwifiex_private *priv,
-                          struct mwifiex_wait_queue *wait_queue,
-                          u8 *mac);
-int mwifiex_adhoc_start(struct mwifiex_private *priv, void *wait_queue,
+int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
+int mwifiex_adhoc_start(struct mwifiex_private *priv,
                        struct mwifiex_802_11_ssid *adhoc_ssid);
-int mwifiex_adhoc_join(struct mwifiex_private *priv, void *wait_queue,
+int mwifiex_adhoc_join(struct mwifiex_private *priv,
                       struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                                    struct host_cmd_ds_command *cmd,
@@ -824,11 +804,8 @@ int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *cmd,
                                   void *data_buf);
 int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp,
-                             void *wait_queue);
-int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv,
-                                    struct host_cmd_ds_command *cmd,
-                                    void *data_buf);
+                             struct host_cmd_ds_command *resp);
+int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
 struct mwifiex_chan_freq_power *
                        mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
                                                struct mwifiex_private *priv,
@@ -836,20 +813,16 @@ struct mwifiex_chan_freq_power *
 struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211(
                                                struct mwifiex_private *priv,
                                                u8 band, u32 freq);
-u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,
-                                u8 ht_info);
+u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info);
 u32 mwifiex_find_freq_from_band_chan(u8, u8);
 int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
                                u8 **buffer);
-u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,
-                                u8 ht_info);
 u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,
                                    u8 *rates);
 u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates);
-u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate);
+u8 mwifiex_data_rate_to_index(u32 rate);
 u8 mwifiex_is_rate_auto(struct mwifiex_private *priv);
-int mwifiex_get_rate_index(struct mwifiex_adapter *adapter,
-                          u16 *rateBitmap, int size);
+int mwifiex_get_rate_index(u16 *rateBitmap, int size);
 extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];
 void mwifiex_save_curr_bcn(struct mwifiex_private *priv);
 void mwifiex_free_curr_bcn(struct mwifiex_private *priv);
@@ -899,7 +872,7 @@ mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len)
  */
 static inline struct mwifiex_private *
 mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter,
-                      u32 bss_num, u32 bss_type)
+                      u8 bss_num, u8 bss_type)
 {
        int i;
 
@@ -943,52 +916,34 @@ mwifiex_netdev_get_priv(struct net_device *dev)
        return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev));
 }
 
-struct mwifiex_wait_queue *mwifiex_alloc_fill_wait_queue(
-                               struct mwifiex_private *,
-                               u8 wait_option);
 struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter
                                                *adapter, u8 bss_index);
-int mwifiex_shutdown_fw(struct mwifiex_private *, u8);
-
+int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
+                            u32 func_init_shutdown);
 int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *);
 int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);
 
 void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,
                         int maxlen);
-int mwifiex_request_set_mac_address(struct mwifiex_private *priv);
-void mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
-                                       struct net_device *dev);
-int mwifiex_request_ioctl(struct mwifiex_private *priv,
-                         struct mwifiex_wait_queue *req,
-                         int, u8 wait_option);
-int mwifiex_disconnect(struct mwifiex_private *, u8, u8 *);
+int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
+                       struct mwifiex_multicast_list *mcast_list);
+int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
+                           struct net_device *dev);
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
 int mwifiex_bss_start(struct mwifiex_private *priv,
-                     u8 wait_option,
                      struct mwifiex_ssid_bssid *ssid_bssid);
 int mwifiex_set_hs_params(struct mwifiex_private *priv,
-                             u16 action, u8 wait_option,
+                             u16 action, int cmd_type,
                              struct mwifiex_ds_hs_cfg *hscfg);
-int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option);
+int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
 int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
-void mwifiex_process_ioctl_resp(struct mwifiex_private *priv,
-                               struct mwifiex_wait_queue *req);
-u32 mwifiex_get_mode(struct mwifiex_private *priv, u8 wait_option);
 int mwifiex_get_signal_info(struct mwifiex_private *priv,
-                           u8 wait_option,
                            struct mwifiex_ds_get_signal *signal);
 int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
                              struct mwifiex_rate_cfg *rate);
-int mwifiex_get_channel_list(struct mwifiex_private *priv,
-                            u8 wait_option,
-                            struct mwifiex_chan_list *chanlist);
-int mwifiex_get_scan_table(struct mwifiex_private *priv,
-                          u8 wait_option,
-                          struct mwifiex_scan_resp *scanresp);
-int mwifiex_enable_wep_key(struct mwifiex_private *priv, u8 wait_option);
-int mwifiex_find_best_bss(struct mwifiex_private *priv, u8 wait_option,
+int mwifiex_find_best_bss(struct mwifiex_private *priv,
                          struct mwifiex_ssid_bssid *ssid_bssid);
 int mwifiex_request_scan(struct mwifiex_private *priv,
-                        u8 wait_option,
                         struct mwifiex_802_11_ssid *req_ssid);
 int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
                                struct mwifiex_user_scan_cfg *scan_req);
@@ -1024,27 +979,22 @@ int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index);
 
 int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index);
 
-int mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on);
+int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode);
 
 int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter,
                                   char *version, int max_len);
 
-int mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm);
+int mwifiex_set_tx_power(struct mwifiex_private *priv,
+                        struct mwifiex_power_cfg *power_cfg);
 
 int mwifiex_main_process(struct mwifiex_adapter *);
 
-int mwifiex_bss_ioctl_channel(struct mwifiex_private *,
-                             u16 action,
-                             struct mwifiex_chan_freq_power *cfp);
+int mwifiex_bss_set_channel(struct mwifiex_private *,
+                           struct mwifiex_chan_freq_power *cfp);
 int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *,
-                              struct mwifiex_wait_queue *,
                               struct mwifiex_ssid_bssid *);
-int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *,
-                                u16 action,
-                                struct mwifiex_ds_band_cfg *);
-int mwifiex_snmp_mib_ioctl(struct mwifiex_private *,
-                          struct mwifiex_wait_queue *,
-                          u32 cmd_oid, u16 action, u32 *value);
+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 *);
 
index 6bb52d0e6cfa0b3758b73e62c6823a267e90e588..68d905d58606b135cb8acc8787e4d4403374037d 100644 (file)
@@ -178,35 +178,27 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
  * with requisite parameters and calls the IOCTL handler.
  */
 int mwifiex_find_best_bss(struct mwifiex_private *priv,
-                         u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid)
+                         struct mwifiex_ssid_bssid *ssid_bssid)
 {
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ssid_bssid tmp_ssid_bssid;
-       int ret = 0;
        u8 *mac = NULL;
 
        if (!ssid_bssid)
                return -1;
 
-       /* Allocate wait request buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
        memcpy(&tmp_ssid_bssid, ssid_bssid,
               sizeof(struct mwifiex_ssid_bssid));
-       ret = mwifiex_bss_ioctl_find_bss(priv, wait, &tmp_ssid_bssid);
 
-       if (!ret) {
+       if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {
                memcpy(ssid_bssid, &tmp_ssid_bssid,
                       sizeof(struct mwifiex_ssid_bssid));
                mac = (u8 *) &ssid_bssid->bssid;
                dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
                                " %pM\n", ssid_bssid->ssid.ssid, mac);
+               return 0;
        }
 
-       kfree(wait);
-       return ret;
+       return -1;
 }
 
 /*
@@ -221,22 +213,14 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv,
 int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
                                struct mwifiex_user_scan_cfg *scan_req)
 {
-       struct mwifiex_wait_queue *wait = NULL;
        int status = 0;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
 
-       /* Allocate an IOCTL request buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
+       priv->adapter->cmd_wait_q.condition = false;
 
-       status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET,
-                                      scan_req, NULL);
+       status = mwifiex_scan_networks(priv, scan_req);
+       if (!status)
+               status = mwifiex_wait_queue_complete(priv->adapter);
 
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-
-       if (wait && (status != -EINPROGRESS))
-               kfree(wait);
        return status;
 }
 
@@ -674,7 +658,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
  * along with the other TLVs, to the firmware.
  */
 static int
-mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf,
+mwifiex_scan_channel_list(struct mwifiex_private *priv,
                          u32 max_chan_per_scan, u8 filtered_scan,
                          struct mwifiex_scan_cmd_config *scan_cfg_out,
                          struct mwifiex_ie_types_chan_list_param_set
@@ -808,9 +792,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf,
 
                /* Send the scan command to the firmware with the specified
                   cfg */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN,
-                                         HostCmd_ACT_GEN_SET,
-                                         0, wait_buf, scan_cfg_out);
+               ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN,
+                                            HostCmd_ACT_GEN_SET, 0,
+                                            scan_cfg_out);
                if (ret)
                        break;
        }
@@ -2076,19 +2060,13 @@ mwifiex_process_scan_results(struct mwifiex_private *priv)
 static u8
 mwifiex_radio_type_to_band(u8 radio_type)
 {
-       u8 ret_band;
-
        switch (radio_type) {
        case HostCmd_SCAN_RADIO_TYPE_A:
-               ret_band = BAND_A;
-               break;
+               return BAND_A;
        case HostCmd_SCAN_RADIO_TYPE_BG:
        default:
-               ret_band = BAND_G;
-               break;
+               return BAND_G;
        }
-
-       return ret_band;
 }
 
 /*
@@ -2241,8 +2219,7 @@ static int
 mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
                                     struct mwifiex_802_11_ssid *del_ssid)
 {
-       int ret = -1;
-       s32 table_idx;
+       s32 table_idx = -1;
 
        dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
                        del_ssid->ssid);
@@ -2255,11 +2232,10 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
                dev_dbg(priv->adapter->dev,
                        "info: Scan: Delete SSID Entry: Found Idx = %d\n",
                       table_idx);
-               ret = 0;
                mwifiex_scan_delete_table_entry(priv, table_idx);
        }
 
-       return ret;
+       return table_idx == -1 ? -1 : 0;
 }
 
 /*
@@ -2271,9 +2247,7 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
  * update the internal driver scan table.
  */
 int mwifiex_scan_networks(struct mwifiex_private *priv,
-                         void *wait_buf, u16 action,
-                         const struct mwifiex_user_scan_cfg *user_scan_in,
-                         struct mwifiex_scan_resp *scan_resp)
+                         const struct mwifiex_user_scan_cfg *user_scan_in)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -2288,18 +2262,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
        u8 max_chan_per_scan;
        unsigned long flags;
 
-       if (action == HostCmd_ACT_GEN_GET) {
-               if (scan_resp) {
-                       scan_resp->scan_table = (u8 *) adapter->scan_table;
-                       scan_resp->num_in_scan_table =
-                               adapter->num_in_scan_table;
-               } else {
-                       ret = -1;
-               }
-               return ret;
-       }
-
-       if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
+       if (adapter->scan_processing) {
                dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
                return ret;
        }
@@ -2308,7 +2271,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
        adapter->scan_processing = true;
        spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 
-       if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
+       if (priv->scan_block) {
                dev_dbg(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
                return ret;
@@ -2348,9 +2311,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
                adapter->bcn_buf_end = adapter->bcn_buf;
        }
 
-       ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan,
-                                       filtered_scan, &scan_cfg_out->config,
-                                       chan_list_out, scan_chan_list);
+       ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
+                                       &scan_cfg_out->config, chan_list_out,
+                                       scan_chan_list);
 
        /* Get scan command from scan_pending_q and put to cmd_pending_q */
        if (!ret) {
@@ -2367,7 +2330,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
                        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                                               flags);
                }
-               ret = -EINPROGRESS;
        } else {
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
                adapter->scan_processing = true;
@@ -2393,8 +2355,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
  *      - Setting command ID, and proper size
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
 {
        struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
        struct mwifiex_scan_cmd_config *scan_cfg;
@@ -2437,11 +2398,10 @@ int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,
  *      .-------------------------------------------------------------.
  */
 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
-                           struct host_cmd_ds_command *resp, void *wq_buf)
+                           struct host_cmd_ds_command *resp)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
-       struct mwifiex_wait_queue *wait_queue = NULL;
        struct cmd_ctrl_node *cmd_node = NULL;
        struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL;
        struct mwifiex_bssdescriptor *bss_new_entry = NULL;
@@ -2653,13 +2613,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                mwifiex_process_scan_results(priv);
 
                /* Need to indicate IOCTL complete */
-               wait_queue = (struct mwifiex_wait_queue *) wq_buf;
-               if (wait_queue) {
-                       wait_queue->status = MWIFIEX_ERROR_NO_ERROR;
-
-                       /* Indicate ioctl complete */
-                       mwifiex_ioctl_complete(adapter,
-                              (struct mwifiex_wait_queue *) wait_queue, 0);
+               if (adapter->curr_cmd->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = 0;
+                       mwifiex_complete_cmd(adapter);
                }
                if (priv->report_scan_result)
                        priv->report_scan_result = false;
@@ -2692,9 +2648,7 @@ done:
  *      - Setting background scan flush parameter
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv,
-                                    struct host_cmd_ds_command *cmd,
-                                    void *data_buf)
+int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
 {
        struct host_cmd_ds_802_11_bg_scan_query *bg_query =
                &cmd->params.bg_scan_query;
@@ -2853,6 +2807,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
        struct mwifiex_adapter *adapter = priv->adapter;
        unsigned long flags;
 
+       cmd_node->wait_q_enabled = true;
        spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
        list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
        spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
@@ -2899,9 +2854,7 @@ int mwifiex_find_best_network(struct mwifiex_private *priv,
  * firmware, filtered on a specific SSID.
  */
 static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
-                                     void *wait_buf, u16 action,
-                                     struct mwifiex_802_11_ssid *req_ssid,
-                                     struct mwifiex_scan_resp *scan_resp)
+                                     struct mwifiex_802_11_ssid *req_ssid)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        int ret = 0;
@@ -2910,24 +2863,12 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
        if (!req_ssid)
                return -1;
 
-       if (action == HostCmd_ACT_GEN_GET) {
-               if (scan_resp) {
-                       scan_resp->scan_table =
-                               (u8 *) &priv->curr_bss_params.bss_descriptor;
-                       scan_resp->num_in_scan_table =
-                               adapter->num_in_scan_table;
-               } else {
-                       ret = -1;
-               }
-               return ret;
-       }
-
-       if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) {
+       if (adapter->scan_processing) {
                dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
                return ret;
        }
 
-       if (priv->scan_block && action == HostCmd_ACT_GEN_SET) {
+       if (priv->scan_block) {
                dev_dbg(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
                return ret;
@@ -2945,7 +2886,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
               req_ssid->ssid_len);
        scan_cfg->keep_previous_scan = true;
 
-       ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL);
+       ret = mwifiex_scan_networks(priv, scan_cfg);
 
        kfree(scan_cfg);
        return ret;
@@ -2960,12 +2901,10 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
  * Scan command can be issued for both normal scan and specific SSID
  * scan, depending upon whether an SSID is provided or not.
  */
-int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option,
+int mwifiex_request_scan(struct mwifiex_private *priv,
                         struct mwifiex_802_11_ssid *req_ssid)
 {
        int ret = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
 
        if (down_interruptible(&priv->async_sem)) {
                dev_err(priv->adapter->dev, "%s: acquire semaphore\n",
@@ -2974,32 +2913,23 @@ int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option,
        }
        priv->scan_pending_on_block = true;
 
-       /* Allocate wait request buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait) {
-               ret = -1;
-               goto done;
-       }
+       priv->adapter->cmd_wait_q.condition = false;
 
        if (req_ssid && req_ssid->ssid_len != 0)
                /* Specific SSID scan */
-               status = mwifiex_scan_specific_ssid(priv, wait,
-                                                   HostCmd_ACT_GEN_SET,
-                                                   req_ssid, NULL);
+               ret = mwifiex_scan_specific_ssid(priv, req_ssid);
        else
                /* Normal scan */
-               status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET,
-                                              NULL, NULL);
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-       if (status == -1)
-               ret = -1;
-done:
-       if ((wait) && (status != -EINPROGRESS))
-               kfree(wait);
+               ret = mwifiex_scan_networks(priv, NULL);
+
+       if (!ret)
+               ret = mwifiex_wait_queue_complete(priv->adapter);
+
        if (ret == -1) {
                priv->scan_pending_on_block = false;
                up(&priv->async_sem);
        }
+
        return ret;
 }
 
index f21e5cd19839776e0d90b9a766d832e822b92086..5148d0e0fad6dbf54e74e81b71a32125a110e55a 100644 (file)
@@ -208,7 +208,7 @@ static int mwifiex_sdio_resume(struct device *dev)
 
        /* Disable Host Sleep */
        mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
-                             MWIFIEX_NO_WAIT);
+                         MWIFIEX_ASYNC_CMD);
 
        return 0;
 }
@@ -282,7 +282,7 @@ mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data)
  */
 static int
 mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
-                       u8 *buffer, u32 pkt_len, u32 port, u32 timeout)
+                       u8 *buffer, u32 pkt_len, u32 port)
 {
        struct sdio_mmc_card *card = adapter->card;
        int ret = -1;
@@ -314,9 +314,8 @@ mwifiex_write_data_sync(struct mwifiex_adapter *adapter,
 /*
  * This function reads multiple data from SDIO card memory.
  */
-static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter,
-                                 u8 *buffer, u32 len,
-                      u32 port, u32 timeout, u8 claim)
+static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
+                                 u32 len, u32 port, u8 claim)
 {
        struct sdio_mmc_card *card = adapter->card;
        int ret = -1;
@@ -348,12 +347,9 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter,
  */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
-       int ret;
-
        dev_dbg(adapter->dev, "event: wakeup device...\n");
-       ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
 
-       return ret;
+       return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);
 }
 
 /*
@@ -363,12 +359,9 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
 {
-       int ret;
-
        dev_dbg(adapter->dev, "cmd: wakeup device completed\n");
-       ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
 
-       return ret;
+       return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);
 }
 
 /*
@@ -430,8 +423,7 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,
        int ret = 0;
 
        do {
-               ret = mwifiex_write_data_sync(adapter, payload, pkt_len,
-                                                               port, 0);
+               ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);
                if (ret) {
                        i++;
                        dev_err(adapter->dev, "host_to_card, write iomem"
@@ -630,7 +622,7 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,
                return -1;
        }
 
-       ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 0, 1);
+       ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);
 
        if (ret) {
                dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__,
@@ -769,7 +761,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
 
                ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks *
                                              MWIFIEX_SDIO_BLOCK_SIZE,
-                                             adapter->ioport, 0);
+                                             adapter->ioport);
                if (ret) {
                        dev_err(adapter->dev, "FW download, write iomem (%d)"
                                        " failed @ %d\n", i, offset);
@@ -842,7 +834,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
        unsigned long flags;
 
        if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS,
-                                  REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0,
+                                  REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK,
                                   0)) {
                dev_err(adapter->dev, "read mp_regs failed\n");
                return;
@@ -859,8 +851,6 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                adapter->int_status |= sdio_ireg;
                spin_unlock_irqrestore(&adapter->int_lock, flags);
        }
-
-       return;
 }
 
 /*
@@ -891,8 +881,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
 
        mwifiex_interrupt_status(adapter);
        queue_work(adapter->workqueue, &adapter->main_work);
-
-       return;
 }
 
 /*
@@ -1054,7 +1042,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                           card->mpa_rx.buf_len,
                                           (adapter->ioport | 0x1000 |
                                            (card->mpa_rx.ports << 4)) +
-                                          card->mpa_rx.start_port, 0, 1))
+                                          card->mpa_rx.start_port, 1))
                        return -1;
 
                curr_ptr = card->mpa_rx.buf;
@@ -1709,13 +1697,9 @@ static struct mwifiex_if_ops sdio_ops = {
 static int
 mwifiex_sdio_init_module(void)
 {
-       int ret;
-
        sema_init(&add_remove_card_sem, 1);
 
-       ret = sdio_register_driver(&mwifiex_sdio);
-
-       return ret;
+       return sdio_register_driver(&mwifiex_sdio);
 }
 
 /*
@@ -1745,13 +1729,12 @@ mwifiex_sdio_cleanup_module(void)
        for (i = 0; i < adapter->priv_num; i++)
                if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&
                    adapter->priv[i]->media_connected)
-                       mwifiex_disconnect(adapter->priv[i], MWIFIEX_CMD_WAIT,
-                                          NULL);
+                       mwifiex_deauthenticate(adapter->priv[i], NULL);
 
        if (!adapter->surprise_removed)
-               mwifiex_shutdown_fw(mwifiex_get_priv
-                                   (adapter, MWIFIEX_BSS_ROLE_ANY),
-                                   MWIFIEX_CMD_WAIT);
+               mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+                                                         MWIFIEX_BSS_ROLE_ANY),
+                                        MWIFIEX_FUNC_SHUTDOWN);
 
 exit:
        up(&add_remove_card_sem);
index 6fff26153e26e49694d5c678f44990d358e8e83d..33c8ba1f5e33c54cc8b7f6ee151e3afca7c2afda 100644 (file)
@@ -190,8 +190,7 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int
-mwifiex_cmd_802_11_get_log(struct mwifiex_private *priv,
-                          struct host_cmd_ds_command *cmd)
+mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
 {
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) +
@@ -272,8 +271,7 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
  *        (as required)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_tx_power_cfg(struct mwifiex_private *priv,
-                                   struct host_cmd_ds_command *cmd,
+static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
                                    u16 cmd_action, void *data_buf)
 {
        struct mwifiex_types_power_group *pg_tlv = NULL;
@@ -407,8 +405,7 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
  *      - Setting MAC multicast address
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_mac_multicast_adr(struct mwifiex_private *priv,
-                                        struct host_cmd_ds_command *cmd,
+static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
                                         u16 cmd_action, void *data_buf)
 {
        struct mwifiex_multicast_list *mcast_list =
@@ -463,8 +460,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
  *      - Setting command ID and proper size
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_802_11_ad_hoc_stop(struct mwifiex_private *priv,
-                                         struct host_cmd_ds_command *cmd)
+static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd)
 {
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
        cmd->size = cpu_to_le16(S_DS_GEN);
@@ -500,9 +496,8 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
                        key_param_set->key_type_id =
                                cpu_to_le16(KEY_TYPE_ID_WEP);
                        key_param_set->key_info =
-                               cpu_to_le16(KEY_INFO_WEP_ENABLED |
-                                           KEY_INFO_WEP_UNICAST |
-                                           KEY_INFO_WEP_MCAST);
+                               cpu_to_le16(KEY_ENABLED | KEY_UNICAST |
+                                           KEY_MCAST);
                        key_param_set->key_len =
                                cpu_to_le16(priv->wep_key[i].key_length);
                        /* Set WEP key index */
@@ -589,10 +584,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
                        cpu_to_le16(KEY_TYPE_ID_WAPI);
                if (cmd_oid == KEY_INFO_ENABLED)
                        key_material->key_param_set.key_info =
-                               cpu_to_le16(KEY_INFO_WAPI_ENABLED);
+                               cpu_to_le16(KEY_ENABLED);
                else
                        key_material->key_param_set.key_info =
-                               cpu_to_le16(!KEY_INFO_WAPI_ENABLED);
+                               cpu_to_le16(!KEY_ENABLED);
 
                key_material->key_param_set.key[0] = enc_key->key_index;
                if (!priv->sec_info.wapi_key_on)
@@ -604,10 +599,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
                if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) {
                        /* WAPI pairwise key: unicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_WAPI_UNICAST);
+                               cpu_to_le16(KEY_UNICAST);
                } else {        /* WAPI group key: multicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_WAPI_MCAST);
+                               cpu_to_le16(KEY_MCAST);
                        priv->sec_info.wapi_key_on = true;
                }
 
@@ -634,32 +629,32 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
                        cpu_to_le16(KEY_TYPE_ID_AES);
                if (cmd_oid == KEY_INFO_ENABLED)
                        key_material->key_param_set.key_info =
-                               cpu_to_le16(KEY_INFO_AES_ENABLED);
+                               cpu_to_le16(KEY_ENABLED);
                else
                        key_material->key_param_set.key_info =
-                               cpu_to_le16(!KEY_INFO_AES_ENABLED);
+                               cpu_to_le16(!KEY_ENABLED);
 
                if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
                                /* AES pairwise key: unicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_AES_UNICAST);
+                               cpu_to_le16(KEY_UNICAST);
                else            /* AES group key: multicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_AES_MCAST);
+                               cpu_to_le16(KEY_MCAST);
        } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
                dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
                key_material->key_param_set.key_type_id =
                        cpu_to_le16(KEY_TYPE_ID_TKIP);
                key_material->key_param_set.key_info =
-                       cpu_to_le16(KEY_INFO_TKIP_ENABLED);
+                       cpu_to_le16(KEY_ENABLED);
 
                if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
                                /* TKIP pairwise key: unicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_TKIP_UNICAST);
+                               cpu_to_le16(KEY_UNICAST);
                else            /* TKIP group key: multicast */
                        key_material->key_param_set.key_info |=
-                               cpu_to_le16(KEY_INFO_TKIP_MCAST);
+                               cpu_to_le16(KEY_MCAST);
        }
 
        if (key_material->key_param_set.key_type_id) {
@@ -778,8 +773,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
  *      - Setting status to enable or disable (for SET only)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_ibss_coalescing_status(struct mwifiex_private *priv,
-                                             struct host_cmd_ds_command *cmd,
+static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
                                              u16 cmd_action, void *data_buf)
 {
        struct host_cmd_ds_802_11_ibss_status *ibss_coal =
@@ -947,7 +941,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                                     cmd_action);
                break;
        case HostCmd_CMD_MAC_MULTICAST_ADR:
-               ret = mwifiex_cmd_mac_multicast_adr(priv, cmd_ptr, cmd_action,
+               ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action,
                                                    data_buf);
                break;
        case HostCmd_CMD_TX_RATE_CFG:
@@ -955,7 +949,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                              data_buf);
                break;
        case HostCmd_CMD_TXPWR_CFG:
-               ret = mwifiex_cmd_tx_power_cfg(priv, cmd_ptr, cmd_action,
+               ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,
                                               data_buf);
                break;
        case HostCmd_CMD_802_11_PS_MODE_ENH:
@@ -967,11 +961,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                (struct mwifiex_hs_config_param *) data_buf);
                break;
        case HostCmd_CMD_802_11_SCAN:
-               ret = mwifiex_cmd_802_11_scan(priv, cmd_ptr, data_buf);
+               ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf);
                break;
        case HostCmd_CMD_802_11_BG_SCAN_QUERY:
-               ret = mwifiex_cmd_802_11_bg_scan_query(priv, cmd_ptr,
-                                                      data_buf);
+               ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr);
                break;
        case HostCmd_CMD_802_11_ASSOCIATE:
                ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf);
@@ -985,14 +978,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                                      data_buf);
                break;
        case HostCmd_CMD_802_11_GET_LOG:
-               ret = mwifiex_cmd_802_11_get_log(priv, cmd_ptr);
+               ret = mwifiex_cmd_802_11_get_log(cmd_ptr);
                break;
        case HostCmd_CMD_802_11_AD_HOC_JOIN:
                ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr,
                                                     data_buf);
                break;
        case HostCmd_CMD_802_11_AD_HOC_STOP:
-               ret = mwifiex_cmd_802_11_ad_hoc_stop(priv, cmd_ptr);
+               ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr);
                break;
        case HostCmd_CMD_RSSI_INFO:
                ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action);
@@ -1037,10 +1030,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                cmd_ptr->size = cpu_to_le16(S_DS_GEN);
                break;
        case HostCmd_CMD_11N_ADDBA_REQ:
-               ret = mwifiex_cmd_11n_addba_req(priv, cmd_ptr, data_buf);
+               ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf);
                break;
        case HostCmd_CMD_11N_DELBA:
-               ret = mwifiex_cmd_11n_delba(priv, cmd_ptr, data_buf);
+               ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf);
                break;
        case HostCmd_CMD_11N_ADDBA_RSP:
                ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf);
@@ -1059,11 +1052,11 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                                               data_buf);
                break;
        case HostCmd_CMD_AMSDU_AGGR_CTRL:
-               ret = mwifiex_cmd_amsdu_aggr_ctrl(priv, cmd_ptr, cmd_action,
+               ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action,
                                                  data_buf);
                break;
        case HostCmd_CMD_11N_CFG:
-               ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action,
+               ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action,
                                          data_buf);
                break;
        case HostCmd_CMD_WMM_GET_STATUS:
@@ -1076,8 +1069,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                ret = 0;
                break;
        case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
-               ret = mwifiex_cmd_ibss_coalescing_status(priv, cmd_ptr,
-                                                        cmd_action, data_buf);
+               ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action,
+                                                        data_buf);
                break;
        case HostCmd_CMD_MAC_REG_ACCESS:
        case HostCmd_CMD_BBP_REG_ACCESS:
@@ -1136,65 +1129,66 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
 
        if (first_sta) {
 
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT,
-                                         HostCmd_ACT_GEN_SET, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT,
+                                            HostCmd_ACT_GEN_SET, 0, NULL);
                if (ret)
                        return -1;
                /* Read MAC address from HW */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
-                                         HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC,
+                                            HostCmd_ACT_GEN_GET, 0, NULL);
                if (ret)
                        return -1;
 
                /* Reconfigure tx buf size */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
-                                         HostCmd_ACT_GEN_SET, 0, NULL,
-                                         &priv->adapter->tx_buf_size);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_RECONFIGURE_TX_BUFF,
+                                            HostCmd_ACT_GEN_SET, 0,
+                                            &priv->adapter->tx_buf_size);
                if (ret)
                        return -1;
 
                /* Enable IEEE PS by default */
                priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                                         EN_AUTO_PS, BITMAP_STA_PS, NULL,
-                                         NULL);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_802_11_PS_MODE_ENH,
+                                            EN_AUTO_PS, BITMAP_STA_PS, NULL);
                if (ret)
                        return -1;
        }
 
        /* get tx rate */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
-                                 HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG,
+                                    HostCmd_ACT_GEN_GET, 0, NULL);
        if (ret)
                return -1;
        priv->data_rate = 0;
 
        /* get tx power */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG,
-                                 HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG,
+                                    HostCmd_ACT_GEN_GET, 0, NULL);
        if (ret)
                return -1;
 
        /* set ibss coalescing_status */
-       ret = mwifiex_prepare_cmd(priv,
-                                 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
-                                 HostCmd_ACT_GEN_SET, 0, NULL, &enable);
+       ret = mwifiex_send_cmd_async(priv,
+                                    HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
+                                    HostCmd_ACT_GEN_SET, 0, &enable);
        if (ret)
                return -1;
 
        memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
        amsdu_aggr_ctrl.enable = true;
        /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
-                                 HostCmd_ACT_GEN_SET, 0, NULL,
-                                 (void *) &amsdu_aggr_ctrl);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
+                                    HostCmd_ACT_GEN_SET, 0,
+                                    (void *) &amsdu_aggr_ctrl);
        if (ret)
                return -1;
        /* MAC Control must be the last command in init_fw */
        /* set MAC Control */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                 HostCmd_ACT_GEN_SET, 0, NULL,
-                                 &priv->curr_pkt_filter);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
+                                    HostCmd_ACT_GEN_SET, 0,
+                                    &priv->curr_pkt_filter);
        if (ret)
                return -1;
 
@@ -1202,19 +1196,18 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
                /* Enable auto deep sleep */
                auto_ds.auto_ds = DEEP_SLEEP_ON;
                auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
-               ret = mwifiex_prepare_cmd(priv,
-                               HostCmd_CMD_802_11_PS_MODE_ENH,
-                               EN_AUTO_PS, BITMAP_AUTO_DS, NULL,
-                               &auto_ds);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_802_11_PS_MODE_ENH,
+                                            EN_AUTO_PS, BITMAP_AUTO_DS,
+                                            &auto_ds);
                if (ret)
                        return -1;
        }
 
        /* Send cmd to FW to enable/disable 11D function */
        state_11d = ENABLE_11D;
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                                 HostCmd_ACT_GEN_SET, DOT11D_I,
-                                 NULL, &state_11d);
+       ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                                    HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d);
        if (ret)
                dev_err(priv->adapter->dev, "11D: failed to enable 11D\n");
 
index 74add45b99b66a70f879530fdaa3e40a8481e041..7f4f10b752fbc64733da04d72990abe53635591e 100644 (file)
@@ -41,8 +41,7 @@
  */
 static void
 mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
-                             struct host_cmd_ds_command *resp,
-                             struct mwifiex_wait_queue *wq_buf)
+                             struct host_cmd_ds_command *resp)
 {
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -51,8 +50,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
 
        dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",
                        resp->command, resp->result);
-       if (wq_buf)
-               wq_buf->status = MWIFIEX_ERROR_FW_CMDRESP;
+
+       if (adapter->curr_cmd->wait_q_enabled)
+               adapter->cmd_wait_q.status = -1;
 
        switch (le16_to_cpu(resp->command)) {
        case HostCmd_CMD_802_11_PS_MODE_ENH:
@@ -103,8 +103,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
        spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
        adapter->curr_cmd = NULL;
        spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
-
-       return;
 }
 
 /*
@@ -282,7 +280,6 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *resp,
                                   void *data_buf)
 {
-       struct mwifiex_adapter *adapter = priv->adapter;
        struct mwifiex_rate_cfg *ds_rate = NULL;
        struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
        struct mwifiex_rate_scope *rate_scope;
@@ -328,9 +325,9 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
        if (priv->is_data_rate_auto)
                priv->data_rate = 0;
        else
-               ret = mwifiex_prepare_cmd(priv,
+               ret = mwifiex_send_cmd_async(priv,
                                          HostCmd_CMD_802_11_TX_RATE_QUERY,
-                                         HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+                                         HostCmd_ACT_GEN_GET, 0, NULL);
 
        if (data_buf) {
                ds_rate = (struct mwifiex_rate_cfg *) data_buf;
@@ -338,9 +335,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
                        if (priv->is_data_rate_auto) {
                                ds_rate->is_rate_auto = 1;
                        } else {
-                               ds_rate->rate =
-                                       mwifiex_get_rate_index(adapter,
-                                                              priv->
+                               ds_rate->rate = mwifiex_get_rate_index(priv->
                                                               bitmap_rates,
                                                               sizeof(priv->
                                                               bitmap_rates));
@@ -516,13 +511,11 @@ static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
 static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
                                            struct host_cmd_ds_command *resp)
 {
-       struct mwifiex_adapter *adapter = priv->adapter;
-
        priv->tx_rate = resp->params.tx_rate.tx_rate;
        priv->tx_htinfo = resp->params.tx_rate.ht_info;
        if (!priv->is_data_rate_auto)
                priv->data_rate =
-                       mwifiex_index_to_data_rate(adapter, priv->tx_rate,
+                       mwifiex_index_to_data_rate(priv->tx_rate,
                                                   priv->tx_htinfo);
 
        return 0;
@@ -574,8 +567,7 @@ static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
                &resp->params.key_material;
 
        if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
-               if ((le16_to_cpu(key->key_param_set.key_info) &
-                    KEY_INFO_TKIP_MCAST)) {
+               if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
                        dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");
                        priv->wpa_is_gtk_set = true;
                        priv->scan_block = false;
@@ -834,19 +826,17 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
  * response handlers based on the command ID.
  */
 int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
-                               u16 cmdresp_no, void *cmd_buf, void *wq_buf)
+                               u16 cmdresp_no, void *cmd_buf)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_command *resp =
                (struct host_cmd_ds_command *) cmd_buf;
-       struct mwifiex_wait_queue *wait_queue =
-               (struct mwifiex_wait_queue *) wq_buf;
        void *data_buf = adapter->curr_cmd->data_buf;
 
        /* If the command is not successful, cleanup and return failure */
        if (resp->result != HostCmd_RESULT_OK) {
-               mwifiex_process_cmdresp_error(priv, resp, wait_queue);
+               mwifiex_process_cmdresp_error(priv, resp);
                return -1;
        }
        /* Command successful, handle response */
@@ -866,12 +856,11 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
                ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf);
                break;
        case HostCmd_CMD_802_11_SCAN:
-               ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue);
-               wait_queue = NULL;
-               adapter->curr_cmd->wq_buf = NULL;
+               ret = mwifiex_ret_802_11_scan(priv, resp);
+               adapter->curr_cmd->wait_q_enabled = false;
                break;
        case HostCmd_CMD_802_11_BG_SCAN_QUERY:
-               ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue);
+               ret = mwifiex_ret_802_11_scan(priv, resp);
                dev_dbg(adapter->dev,
                        "info: CMD_RESP: BG_SCAN result is ready!\n");
                break;
@@ -885,14 +874,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
                ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
                break;
        case HostCmd_CMD_802_11_ASSOCIATE:
-               ret = mwifiex_ret_802_11_associate(priv, resp, wait_queue);
+               ret = mwifiex_ret_802_11_associate(priv, resp);
                break;
        case HostCmd_CMD_802_11_DEAUTHENTICATE:
                ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
                break;
        case HostCmd_CMD_802_11_AD_HOC_START:
        case HostCmd_CMD_802_11_AD_HOC_JOIN:
-               ret = mwifiex_ret_802_11_ad_hoc(priv, resp, wait_queue);
+               ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
                break;
        case HostCmd_CMD_802_11_AD_HOC_STOP:
                ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
@@ -952,7 +941,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
                                                mp_end_port));
                break;
        case HostCmd_CMD_AMSDU_AGGR_CTRL:
-               ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf);
+               ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf);
                break;
        case HostCmd_CMD_WMM_GET_STATUS:
                ret = mwifiex_ret_wmm_get_status(priv, resp);
@@ -971,7 +960,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
        case HostCmd_CMD_SET_BSS_MODE:
                break;
        case HostCmd_CMD_11N_CFG:
-               ret = mwifiex_ret_11n_cfg(priv, resp, data_buf);
+               ret = mwifiex_ret_11n_cfg(resp, data_buf);
                break;
        default:
                dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
index 936d7c175e75421f8e18ab180dd003e66ad8bf45..fc265cab09078685114fb1138add648c4108f310 100644 (file)
@@ -271,8 +271,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        case EVENT_HS_ACT_REQ:
                dev_dbg(adapter->dev, "event: HS_ACT_REQ\n");
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
-                                         0, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_802_11_HS_CFG_ENH,
+                                            0, 0, NULL);
                break;
 
        case EVENT_MIC_ERR_UNICAST:
@@ -303,9 +304,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                       sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
                adapter->num_in_scan_table = 0;
                adapter->bcn_buf_end = adapter->bcn_buf;
-               ret = mwifiex_prepare_cmd(priv,
-                                         HostCmd_CMD_802_11_BG_SCAN_QUERY,
-                                         HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_802_11_BG_SCAN_QUERY,
+                                            HostCmd_ACT_GEN_GET, 0, NULL);
                break;
 
        case EVENT_PORT_RELEASE:
@@ -314,8 +315,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        case EVENT_WMM_STATUS_CHANGE:
                dev_dbg(adapter->dev, "event: WMM status changed\n");
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
-                                         0, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS,
+                                            0, 0, NULL);
                break;
 
        case EVENT_RSSI_LOW:
@@ -353,15 +354,15 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                break;
        case EVENT_IBSS_COALESCED:
                dev_dbg(adapter->dev, "event: IBSS_COALESCED\n");
-               ret = mwifiex_prepare_cmd(priv,
+               ret = mwifiex_send_cmd_async(priv,
                                HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
-                               HostCmd_ACT_GEN_GET, 0, NULL, NULL);
+                               HostCmd_ACT_GEN_GET, 0, NULL);
                break;
        case EVENT_ADDBA:
                dev_dbg(adapter->dev, "event: ADDBA Request\n");
-               mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
-                                   HostCmd_ACT_GEN_SET, 0, NULL,
-                                   adapter->event_body);
+               mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
+                                      HostCmd_ACT_GEN_SET, 0,
+                                      adapter->event_body);
                break;
        case EVENT_DELBA:
                dev_dbg(adapter->dev, "event: DELBA Request\n");
index b163507b1fe0b17bf1393f21adb25d8dcf41e41c..e7adaab352266c71bcd033c22c1d25e3ca92e1f7 100644 (file)
@@ -33,9 +33,8 @@
  * size, and the calling function must ensure enough memory is
  * available.
  */
-static int
-mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
-                       struct net_device *dev)
+int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
+                           struct net_device *dev)
 {
        int i = 0;
        struct netdev_hw_addr *ha;
@@ -46,217 +45,52 @@ mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
        return i;
 }
 
-/*
- * Allocate and fills a wait queue with proper parameters.
- *
- * This function needs to be called before an IOCTL request can be made.
- * It can handle the following wait options:
- *      MWIFIEX_NO_WAIT     - Waiting is disabled
- *      MWIFIEX_IOCTL_WAIT  - Waiting is done on IOCTL wait queue
- *      MWIFIEX_CMD_WAIT    - Waiting is done on command wait queue
- *      MWIFIEX_WSTATS_WAIT - Waiting is done on stats wait queue
- */
-struct mwifiex_wait_queue *
-mwifiex_alloc_fill_wait_queue(struct mwifiex_private *priv,
-                             u8 wait_option)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-
-       wait = (struct mwifiex_wait_queue *)
-               kzalloc(sizeof(struct mwifiex_wait_queue), GFP_ATOMIC);
-       if (!wait) {
-               dev_err(priv->adapter->dev, "%s: fail to alloc buffer\n",
-                                               __func__);
-               return wait;
-       }
-
-       wait->bss_index = priv->bss_index;
-
-       switch (wait_option) {
-       case MWIFIEX_NO_WAIT:
-               wait->enabled = 0;
-               break;
-       case MWIFIEX_IOCTL_WAIT:
-               priv->ioctl_wait_q_woken = false;
-               wait->start_time = jiffies;
-               wait->wait = &priv->ioctl_wait_q;
-               wait->condition = &priv->ioctl_wait_q_woken;
-               wait->enabled = 1;
-               break;
-       case MWIFIEX_CMD_WAIT:
-               priv->cmd_wait_q_woken = false;
-               wait->start_time = jiffies;
-               wait->wait = &priv->cmd_wait_q;
-               wait->condition = &priv->cmd_wait_q_woken;
-               wait->enabled = 1;
-               break;
-       case MWIFIEX_WSTATS_WAIT:
-               priv->w_stats_wait_q_woken = false;
-               wait->start_time = jiffies;
-               wait->wait = &priv->w_stats_wait_q;
-               wait->condition = &priv->w_stats_wait_q_woken;
-               wait->enabled = 1;
-               break;
-       }
-
-       return wait;
-}
-
 /*
  * Wait queue completion handler.
  *
- * This function waits on a particular wait queue.
- * For NO_WAIT option, it returns immediately. It also cancels the
- * pending IOCTL request after waking up, in case of errors.
+ * This function waits on a cmd wait queue. It also cancels the pending
+ * request after waking up, in case of errors.
  */
-static void
-mwifiex_wait_ioctl_complete(struct mwifiex_private *priv,
-                           struct mwifiex_wait_queue *wait,
-                           u8 wait_option)
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 {
        bool cancel_flag = false;
+       int status = adapter->cmd_wait_q.status;
 
-       switch (wait_option) {
-       case MWIFIEX_NO_WAIT:
-               break;
-       case MWIFIEX_IOCTL_WAIT:
-               wait_event_interruptible(priv->ioctl_wait_q,
-                                        priv->ioctl_wait_q_woken);
-               if (!priv->ioctl_wait_q_woken)
-                       cancel_flag = true;
-               break;
-       case MWIFIEX_CMD_WAIT:
-               wait_event_interruptible(priv->cmd_wait_q,
-                                        priv->cmd_wait_q_woken);
-               if (!priv->cmd_wait_q_woken)
-                       cancel_flag = true;
-               break;
-       case MWIFIEX_WSTATS_WAIT:
-               wait_event_interruptible(priv->w_stats_wait_q,
-                                        priv->w_stats_wait_q_woken);
-               if (!priv->w_stats_wait_q_woken)
-                       cancel_flag = true;
-               break;
-       }
-       if (cancel_flag) {
-               mwifiex_cancel_pending_ioctl(priv->adapter, wait);
-               dev_dbg(priv->adapter->dev, "cmd: IOCTL cancel: wait=%p, wait_option=%d\n",
-                       wait, wait_option);
-       }
+       dev_dbg(adapter->dev, "cmd pending\n");
+       atomic_inc(&adapter->cmd_pending);
 
-       return;
-}
-
-/*
- * The function waits for the request to complete and issues the
- * completion handler, if required.
- */
-int mwifiex_request_ioctl(struct mwifiex_private *priv,
-                         struct mwifiex_wait_queue *wait,
-                         int status, u8 wait_option)
-{
-       switch (status) {
-       case -EINPROGRESS:
-               dev_dbg(priv->adapter->dev, "cmd: IOCTL pending: wait=%p, wait_option=%d\n",
-                               wait, wait_option);
-               atomic_inc(&priv->adapter->ioctl_pending);
-               /* Status pending, wake up main process */
-               queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
-
-               /* Wait for completion */
-               if (wait_option) {
-                       mwifiex_wait_ioctl_complete(priv, wait, wait_option);
-                       status = wait->status;
-               }
-               break;
-       case 0:
-       case -1:
-       case -EBUSY:
-       default:
-               break;
-       }
-       return status;
-}
-EXPORT_SYMBOL_GPL(mwifiex_request_ioctl);
+       /* Status pending, wake up main process */
+       queue_work(adapter->workqueue, &adapter->main_work);
 
-/*
- * IOCTL request handler to set/get MAC address.
- *
- * This function prepares the correct firmware command and
- * issues it to get the extended version information.
- */
-static int mwifiex_bss_ioctl_mac_address(struct mwifiex_private *priv,
-                                        struct mwifiex_wait_queue *wait,
-                                        u8 action, u8 *mac)
-{
-       int ret = 0;
+       /* Wait for completion */
+       wait_event_interruptible(adapter->cmd_wait_q.wait,
+                                       adapter->cmd_wait_q.condition);
+       if (!adapter->cmd_wait_q.condition)
+               cancel_flag = true;
 
-       if ((action == HostCmd_ACT_GEN_GET) && mac) {
-               memcpy(mac, priv->curr_addr, ETH_ALEN);
-               return 0;
+       if (cancel_flag) {
+               mwifiex_cancel_pending_ioctl(adapter);
+               dev_dbg(adapter->dev, "cmd cancel\n");
        }
+       adapter->cmd_wait_q.status = 0;
 
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
-                                 action, 0, wait, mac);
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
-}
-
-/*
- * Sends IOCTL request to set MAC address.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_request_set_mac_address(struct mwifiex_private *priv)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-       u8 wait_option = MWIFIEX_CMD_WAIT;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_bss_ioctl_mac_address(priv, wait, HostCmd_ACT_GEN_SET,
-                                              NULL);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-       if (!status)
-               memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
-       else
-               dev_err(priv->adapter->dev, "set mac address failed: status=%d"
-                               " error_code=%#x\n", status, wait->status);
-
-       kfree(wait);
        return status;
 }
 
 /*
- * IOCTL request handler to set multicast list.
- *
  * This function prepares the correct firmware command and
  * issues it to set the multicast list.
  *
  * This function can be used to enable promiscuous mode, or enable all
  * multicast packets, or to enable selective multicast.
  */
-static int
-mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv,
-                                struct mwifiex_wait_queue *wait,
-                                u16 action,
-                                struct mwifiex_multicast_list *mcast_list)
+int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
+                               struct mwifiex_multicast_list *mcast_list)
 {
        int ret = 0;
        u16 old_pkt_filter;
 
        old_pkt_filter = priv->curr_pkt_filter;
-       if (action == HostCmd_ACT_GEN_GET)
-               return -1;
 
        if (mcast_list->mode == MWIFIEX_PROMISC_MODE) {
                dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n");
@@ -281,16 +115,15 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv,
                                /* Set multicast addresses to firmware */
                                if (old_pkt_filter == priv->curr_pkt_filter) {
                                        /* Send request to firmware */
-                                       ret = mwifiex_prepare_cmd(priv,
+                                       ret = mwifiex_send_cmd_async(priv,
                                                HostCmd_CMD_MAC_MULTICAST_ADR,
-                                               action, 0, wait, mcast_list);
-                                       if (!ret)
-                                               ret = -EINPROGRESS;
+                                               HostCmd_ACT_GEN_SET, 0,
+                                               mcast_list);
                                } else {
                                        /* Send request to firmware */
-                                       ret = mwifiex_prepare_cmd(priv,
+                                       ret = mwifiex_send_cmd_async(priv,
                                                HostCmd_CMD_MAC_MULTICAST_ADR,
-                                               action, 0, NULL,
+                                               HostCmd_ACT_GEN_SET, 0,
                                                mcast_list);
                                }
                        }
@@ -300,101 +133,21 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv,
                "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",
               old_pkt_filter, priv->curr_pkt_filter);
        if (old_pkt_filter != priv->curr_pkt_filter) {
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, action,
-                                         0, wait, &priv->curr_pkt_filter);
-               if (!ret)
-                       ret = -EINPROGRESS;
+               ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL,
+                                            HostCmd_ACT_GEN_SET,
+                                            0, &priv->curr_pkt_filter);
        }
 
        return ret;
 }
 
 /*
- * Sends IOCTL request to set multicast list.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-void
-mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
-                                  struct net_device *dev)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       struct mwifiex_multicast_list mcast_list;
-       u8 wait_option = MWIFIEX_NO_WAIT;
-       int status = 0;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return;
-
-       if (dev->flags & IFF_PROMISC) {
-               mcast_list.mode = MWIFIEX_PROMISC_MODE;
-       } else if (dev->flags & IFF_ALLMULTI ||
-                  netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
-               mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
-       } else {
-               mcast_list.mode = MWIFIEX_MULTICAST_MODE;
-               if (netdev_mc_count(dev))
-                       mcast_list.num_multicast_addr =
-                               mwifiex_copy_mcast_addr(&mcast_list, dev);
-       }
-       status = mwifiex_bss_ioctl_multicast_list(priv, wait,
-                                                 HostCmd_ACT_GEN_SET,
-                                                 &mcast_list);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-       if (wait && status != -EINPROGRESS)
-               kfree(wait);
-
-       return;
-}
-
-/*
- * IOCTL request handler to disconnect from a BSS/IBSS.
- */
-static int mwifiex_bss_ioctl_stop(struct mwifiex_private *priv,
-                                 struct mwifiex_wait_queue *wait, u8 *mac)
-{
-       return mwifiex_deauthenticate(priv, wait, mac);
-}
-
-/*
- * Sends IOCTL request to disconnect from a BSS.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_disconnect(struct mwifiex_private *priv, u8 wait_option, u8 *mac)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_bss_ioctl_stop(priv, wait, mac);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-
-       kfree(wait);
-       return status;
-}
-EXPORT_SYMBOL_GPL(mwifiex_disconnect);
-
-/*
- * IOCTL request handler to join a BSS/IBSS.
- *
  * In Ad-Hoc mode, the IBSS is created if not found in scan list.
  * In both Ad-Hoc and infra mode, an deauthentication is performed
  * first.
  */
-static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,
-                                  struct mwifiex_wait_queue *wait,
-                                  struct mwifiex_ssid_bssid *ssid_bssid)
+int mwifiex_bss_start(struct mwifiex_private *priv,
+                     struct mwifiex_ssid_bssid *ssid_bssid)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -406,7 +159,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,
 
        if (priv->bss_mode == NL80211_IFTYPE_STATION) {
                /* Infra mode */
-               ret = mwifiex_deauthenticate(priv, NULL, NULL);
+               ret = mwifiex_deauthenticate(priv, NULL);
                if (ret)
                        return ret;
 
@@ -427,7 +180,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,
                /* Clear any past association response stored for
                 * application retrieval */
                priv->assoc_rsp_size = 0;
-               ret = mwifiex_associate(priv, wait, &adapter->scan_table[i]);
+               ret = mwifiex_associate(priv, &adapter->scan_table[i]);
                if (ret)
                        return ret;
        } else {
@@ -441,7 +194,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,
 
                /* Exit Adhoc mode first */
                dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
-               ret = mwifiex_deauthenticate(priv, NULL, NULL);
+               ret = mwifiex_deauthenticate(priv, NULL);
                if (ret)
                        return ret;
 
@@ -460,75 +213,39 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,
                if (i >= 0) {
                        dev_dbg(adapter->dev, "info: network found in scan"
                                                        " list. Joining...\n");
-                       ret = mwifiex_adhoc_join(priv, wait,
-                                                &adapter->scan_table[i]);
+                       ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);
                        if (ret)
                                return ret;
-               } else {        /* i >= 0 */
+               } else {
                        dev_dbg(adapter->dev, "info: Network not found in "
                                "the list, creating adhoc with ssid = %s\n",
                               ssid_bssid->ssid.ssid);
-                       ret = mwifiex_adhoc_start(priv, wait,
-                                                 &ssid_bssid->ssid);
+                       ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);
                        if (ret)
                                return ret;
                }
        }
 
-       if (!ret)
-               ret = -EINPROGRESS;
-
        return ret;
 }
 
-/*
- * Sends IOCTL request to connect with a BSS.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_bss_start(struct mwifiex_private *priv, u8 wait_option,
-                     struct mwifiex_ssid_bssid *ssid_bssid)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       struct mwifiex_ssid_bssid tmp_ssid_bssid;
-       int status = 0;
-
-       /* Stop the O.S. TX queue if needed */
-       if (!netif_queue_stopped(priv->netdev))
-               netif_stop_queue(priv->netdev);
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       if (ssid_bssid)
-               memcpy(&tmp_ssid_bssid, ssid_bssid,
-                      sizeof(struct mwifiex_ssid_bssid));
-       status = mwifiex_bss_ioctl_start(priv, wait, &tmp_ssid_bssid);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-
-       kfree(wait);
-       return status;
-}
-
 /*
  * IOCTL request handler to set host sleep configuration.
  *
  * This function prepares the correct firmware command and
  * issues it.
  */
-static int
-mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv,
-                       struct mwifiex_wait_queue *wait,
-                       u16 action, struct mwifiex_ds_hs_cfg *hs_cfg)
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+                         int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        int status = 0;
        u32 prev_cond = 0;
 
+       if (!hs_cfg)
+               return -ENOMEM;
+
        switch (action) {
        case HostCmd_ACT_GEN_SET:
                if (adapter->pps_uapsd_mode) {
@@ -561,12 +278,16 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv,
                                status = -1;
                                break;
                        }
-                       status = mwifiex_prepare_cmd(priv,
-                                       HostCmd_CMD_802_11_HS_CFG_ENH,
-                                       HostCmd_ACT_GEN_SET,
-                                       0, wait, &adapter->hs_cfg);
-                       if (!status)
-                               status = -EINPROGRESS;
+                       if (cmd_type == MWIFIEX_SYNC_CMD)
+                               status = mwifiex_send_cmd_sync(priv,
+                                               HostCmd_CMD_802_11_HS_CFG_ENH,
+                                               HostCmd_ACT_GEN_SET, 0,
+                                               &adapter->hs_cfg);
+                       else
+                               status = mwifiex_send_cmd_async(priv,
+                                               HostCmd_CMD_802_11_HS_CFG_ENH,
+                                               HostCmd_ACT_GEN_SET, 0,
+                                               &adapter->hs_cfg);
                        if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL)
                                /* Restore previous condition */
                                adapter->hs_cfg.conditions =
@@ -591,54 +312,21 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv,
        return status;
 }
 
-/*
- * Sends IOCTL request to set Host Sleep parameters.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
-                             u8 wait_option,
-                             struct mwifiex_ds_hs_cfg *hscfg)
-{
-       int ret = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-
-       if (!hscfg)
-               return -ENOMEM;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       ret = mwifiex_pm_ioctl_hs_cfg(priv, wait, action, hscfg);
-
-       ret = mwifiex_request_ioctl(priv, wait, ret, wait_option);
-
-       if (wait && (ret != -EINPROGRESS))
-               kfree(wait);
-       return ret;
-}
-
 /*
  * Sends IOCTL request to cancel the existing Host Sleep configuration.
  *
  * This function allocates the IOCTL request buffer, fills it
  * with requisite parameters and calls the IOCTL handler.
  */
-int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option)
+int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
 {
-       int ret = 0;
        struct mwifiex_ds_hs_cfg hscfg;
 
-       /* Cancel Host Sleep */
        hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
        hscfg.is_invoke_hostcmd = true;
-       ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
-                                       wait_option, &hscfg);
 
-       return ret;
+       return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+                                   cmd_type, &hscfg);
 }
 EXPORT_SYMBOL_GPL(mwifiex_cancel_hs);
 
@@ -657,7 +345,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
                return true;
        }
 
-       /* Enable Host Sleep */
        adapter->hs_activate_wait_q_woken = false;
 
        memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param));
@@ -665,8 +352,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
 
        if (mwifiex_set_hs_params(mwifiex_get_priv(adapter,
                                                       MWIFIEX_BSS_ROLE_STA),
-                                     HostCmd_ACT_GEN_SET,
-                                     MWIFIEX_IOCTL_WAIT, &hscfg)) {
+                                 HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD,
+                                 &hscfg)) {
                dev_err(adapter->dev, "IOCTL request HS enable failed\n");
                return false;
        }
@@ -678,69 +365,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
 }
 EXPORT_SYMBOL_GPL(mwifiex_enable_hs);
 
-/*
- * IOCTL request handler to get signal information.
- *
- * This function prepares the correct firmware command and
- * issues it to get the signal (RSSI) information.
- *
- * This only works in the connected mode.
- */
-static int mwifiex_get_info_signal(struct mwifiex_private *priv,
-                                  struct mwifiex_wait_queue *wait,
-                                  struct mwifiex_ds_get_signal *signal)
-{
-       int ret = 0;
-
-       if (!wait) {
-               dev_err(priv->adapter->dev, "WAIT information is not present\n");
-               return -1;
-       }
-
-       /* Signal info can be obtained only if connected */
-       if (!priv->media_connected) {
-               dev_dbg(priv->adapter->dev,
-                       "info: Can not get signal in disconnected state\n");
-               return -1;
-       }
-
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RSSI_INFO,
-                                 HostCmd_ACT_GEN_GET, 0, wait, signal);
-
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to get statistics.
- *
- * This function prepares the correct firmware command and
- * issues it to get the statistics (RSSI) information.
- */
-static int mwifiex_get_info_stats(struct mwifiex_private *priv,
-                          struct mwifiex_wait_queue *wait,
-                          struct mwifiex_ds_get_stats *log)
-{
-       int ret = 0;
-
-       if (!wait) {
-               dev_err(priv->adapter->dev, "MWIFIEX IOCTL information is not present\n");
-               return -1;
-       }
-
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_GET_LOG,
-                                 HostCmd_ACT_GEN_GET, 0, wait, log);
-
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
-}
-
 /*
  * IOCTL request handler to get BSS information.
  *
@@ -757,23 +381,17 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
        if (!info)
                return -1;
 
-       /* Get current BSS info */
        bss_desc = &priv->curr_bss_params.bss_descriptor;
 
-       /* BSS mode */
        info->bss_mode = priv->bss_mode;
 
-       /* SSID */
        memcpy(&info->ssid, &bss_desc->ssid,
               sizeof(struct mwifiex_802_11_ssid));
 
-       /* BSSID */
        memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN);
 
-       /* Channel */
        info->bss_chan = bss_desc->channel;
 
-       /* Region code */
        info->region_code = adapter->region_code;
 
        /* Scan table index if connected */
@@ -787,20 +405,15 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
                        info->scan_table_idx = tbl_idx;
        }
 
-       /* Connection status */
        info->media_connected = priv->media_connected;
 
-       /* Tx power information */
        info->max_power_level = priv->max_tx_power_level;
        info->min_power_level = priv->min_tx_power_level;
 
-       /* AdHoc state */
        info->adhoc_state = priv->adhoc_state;
 
-       /* Last beacon NF */
        info->bcn_nf_last = priv->bcn_nf_last;
 
-       /* wep status */
        if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED)
                info->wep_status = true;
        else
@@ -813,90 +426,20 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
 }
 
 /*
- * IOCTL request handler to get extended version information.
+ * The function sets band configurations.
  *
- * This function prepares the correct firmware command and
- * issues it to get the extended version information.
- */
-static int mwifiex_get_info_ver_ext(struct mwifiex_private *priv,
-                                   struct mwifiex_wait_queue *wait,
-                                   struct mwifiex_ver_ext *ver_ext)
-{
-       int ret = 0;
-
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_VERSION_EXT,
-                                 HostCmd_ACT_GEN_GET, 0, wait, ver_ext);
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set/get SNMP MIB parameters.
- *
- * This function prepares the correct firmware command and
- * issues it.
- *
- * Currently the following parameters are supported -
- *      Set/get RTS Threshold
- *      Set/get fragmentation threshold
- *      Set/get retry count
- */
-int mwifiex_snmp_mib_ioctl(struct mwifiex_private *priv,
-                          struct mwifiex_wait_queue *wait,
-                          u32 cmd_oid, u16 action, u32 *value)
-{
-       int ret = 0;
-
-       if (!value)
-               return -1;
-
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
-                                 action, cmd_oid, wait, value);
-
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
-}
-
-/*
- * IOCTL request handler to set/get band configurations.
- *
- * For SET operation, it performs extra checks to make sure the Ad-Hoc
+ * it performs extra checks to make sure the Ad-Hoc
  * band and channel are compatible. Otherwise it returns an error.
  *
- * For GET operation, this function retrieves the following information -
- *      - Infra bands
- *      - Ad-hoc band
- *      - Ad-hoc channel
- *      - Secondary channel offset
  */
-int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv,
-                                u16 action,
-                                struct mwifiex_ds_band_cfg *radio_cfg)
+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 = 0;
        u8 adhoc_band = 0;
        u32 adhoc_channel = 0;
 
-       if (action == HostCmd_ACT_GEN_GET) {
-               /* Infra Bands */
-               radio_cfg->config_bands = adapter->config_bands;
-               /* Adhoc Band */
-               radio_cfg->adhoc_start_band = adapter->adhoc_start_band;
-               /* Adhoc channel */
-               radio_cfg->adhoc_channel = priv->adhoc_channel;
-               /* Secondary channel offset */
-               radio_cfg->sec_chan_offset = adapter->chan_offset;
-               return 0;
-       }
-
-       /* For action = SET */
        infra_band = (u8) radio_cfg->config_bands;
        adhoc_band = (u8) radio_cfg->adhoc_start_band;
        adhoc_channel = radio_cfg->adhoc_channel;
@@ -950,8 +493,8 @@ int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv,
  * This function performs validity checking on channel/frequency
  * compatibility and returns failure if not valid.
  */
-int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action,
-                             struct mwifiex_chan_freq_power *chan)
+int mwifiex_bss_set_channel(struct mwifiex_private *priv,
+                           struct mwifiex_chan_freq_power *chan)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct mwifiex_chan_freq_power *cfp = NULL;
@@ -959,16 +502,6 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action,
        if (!chan)
                return -1;
 
-       if (action == HostCmd_ACT_GEN_GET) {
-               cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
-                               priv->curr_bss_params.band,
-                               (u16) priv->curr_bss_params.bss_descriptor.
-                                       channel);
-               chan->channel = cfp->channel;
-               chan->freq = cfp->freq;
-
-               return 0;
-       }
        if (!chan->channel && !chan->freq)
                return -1;
        if (adapter->adhoc_start_band & BAND_AN)
@@ -1024,27 +557,19 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action,
  * issues it to set or get the ad-hoc channel.
  */
 static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
-                                         struct mwifiex_wait_queue *wait,
                                          u16 action, u16 *channel)
 {
-       int ret = 0;
-
        if (action == HostCmd_ACT_GEN_GET) {
                if (!priv->media_connected) {
                        *channel = priv->adhoc_channel;
-                       return ret;
+                       return 0;
                }
        } else {
                priv->adhoc_channel = (u8) *channel;
        }
 
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_RF_CHANNEL,
-                                 action, 0, wait, channel);
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL,
+                                   action, 0, channel);
 }
 
 /*
@@ -1054,11 +579,9 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
  * these are provided, just the best BSS (best RSSI) is returned.
  */
 int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
-                              struct mwifiex_wait_queue *wait,
                               struct mwifiex_ssid_bssid *ssid_bssid)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
        struct mwifiex_bssdescriptor *bss_desc;
        u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
        u8 mac[ETH_ALEN];
@@ -1087,10 +610,10 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
                bss_desc = &adapter->scan_table[i];
                memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
        } else {
-               ret = mwifiex_find_best_network(priv, ssid_bssid);
+               return mwifiex_find_best_network(priv, ssid_bssid);
        }
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1114,10 +637,7 @@ int
 mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
 {
        int ret = 0;
-       int status = 0;
        struct mwifiex_bss_info bss_info;
-       struct mwifiex_wait_queue *wait = NULL;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
        struct mwifiex_ssid_bssid ssid_bssid;
        u16 curr_chan = 0;
 
@@ -1127,19 +647,10 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
        if (mwifiex_get_bss_info(priv, &bss_info))
                return -1;
 
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
        /* Get current channel */
-       status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_GET,
-                                               &curr_chan);
+       ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET,
+                                            &curr_chan);
 
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option)) {
-               ret = -1;
-               goto done;
-       }
        if (curr_chan == channel) {
                ret = 0;
                goto done;
@@ -1154,23 +665,13 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
 
        /* Do disonnect */
        memset(&ssid_bssid, 0, ETH_ALEN);
-       status = mwifiex_bss_ioctl_stop(priv, wait, ssid_bssid.bssid);
-
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option)) {
-               ret = -1;
-               goto done;
-       }
+       ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid);
 
-       status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_SET,
-                                               (u16 *) &channel);
-
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option)) {
-               ret = -1;
-               goto done;
-       }
+       ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET,
+                                            (u16 *) &channel);
 
        /* Do specific SSID scanning */
-       if (mwifiex_request_scan(priv, wait_option, &bss_info.ssid)) {
+       if (mwifiex_request_scan(priv, &bss_info.ssid)) {
                ret = -1;
                goto done;
        }
@@ -1179,13 +680,8 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
        memcpy(&ssid_bssid.ssid, &bss_info.ssid,
               sizeof(struct mwifiex_802_11_ssid));
 
-       status = mwifiex_bss_ioctl_start(priv, wait, &ssid_bssid);
-
-       if (mwifiex_request_ioctl(priv, wait, status, wait_option))
-               ret = -1;
-
+       ret = mwifiex_bss_start(priv, &ssid_bssid);
 done:
-       kfree(wait);
        return ret;
 }
 
@@ -1198,11 +694,9 @@ done:
  * for the band.
  */
 static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
-                                            struct mwifiex_wait_queue *wait,
                                             struct mwifiex_rate_cfg *rate_cfg)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
 
        rate_cfg->is_rate_auto = priv->is_data_rate_auto;
        if (!priv->media_connected) {
@@ -1241,15 +735,12 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
                        break;
                }
        } else {
-               /* Send request to firmware */
-               ret = mwifiex_prepare_cmd(priv,
-                                         HostCmd_CMD_802_11_TX_RATE_QUERY,
-                                         HostCmd_ACT_GEN_GET, 0, wait, NULL);
-               if (!ret)
-                       ret = -EINPROGRESS;
+               return mwifiex_send_cmd_sync(priv,
+                                           HostCmd_CMD_802_11_TX_RATE_QUERY,
+                                           HostCmd_ACT_GEN_GET, 0, NULL);
        }
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1261,7 +752,6 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
  * The function also performs validation checking on the supplied value.
  */
 static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
-                                            struct mwifiex_wait_queue *wait,
                                             struct mwifiex_rate_cfg *rate_cfg)
 {
        u8 rates[MWIFIEX_SUPPORTED_RATES];
@@ -1299,8 +789,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
                }
                memset(bitmap_rates, 0, sizeof(bitmap_rates));
 
-               rate_index =
-                       mwifiex_data_rate_to_index(adapter, rate_cfg->rate);
+               rate_index = mwifiex_data_rate_to_index(rate_cfg->rate);
 
                /* Only allow b/g rates to be set */
                if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 &&
@@ -1315,11 +804,8 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
                }
        }
 
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
-                                 HostCmd_ACT_GEN_SET, 0, wait, bitmap_rates);
-       if (!ret)
-               ret = -EINPROGRESS;
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
+                                   HostCmd_ACT_GEN_SET, 0, bitmap_rates);
 
        return ret;
 }
@@ -1331,7 +817,6 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
  * rate index.
  */
 static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv,
-                                 struct mwifiex_wait_queue *wait,
                                  struct mwifiex_rate_cfg *rate_cfg)
 {
        int status = 0;
@@ -1340,11 +825,9 @@ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv,
                return -1;
 
        if (rate_cfg->action == HostCmd_ACT_GEN_GET)
-               status = mwifiex_rate_ioctl_get_rate_value(
-                               priv, wait, rate_cfg);
+               status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg);
        else
-               status = mwifiex_rate_ioctl_set_rate_value(
-                               priv, wait, rate_cfg);
+               status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg);
 
        return status;
 }
@@ -1359,30 +842,21 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
                              struct mwifiex_rate_cfg *rate)
 {
        int ret = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
 
        memset(rate, 0, sizeof(struct mwifiex_rate_cfg));
        rate->action = HostCmd_ACT_GEN_GET;
-       ret = mwifiex_rate_ioctl_cfg(priv, wait, rate);
+       ret = mwifiex_rate_ioctl_cfg(priv, rate);
 
-       ret = mwifiex_request_ioctl(priv, wait, ret, wait_option);
        if (!ret) {
                if (rate && rate->is_rate_auto)
-                       rate->rate = mwifiex_index_to_data_rate(priv->adapter,
-                                       priv->tx_rate, priv->tx_htinfo);
+                       rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
+                                                       priv->tx_htinfo);
                else if (rate)
                        rate->rate = priv->data_rate;
        } else {
                ret = -1;
        }
 
-       kfree(wait);
        return ret;
 }
 
@@ -1398,9 +872,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
  *      - Modulation class HTBW20
  *      - Modulation class HTBW40
  */
-static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv,
-                                        struct mwifiex_wait_queue *wait,
-                                        struct mwifiex_power_cfg *power_cfg)
+int mwifiex_set_tx_power(struct mwifiex_private *priv,
+                        struct mwifiex_power_cfg *power_cfg)
 {
        int ret = 0;
        struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL;
@@ -1472,13 +945,10 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv,
                pg->power_max = (s8) dbm;
                pg->ht_bandwidth = HT_BW_40;
        }
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG,
-                                 HostCmd_ACT_GEN_SET, 0, wait, buf);
-       if (!ret)
-               ret = -EINPROGRESS;
-       kfree(buf);
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG,
+                                   HostCmd_ACT_GEN_SET, 0, buf);
 
+       kfree(buf);
        return ret;
 }
 
@@ -1488,33 +958,23 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv,
  * This function prepares the correct firmware command and
  * issues it.
  */
-static int mwifiex_pm_ioctl_ps_mode(struct mwifiex_private *priv,
-                                   struct mwifiex_wait_queue *wait,
-                                   u32 *ps_mode, u16 action)
+int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
        u16 sub_cmd;
 
-       if (action == HostCmd_ACT_GEN_SET) {
-               if (*ps_mode)
-                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
-               else
-                       adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
-               sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS;
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                                         sub_cmd, BITMAP_STA_PS, wait, NULL);
-               if ((!ret) && (sub_cmd == DIS_AUTO_PS))
-                       ret = mwifiex_prepare_cmd(priv,
-                                       HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS,
-                                       0, NULL, NULL);
-       } else {
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
-                                         GET_PS, 0, wait, NULL);
-       }
-
-       if (!ret)
-               ret = -EINPROGRESS;
+       if (*ps_mode)
+               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
+       else
+               adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
+       sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS;
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+                                   sub_cmd, BITMAP_STA_PS, NULL);
+       if ((!ret) && (sub_cmd == DIS_AUTO_PS))
+               ret = mwifiex_send_cmd_async(priv,
+                               HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS,
+                               0, NULL);
 
        return ret;
 }
@@ -1600,20 +1060,13 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,
  * This function prepares the correct firmware command and
  * issues it.
  */
-static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter,
-                              struct mwifiex_wait_queue *wait,
+static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv,
                               struct mwifiex_ds_encrypt_key *encrypt_key)
 {
-       int ret = 0;
-       struct mwifiex_private *priv = adapter->priv[wait->bss_index];
 
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                 HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-                                 wait, encrypt_key);
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+                                   HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+                                   encrypt_key);
 }
 
 /*
@@ -1622,12 +1075,10 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter,
  * This function prepares the correct firmware command and
  * issues it, after validation checks.
  */
-static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
-                             struct mwifiex_wait_queue *wait,
+static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
                              struct mwifiex_ds_encrypt_key *encrypt_key)
 {
        int ret = 0;
-       struct mwifiex_private *priv = adapter->priv[wait->bss_index];
        struct mwifiex_wep_key *wep_key = NULL;
        int index;
 
@@ -1641,7 +1092,7 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
                /* Copy the required key as the current key */
                wep_key = &priv->wep_key[index];
                if (!wep_key->key_length) {
-                       dev_err(adapter->dev,
+                       dev_err(priv->adapter->dev,
                                "key not set, so cannot enable it\n");
                        return -1;
                }
@@ -1649,7 +1100,6 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
                priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED;
        } else {
                wep_key = &priv->wep_key[index];
-               /* Cleanup */
                memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
                /* Copy the key in the driver */
                memcpy(wep_key->key_material,
@@ -1661,8 +1111,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
        }
        if (wep_key->key_length) {
                /* Send request to firmware */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                         HostCmd_ACT_GEN_SET, 0, NULL, NULL);
+               ret = mwifiex_send_cmd_async(priv,
+                                            HostCmd_CMD_802_11_KEY_MATERIAL,
+                                            HostCmd_ACT_GEN_SET, 0, NULL);
                if (ret)
                        return ret;
        }
@@ -1671,12 +1122,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
        else
                priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
 
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-                                 HostCmd_ACT_GEN_SET, 0, wait,
-                                 &priv->curr_pkt_filter);
-       if (!ret)
-               ret = -EINPROGRESS;
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL,
+                                   HostCmd_ACT_GEN_SET, 0,
+                                   &priv->curr_pkt_filter);
 
        return ret;
 }
@@ -1691,18 +1139,16 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,
  *
  * This function can also be used to disable a currently set key.
  */
-static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,
-                             struct mwifiex_wait_queue *wait,
+static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv,
                              struct mwifiex_ds_encrypt_key *encrypt_key)
 {
        int ret = 0;
-       struct mwifiex_private *priv = adapter->priv[wait->bss_index];
        u8 remove_key = false;
        struct host_cmd_ds_802_11_key_material *ibss_key;
 
        /* Current driver only supports key length of up to 32 bytes */
-       if (encrypt_key->key_len > MWIFIEX_MAX_KEY_LENGTH) {
-               dev_err(adapter->dev, "key length too long\n");
+       if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) {
+               dev_err(priv->adapter->dev, "key length too long\n");
                return -1;
        }
 
@@ -1713,9 +1159,10 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,
                 */
                /* Send the key as PTK to firmware */
                encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                         HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-                                         NULL, encrypt_key);
+               ret = mwifiex_send_cmd_async(priv,
+                                       HostCmd_CMD_802_11_KEY_MATERIAL,
+                                       HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+                                       encrypt_key);
                if (ret)
                        return ret;
 
@@ -1729,8 +1176,7 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,
                       sizeof(ibss_key->key_param_set.key_len));
                ibss_key->key_param_set.key_type_id
                        = cpu_to_le16(KEY_TYPE_ID_TKIP);
-               ibss_key->key_param_set.key_info
-                       = cpu_to_le16(KEY_INFO_TKIP_ENABLED);
+               ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED);
 
                /* Send the key as GTK to firmware */
                encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST;
@@ -1740,19 +1186,15 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,
                encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;
 
        if (remove_key)
-               /* Send request to firmware */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                         HostCmd_ACT_GEN_SET,
-                                         !(KEY_INFO_ENABLED),
-                                         wait, encrypt_key);
+               ret = mwifiex_send_cmd_sync(priv,
+                                      HostCmd_CMD_802_11_KEY_MATERIAL,
+                                      HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED),
+                                      encrypt_key);
        else
-               /* Send request to firmware */
-               ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
-                                         HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
-                                         wait, encrypt_key);
-
-       if (!ret)
-               ret = -EINPROGRESS;
+               ret = mwifiex_send_cmd_sync(priv,
+                                       HostCmd_CMD_802_11_KEY_MATERIAL,
+                                       HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
+                                       encrypt_key);
 
        return ret;
 }
@@ -1765,21 +1207,16 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,
  */
 static int
 mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv,
-                             struct mwifiex_wait_queue *wait,
                              struct mwifiex_ds_encrypt_key *encrypt_key)
 {
        int status = 0;
-       struct mwifiex_adapter *adapter = priv->adapter;
 
        if (encrypt_key->is_wapi_key)
-               status = mwifiex_sec_ioctl_set_wapi_key(adapter, wait,
-                                                       encrypt_key);
+               status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key);
        else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104)
-               status = mwifiex_sec_ioctl_set_wpa_key(adapter, wait,
-                                                      encrypt_key);
+               status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key);
        else
-               status = mwifiex_sec_ioctl_set_wep_key(adapter, wait,
-                                                      encrypt_key);
+               status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key);
        return status;
 }
 
@@ -1806,95 +1243,31 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
        return 0;
 }
 
-/*
- * Sends IOCTL request to set Tx power. It can be set to either auto
- * or a fixed value.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm)
-{
-       struct mwifiex_power_cfg power_cfg;
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-       int ret = 0;
-
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
-       if (type == NL80211_TX_POWER_FIXED) {
-               power_cfg.is_power_auto = 0;
-               power_cfg.power_level = dbm;
-       } else {
-               power_cfg.is_power_auto = 1;
-       }
-       status = mwifiex_power_ioctl_set_power(priv, wait, &power_cfg);
-
-       ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);
-
-       kfree(wait);
-       return ret;
-}
-
-/*
- * Sends IOCTL request to get scan table.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int mwifiex_get_scan_table(struct mwifiex_private *priv, u8 wait_option,
-                          struct mwifiex_scan_resp *scan_resp)
-{
-       struct mwifiex_wait_queue *wait = NULL;
-       struct mwifiex_scan_resp scan;
-       int status = 0;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_GET,
-                                      NULL, &scan);
-
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
-       if (!status) {
-               if (scan_resp)
-                       memcpy(scan_resp, &scan,
-                              sizeof(struct mwifiex_scan_resp));
-       }
-
-       if (wait && (status != -EINPROGRESS))
-               kfree(wait);
-       return status;
-}
-
 /*
  * Sends IOCTL request to get signal information.
  *
  * This function allocates the IOCTL request buffer, fills it
  * with requisite parameters and calls the IOCTL handler.
  */
-int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option,
+int mwifiex_get_signal_info(struct mwifiex_private *priv,
                            struct mwifiex_ds_get_signal *signal)
 {
        struct mwifiex_ds_get_signal info;
-       struct mwifiex_wait_queue *wait = NULL;
        int status = 0;
 
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
+       memset(&info, 0, sizeof(struct mwifiex_ds_get_signal));
        info.selector = ALL_RSSI_INFO_MASK;
 
-       status = mwifiex_get_info_signal(priv, wait, &info);
+       /* Signal info can be obtained only if connected */
+       if (!priv->media_connected) {
+               dev_dbg(priv->adapter->dev,
+                       "info: Can not get signal in disconnected state\n");
+               return -1;
+       }
+
+       status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO,
+                                      HostCmd_ACT_GEN_GET, 0, signal);
 
-       status = mwifiex_request_ioctl(priv, wait, status, wait_option);
        if (!status) {
                if (signal)
                        memcpy(signal, &info,
@@ -1905,8 +1278,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option,
                        priv->w_stats.qual.noise = info.bcn_nf_avg;
        }
 
-       if (wait && (status != -EINPROGRESS))
-               kfree(wait);
        return status;
 }
 
@@ -1919,14 +1290,7 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option,
 int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
                        int key_len, u8 key_index, int disable)
 {
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ds_encrypt_key encrypt_key;
-       int status = 0;
-       int ret = 0;
-
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
 
        memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
        encrypt_key.key_len = key_len;
@@ -1938,41 +1302,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
                encrypt_key.key_disable = true;
        }
 
-       status = mwifiex_sec_ioctl_encrypt_key(priv, wait, &encrypt_key);
-
-       if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT))
-               ret = -EFAULT;
-
-       kfree(wait);
-       return ret;
-}
-
-/*
- * Sends IOCTL request to set power management parameters.
- *
- * This function allocates the IOCTL request buffer, fills it
- * with requisite parameters and calls the IOCTL handler.
- */
-int
-mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on)
-{
-       int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
-       u32 ps_mode;
-
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
-       ps_mode = power_on;
-       status = mwifiex_pm_ioctl_ps_mode(priv, wait, &ps_mode,
-                                         HostCmd_ACT_GEN_SET);
-
-       ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);
-
-       kfree(wait);
-       return ret;
+       return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key);
 }
 
 /*
@@ -1985,27 +1315,13 @@ int
 mwifiex_get_ver_ext(struct mwifiex_private *priv)
 {
        struct mwifiex_ver_ext ver_ext;
-       struct mwifiex_wait_queue *wait = NULL;
-       int status = 0;
-       int ret = 0;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
 
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
-
-       /* get fw version */
        memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext));
-       status = mwifiex_get_info_ver_ext(priv, wait, &ver_ext);
-
-       ret = mwifiex_request_ioctl(priv, wait, status, wait_option);
-
-       if (ret)
-               ret = -1;
+       if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT,
+                                   HostCmd_ACT_GEN_GET, 0, &ver_ext))
+               return -1;
 
-       kfree(wait);
-       return ret;
+       return 0;
 }
 
 /*
@@ -2019,21 +1335,12 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,
                       struct mwifiex_ds_get_stats *log)
 {
        int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ds_get_stats get_log;
-       u8 wait_option = MWIFIEX_IOCTL_WAIT;
-
-       /* Allocate wait buffer */
-       wait = mwifiex_alloc_fill_wait_queue(priv, wait_option);
-       if (!wait)
-               return -ENOMEM;
 
        memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats));
-       status = mwifiex_get_info_stats(priv, wait, &get_log);
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
+                                   HostCmd_ACT_GEN_GET, 0, &get_log);
 
-       /* Send IOCTL request to MWIFIEX */
-       ret = mwifiex_request_ioctl(priv, wait, status, wait_option);
        if (!ret) {
                if (log)
                        memcpy(log, &get_log, sizeof(struct
@@ -2043,7 +1350,6 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,
                priv->w_stats.discard.misc = get_log.ack_failure;
        }
 
-       kfree(wait);
        return ret;
 }
 
@@ -2061,11 +1367,9 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,
  *      - CAU
  */
 static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,
-                                       struct mwifiex_wait_queue *wait,
                                        struct mwifiex_ds_reg_rw *reg_rw,
                                        u16 action)
 {
-       int ret = 0;
        u16 cmd_no;
 
        switch (le32_to_cpu(reg_rw->type)) {
@@ -2088,13 +1392,8 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,
                return -1;
        }
 
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, cmd_no, action, 0, wait, reg_rw);
-
-       if (!ret)
-               ret = -EINPROGRESS;
+       return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw);
 
-       return ret;
 }
 
 /*
@@ -2107,25 +1406,13 @@ int
 mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
                  u32 reg_offset, u32 reg_value)
 {
-       int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ds_reg_rw reg_rw;
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
        reg_rw.type = cpu_to_le32(reg_type);
        reg_rw.offset = cpu_to_le32(reg_offset);
        reg_rw.value = cpu_to_le32(reg_value);
-       status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, &reg_rw,
-                                             HostCmd_ACT_GEN_SET);
-
-       ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);
 
-       kfree(wait);
-       return ret;
+       return mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_SET);
 }
 
 /*
@@ -2139,50 +1426,18 @@ mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
                 u32 reg_offset, u32 *value)
 {
        int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ds_reg_rw reg_rw;
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
        reg_rw.type = cpu_to_le32(reg_type);
        reg_rw.offset = cpu_to_le32(reg_offset);
-       status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, &reg_rw,
-                                             HostCmd_ACT_GEN_GET);
+       ret = mwifiex_reg_mem_ioctl_reg_rw(priv, &reg_rw, HostCmd_ACT_GEN_GET);
 
-       ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);
        if (ret)
                goto done;
 
        *value = le32_to_cpu(reg_rw.value);
 
 done:
-       kfree(wait);
-       return ret;
-}
-
-/*
- * IOCTL request handler to read EEPROM.
- *
- * This function prepares the correct firmware command and
- * issues it.
- */
-static int
-mwifiex_reg_mem_ioctl_read_eeprom(struct mwifiex_private *priv,
-                                 struct mwifiex_wait_queue *wait,
-                                 struct mwifiex_ds_read_eeprom *rd_eeprom)
-{
-       int ret = 0;
-
-       /* Send request to firmware */
-       ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
-                                 HostCmd_ACT_GEN_GET, 0, wait, rd_eeprom);
-
-       if (!ret)
-               ret = -EINPROGRESS;
-
        return ret;
 }
 
@@ -2197,25 +1452,17 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
                    u8 *value)
 {
        int ret = 0;
-       int status = 0;
-       struct mwifiex_wait_queue *wait = NULL;
        struct mwifiex_ds_read_eeprom rd_eeprom;
 
-       wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT);
-       if (!wait)
-               return -ENOMEM;
-
        rd_eeprom.offset = cpu_to_le16((u16) offset);
        rd_eeprom.byte_count = cpu_to_le16((u16) bytes);
-       status = mwifiex_reg_mem_ioctl_read_eeprom(priv, wait, &rd_eeprom);
 
-       ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);
-       if (ret)
-               goto done;
+       /* Send request to firmware */
+       ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
+                                   HostCmd_ACT_GEN_GET, 0, &rd_eeprom);
 
-       memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);
-done:
-       kfree(wait);
+       if (!ret)
+               memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);
        return ret;
 }
 
@@ -2344,7 +1591,6 @@ int
 mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
 {
        struct mwifiex_ds_misc_gen_ie gen_ie;
-       int status = 0;
 
        if (ie_len > IW_CUSTOM_MAX)
                return -EFAULT;
@@ -2352,8 +1598,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
        gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
        gen_ie.len = ie_len;
        memcpy(gen_ie.ie_data, ie, ie_len);
-       status = mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET);
-       if (status)
+       if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET))
                return -EFAULT;
 
        return 0;
index e8db6bd021c6f70360d382cc5bd2caafbf39cfb5..5d37ef160121c17315b657af47aac9278d31820c 100644 (file)
@@ -51,7 +51,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
        if (!skb->len) {
                dev_err(adapter->dev, "Tx: bad packet length: %d\n",
                       skb->len);
-               tx_info->status_code = MWIFIEX_ERROR_PKT_SIZE_INVALID;
+               tx_info->status_code = -1;
                return skb->data;
        }
 
@@ -180,15 +180,11 @@ mwifiex_check_last_packet_indication(struct mwifiex_private *priv)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        u8 ret = false;
-       u8 prop_ps = true;
 
        if (!adapter->sleep_period.period)
                return ret;
-       if (mwifiex_wmm_lists_empty(adapter)) {
-               if ((priv->curr_bss_params.wmm_uapsd_enabled &&
-                    priv->wmm_qosinfo) || prop_ps)
+       if (mwifiex_wmm_lists_empty(adapter))
                        ret = true;
-       }
 
        if (ret && !adapter->cmd_sent && !adapter->curr_cmd
            && !is_command_pending(adapter)) {
index f06923cb1c4bae4468866af3a446f0414f7102b4..ce772e078db8ab695f1dcc21d6f1b16b008d953e 100644 (file)
@@ -36,7 +36,6 @@
 int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
                             struct sk_buff *skb)
 {
-       int ret = 0;
        struct mwifiex_private *priv =
                mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
        struct rxpd *local_rx_pd;
@@ -50,9 +49,8 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
                priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 
        rx_info->bss_index = priv->bss_index;
-       ret = mwifiex_process_sta_rx_packet(adapter, skb);
 
-       return ret;
+       return mwifiex_process_sta_rx_packet(adapter, skb);
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
 
index 205022aa52f5ddd1a25180ce1a90cc4de2271231..7ab4fb279f8a61121e61c7920d0faad5b47eb044 100644 (file)
@@ -55,18 +55,12 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter)
 }
 
 /*
- * IOCTL request handler to send function init/shutdown command
+ * This function sends init/shutdown command
  * to firmware.
- *
- * This function prepares the correct firmware command and
- * issues it.
  */
-int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter,
-                                    struct mwifiex_wait_queue *wait,
-                                    u32 func_init_shutdown)
+int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
+                            u32 func_init_shutdown)
 {
-       struct mwifiex_private *priv = adapter->priv[wait->bss_index];
-       int ret;
        u16 cmd;
 
        if (func_init_shutdown == MWIFIEX_FUNC_INIT) {
@@ -74,19 +68,13 @@ int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter,
        } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {
                cmd = HostCmd_CMD_FUNC_SHUTDOWN;
        } else {
-               dev_err(adapter->dev, "unsupported parameter\n");
+               dev_err(priv->adapter->dev, "unsupported parameter\n");
                return -1;
        }
 
-       /* Send command to firmware */
-       ret = mwifiex_prepare_cmd(priv, cmd, HostCmd_ACT_GEN_SET,
-                                 0, wait, NULL);
-
-       if (!ret)
-               ret = -EINPROGRESS;
-
-       return ret;
+       return mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL);
 }
+EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw);
 
 /*
  * IOCTL request handler to set/get debug information.
@@ -222,31 +210,18 @@ int mwifiex_recv_complete(struct mwifiex_adapter *adapter,
  * corresponding waiting function. Otherwise, it processes the
  * IOCTL response and frees the response buffer.
  */
-int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter,
-                          struct mwifiex_wait_queue *wait_queue,
-                          int status)
+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter)
 {
-       enum mwifiex_error_code status_code =
-               (enum mwifiex_error_code) wait_queue->status;
-
-       atomic_dec(&adapter->ioctl_pending);
+       atomic_dec(&adapter->cmd_pending);
+       dev_dbg(adapter->dev, "cmd completed: status=%d\n",
+                                       adapter->cmd_wait_q.status);
 
-       dev_dbg(adapter->dev, "cmd: IOCTL completed: status=%d,"
-                       " status_code=%#x\n", status, status_code);
+       adapter->cmd_wait_q.condition = true;
 
-       if (wait_queue->enabled) {
-               *wait_queue->condition = true;
-               wait_queue->status = status;
-               if (status && (status_code == MWIFIEX_ERROR_CMD_TIMEOUT))
-                       dev_err(adapter->dev, "cmd timeout\n");
-               else
-                       wake_up_interruptible(wait_queue->wait);
-       } else {
-               if (status)
-                       dev_err(adapter->dev, "cmd failed: status_code=%#x\n",
-                              status_code);
-               kfree(wait_queue);
-       }
+       if (adapter->cmd_wait_q.status == -ETIMEDOUT)
+               dev_err(adapter->dev, "cmd timeout\n");
+       else
+               wake_up_interruptible(&adapter->cmd_wait_q.wait);
 
        return 0;
 }
index 1cfbc6bed6929eccdf6d819ba45aaaa2fe3c5ee9..c009370f309e8f9d74db7d782d0547ef68f4adba 100644 (file)
@@ -177,8 +177,7 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)
  * This function map ACs to TIDs.
  */
 static void
-mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv,
-                                u8 queue_priority[])
+mwifiex_wmm_queue_priorities_tid(u8 queue_priority[])
 {
        int i;
 
@@ -247,7 +246,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
                }
        }
 
-       mwifiex_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority);
+       mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority);
 }
 
 /*
@@ -416,7 +415,7 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
                priv = adapter->priv[j];
                if (priv) {
                        for (i = 0; i < MAX_NUM_TID; i++)
-                               if (!mwifiex_wmm_is_ra_list_empty(adapter,
+                               if (!mwifiex_wmm_is_ra_list_empty(
                                             &priv->wmm.tid_tbl_ptr[i].ra_list))
                                        return false;
                }
@@ -974,7 +973,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
        struct sk_buff *skb, *skb_next;
        struct mwifiex_tx_param tx_param;
        struct mwifiex_adapter *adapter = priv->adapter;
-       int status = 0;
        struct mwifiex_txinfo *tx_info;
 
        if (skb_queue_empty(&ptr->skb_head)) {
@@ -1001,9 +999,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
        tx_param.next_pkt_len = ((skb_next) ? skb_next->len +
                                sizeof(struct txpd) : 0);
 
-       status = mwifiex_process_tx(priv, skb, &tx_param);
-
-       if (status == -EBUSY) {
+       if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
                /* Queue the packet back at the head */
                spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
 
@@ -1161,7 +1157,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
        if (!ptr)
                return -1;
 
-       tid = mwifiex_get_tid(priv->adapter, ptr);
+       tid = mwifiex_get_tid(ptr);
 
        dev_dbg(adapter->dev, "data: tid=%d\n", tid);
 
@@ -1186,14 +1182,14 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
                /* ra_list_spinlock has been freed in
                   mwifiex_send_single_packet() */
        } else {
-               if (mwifiex_is_ampdu_allowed(priv, ptr, tid)) {
-                       if (mwifiex_is_ba_stream_avail(priv)) {
+               if (mwifiex_is_ampdu_allowed(priv, tid)) {
+                       if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
                                mwifiex_11n_create_tx_ba_stream_tbl(priv,
                                                ptr->ra, tid,
                                                BA_STREAM_SETUP_INPROGRESS);
                                mwifiex_send_addba(priv, tid, ptr->ra);
                        } else if (mwifiex_find_stream_to_delete
-                                  (priv, ptr, tid, &tid_del, ra)) {
+                                  (priv, tid, &tid_del, ra)) {
                                mwifiex_11n_create_tx_ba_stream_tbl(priv,
                                                ptr->ra, tid,
                                                BA_STREAM_SETUP_INPROGRESS);
@@ -1202,7 +1198,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
                }
 /* Minimum number of AMSDU */
 #define MIN_NUM_AMSDU 2
-               if (mwifiex_is_amsdu_allowed(priv, ptr, tid) &&
+               if (mwifiex_is_amsdu_allowed(priv, tid) &&
                    (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=
                     MIN_NUM_AMSDU))
                        mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
@@ -1232,6 +1228,4 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter)
                if (mwifiex_dequeue_tx_packet(adapter))
                        break;
        } while (true);
-
-       return;
 }
index 241f1b0b77f9f87a06107533fac7d985a4701a23..fcea1f68792f8c06e053352a69a17164194d0987 100644 (file)
@@ -35,8 +35,7 @@ enum ieee_types_wmm_ecw_bitmasks {
  * This function retrieves the TID of the given RA list.
  */
 static inline int
-mwifiex_get_tid(struct mwifiex_adapter *adapter,
-               struct mwifiex_ra_list_tbl *ptr)
+mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)
 {
        struct sk_buff *skb;
 
@@ -52,7 +51,7 @@ mwifiex_get_tid(struct mwifiex_adapter *adapter,
  * This function gets the length of a list.
  */
 static inline int
-mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head)
+mwifiex_wmm_list_len(struct list_head *head)
 {
        struct list_head *pos;
        int count = 0;
@@ -67,8 +66,7 @@ mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head)
  * This function checks if a RA list is empty or not.
  */
 static inline u8
-mwifiex_wmm_is_ra_list_empty(struct mwifiex_adapter *adapter,
-                            struct list_head *ra_list_hhead)
+mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
 {
        struct mwifiex_ra_list_tbl *ra_list;
        int is_list_empty;
index 8913180a7bd37c4cbc87191b7e00c56f48c464e6..28ebaec80be6b5cc439fe5208ba007fa1c0a3496 100644 (file)
@@ -289,10 +289,17 @@ struct mwl8k_vif {
 #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
 #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
 
+struct tx_traffic_info {
+       u32 start_time;
+       u32 pkts;
+};
+
+#define MWL8K_MAX_TID 8
 struct mwl8k_sta {
        /* Index into station database. Returned by UPDATE_STADB.  */
        u8 peer_id;
        u8 is_ampdu_allowed;
+       struct tx_traffic_info tx_stats[MWL8K_MAX_TID];
 };
 #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
 
@@ -701,7 +708,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
                               "helper image\n", pci_name(priv->pdev));
                        return rc;
                }
-               msleep(5);
+               msleep(20);
 
                rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
        } else {
@@ -823,8 +830,8 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
        /*
         * Make sure the packet header is in the DMA header format (4-address
         * without QoS), the necessary crypto padding between the header and the
-        * payload has already been provided by mac80211, but it doesn't add tail
-        * padding when HW crypto is enabled.
+        * payload has already been provided by mac80211, but it doesn't add
+        * tail padding when HW crypto is enabled.
         *
         * We have the following trailer padding requirements:
         * - WEP: 4 trailer bytes (ICV)
@@ -1487,9 +1494,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 
                if (timeout) {
                        WARN_ON(priv->pending_tx_pkts);
-                       if (retry) {
+                       if (retry)
                                wiphy_notice(hw->wiphy, "tx rings drained\n");
-                       }
                        break;
                }
 
@@ -1649,8 +1655,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
                /* Rate control is happening in the firmware.
                 * Ensure no tx rate is being reported.
                 */
-                info->status.rates[0].idx = -1;
-                info->status.rates[0].count = 1;
+               info->status.rates[0].idx = -1;
+               info->status.rates[0].count = 1;
 
                if (MWL8K_TXD_SUCCESS(status))
                        info->flags |= IEEE80211_TX_STAT_ACK;
@@ -1688,7 +1694,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
 }
 
 /* caller must hold priv->stream_lock when calling the stream functions */
-struct mwl8k_ampdu_stream *
+static struct mwl8k_ampdu_stream *
 mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)
 {
        struct mwl8k_ampdu_stream *stream;
@@ -1755,6 +1761,41 @@ mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)
        return NULL;
 }
 
+#define MWL8K_AMPDU_PACKET_THRESHOLD 64
+static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid)
+{
+       struct mwl8k_sta *sta_info = MWL8K_STA(sta);
+       struct tx_traffic_info *tx_stats;
+
+       BUG_ON(tid >= MWL8K_MAX_TID);
+       tx_stats = &sta_info->tx_stats[tid];
+
+       return sta_info->is_ampdu_allowed &&
+               tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD;
+}
+
+static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid)
+{
+       struct mwl8k_sta *sta_info = MWL8K_STA(sta);
+       struct tx_traffic_info *tx_stats;
+
+       BUG_ON(tid >= MWL8K_MAX_TID);
+       tx_stats = &sta_info->tx_stats[tid];
+
+       if (tx_stats->start_time == 0)
+               tx_stats->start_time = jiffies;
+
+       /* reset the packet count after each second elapses.  If the number of
+        * packets ever exceeds the ampdu_min_traffic threshold, we will allow
+        * an ampdu stream to be started.
+        */
+       if (jiffies - tx_stats->start_time > HZ) {
+               tx_stats->pkts = 0;
+               tx_stats->start_time = 0;
+       } else
+               tx_stats->pkts++;
+}
+
 static void
 mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 {
@@ -1841,6 +1882,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
            skb->protocol != cpu_to_be16(ETH_P_PAE) &&
            sta->ht_cap.ht_supported && priv->ap_fw) {
                tid = qos & 0xf;
+               mwl8k_tx_count_packet(sta, tid);
                spin_lock(&priv->stream_lock);
                stream = mwl8k_lookup_stream(hw, sta->addr, tid);
                if (stream != NULL) {
@@ -1881,7 +1923,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
                         * prevents sequence number mismatch at the recepient
                         * as described above.
                         */
-                       if (MWL8K_STA(sta)->is_ampdu_allowed) {
+                       if (mwl8k_ampdu_allowed(sta, tid)) {
                                stream = mwl8k_add_stream(hw, sta, tid);
                                if (stream != NULL)
                                        start_ba_session = true;
@@ -2657,7 +2699,7 @@ struct mwl8k_cmd_tx_power {
        __le16 bw;
        __le16 sub_ch;
        __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
-} __attribute__((packed));
+} __packed;
 
 static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
                                     struct ieee80211_conf *conf,
@@ -3520,13 +3562,13 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
 #define BASTREAM_FLAG_DIRECTION_UPSTREAM       0x00
 #define BASTREAM_FLAG_IMMEDIATE_TYPE           0x01
 
-enum {
+enum ba_stream_action_type {
        MWL8K_BA_CREATE,
        MWL8K_BA_UPDATE,
        MWL8K_BA_DESTROY,
        MWL8K_BA_FLUSH,
        MWL8K_BA_CHECK,
-} ba_stream_action_type;
+};
 
 
 struct mwl8k_create_ba_stream {
@@ -3780,7 +3822,7 @@ struct mwl8k_cmd_update_encryption {
        __u8 mac_addr[6];
        __u8 encr_type;
 
-} __attribute__((packed));
+} __packed;
 
 struct mwl8k_cmd_set_key {
        struct mwl8k_cmd_pkt header;
@@ -3800,7 +3842,7 @@ struct mwl8k_cmd_set_key {
        __le16 tkip_tsc_low;
        __le32 tkip_tsc_high;
        __u8 mac_addr[6];
-} __attribute__((packed));
+} __packed;
 
 enum {
        MWL8K_ENCR_ENABLE,
@@ -4285,6 +4327,8 @@ static int mwl8k_start(struct ieee80211_hw *hw)
 
        /* Enable interrupts */
        iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+       iowrite32(MWL8K_A2H_EVENTS,
+                 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
 
        rc = mwl8k_fw_lock(hw);
        if (!rc) {
@@ -4502,7 +4546,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                           struct ieee80211_bss_conf *info, u32 changed)
 {
        struct mwl8k_priv *priv = hw->priv;
-       u32 ap_legacy_rates;
+       u32 ap_legacy_rates = 0;
        u8 ap_mcs_rates[16];
        int rc;
 
@@ -5283,7 +5327,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)
        iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY|
                  MWL8K_A2H_INT_BA_WATCHDOG,
                  priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
-       iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
+       iowrite32(MWL8K_A2H_INT_OPC_DONE,
+                 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
 
        rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
                         IRQF_SHARED, MWL8K_NAME, hw);
index f630552427b7ce70c36612402b5ff040c346cae0..c45773108283f3761a61ea1b666d3489b442462c 100644 (file)
@@ -59,7 +59,6 @@ config RT2800PCI
        select RT2800_LIB
        select RT2X00_LIB_PCI if PCI
        select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
-       select RT2X00_LIB_HT
        select RT2X00_LIB_FIRMWARE
        select RT2X00_LIB_CRYPTO
        select CRC_CCITT
@@ -74,17 +73,13 @@ config RT2800PCI
 if RT2800PCI
 
 config RT2800PCI_RT33XX
-       bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       default n
+       bool "rt2800pci - Include support for rt33xx devices"
+       default y
        ---help---
          This adds support for rt33xx wireless chipset family to the
          rt2800pci driver.
          Supported chips: RT3390
 
-         Support for these devices is non-functional at the moment and is
-         intended for testers and developers.
-
 config RT2800PCI_RT35XX
        bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
@@ -100,15 +95,12 @@ config RT2800PCI_RT35XX
 config RT2800PCI_RT53XX
        bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       default n
+       default y
        ---help---
          This adds support for rt53xx wireless chipset family to the
          rt2800pci driver.
          Supported chips: RT5390
 
-         Support for these devices is non-functional at the moment and is
-         intended for testers and developers.
-
 endif
 
 config RT2500USB
@@ -140,7 +132,6 @@ config RT2800USB
        depends on USB
        select RT2800_LIB
        select RT2X00_LIB_USB
-       select RT2X00_LIB_HT
        select RT2X00_LIB_FIRMWARE
        select RT2X00_LIB_CRYPTO
        select CRC_CCITT
@@ -153,17 +144,13 @@ config RT2800USB
 if RT2800USB
 
 config RT2800USB_RT33XX
-       bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       default n
+       bool "rt2800usb - Include support for rt33xx devices"
+       default y
        ---help---
          This adds support for rt33xx wireless chipset family to the
          rt2800usb driver.
          Supported chips: RT3370
 
-         Support for these devices is non-functional at the moment and is
-         intended for testers and developers.
-
 config RT2800USB_RT35XX
        bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
@@ -207,9 +194,6 @@ config RT2X00_LIB_USB
 config RT2X00_LIB
        tristate
 
-config RT2X00_LIB_HT
-       boolean
-
 config RT2X00_LIB_FIRMWARE
        boolean
        select FW_LOADER
index 971339858297d1de6b5c4ce732cab99f3ac6e121..349d5b8284a4f6c64faaa58d6b750864c3a8252e 100644 (file)
@@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)  += rt2x00debug.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)  += rt2x00crypto.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)        += rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)    += rt2x00leds.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_HT)      += rt2x00ht.o
 
 obj-$(CONFIG_RT2X00_LIB)               += rt2x00lib.o
 obj-$(CONFIG_RT2X00_LIB_PCI)           += rt2x00pci.o
index 137a24e520daf52d0cb98aa680e71bef8017ae64..937f9e8bf05f51ba38fda4d7e5517f292251960f 100644 (file)
@@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
        }
 }
 
-static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00_field32 irq_field)
+static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                             struct rt2x00_field32 irq_field)
 {
        u32 reg;
 
@@ -1536,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Detect if this device has an hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Check if the BBP tuning should be enabled.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
-               __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
        return 0;
 }
@@ -1640,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * This device requires the atim queue and DMA-mapped skbs.
         */
-       __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -1720,6 +1720,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
        .tx_last_beacon         = rt2400pci_tx_last_beacon,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
@@ -1740,6 +1743,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
        .start_queue            = rt2400pci_start_queue,
        .kick_queue             = rt2400pci_kick_queue,
        .stop_queue             = rt2400pci_stop_queue,
+       .flush_queue            = rt2x00pci_flush_queue,
        .write_tx_desc          = rt2400pci_write_tx_desc,
        .write_beacon           = rt2400pci_write_beacon,
        .fill_rxdone            = rt2400pci_fill_rxdone,
@@ -1801,10 +1805,11 @@ static const struct rt2x00_ops rt2400pci_ops = {
  * RT2400pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
-       { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0101) },
        { 0, }
 };
 
+
 MODULE_AUTHOR(DRV_PROJECT);
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
@@ -1812,10 +1817,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
 MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2400pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
 static struct pci_driver rt2400pci_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt2400pci_device_table,
-       .probe          = rt2x00pci_probe,
+       .probe          = rt2400pci_probe,
        .remove         = __devexit_p(rt2x00pci_remove),
        .suspend        = rt2x00pci_suspend,
        .resume         = rt2x00pci_resume,
index 198fc0a0d77c569defb9fb88f552f80af9522253..d27d7b8ba3b648f88331ff6e4be7b0c8eeadf2dd 100644 (file)
@@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
        }
 }
 
-static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00_field32 irq_field)
+static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                             struct rt2x00_field32 irq_field)
 {
        u32 reg;
 
@@ -1687,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Detect if this device has an hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Check if the BBP tuning should be enabled.
         */
        rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
        if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
-               __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
        /*
         * Read the RSSI <-> dBm offset information.
@@ -1958,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * This device requires the atim queue and DMA-mapped skbs.
         */
-       __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -2013,6 +2013,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
        .tx_last_beacon         = rt2500pci_tx_last_beacon,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
@@ -2033,6 +2036,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
        .start_queue            = rt2500pci_start_queue,
        .kick_queue             = rt2500pci_kick_queue,
        .stop_queue             = rt2500pci_stop_queue,
+       .flush_queue            = rt2x00pci_flush_queue,
        .write_tx_desc          = rt2500pci_write_tx_desc,
        .write_beacon           = rt2500pci_write_beacon,
        .fill_rxdone            = rt2500pci_fill_rxdone,
@@ -2094,7 +2098,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
  * RT2500pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
-       { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0201) },
        { 0, }
 };
 
@@ -2105,10 +2109,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
 MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
 static struct pci_driver rt2500pci_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt2500pci_device_table,
-       .probe          = rt2x00pci_probe,
+       .probe          = rt2500pci_probe,
        .remove         = __devexit_p(rt2x00pci_remove),
        .suspend        = rt2x00pci_suspend,
        .resume         = rt2x00pci_resume,
index eac788160f5567cc37a51d7f65d652fdec611238..b21f81231a09df260f35d81d85317cb90b6f9d83 100644 (file)
@@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Detect if this device has an hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Read the RSSI <-> dBm offset information.
@@ -1790,13 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * This device requires the atim queue
         */
-       __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
        if (!modparam_nohwcrypt) {
-               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-               __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+               __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
        }
-       __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -1823,6 +1823,9 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .conf_tx                = rt2x00mac_conf_tx,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1904,54 +1907,54 @@ static const struct rt2x00_ops rt2500usb_ops = {
  */
 static struct usb_device_id rt2500usb_device_table[] = {
        /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0b05, 0x1706) },
+       { USB_DEVICE(0x0b05, 0x1707) },
        /* Belkin */
-       { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x050d, 0x7050) },
+       { USB_DEVICE(0x050d, 0x7051) },
        /* Cisco Systems */
-       { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x13b1, 0x000d) },
+       { USB_DEVICE(0x13b1, 0x0011) },
+       { USB_DEVICE(0x13b1, 0x001a) },
        /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x14b2, 0x3c02) },
        /* D-LINK */
-       { USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x2001, 0x3c00) },
        /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x1044, 0x8001) },
+       { USB_DEVICE(0x1044, 0x8007) },
        /* Hercules */
-       { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x06f8, 0xe000) },
        /* Melco */
-       { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0411, 0x005e) },
+       { USB_DEVICE(0x0411, 0x0066) },
+       { USB_DEVICE(0x0411, 0x0067) },
+       { USB_DEVICE(0x0411, 0x008b) },
+       { USB_DEVICE(0x0411, 0x0097) },
        /* MSI */
-       { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0db0, 0x6861) },
+       { USB_DEVICE(0x0db0, 0x6865) },
+       { USB_DEVICE(0x0db0, 0x6869) },
        /* Ralink */
-       { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) },
-       { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x148f, 0x1706) },
+       { USB_DEVICE(0x148f, 0x2570) },
+       { USB_DEVICE(0x148f, 0x9020) },
        /* Sagem */
-       { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x079b, 0x004b) },
        /* Siemens */
-       { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0681, 0x3c06) },
        /* SMC */
-       { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0707, 0xee13) },
        /* Spairon */
-       { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x114b, 0x0110) },
        /* SURECOM */
-       { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0769, 0x11f3) },
        /* Trust */
-       { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0eb0, 0x9020) },
        /* VTech */
-       { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x0f88, 0x3012) },
        /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) },
+       { USB_DEVICE(0x5a57, 0x0260) },
        { 0, }
 };
 
@@ -1962,10 +1965,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
 MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500usb_probe(struct usb_interface *usb_intf,
+                          const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
 static struct usb_driver rt2500usb_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt2500usb_device_table,
-       .probe          = rt2x00usb_probe,
+       .probe          = rt2500usb_probe,
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
index 6331c61957a36b01d8476fe937d85f25a061b585..5cd096e2ae36a606f82220dde23d141812c28756 100644 (file)
@@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
        struct queue_entry *entry;
        u32 reg;
-       u8 pid;
-       int i;
+       u8 qid;
 
-       /*
-        * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
-        * at most X times and also stop processing once the TX_STA_FIFO_VALID
-        * flag is not set anymore.
-        *
-        * The legacy drivers use X=TX_RING_SIZE but state in a comment
-        * that the TX_STA_FIFO stack has a size of 16. We stick to our
-        * tx ring size for now.
-        */
-       for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-               rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
-               if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
-                       break;
+       while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
 
-               /*
-                * Skip this entry when it contains an invalid
-                * queue identication number.
+               /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+                * qid is guaranteed to be one of the TX QIDs
                 */
-               pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
-               if (pid >= QID_RX)
-                       continue;
-
-               queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
-               if (unlikely(!queue))
+               qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+               queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+               if (unlikely(!queue)) {
+                       WARNING(rt2x00dev, "Got TX status for an unavailable "
+                                          "queue %u, dropping\n", qid);
                        continue;
+               }
 
                /*
                 * Inside each queue, we process each entry in a chronological
@@ -949,25 +935,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
        unsigned int ledmode =
                rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
                                   EEPROM_FREQ_LED_MODE);
+       u32 reg;
 
-       if (led->type == LED_TYPE_RADIO) {
-               rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-                                     enabled ? 0x20 : 0);
-       } else if (led->type == LED_TYPE_ASSOC) {
-               rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-                                     enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
-       } else if (led->type == LED_TYPE_QUALITY) {
-               /*
-                * The brightness is divided into 6 levels (0 - 5),
-                * The specs tell us the following levels:
-                *      0, 1 ,3, 7, 15, 31
-                * to determine the level in a simple way we can simply
-                * work with bitshifting:
-                *      (1 << level) - 1
-                */
-               rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-                                     (1 << brightness / (LED_FULL / 6)) - 1,
-                                     polarity);
+       /* Check for SoC (SOC devices don't support MCU requests) */
+       if (rt2x00_is_soc(led->rt2x00dev)) {
+               rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+
+               /* Set LED Polarity */
+               rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
+
+               /* Set LED Mode */
+               if (led->type == LED_TYPE_RADIO) {
+                       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
+                                          enabled ? 3 : 0);
+               } else if (led->type == LED_TYPE_ASSOC) {
+                       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
+                                          enabled ? 3 : 0);
+               } else if (led->type == LED_TYPE_QUALITY) {
+                       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
+                                          enabled ? 3 : 0);
+               }
+
+               rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+       } else {
+               if (led->type == LED_TYPE_RADIO) {
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+                                             enabled ? 0x20 : 0);
+               } else if (led->type == LED_TYPE_ASSOC) {
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+                                             enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+               } else if (led->type == LED_TYPE_QUALITY) {
+                       /*
+                        * The brightness is divided into 6 levels (0 - 5),
+                        * The specs tell us the following levels:
+                        *      0, 1 ,3, 7, 15, 31
+                        * to determine the level in a simple way we can simply
+                        * work with bitshifting:
+                        *      (1 << level) - 1
+                        */
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+                                             (1 << brightness / (LED_FULL / 6)) - 1,
+                                             polarity);
+               }
        }
 }
 
@@ -1221,6 +1231,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
                rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
                rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+               if (conf->sync == TSF_SYNC_AP_NONE) {
+                       /*
+                        * Tune beacon queue transmit parameters for AP mode
+                        */
+                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
+                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+               } else {
+                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
+                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+               }
        }
 
        if (flags & CONFIG_UPDATE_MAC) {
@@ -1739,8 +1768,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 
        if (rf->channel <= 14) {
                if (!rt2x00_rt(rt2x00dev, RT5390)) {
-                       if (test_bit(CONFIG_EXTERNAL_LNA_BG,
-                                    &rt2x00dev->flags)) {
+                       if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+                                    &rt2x00dev->cap_flags)) {
                                rt2800_bbp_write(rt2x00dev, 82, 0x62);
                                rt2800_bbp_write(rt2x00dev, 75, 0x46);
                        } else {
@@ -1751,7 +1780,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        } else {
                rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
-               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
                        rt2800_bbp_write(rt2x00dev, 75, 0x46);
                else
                        rt2800_bbp_write(rt2x00dev, 75, 0x50);
@@ -1984,7 +2013,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
        if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
                return txpower;
 
-       if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+       if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
                /*
                 * Check if eirp txpower exceed txpower_limit.
                 * We use OFDM 6M as criterion and its eirp txpower
@@ -2384,7 +2413,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
        } else if (rt2800_is_305x_soc(rt2x00dev)) {
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
        } else if (rt2x00_rt(rt2x00dev, RT5390)) {
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
                rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -3285,8 +3314,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
                    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
                    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-                       if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
-                                     &rt2x00dev->flags))
+                       if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+                                     &rt2x00dev->cap_flags))
                                rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
                }
                rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
@@ -3709,15 +3738,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
-               __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
-               __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
        /*
         * Detect if this device has an hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Store led settings, for correct led behaviour.
@@ -3737,7 +3766,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 
        if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
                                        EIRP_MAX_TX_POWER_LIMIT)
-               __set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
 
        return 0;
 }
index adc3534254df2fff7bcba628e8bbb5d9e623f075..08d3947fcb26b7e4e75ee6f9228adc77c3c56557 100644 (file)
@@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
                return;
 
        for (i = 0; i < 200; i++) {
-               rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+               rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
 
                if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
                    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
        if (i == 200)
                ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
 
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+       rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+       rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 }
 
 #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
@@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
        struct rt2x00_dev *rt2x00dev = eeprom->data;
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
        eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
        eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
        rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
                           !!eeprom->reg_chip_select);
 
-       rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+       rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
 }
 
 static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
        struct eeprom_93cx6 eeprom;
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+       rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
        eeprom.data = rt2x00dev;
        eeprom.register_read = rt2800pci_eepromregister_read;
@@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-               rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
                /*
@@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue)
                tasklet_enable(&rt2x00dev->tbtt_tasklet);
                tasklet_enable(&rt2x00dev->pretbtt_tasklet);
 
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-               rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
                rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
-               rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+               rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
                break;
        default:
                break;
@@ -233,11 +233,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
        case QID_AC_BE:
        case QID_AC_BK:
                entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx);
+               rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+                                        entry->entry_idx);
                break;
        case QID_MGMT:
                entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx);
+               rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
+                                        entry->entry_idx);
                break;
        default:
                break;
@@ -251,20 +253,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-               rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-               rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
                rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
-               rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+               rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
 
                /*
                 * Wait for tbtt tasklets to finish.
@@ -295,7 +297,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
         */
        reg = 0;
        rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+       rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
 
        /*
         * Write firmware to device.
@@ -303,11 +305,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
        rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
                                   data, len);
 
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+       rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+       rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
 
-       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+       rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
        return 0;
 }
@@ -351,7 +353,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
                 * Set RX IDX in register to inform hardware that we have
                 * handled this entry and it is available for reuse again.
                 */
-               rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+               rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
                                      entry->entry_idx);
        } else {
                rt2x00_desc_read(entry_priv->desc, 1, &word);
@@ -369,45 +371,51 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
         * Initialize registers.
         */
        entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
-       rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
-       rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0);
-       rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
+       rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
+                                rt2x00dev->tx[0].limit);
+       rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
 
        entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
-       rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
-       rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0);
-       rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
+       rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
+                                rt2x00dev->tx[1].limit);
+       rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
 
        entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-       rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
-       rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
-       rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0);
-       rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
+       rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
+                                rt2x00dev->tx[2].limit);
+       rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
 
        entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-       rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
-       rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
-       rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0);
-       rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
+       rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
+                                rt2x00dev->tx[3].limit);
+       rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+       rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
 
        entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
-       rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
-       rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
-       rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0);
+       rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
+       rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
+                                rt2x00dev->rx[0].limit);
+       rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
+                                rt2x00dev->rx[0].limit - 1);
+       rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
 
        /*
         * Enable global DMA configuration
         */
-       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
        rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+       rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
-       rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+       rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
 
        return 0;
 }
@@ -427,8 +435,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
         * should clear the register to assure a clean state.
         */
        if (state == STATE_RADIO_IRQ_ON) {
-               rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-               rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+               rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
                /*
                 * Enable tasklets. The beacon related tasklets are
@@ -440,7 +448,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        }
 
        spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-       rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
@@ -459,7 +467,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
        rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
-       rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 
        if (state == STATE_RADIO_IRQ_OFF) {
@@ -480,7 +488,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
        /*
         * Reset DMA indexes
         */
-       rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+       rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -488,26 +496,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
        rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-       rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+       rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+       rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+       rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
        if (rt2x00_rt(rt2x00dev, RT5390)) {
-               rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+               rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
                rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
                rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
-               rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+               rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
        }
 
-       rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+       rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+       rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+       rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
        return 0;
 }
@@ -525,8 +533,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
        if (rt2x00_is_soc(rt2x00dev)) {
                rt2800_disable_radio(rt2x00dev);
-               rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-               rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+               rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+               rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
        }
 }
 
@@ -537,8 +545,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
                rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
                rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
        } else if (state == STATE_SLEEP) {
-               rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
-               rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+               rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+                                        0xffffffff);
+               rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
+                                        0xffffffff);
                rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
        }
 
@@ -768,8 +778,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
        return !max_tx_done;
 }
 
-static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00_field32 irq_field)
+static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                             struct rt2x00_field32 irq_field)
 {
        u32 reg;
 
@@ -778,9 +788,9 @@ static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
         * access needs locking.
         */
        spin_lock_irq(&rt2x00dev->irqmask_lock);
-       rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
        rt2x00_set_field32(&reg, irq_field, 1);
-       rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock_irq(&rt2x00dev->irqmask_lock);
 }
 
@@ -851,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
         * need to lock the kfifo.
         */
        for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-               rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+               rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
 
                if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
                        break;
@@ -873,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
        u32 reg, mask;
 
        /* Read status and ACK all interrupts */
-       rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-       rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+       rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
        if (!reg)
                return IRQ_NONE;
@@ -914,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
         * the tasklet will reenable the appropriate interrupts.
         */
        spin_lock(&rt2x00dev->irqmask_lock);
-       rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
        reg &= mask;
-       rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
        spin_unlock(&rt2x00dev->irqmask_lock);
 
        return IRQ_HANDLED;
@@ -966,28 +976,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
         * This device has multiple filters for control frames
         * and has a separate filter for PS Poll frames.
         */
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
        /*
         * This device has a pre tbtt interrupt and thus fetches
         * a new beacon directly prior to transmission.
         */
-       __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
+       __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
 
        /*
         * This device requires firmware.
         */
        if (!rt2x00_is_soc(rt2x00dev))
-               __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
+               __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
        if (!modparam_nohwcrypt)
-               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -1018,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
        .ampdu_action           = rt2800_ampdu_action,
        .flush                  = rt2x00mac_flush,
        .get_survey             = rt2800_get_survey,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1057,6 +1068,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
        .start_queue            = rt2800pci_start_queue,
        .kick_queue             = rt2800pci_kick_queue,
        .stop_queue             = rt2800pci_stop_queue,
+       .flush_queue            = rt2x00pci_flush_queue,
        .write_tx_desc          = rt2800pci_write_tx_desc,
        .write_tx_data          = rt2800_write_tx_data,
        .write_beacon           = rt2800_write_beacon,
@@ -1116,36 +1128,36 @@ static const struct rt2x00_ops rt2800pci_ops = {
  */
 #ifdef CONFIG_PCI
 static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
-       { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0601) },
+       { PCI_DEVICE(0x1814, 0x0681) },
+       { PCI_DEVICE(0x1814, 0x0701) },
+       { PCI_DEVICE(0x1814, 0x0781) },
+       { PCI_DEVICE(0x1814, 0x3090) },
+       { PCI_DEVICE(0x1814, 0x3091) },
+       { PCI_DEVICE(0x1814, 0x3092) },
+       { PCI_DEVICE(0x1432, 0x7708) },
+       { PCI_DEVICE(0x1432, 0x7727) },
+       { PCI_DEVICE(0x1432, 0x7728) },
+       { PCI_DEVICE(0x1432, 0x7738) },
+       { PCI_DEVICE(0x1432, 0x7748) },
+       { PCI_DEVICE(0x1432, 0x7758) },
+       { PCI_DEVICE(0x1432, 0x7768) },
+       { PCI_DEVICE(0x1462, 0x891a) },
+       { PCI_DEVICE(0x1a3b, 0x1059) },
 #ifdef CONFIG_RT2800PCI_RT33XX
-       { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+       { PCI_DEVICE(0x1814, 0x3390) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT35XX
-       { PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
-       { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
+       { PCI_DEVICE(0x1432, 0x7711) },
+       { PCI_DEVICE(0x1432, 0x7722) },
+       { PCI_DEVICE(0x1814, 0x3060) },
+       { PCI_DEVICE(0x1814, 0x3062) },
+       { PCI_DEVICE(0x1814, 0x3562) },
+       { PCI_DEVICE(0x1814, 0x3592) },
+       { PCI_DEVICE(0x1814, 0x3593) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT53XX
-       { PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+       { PCI_DEVICE(0x1814, 0x5390) },
 #endif
        { 0, }
 };
@@ -1181,10 +1193,16 @@ static struct platform_driver rt2800soc_driver = {
 #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
 
 #ifdef CONFIG_PCI
+static int rt2800pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
+}
+
 static struct pci_driver rt2800pci_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt2800pci_device_table,
-       .probe          = rt2x00pci_probe,
+       .probe          = rt2800pci_probe,
        .remove         = __devexit_p(rt2x00pci_remove),
        .suspend        = rt2x00pci_suspend,
        .resume         = rt2x00pci_resume,
index 6ba31a0e8f78dab5e4dd21c0611a0ade26e14565..0d4e8fa3e1f8e065b15752093d106415e7427407 100644 (file)
@@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-               rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
                break;
        default:
                break;
@@ -82,22 +82,78 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 
        switch (queue->qid) {
        case QID_RX:
-               rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
                rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-               rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
                break;
        case QID_BEACON:
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
                rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
                break;
        default:
                break;
        }
 }
 
+/*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+                   rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+                       return true;
+       }
+       return false;
+}
+
+static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+                                                int urb_status, u32 tx_status)
+{
+       if (urb_status) {
+               WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
+               return;
+       }
+
+       /* try to read all TX_STA_FIFO entries before scheduling txdone_work */
+       if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
+               if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
+                       WARNING(rt2x00dev, "TX status FIFO overrun, "
+                               "drop tx status report.\n");
+                       queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+               } else
+                       rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+                                                     rt2800usb_tx_sta_fifo_read_completed);
+       } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+       } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+               mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
+       }
+}
+
+static void rt2800usb_tx_dma_done(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+                                     rt2800usb_tx_sta_fifo_read_completed);
+}
+
+static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+       rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+                                     rt2800usb_tx_sta_fifo_read_completed);
+}
+
 /*
  * Firmware functions
  */
@@ -129,11 +185,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
        /*
         * Write firmware to device.
         */
-       rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-                                  data + offset, length);
+       rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+                                     data + offset, length);
 
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 
        /*
         * Send firmware request to device to load firmware,
@@ -148,7 +204,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
        }
 
        msleep(10);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
        return 0;
 }
@@ -166,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
        if (rt2800_wait_csr_ready(rt2x00dev))
                return -EBUSY;
 
-       rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-       rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+       rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+       rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 
-       rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+       rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
        rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-       rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
 
        rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
                                    USB_MODE_RESET, REGISTER_TIMEOUT);
 
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
        return 0;
 }
@@ -193,7 +249,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
        if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
                return -EIO;
 
-       rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+       rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
        rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
        rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
        rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
@@ -206,7 +262,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
                            / 1024) - 3);
        rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
        rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
-       rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
+       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
 
        return rt2800_enable_radio(rt2x00dev);
 }
@@ -282,12 +338,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
        unsigned int i;
        u32 reg;
 
-       rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
        if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
                WARNING(rt2x00dev, "TX HW queue 0 timed out,"
                        " invoke forced kick\n");
 
-               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
 
                for (i = 0; i < 10; i++) {
                        udelay(10);
@@ -295,15 +351,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
                                break;
                }
 
-               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
        }
 
-       rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
        if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
                WARNING(rt2x00dev, "TX HW queue 1 timed out,"
                        " invoke forced kick\n");
 
-               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
 
                for (i = 0; i < 10; i++) {
                        udelay(10);
@@ -311,7 +367,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
                                break;
                }
 
-               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
        }
 
        rt2x00usb_watchdog(rt2x00dev);
@@ -420,13 +476,24 @@ static void rt2800usb_work_txdone(struct work_struct *work)
                while (!rt2x00queue_empty(queue)) {
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                           !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                               break;
+                       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+                               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+                       else if (rt2x00queue_status_timeout(entry))
+                               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+                       else
                                break;
-
-                       rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
                }
        }
+
+       /*
+        * The hw may delay sending the packet after DMA complete
+        * if the medium is busy, thus the TX_STA_FIFO entry is
+        * also delayed -> use a timer to retrieve it.
+        */
+       if (rt2800usb_txstatus_pending(rt2x00dev))
+               mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
 }
 
 /*
@@ -553,18 +620,23 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
         * This device has multiple filters for control frames
         * and has a separate filter for PS Poll frames.
         */
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
        /*
         * This device requires firmware.
         */
-       __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
        if (!modparam_nohwcrypt)
-               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+
+       setup_timer(&rt2x00dev->txstatus_timer,
+                   rt2800usb_tx_sta_fifo_timeout,
+                   (unsigned long) rt2x00dev);
 
        /*
         * Set the rssi offset.
@@ -601,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
        .ampdu_action           = rt2800_ampdu_action,
        .flush                  = rt2x00mac_flush,
        .get_survey             = rt2800_get_survey,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -635,6 +708,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
        .kick_queue             = rt2x00usb_kick_queue,
        .stop_queue             = rt2800usb_stop_queue,
        .flush_queue            = rt2x00usb_flush_queue,
+       .tx_dma_done            = rt2800usb_tx_dma_done,
        .write_tx_desc          = rt2800usb_write_tx_desc,
        .write_tx_data          = rt2800usb_write_tx_data,
        .write_beacon           = rt2800_write_beacon,
@@ -695,295 +769,332 @@ static const struct rt2x00_ops rt2800usb_ops = {
  */
 static struct usb_device_id rt2800usb_device_table[] = {
        /* Abocom */
-       { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07b8, 0x2870) },
+       { USB_DEVICE(0x07b8, 0x2770) },
+       { USB_DEVICE(0x07b8, 0x3070) },
+       { USB_DEVICE(0x07b8, 0x3071) },
+       { USB_DEVICE(0x07b8, 0x3072) },
+       { USB_DEVICE(0x1482, 0x3c09) },
        /* AirTies */
-       { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1eda, 0x2012) },
+       { USB_DEVICE(0x1eda, 0x2310) },
        /* Allwin */
-       { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x2070) },
+       { USB_DEVICE(0x8516, 0x2770) },
+       { USB_DEVICE(0x8516, 0x2870) },
+       { USB_DEVICE(0x8516, 0x3070) },
+       { USB_DEVICE(0x8516, 0x3071) },
+       { USB_DEVICE(0x8516, 0x3072) },
+       /* Alpha Networks */
+       { USB_DEVICE(0x14b2, 0x3c06) },
+       { USB_DEVICE(0x14b2, 0x3c07) },
+       { USB_DEVICE(0x14b2, 0x3c09) },
+       { USB_DEVICE(0x14b2, 0x3c12) },
+       { USB_DEVICE(0x14b2, 0x3c23) },
+       { USB_DEVICE(0x14b2, 0x3c25) },
+       { USB_DEVICE(0x14b2, 0x3c27) },
+       { USB_DEVICE(0x14b2, 0x3c28) },
+       { USB_DEVICE(0x14b2, 0x3c2c) },
        /* Amit */
-       { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x15c5, 0x0008) },
        /* Askey */
-       { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1690, 0x0740) },
        /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0b05, 0x1731) },
+       { USB_DEVICE(0x0b05, 0x1732) },
+       { USB_DEVICE(0x0b05, 0x1742) },
+       { USB_DEVICE(0x0b05, 0x1784) },
+       { USB_DEVICE(0x1761, 0x0b05) },
        /* AzureWave */
-       { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13d3, 0x3247) },
+       { USB_DEVICE(0x13d3, 0x3273) },
+       { USB_DEVICE(0x13d3, 0x3305) },
+       { USB_DEVICE(0x13d3, 0x3307) },
+       { USB_DEVICE(0x13d3, 0x3321) },
        /* Belkin */
-       { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x050d, 0x8053) },
+       { USB_DEVICE(0x050d, 0x805c) },
+       { USB_DEVICE(0x050d, 0x815c) },
+       { USB_DEVICE(0x050d, 0x825b) },
+       { USB_DEVICE(0x050d, 0x935a) },
+       { USB_DEVICE(0x050d, 0x935b) },
        /* Buffalo */
-       { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0411, 0x00e8) },
+       { USB_DEVICE(0x0411, 0x016f) },
+       { USB_DEVICE(0x0411, 0x01a2) },
        /* Corega */
-       { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07aa, 0x002f) },
+       { USB_DEVICE(0x07aa, 0x003c) },
+       { USB_DEVICE(0x07aa, 0x003f) },
+       { USB_DEVICE(0x18c5, 0x0012) },
        /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07d1, 0x3c09) },
+       { USB_DEVICE(0x07d1, 0x3c0a) },
+       { USB_DEVICE(0x07d1, 0x3c0d) },
+       { USB_DEVICE(0x07d1, 0x3c0e) },
+       { USB_DEVICE(0x07d1, 0x3c0f) },
+       { USB_DEVICE(0x07d1, 0x3c11) },
+       { USB_DEVICE(0x07d1, 0x3c16) },
        /* Draytek */
-       { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07fa, 0x7712) },
        /* Edimax */
-       { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x7392, 0x7711) },
+       { USB_DEVICE(0x7392, 0x7717) },
+       { USB_DEVICE(0x7392, 0x7718) },
        /* Encore */
-       { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x203d, 0x1480) },
+       { USB_DEVICE(0x203d, 0x14a9) },
        /* EnGenius */
-       { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x9701) },
+       { USB_DEVICE(0x1740, 0x9702) },
+       { USB_DEVICE(0x1740, 0x9703) },
+       { USB_DEVICE(0x1740, 0x9705) },
+       { USB_DEVICE(0x1740, 0x9706) },
+       { USB_DEVICE(0x1740, 0x9707) },
+       { USB_DEVICE(0x1740, 0x9708) },
+       { USB_DEVICE(0x1740, 0x9709) },
+       /* Gemtek */
+       { USB_DEVICE(0x15a9, 0x0012) },
        /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1044, 0x800b) },
+       { USB_DEVICE(0x1044, 0x800d) },
        /* Hawking */
-       { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e66, 0x0001) },
+       { USB_DEVICE(0x0e66, 0x0003) },
+       { USB_DEVICE(0x0e66, 0x0009) },
+       { USB_DEVICE(0x0e66, 0x000b) },
+       { USB_DEVICE(0x0e66, 0x0013) },
+       { USB_DEVICE(0x0e66, 0x0017) },
+       { USB_DEVICE(0x0e66, 0x0018) },
        /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x04bb, 0x0945) },
+       { USB_DEVICE(0x04bb, 0x0947) },
+       { USB_DEVICE(0x04bb, 0x0948) },
        /* Linksys */
-       { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13b1, 0x0031) },
+       { USB_DEVICE(0x1737, 0x0070) },
+       { USB_DEVICE(0x1737, 0x0071) },
        /* Logitec */
-       { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0789, 0x0162) },
+       { USB_DEVICE(0x0789, 0x0163) },
+       { USB_DEVICE(0x0789, 0x0164) },
+       { USB_DEVICE(0x0789, 0x0166) },
        /* Motorola */
-       { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x100d, 0x9031) },
        /* MSI */
-       { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0db0, 0x3820) },
+       { USB_DEVICE(0x0db0, 0x3821) },
+       { USB_DEVICE(0x0db0, 0x3822) },
+       { USB_DEVICE(0x0db0, 0x3870) },
+       { USB_DEVICE(0x0db0, 0x3871) },
+       { USB_DEVICE(0x0db0, 0x6899) },
+       { USB_DEVICE(0x0db0, 0x821a) },
+       { USB_DEVICE(0x0db0, 0x822a) },
+       { USB_DEVICE(0x0db0, 0x822b) },
+       { USB_DEVICE(0x0db0, 0x822c) },
+       { USB_DEVICE(0x0db0, 0x870a) },
+       { USB_DEVICE(0x0db0, 0x871a) },
+       { USB_DEVICE(0x0db0, 0x871b) },
+       { USB_DEVICE(0x0db0, 0x871c) },
+       { USB_DEVICE(0x0db0, 0x899a) },
        /* Para */
-       { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x20b8, 0x8888) },
        /* Pegatron */
-       { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1d4d, 0x000c) },
+       { USB_DEVICE(0x1d4d, 0x000e) },
+       { USB_DEVICE(0x1d4d, 0x0011) },
        /* Philips */
-       { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0471, 0x200f) },
        /* Planex */
-       { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x2019, 0xab25) },
+       { USB_DEVICE(0x2019, 0xed06) },
        /* Quanta */
-       { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1a32, 0x0304) },
        /* Ralink */
-       { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x148f, 0x2070) },
+       { USB_DEVICE(0x148f, 0x2770) },
+       { USB_DEVICE(0x148f, 0x2870) },
+       { USB_DEVICE(0x148f, 0x3070) },
+       { USB_DEVICE(0x148f, 0x3071) },
+       { USB_DEVICE(0x148f, 0x3072) },
        /* Samsung */
-       { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x04e8, 0x2018) },
        /* Siemens */
-       { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x129b, 0x1828) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0017) },
+       { USB_DEVICE(0x0df6, 0x002b) },
+       { USB_DEVICE(0x0df6, 0x002c) },
+       { USB_DEVICE(0x0df6, 0x002d) },
+       { USB_DEVICE(0x0df6, 0x0039) },
+       { USB_DEVICE(0x0df6, 0x003b) },
+       { USB_DEVICE(0x0df6, 0x003d) },
+       { USB_DEVICE(0x0df6, 0x003e) },
+       { USB_DEVICE(0x0df6, 0x003f) },
+       { USB_DEVICE(0x0df6, 0x0040) },
+       { USB_DEVICE(0x0df6, 0x0042) },
+       { USB_DEVICE(0x0df6, 0x0047) },
+       { USB_DEVICE(0x0df6, 0x0048) },
+       { USB_DEVICE(0x0df6, 0x0051) },
+       { USB_DEVICE(0x0df6, 0x005f) },
        /* SMC */
-       { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x083a, 0x6618) },
+       { USB_DEVICE(0x083a, 0x7511) },
+       { USB_DEVICE(0x083a, 0x7512) },
+       { USB_DEVICE(0x083a, 0x7522) },
+       { USB_DEVICE(0x083a, 0x8522) },
+       { USB_DEVICE(0x083a, 0xa618) },
+       { USB_DEVICE(0x083a, 0xa701) },
+       { USB_DEVICE(0x083a, 0xa702) },
+       { USB_DEVICE(0x083a, 0xa703) },
+       { USB_DEVICE(0x083a, 0xb522) },
        /* Sparklan */
-       { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x15a9, 0x0006) },
        /* Sweex */
-       { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* U-Media*/
-       { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x177f, 0x0302) },
+       /* U-Media */
+       { USB_DEVICE(0x157e, 0x300e) },
+       { USB_DEVICE(0x157e, 0x3013) },
        /* ZCOM */
-       { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0cde, 0x0022) },
+       { USB_DEVICE(0x0cde, 0x0025) },
        /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x5a57, 0x0280) },
+       { USB_DEVICE(0x5a57, 0x0282) },
+       { USB_DEVICE(0x5a57, 0x0283) },
+       { USB_DEVICE(0x5a57, 0x5257) },
        /* Zyxel */
-       { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0586, 0x3416) },
+       { USB_DEVICE(0x0586, 0x3418) },
+       { USB_DEVICE(0x0586, 0x341e) },
+       { USB_DEVICE(0x0586, 0x343e) },
 #ifdef CONFIG_RT2800USB_RT33XX
        /* Ralink */
-       { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x148f, 0x3370) },
+       { USB_DEVICE(0x148f, 0x8070) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0050) },
 #endif
 #ifdef CONFIG_RT2800USB_RT35XX
        /* Allwin */
-       { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x8516, 0x3572) },
        /* Askey */
-       { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1690, 0x0744) },
        /* Cisco */
-       { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x167b, 0x4001) },
        /* EnGenius */
-       { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x9801) },
        /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x04bb, 0x0944) },
+       /* Linksys */
+       { USB_DEVICE(0x13b1, 0x002f) },
+       { USB_DEVICE(0x1737, 0x0079) },
        /* Ralink */
-       { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x148f, 0x3572) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0041) },
        /* Toshiba */
-       { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0930, 0x0a07) },
        /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x5a57, 0x0284) },
 #endif
 #ifdef CONFIG_RT2800USB_UNKNOWN
        /*
         * Unclear what kind of devices these are (they aren't supported by the
         * vendor linux driver).
         */
+       /* Abocom */
+       { USB_DEVICE(0x07b8, 0x3073) },
+       { USB_DEVICE(0x07b8, 0x3074) },
+       /* Alpha Networks */
+       { USB_DEVICE(0x14b2, 0x3c08) },
+       { USB_DEVICE(0x14b2, 0x3c11) },
        /* Amigo */
-       { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0e0b, 0x9031) },
+       { USB_DEVICE(0x0e0b, 0x9041) },
        /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0b05, 0x166a) },
+       { USB_DEVICE(0x0b05, 0x1760) },
+       { USB_DEVICE(0x0b05, 0x1761) },
+       { USB_DEVICE(0x0b05, 0x1790) },
+       { USB_DEVICE(0x0b05, 0x179d) },
        /* AzureWave */
-       { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x13d3, 0x3262) },
+       { USB_DEVICE(0x13d3, 0x3284) },
+       { USB_DEVICE(0x13d3, 0x3322) },
        /* Belkin */
-       { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x050d, 0x1003) },
+       { USB_DEVICE(0x050d, 0x825a) },
        /* Buffalo */
-       { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
-       /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0411, 0x012e) },
+       { USB_DEVICE(0x0411, 0x0148) },
+       { USB_DEVICE(0x0411, 0x0150) },
+       { USB_DEVICE(0x0411, 0x015d) },
        /* Corega */
-       { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07aa, 0x0041) },
+       { USB_DEVICE(0x07aa, 0x0042) },
+       { USB_DEVICE(0x18c5, 0x0008) },
        /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x07d1, 0x3c0b) },
+       { USB_DEVICE(0x07d1, 0x3c13) },
+       { USB_DEVICE(0x07d1, 0x3c15) },
+       { USB_DEVICE(0x07d1, 0x3c17) },
+       { USB_DEVICE(0x2001, 0x3c17) },
        /* Edimax */
-       { USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x7392, 0x4085) },
+       { USB_DEVICE(0x7392, 0x7722) },
        /* Encore */
-       { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x203d, 0x14a1) },
        /* Gemtek */
-       { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x15a9, 0x0010) },
        /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1044, 0x800c) },
+       /* Huawei */
+       { USB_DEVICE(0x148f, 0xf101) },
+       /* I-O DATA */
+       { USB_DEVICE(0x04bb, 0x094b) },
        /* LevelOne */
-       { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1740, 0x0605) },
+       { USB_DEVICE(0x1740, 0x0615) },
        /* Linksys */
-       { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1737, 0x0077) },
+       { USB_DEVICE(0x1737, 0x0078) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x0168) },
+       { USB_DEVICE(0x0789, 0x0169) },
        /* Motorola */
-       { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x100d, 0x9032) },
        /* Ovislink */
-       { USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x1b75, 0x3071) },
+       { USB_DEVICE(0x1b75, 0x3072) },
        /* Pegatron */
-       { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x05a6, 0x0101) },
+       { USB_DEVICE(0x1d4d, 0x0002) },
+       { USB_DEVICE(0x1d4d, 0x0010) },
        /* Planex */
-       { USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x2019, 0x5201) },
+       { USB_DEVICE(0x2019, 0xab24) },
        /* Qcom */
-       { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x18e8, 0x6259) },
+       /* RadioShack */
+       { USB_DEVICE(0x08b9, 0x1197) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x003c) },
+       { USB_DEVICE(0x0df6, 0x004a) },
+       { USB_DEVICE(0x0df6, 0x004d) },
+       { USB_DEVICE(0x0df6, 0x0053) },
+       { USB_DEVICE(0x0df6, 0x0060) },
+       { USB_DEVICE(0x0df6, 0x0062) },
        /* SMC */
-       { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x083a, 0xa512) },
+       { USB_DEVICE(0x083a, 0xc522) },
+       { USB_DEVICE(0x083a, 0xd522) },
+       { USB_DEVICE(0x083a, 0xf511) },
        /* Sweex */
-       { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
-       { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x177f, 0x0153) },
+       { USB_DEVICE(0x177f, 0x0313) },
        /* Zyxel */
-       { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
+       { USB_DEVICE(0x0586, 0x341a) },
 #endif
        { 0, }
 };
@@ -996,10 +1107,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
 MODULE_FIRMWARE(FIRMWARE_RT2870);
 MODULE_LICENSE("GPL");
 
+static int rt2800usb_probe(struct usb_interface *usb_intf,
+                          const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
 static struct usb_driver rt2800usb_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt2800usb_device_table,
-       .probe          = rt2x00usb_probe,
+       .probe          = rt2800usb_probe,
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
index a2bd5feb9d5ce6bb9c486595bf0c3baad8ba5ad2..9d1a158e2c333f330ba3bdf8b2a78b1879b54ec3 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
 #include <linux/kfifo.h>
+#include <linux/timer.h>
 
 #include <net/mac80211.h>
 
@@ -570,7 +571,8 @@ struct rt2x00lib_ops {
        void (*start_queue) (struct data_queue *queue);
        void (*kick_queue) (struct data_queue *queue);
        void (*stop_queue) (struct data_queue *queue);
-       void (*flush_queue) (struct data_queue *queue);
+       void (*flush_queue) (struct data_queue *queue, bool drop);
+       void (*tx_dma_done) (struct queue_entry *entry);
 
        /*
         * TX control handlers
@@ -643,11 +645,11 @@ struct rt2x00_ops {
 };
 
 /*
- * rt2x00 device flags
+ * rt2x00 state flags
  */
-enum rt2x00_flags {
+enum rt2x00_state_flags {
        /*
-        * Device state flags
+        * Device flags
         */
        DEVICE_STATE_PRESENT,
        DEVICE_STATE_REGISTERED_HW,
@@ -656,42 +658,47 @@ enum rt2x00_flags {
        DEVICE_STATE_ENABLED_RADIO,
        DEVICE_STATE_SCANNING,
 
-       /*
-        * Driver requirements
-        */
-       DRIVER_REQUIRE_FIRMWARE,
-       DRIVER_REQUIRE_BEACON_GUARD,
-       DRIVER_REQUIRE_ATIM_QUEUE,
-       DRIVER_REQUIRE_DMA,
-       DRIVER_REQUIRE_COPY_IV,
-       DRIVER_REQUIRE_L2PAD,
-       DRIVER_REQUIRE_TXSTATUS_FIFO,
-       DRIVER_REQUIRE_TASKLET_CONTEXT,
-       DRIVER_REQUIRE_SW_SEQNO,
-       DRIVER_REQUIRE_HT_TX_DESC,
-
-       /*
-        * Driver features
-        */
-       CONFIG_SUPPORT_HW_BUTTON,
-       CONFIG_SUPPORT_HW_CRYPTO,
-       CONFIG_SUPPORT_POWER_LIMIT,
-       DRIVER_SUPPORT_CONTROL_FILTERS,
-       DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
-       DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
-       DRIVER_SUPPORT_LINK_TUNING,
-
        /*
         * Driver configuration
         */
-       CONFIG_FRAME_TYPE,
-       CONFIG_RF_SEQUENCE,
-       CONFIG_EXTERNAL_LNA_A,
-       CONFIG_EXTERNAL_LNA_BG,
-       CONFIG_DOUBLE_ANTENNA,
        CONFIG_CHANNEL_HT40,
 };
 
+/*
+ * rt2x00 capability flags
+ */
+enum rt2x00_capability_flags {
+       /*
+        * Requirements
+        */
+       REQUIRE_FIRMWARE,
+       REQUIRE_BEACON_GUARD,
+       REQUIRE_ATIM_QUEUE,
+       REQUIRE_DMA,
+       REQUIRE_COPY_IV,
+       REQUIRE_L2PAD,
+       REQUIRE_TXSTATUS_FIFO,
+       REQUIRE_TASKLET_CONTEXT,
+       REQUIRE_SW_SEQNO,
+       REQUIRE_HT_TX_DESC,
+
+       /*
+        * Capabilities
+        */
+       CAPABILITY_HW_BUTTON,
+       CAPABILITY_HW_CRYPTO,
+       CAPABILITY_POWER_LIMIT,
+       CAPABILITY_CONTROL_FILTERS,
+       CAPABILITY_CONTROL_FILTER_PSPOLL,
+       CAPABILITY_PRE_TBTT_INTERRUPT,
+       CAPABILITY_LINK_TUNING,
+       CAPABILITY_FRAME_TYPE,
+       CAPABILITY_RF_SEQUENCE,
+       CAPABILITY_EXTERNAL_LNA_A,
+       CAPABILITY_EXTERNAL_LNA_BG,
+       CAPABILITY_DOUBLE_ANTENNA,
+};
+
 /*
  * rt2x00 device structure.
  */
@@ -738,12 +745,19 @@ struct rt2x00_dev {
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
        /*
-        * Device flags.
-        * In these flags the current status and some
-        * of the device capabilities are stored.
+        * Device state flags.
+        * In these flags the current status is stored.
+        * Access to these flags should occur atomically.
         */
        unsigned long flags;
 
+       /*
+        * Device capabiltiy flags.
+        * In these flags the device/driver capabilities are stored.
+        * Access to these flags should occur non-atomically.
+        */
+       unsigned long cap_flags;
+
        /*
         * Device information, Bus IRQ and name (PCI, SoC)
         */
@@ -910,6 +924,11 @@ struct rt2x00_dev {
         */
        DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
+       /*
+        * Timer to ensure tx status reports are read (rt2800usb).
+        */
+       struct timer_list txstatus_timer;
+
        /*
         * Tasklet for processing tx status reports (rt2800pci).
         */
@@ -1235,6 +1254,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
 void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 
 /*
  * Driver allocation handlers.
index 9416e36de29e900f253a69022ee735ea29b89052..f7872640459278d6ec69f788fa5f2019429d891a 100644 (file)
@@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
        rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
 }
 
-static inline
-enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
-                                           enum antenna default_ant)
-{
-       if (current_ant != ANTENNA_SW_DIVERSITY)
-               return current_ant;
-       return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
-}
-
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
                              struct antenna_setup config)
 {
@@ -126,19 +117,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
        struct antenna_setup *active = &rt2x00dev->link.ant.active;
 
        /*
-        * Failsafe: Make sure we are not sending the
-        * ANTENNA_SW_DIVERSITY state to the driver.
-        * If that happens, fallback to hardware defaults,
-        * or our own default.
+        * When the caller tries to send the SW diversity,
+        * we must update the ANTENNA_RX_DIVERSITY flag to
+        * enable the antenna diversity in the link tuner.
+        *
+        * Secondly, we must guarentee we never send the
+        * software antenna diversity command to the driver.
         */
-       if (!(ant->flags & ANTENNA_RX_DIVERSITY))
-               config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
-       else if (config.rx == ANTENNA_SW_DIVERSITY)
+       if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
+               if (config.rx == ANTENNA_SW_DIVERSITY) {
+                       ant->flags |= ANTENNA_RX_DIVERSITY;
+
+                       if (def->rx == ANTENNA_SW_DIVERSITY)
+                               config.rx = ANTENNA_B;
+                       else
+                               config.rx = def->rx;
+               }
+       } else if (config.rx == ANTENNA_SW_DIVERSITY)
                config.rx = active->rx;
 
-       if (!(ant->flags & ANTENNA_TX_DIVERSITY))
-               config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
-       else if (config.tx == ANTENNA_SW_DIVERSITY)
+       if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
+               if (config.tx == ANTENNA_SW_DIVERSITY) {
+                       ant->flags |= ANTENNA_TX_DIVERSITY;
+
+                       if (def->tx == ANTENNA_SW_DIVERSITY)
+                               config.tx = ANTENNA_B;
+                       else
+                               config.tx = def->tx;
+               }
+       } else if (config.tx == ANTENNA_SW_DIVERSITY)
                config.tx = active->tx;
 
        /*
@@ -163,6 +170,34 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
                rt2x00queue_start_queue(rt2x00dev->rx);
 }
 
+static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
+                                  struct ieee80211_conf *conf)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       int center_channel;
+       u16 i;
+
+       /*
+        * Initialize center channel to current channel.
+        */
+       center_channel = spec->channels[conf->channel->hw_value].channel;
+
+       /*
+        * Adjust center channel to HT40+ and HT40- operation.
+        */
+       if (conf_is_ht40_plus(conf))
+               center_channel += 2;
+       else if (conf_is_ht40_minus(conf))
+               center_channel -= (center_channel == 14) ? 1 : 2;
+
+       for (i = 0; i < spec->num_channels; i++)
+               if (spec->channels[i].channel == center_channel)
+                       return i;
+
+       WARN_ON(1);
+       return conf->channel->hw_value;
+}
+
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
                      struct ieee80211_conf *conf,
                      unsigned int ieee80211_flags)
@@ -176,10 +211,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 
        if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
                if (conf_is_ht40(conf)) {
-                       __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+                       set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
                        hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
                } else {
-                       __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+                       clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
                        hw_value = conf->channel->hw_value;
                }
 
index 3f5688fbf3f7aa89624ba3c4b0a721a3872a795e..1bb9d46077ffe88c9c9e8bd56f5b5cca0ebc299b 100644 (file)
@@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
        struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 
-       if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key)
+       if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
                return;
 
        __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
@@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
        struct ieee80211_key_conf *key = tx_info->control.hw_key;
        unsigned int overhead = 0;
 
-       if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key)
+       if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key)
                return overhead;
 
        /*
index 66166ef037f59c123d6f1acd594ed010d4bf3ad8..78787fcc919e2fef034a5f1b6766751f0588df99 100644 (file)
@@ -63,7 +63,8 @@ struct rt2x00debug_intf {
         * - driver folder
         *   - driver file
         *   - chipset file
-        *   - device flags file
+        *   - device state flags file
+        *   - device capability flags file
         *   - register folder
         *     - csr offset/value files
         *     - eeprom offset/value files
@@ -78,6 +79,7 @@ struct rt2x00debug_intf {
        struct dentry *driver_entry;
        struct dentry *chipset_entry;
        struct dentry *dev_flags;
+       struct dentry *cap_flags;
        struct dentry *register_folder;
        struct dentry *csr_off_entry;
        struct dentry *csr_val_entry;
@@ -553,6 +555,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
        .llseek         = default_llseek,
 };
 
+static ssize_t rt2x00debug_read_cap_flags(struct file *file,
+                                         char __user *buf,
+                                         size_t length,
+                                         loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       char line[16];
+       size_t size;
+
+       if (*offset)
+               return 0;
+
+       size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
+
+       if (copy_to_user(buf, line, size))
+               return -EFAULT;
+
+       *offset += size;
+       return size;
+}
+
+static const struct file_operations rt2x00debug_fop_cap_flags = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_cap_flags,
+       .open           = rt2x00debug_file_open,
+       .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
                                                     struct rt2x00debug_intf
                                                     *intf,
@@ -652,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
        if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
                goto exit;
 
+       intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
+                                             intf->driver_folder, intf,
+                                             &rt2x00debug_fop_cap_flags);
+       if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
+               goto exit;
+
        intf->register_folder =
            debugfs_create_dir("register", intf->driver_folder);
        if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -705,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
                                intf, &rt2x00debug_fop_queue_stats);
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
-       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
                intf->crypto_stats_entry =
                    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
                                        intf, &rt2x00debug_fop_crypto_stats);
@@ -743,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
        debugfs_remove(intf->csr_off_entry);
        debugfs_remove(intf->register_folder);
        debugfs_remove(intf->dev_flags);
+       debugfs_remove(intf->cap_flags);
        debugfs_remove(intf->chipset_entry);
        debugfs_remove(intf->driver_entry);
        debugfs_remove(intf->driver_folder);
index 9bffe8438d1fed657c9d465894682b5998a58bd7..7776d9f1f29750ee3d4669e29c1bd708c8315888 100644 (file)
@@ -200,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
         * here as they will fetch the next beacon directly prior to
         * transmission.
         */
-       if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags))
                return;
 
        /* fetch next beacon */
@@ -225,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 void rt2x00lib_dmastart(struct queue_entry *entry)
 {
        set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-       rt2x00queue_index_inc(entry->queue, Q_INDEX);
+       rt2x00queue_index_inc(entry, Q_INDEX);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
 
@@ -233,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry)
 {
        set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
        clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-       rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+       rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
 
@@ -271,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
        /*
         * Remove L2 padding which was added during
         */
-       if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+       if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
                rt2x00queue_remove_l2pad(entry->skb, header_length);
 
        /*
@@ -280,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
         * mac80211 will expect the same data to be present it the
         * frame as it was passed to us.
         */
-       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
                rt2x00crypto_tx_insert_iv(entry->skb, header_length);
 
        /*
@@ -377,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
         * send the status report back.
         */
        if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
-               if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+               if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags))
                        ieee80211_tx_status(rt2x00dev->hw, entry->skb);
                else
                        ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
@@ -392,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 
        rt2x00dev->ops->lib->clear_entry(entry);
 
-       rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
 
        /*
         * If the data queue was below the threshold before the txdone
@@ -559,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 
 submit_entry:
        entry->flags = 0;
-       rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
        if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
            test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
                rt2x00dev->ops->lib->clear_entry(entry);
@@ -806,15 +806,15 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * Take TX headroom required for alignment into account.
         */
-       if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+       if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
                rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
-       else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+       else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
                rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
 
        /*
         * Allocate tx status FIFO for driver use.
         */
-       if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
+       if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
                /*
                 * Allocate the txstatus fifo. In the worst case the tx
                 * status fifo has to hold the tx status of all entries
@@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
        /*
         * Stop all work.
         */
+       del_timer_sync(&rt2x00dev->txstatus_timer);
        cancel_work_sync(&rt2x00dev->intf_work);
        if (rt2x00_is_usb(rt2x00dev)) {
                cancel_work_sync(&rt2x00dev->rxdone_work);
index be0ff78c1b1666178864c62e8f367a6fae939a9a..f316aad30612d53ac70e22874740f02a09091273 100644 (file)
@@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
 
-       if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
+       if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))
                return 0;
 
        if (!rt2x00dev->fw) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
deleted file mode 100644 (file)
index e8c0c3e..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the
-       Free Software Foundation, Inc.,
-       59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 HT specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-                                  struct txentry_desc *txdesc,
-                                  const struct rt2x00_rate *hwrate)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-
-       if (tx_info->control.sta)
-               txdesc->u.ht.mpdu_density =
-                   tx_info->control.sta->ht_cap.ampdu_density;
-
-       txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
-
-       /*
-        * Only one STBC stream is supported for now.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_STBC)
-               txdesc->u.ht.stbc = 1;
-
-       /*
-        * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
-        * mcs rate to be used
-        */
-       if (txrate->flags & IEEE80211_TX_RC_MCS) {
-               txdesc->u.ht.mcs = txrate->idx;
-
-               /*
-                * MIMO PS should be set to 1 for STA's using dynamic SM PS
-                * when using more then one tx stream (>MCS7).
-                */
-               if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
-                   ((tx_info->control.sta->ht_cap.cap &
-                     IEEE80211_HT_CAP_SM_PS) >>
-                    IEEE80211_HT_CAP_SM_PS_SHIFT) ==
-                   WLAN_HT_CAP_SM_PS_DYNAMIC)
-                       __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
-       } else {
-               txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
-               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->u.ht.mcs |= 0x08;
-       }
-
-       /*
-        * This frame is eligible for an AMPDU, however, don't aggregate
-        * frames that are intended to probe a specific tx rate.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
-           !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
-               __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
-
-       /*
-        * Set 40Mhz mode if necessary (for legacy rates this will
-        * duplicate the frame to both channels).
-        */
-       if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
-           txrate->flags & IEEE80211_TX_RC_DUP_DATA)
-               __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
-       if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
-               __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
-
-       /*
-        * Determine IFS values
-        * - Use TXOP_BACKOFF for management frames
-        * - Use TXOP_SIFS for fragment bursts
-        * - Use TXOP_HTTXOP for everything else
-        *
-        * Note: rt2800 devices won't use CTS protection (if used)
-        * for frames not transmitted with TXOP_HTTXOP
-        */
-       if (ieee80211_is_mgmt(hdr->frame_control))
-               txdesc->u.ht.txop = TXOP_BACKOFF;
-       else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-               txdesc->u.ht.txop = TXOP_SIFS;
-       else
-               txdesc->u.ht.txop = TXOP_HTTXOP;
-}
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-                           struct ieee80211_conf *conf)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       int center_channel;
-       u16 i;
-
-       /*
-        * Initialize center channel to current channel.
-        */
-       center_channel = spec->channels[conf->channel->hw_value].channel;
-
-       /*
-        * Adjust center channel to HT40+ and HT40- operation.
-        */
-       if (conf_is_ht40_plus(conf))
-               center_channel += 2;
-       else if (conf_is_ht40_minus(conf))
-               center_channel -= (center_channel == 14) ? 1 : 2;
-
-       for (i = 0; i < spec->num_channels; i++)
-               if (spec->channels[i].channel == center_channel)
-                       return i;
-
-       WARN_ON(1);
-       return conf->channel->hw_value;
-}
index 88f2f92755280fff10748881585a1e82a9a68def..322cc4f3de5d6a6c961e1ed4ff779636cb6b2fcd 100644 (file)
@@ -175,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
 
 /**
  * rt2x00queue_index_inc - Index incrementation function
- * @queue: Queue (&struct data_queue) to perform the action on.
+ * @entry: Queue entry (&struct queue_entry) to perform the action on.
  * @index: Index type (&enum queue_index) to perform the action on.
  *
- * This function will increase the requested index on the queue,
+ * This function will increase the requested index on the entry's queue,
  * it will grab the appropriate locks and handle queue overflow events by
  * resetting the index to the start of the queue.
  */
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);
 
 /**
  * rt2x00queue_init_queues - Initialize all data queues
@@ -387,42 +387,18 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
 }
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
-/*
- * HT handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_HT
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-                                  struct txentry_desc *txdesc,
-                                  const struct rt2x00_rate *hwrate);
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-                           struct ieee80211_conf *conf);
-#else
-static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-                                                struct txentry_desc *txdesc,
-                                                const struct rt2x00_rate *hwrate)
-{
-}
-
-static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-                                         struct ieee80211_conf *conf)
-{
-       return conf->channel->hw_value;
-}
-#endif /* CONFIG_RT2X00_LIB_HT */
-
 /*
  * RFkill handlers.
  */
 static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
 {
-       if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
                wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
 }
 
 static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
 {
-       if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
                wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
 }
 
index 1435976b87798151708814a2f34ec740dd824bf2..ea10b0068f823f503e827f45d9e4c52dd9f8a74f 100644 (file)
@@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
        /*
         * Determine if software diversity is enabled for
         * either the TX or RX antenna (or both).
-        * Always perform this check since within the link
-        * tuner interval the configuration might have changed.
         */
-       ant->flags &= ~ANTENNA_RX_DIVERSITY;
-       ant->flags &= ~ANTENNA_TX_DIVERSITY;
-
-       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-               ant->flags |= ANTENNA_RX_DIVERSITY;
-       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-               ant->flags |= ANTENNA_TX_DIVERSITY;
-
        if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
            !(ant->flags & ANTENNA_TX_DIVERSITY)) {
                ant->flags = 0;
@@ -383,7 +373,7 @@ static void rt2x00link_tuner(struct work_struct *work)
         * do not support link tuning at all, while other devices can disable
         * the feature from the EEPROM.
         */
-       if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags))
+       if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))
                rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
 
        /*
index 661c6baad2b9bd7005c9d9bee9589d10486f9a0a..93bec140e598612145c50b44adc86be70b42bca2 100644 (file)
@@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
         * Use the ATIM queue if appropriate and present.
         */
        if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
-           test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
+           test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))
                qid = QID_ATIM;
 
        queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
@@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        return;
 
  exit_fail:
-       ieee80211_stop_queue(rt2x00dev->hw, qid);
+       rt2x00queue_pause_queue(queue);
        dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
@@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
         * of different types, but has no a separate filter for PS Poll frames,
         * FIF_CONTROL flag implies FIF_PSPOLL.
         */
-       if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
+       if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) {
                if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
                        *total_flags |= FIF_CONTROL | FIF_PSPOLL;
        }
-       if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
+       if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) {
                if (*total_flags & FIF_CONTROL)
                        *total_flags |= FIF_PSPOLL;
        }
@@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
                return 0;
-       else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+       else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
                return -EOPNOTSUPP;
        else if (key->keylen > 32)
                return -ENOSPC;
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
 void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+       set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
        rt2x00link_stop_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
@@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
 void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+       clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
        rt2x00link_start_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
@@ -737,3 +737,84 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
                rt2x00queue_flush_queue(queue, drop);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_flush);
+
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup *def = &rt2x00dev->default_ant;
+       struct antenna_setup setup;
+
+       // The antenna value is not supposed to be 0,
+       // or exceed the maximum number of antenna's.
+       if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
+               return -EINVAL;
+
+       // When the client tried to configure the antenna to or from
+       // diversity mode, we must reset the default antenna as well
+       // as that controls the diversity switch.
+       if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
+               ant->flags &= ~ANTENNA_TX_DIVERSITY;
+       if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
+               ant->flags &= ~ANTENNA_RX_DIVERSITY;
+
+       // If diversity is being enabled, check if we need hardware
+       // or software diversity. In the latter case, reset the value,
+       // and make sure we update the antenna flags to have the
+       // link tuner pick up the diversity tuning.
+       if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
+               tx_ant = ANTENNA_SW_DIVERSITY;
+               ant->flags |= ANTENNA_TX_DIVERSITY;
+       }
+
+       if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
+               rx_ant = ANTENNA_SW_DIVERSITY;
+               ant->flags |= ANTENNA_RX_DIVERSITY;
+       }
+
+       setup.tx = tx_ant;
+       setup.rx = rx_ant;
+
+       rt2x00lib_config_antenna(rt2x00dev, setup);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
+
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+       // When software diversity is active, we must report this to the
+       // client and not the current active antenna state.
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               *tx_ant = ANTENNA_HW_DIVERSITY;
+       else
+               *tx_ant = active->tx;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               *rx_ant = ANTENNA_HW_DIVERSITY;
+       else
+               *rx_ant = active->rx;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
+
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               *tx += queue->length;
+               *tx_max += queue->limit;
+       }
+
+       *rx = rt2x00dev->rx->length;
+       *rx_max = rt2x00dev->rx->limit;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
index 9649bd0cd7188801ab80bb51d17cfdde7ee1a922..17148bb24426727971a91c130931887f7540496e 100644 (file)
@@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
 
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+       unsigned int i;
+
+       for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+               msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
 /*
  * Device initialization handlers.
  */
@@ -242,9 +251,8 @@ exit:
        return -ENOMEM;
 }
 
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 {
-       struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
        struct ieee80211_hw *hw;
        struct rt2x00_dev *rt2x00dev;
        int retval;
index 07961b8b369a291497df773b64d681b4533a506a..e2c99f2b9a1422f5e1dd1af1116f447f8b43c199 100644 (file)
@@ -107,6 +107,16 @@ struct queue_entry_priv_pci {
  */
 bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
 
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
 /*
  * Device initialization handlers.
  */
@@ -116,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
 /*
  * PCI driver handlers.
  */
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
 void rt2x00pci_remove(struct pci_dev *pci_dev);
 #ifdef CONFIG_PM
 int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
index 94b8bbb7ad80a707a3fd54544920d4121931f679..ab8c16f8bcafebec3faeecb412669792eab664a0 100644 (file)
@@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
         * at least 8 bytes bytes available in headroom for IV/EIV
         * and 8 bytes for ICV data as tailroon.
         */
-       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+       if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {
                head_size += 8;
                tail_size += 8;
        }
@@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
        memset(skbdesc, 0, sizeof(*skbdesc));
        skbdesc->entry = entry;
 
-       if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) {
+       if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
                skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
                                                  skb->data,
                                                  skb->len,
@@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 
        __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 
-       if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
+       if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
                return;
 
        /*
@@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
        }
 }
 
+static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+                                               struct txentry_desc *txdesc,
+                                               const struct rt2x00_rate *hwrate)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+
+       if (tx_info->control.sta)
+               txdesc->u.ht.mpdu_density =
+                   tx_info->control.sta->ht_cap.ampdu_density;
+
+       txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
+
+       /*
+        * Only one STBC stream is supported for now.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+               txdesc->u.ht.stbc = 1;
+
+       /*
+        * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
+        * mcs rate to be used
+        */
+       if (txrate->flags & IEEE80211_TX_RC_MCS) {
+               txdesc->u.ht.mcs = txrate->idx;
+
+               /*
+                * MIMO PS should be set to 1 for STA's using dynamic SM PS
+                * when using more then one tx stream (>MCS7).
+                */
+               if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
+                   ((tx_info->control.sta->ht_cap.cap &
+                     IEEE80211_HT_CAP_SM_PS) >>
+                    IEEE80211_HT_CAP_SM_PS_SHIFT) ==
+                   WLAN_HT_CAP_SM_PS_DYNAMIC)
+                       __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
+       } else {
+               txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       txdesc->u.ht.mcs |= 0x08;
+       }
+
+       /*
+        * This frame is eligible for an AMPDU, however, don't aggregate
+        * frames that are intended to probe a specific tx rate.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+           !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+               __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+       /*
+        * Set 40Mhz mode if necessary (for legacy rates this will
+        * duplicate the frame to both channels).
+        */
+       if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+           txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+               __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+       if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+               __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+
+       /*
+        * Determine IFS values
+        * - Use TXOP_BACKOFF for management frames except beacons
+        * - Use TXOP_SIFS for fragment bursts
+        * - Use TXOP_HTTXOP for everything else
+        *
+        * Note: rt2800 devices won't use CTS protection (if used)
+        * for frames not transmitted with TXOP_HTTXOP
+        */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_beacon(hdr->frame_control))
+               txdesc->u.ht.txop = TXOP_BACKOFF;
+       else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+               txdesc->u.ht.txop = TXOP_SIFS;
+       else
+               txdesc->u.ht.txop = TXOP_HTTXOP;
+}
+
 static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
                                             struct txentry_desc *txdesc)
 {
@@ -396,8 +475,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
        rt2x00crypto_create_tx_descriptor(entry, txdesc);
        rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
 
-       if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
-               rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+       if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
+               rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
        else
                rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
@@ -436,7 +515,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
        /*
         * Map the skb to DMA.
         */
-       if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+       if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
                rt2x00queue_map_txskb(entry);
 
        return 0;
@@ -529,7 +608,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
         */
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
            !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
-               if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
+               if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))
                        rt2x00crypto_tx_copy_iv(skb, &txdesc);
                else
                        rt2x00crypto_tx_remove_iv(skb, &txdesc);
@@ -543,9 +622,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
         * PCI and USB devices, while header alignment only is valid
         * for PCI devices.
         */
-       if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+       if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
                rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
-       else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
+       else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
                rt2x00queue_align_frame(entry->skb);
 
        /*
@@ -561,7 +640,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 
        set_bit(ENTRY_DATA_PENDING, &entry->flags);
 
-       rt2x00queue_index_inc(queue, Q_INDEX);
+       rt2x00queue_index_inc(entry, Q_INDEX);
        rt2x00queue_write_tx_descriptor(entry, &txdesc);
        rt2x00queue_kick_tx_queue(queue, &txdesc);
 
@@ -650,10 +729,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
        return ret;
 }
 
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
                                enum queue_index start,
                                enum queue_index end,
-                               void (*fn)(struct queue_entry *entry))
+                               void *data,
+                               bool (*fn)(struct queue_entry *entry,
+                                          void *data))
 {
        unsigned long irqflags;
        unsigned int index_start;
@@ -664,7 +745,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
                ERROR(queue->rt2x00dev,
                      "Entry requested from invalid index range (%d - %d)\n",
                      start, end);
-               return;
+               return true;
        }
 
        /*
@@ -683,15 +764,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
         * send out all frames in the correct order.
         */
        if (index_start < index_end) {
-               for (i = index_start; i < index_end; i++)
-                       fn(&queue->entries[i]);
+               for (i = index_start; i < index_end; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
        } else {
-               for (i = index_start; i < queue->limit; i++)
-                       fn(&queue->entries[i]);
+               for (i = index_start; i < queue->limit; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
 
-               for (i = 0; i < index_end; i++)
-                       fn(&queue->entries[i]);
+               for (i = 0; i < index_end; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
        }
+
+       return false;
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
 
@@ -717,8 +806,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
 
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
 {
+       struct data_queue *queue = entry->queue;
        unsigned long irqflags;
 
        if (unlikely(index >= Q_INDEX_MAX)) {
@@ -733,7 +823,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
        if (queue->index[index] >= queue->limit)
                queue->index[index] = 0;
 
-       queue->last_action[index] = jiffies;
+       entry->last_action = jiffies;
 
        if (index == Q_INDEX) {
                queue->length++;
@@ -838,7 +928,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
 
 void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
 {
-       unsigned int i;
        bool started;
        bool tx_queue =
                (queue->qid == QID_AC_VO) ||
@@ -873,20 +962,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
        }
 
        /*
-        * Check if driver supports flushing, we can only guarantee
-        * full support for flushing if the driver is able
-        * to cancel all pending frames (drop = true).
+        * Check if driver supports flushing, if that is the case we can
+        * defer the flushing to the driver. Otherwise we must use the
+        * alternative which just waits for the queue to become empty.
         */
-       if (drop && queue->rt2x00dev->ops->lib->flush_queue)
-               queue->rt2x00dev->ops->lib->flush_queue(queue);
-
-       /*
-        * When we don't want to drop any frames, or when
-        * the driver doesn't fully flush the queue correcly,
-        * we must wait for the queue to become empty.
-        */
-       for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
-               msleep(10);
+       if (likely(queue->rt2x00dev->ops->lib->flush_queue))
+               queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
 
        /*
         * The queue flush has failed...
@@ -959,10 +1040,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
        queue->count = 0;
        queue->length = 0;
 
-       for (i = 0; i < Q_INDEX_MAX; i++) {
+       for (i = 0; i < Q_INDEX_MAX; i++)
                queue->index[i] = 0;
-               queue->last_action[i] = jiffies;
-       }
 
        spin_unlock_irqrestore(&queue->index_lock, irqflags);
 }
@@ -1069,7 +1148,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
        if (status)
                goto exit;
 
-       if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
+       if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {
                status = rt2x00queue_alloc_entries(rt2x00dev->atim,
                                                   rt2x00dev->ops->atim);
                if (status)
@@ -1121,7 +1200,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
        struct data_queue *queue;
        enum data_queue_qid qid;
        unsigned int req_atim =
-           !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+           !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
 
        /*
         * We need the following queues:
index 5db6a99fce7db34d927dcfeb4cbdb18df067a6be..167d45873dcab4e35fa757f0ea4c70c5e13a56e7 100644 (file)
@@ -364,6 +364,7 @@ enum queue_entry_flags {
  * struct queue_entry: Entry inside the &struct data_queue
  *
  * @flags: Entry flags, see &enum queue_entry_flags.
+ * @last_action: Timestamp of last change.
  * @queue: The data queue (&struct data_queue) to which this entry belongs.
  * @skb: The buffer which is currently being transmitted (for TX queue),
  *     or used to directly receive data in (for RX queue).
@@ -373,6 +374,7 @@ enum queue_entry_flags {
  */
 struct queue_entry {
        unsigned long flags;
+       unsigned long last_action;
 
        struct data_queue *queue;
 
@@ -463,7 +465,6 @@ struct data_queue {
        unsigned short threshold;
        unsigned short length;
        unsigned short index[Q_INDEX_MAX];
-       unsigned long last_action[Q_INDEX_MAX];
 
        unsigned short txop;
        unsigned short aifs;
@@ -580,16 +581,22 @@ struct data_queue_desc {
  * @queue: Pointer to @data_queue
  * @start: &enum queue_index Pointer to start index
  * @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
  * @fn: The function to call for each &struct queue_entry
  *
  * This will walk through all entries in the queue, in chronological
  * order. This means it will start at the current @start pointer
  * and will walk through the queue until it reaches the @end pointer.
+ *
+ * If fn returns true for an entry rt2x00queue_for_each_entry will stop
+ * processing and return true as well.
  */
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
                                enum queue_index start,
                                enum queue_index end,
-                               void (*fn)(struct queue_entry *entry));
+                               void *data,
+                               bool (*fn)(struct queue_entry *entry,
+                                          void *data));
 
 /**
  * rt2x00queue_empty - Check if the queue is empty.
@@ -629,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
 
 /**
  * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports
- * @queue: Queue to check.
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_status_timeout(struct data_queue *queue)
+static inline int rt2x00queue_status_timeout(struct queue_entry *entry)
 {
-       return time_after(queue->last_action[Q_INDEX_DMA_DONE],
-                         queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+       if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+               return false;
+       return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occurred for DMA transfers
- * @queue: Queue to check.
+ * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
 {
-       return time_after(queue->last_action[Q_INDEX],
-                         queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return false;
+       return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
index 36f388f97d658e27c40defe1a9e3a79c585d2a15..cb208d589ff87d48dd8f9260dcddbf0bfa33ab6d 100644 (file)
@@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
 
+
+struct rt2x00_async_read_data {
+       __le32 reg;
+       struct usb_ctrlrequest cr;
+       struct rt2x00_dev *rt2x00dev;
+       void (*callback)(struct rt2x00_dev *,int,u32);
+};
+
+static void rt2x00usb_register_read_async_cb(struct urb *urb)
+{
+       struct rt2x00_async_read_data *rd = urb->context;
+       rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg));
+       kfree(urb->context);
+}
+
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset,
+                                  void (*callback)(struct rt2x00_dev*,int,u32))
+{
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct urb *urb;
+       struct rt2x00_async_read_data *rd;
+
+       rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+       if (!rd)
+               return;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               kfree(rd);
+               return;
+       }
+
+       rd->rt2x00dev = rt2x00dev;
+       rd->callback = callback;
+       rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
+       rd->cr.bRequest = USB_MULTI_READ;
+       rd->cr.wValue = 0;
+       rd->cr.wIndex = cpu_to_le16(offset);
+       rd->cr.wLength = cpu_to_le16(sizeof(u32));
+
+       usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+                            (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
+                            rt2x00usb_register_read_async_cb, rd);
+       if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+               kfree(rd);
+       usb_free_urb(urb);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
+
 /*
  * TX data handlers.
  */
@@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
        if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
 
+       if (rt2x00dev->ops->lib->tx_dma_done)
+               rt2x00dev->ops->lib->tx_dma_done(entry);
+
        /*
         * Report the frame as DMA done
         */
@@ -227,10 +280,12 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
         * Schedule the delayed work for reading the TX status
         * from the device.
         */
-       queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+       if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
+           !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
-static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -240,7 +295,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 
        if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
            test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-               return;
+               return true;
 
        /*
         * USB devices cannot blindly pass the skb->len as the
@@ -261,6 +316,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
                set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
                rt2x00lib_dmadone(entry);
        }
+
+       return false;
 }
 
 /*
@@ -323,7 +380,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
        queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
-static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -332,7 +389,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
 
        if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
            test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-               return;
+               return true;
 
        rt2x00lib_dmastart(entry);
 
@@ -348,6 +405,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
                set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
                rt2x00lib_dmadone(entry);
        }
+
+       return false;
 }
 
 void rt2x00usb_kick_queue(struct data_queue *queue)
@@ -358,12 +417,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
        case QID_AC_BE:
        case QID_AC_BK:
                if (!rt2x00queue_empty(queue))
-                       rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+                       rt2x00queue_for_each_entry(queue,
+                                                  Q_INDEX_DONE,
+                                                  Q_INDEX,
+                                                  NULL,
                                                   rt2x00usb_kick_tx_entry);
                break;
        case QID_RX:
                if (!rt2x00queue_full(queue))
-                       rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+                       rt2x00queue_for_each_entry(queue,
+                                                  Q_INDEX_DONE,
+                                                  Q_INDEX,
+                                                  NULL,
                                                   rt2x00usb_kick_rx_entry);
                break;
        default:
@@ -372,14 +437,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
 
-static void rt2x00usb_flush_entry(struct queue_entry *entry)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct queue_entry_priv_usb *entry_priv = entry->priv_data;
        struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
 
        if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return;
+               return true;
 
        usb_kill_urb(entry_priv->urb);
 
@@ -387,17 +452,20 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
         * Kill guardian urb (if required by driver).
         */
        if ((entry->queue->qid == QID_BEACON) &&
-           (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+           (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
                usb_kill_urb(bcn_priv->guardian_urb);
+
+       return false;
 }
 
-void rt2x00usb_flush_queue(struct data_queue *queue)
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
 {
        struct work_struct *completion;
        unsigned int i;
 
-       rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
-                                  rt2x00usb_flush_entry);
+       if (drop)
+               rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+                                          rt2x00usb_flush_entry);
 
        /*
         * Obtain the queue completion handler
@@ -416,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
                return;
        }
 
-       for (i = 0; i < 20; i++) {
+       for (i = 0; i < 10; i++) {
                /*
                 * Check if the driver is already done, otherwise we
                 * have to sleep a little while to give the driver/hw
@@ -456,15 +524,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
        queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
 }
 
+static int rt2x00usb_status_timeout(struct data_queue *queue)
+{
+       struct queue_entry *entry;
+
+       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+       return rt2x00queue_status_timeout(entry);
+}
+
+static int rt2x00usb_dma_timeout(struct data_queue *queue)
+{
+       struct queue_entry *entry;
+
+       entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+       return rt2x00queue_dma_timeout(entry);
+}
+
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
 {
        struct data_queue *queue;
 
        tx_queue_for_each(rt2x00dev, queue) {
                if (!rt2x00queue_empty(queue)) {
-                       if (rt2x00queue_dma_timeout(queue))
+                       if (rt2x00usb_dma_timeout(queue))
                                rt2x00usb_watchdog_tx_dma(queue);
-                       if (rt2x00queue_status_timeout(queue))
+                       if (rt2x00usb_status_timeout(queue))
                                rt2x00usb_watchdog_tx_status(queue);
                }
        }
@@ -489,7 +573,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
        entry->flags = 0;
 
        if (entry->queue->qid == QID_RX)
-               rt2x00usb_kick_rx_entry(entry);
+               rt2x00usb_kick_rx_entry(entry, NULL);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
 
@@ -583,7 +667,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)
         * then we are done.
         */
        if (queue->qid != QID_BEACON ||
-           !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+           !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
                return 0;
 
        for (i = 0; i < queue->limit; i++) {
@@ -618,7 +702,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue)
         * then we are done.
         */
        if (queue->qid != QID_BEACON ||
-           !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+           !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
                return;
 
        for (i = 0; i < queue->limit; i++) {
@@ -707,10 +791,9 @@ exit:
 }
 
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-                   const struct usb_device_id *id)
+                   const struct rt2x00_ops *ops)
 {
        struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
-       struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
        struct ieee80211_hw *hw;
        struct rt2x00_dev *rt2x00dev;
        int retval;
@@ -735,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 
        INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
        INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+       init_timer(&rt2x00dev->txstatus_timer);
 
        retval = rt2x00usb_alloc_reg(rt2x00dev);
        if (retval)
index e11c759ac9ed928ef85e6aa7a00e9aa20abc9b4b..64be34f612f6b10f59ee99a83383f26815260f58 100644 (file)
        interface_to_usbdev(intf); \
 })
 
-/*
- * This variable should be used with the
- * usb_driver structure initialization.
- */
-#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
-
 /*
  * For USB vendor requests we need to pass a timeout
  * time in ms, for this we use the REGISTER_TIMEOUT,
@@ -345,6 +339,21 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
                           const struct rt2x00_field32 field,
                           u32 *reg);
 
+/**
+ * rt2x00usb_register_read_async - Asynchronously read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @callback: Functon to call when read completes.
+ *
+ * Submit a control URB to read a 32bit register. This safe to
+ * be called from atomic context.  The callback will be called
+ * when the URB completes. Otherwise the function is similar
+ * to rt2x00usb_register_read().
+ */
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset,
+                                  void (*callback)(struct rt2x00_dev*,int,u32));
+
 /*
  * Radio handlers
  */
@@ -389,11 +398,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue);
 /**
  * rt2x00usb_flush_queue - Flush data queue
  * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
  *
- * This will walk through all entries of the queue and kill all
- * URB's which were send to the device.
+ * This will walk through all entries of the queue and will optionally
+ * kill all URB's which were send to the device, or at least wait until
+ * they have been returned from the device..
  */
-void rt2x00usb_flush_queue(struct data_queue *queue);
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
 
 /**
  * rt2x00usb_watchdog - Watchdog for USB communication
@@ -416,7 +427,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
  * USB driver handlers.
  */
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-                   const struct usb_device_id *id);
+                   const struct rt2x00_ops *ops);
 void rt2x00usb_disconnect(struct usb_interface *usb_intf);
 #ifdef CONFIG_PM
 int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
index 8ee1514a7943ddc0ddcb54d436bfc096fcceb2d1..9d35ec16a3a5ff9c8c226837ce69da8c29fc35df 100644 (file)
@@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-                         !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+                         !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
        /*
         * Configure the RX antenna.
@@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
 
        if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                sel = antenna_sel_a;
-               lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+               lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
        } else {
                sel = antenna_sel_bg;
-               lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+               lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
        }
 
        for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
        else if (rt2x00_rf(rt2x00dev, RF2527))
                rt61pci_config_antenna_2x(rt2x00dev, ant);
        else if (rt2x00_rf(rt2x00dev, RF2529)) {
-               if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
+               if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags))
                        rt61pci_config_antenna_2x(rt2x00dev, ant);
                else
                        rt61pci_config_antenna_2529(rt2x00dev, ant);
@@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
        short lna_gain = 0;
 
        if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
                        lna_gain += 14;
 
                rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
                lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
        } else {
-               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
                        lna_gain += 14;
 
                rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
@@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
        if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                low_bound = 0x28;
                up_bound = 0x48;
-               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
                        low_bound += 0x10;
                        up_bound += 0x10;
                }
        } else {
                low_bound = 0x20;
                up_bound = 0x40;
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
                        low_bound += 0x10;
                        up_bound += 0x10;
                }
@@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
        rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                    struct rt2x00_field32 irq_field)
+static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                           struct rt2x00_field32 irq_field)
 {
        u32 reg;
 
@@ -2537,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Determine number of antennas.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
-               __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);
 
        /*
         * Identify default antenna configuration.
@@ -2551,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Read the Frame type.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-               __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
        /*
         * Detect if this device has a hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Read frequency offset and RF programming sequence.
         */
        rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
        if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
-               __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
 
        rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
@@ -2574,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-               __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-               __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
        /*
         * When working with a RF2529 chip without double antenna,
@@ -2584,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * eeprom word.
         */
        if (rt2x00_rf(rt2x00dev, RF2529) &&
-           !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+           !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) {
                rt2x00dev->default_ant.rx =
                    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
                rt2x00dev->default_ant.tx =
@@ -2799,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        spec->supported_bands = SUPPORT_BAND_2GHZ;
        spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
-       if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) {
+       if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) {
                spec->num_channels = 14;
                spec->channels = rf_vals_noseq;
        } else {
@@ -2869,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
         * This device has multiple filters for control frames,
         * but has no a separate filter for PS Poll frames.
         */
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
        /*
         * This device requires firmware and DMA mapped skbs.
         */
-       __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
        if (!modparam_nohwcrypt)
-               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -2979,6 +2979,9 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .get_tsf                = rt61pci_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -3003,6 +3006,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .start_queue            = rt61pci_start_queue,
        .kick_queue             = rt61pci_kick_queue,
        .stop_queue             = rt61pci_stop_queue,
+       .flush_queue            = rt2x00pci_flush_queue,
        .write_tx_desc          = rt61pci_write_tx_desc,
        .write_beacon           = rt61pci_write_beacon,
        .clear_beacon           = rt61pci_clear_beacon,
@@ -3060,11 +3064,11 @@ static const struct rt2x00_ops rt61pci_ops = {
  */
 static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
        /* RT2561s */
-       { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0301) },
        /* RT2561 v2 */
-       { PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0302) },
        /* RT2661 */
-       { PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) },
+       { PCI_DEVICE(0x1814, 0x0401) },
        { 0, }
 };
 
@@ -3079,10 +3083,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);
 MODULE_FIRMWARE(FIRMWARE_RT2661);
 MODULE_LICENSE("GPL");
 
+static int rt61pci_probe(struct pci_dev *pci_dev,
+                        const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
 static struct pci_driver rt61pci_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt61pci_device_table,
-       .probe          = rt2x00pci_probe,
+       .probe          = rt61pci_probe,
        .remove         = __devexit_p(rt2x00pci_remove),
        .suspend        = rt2x00pci_suspend,
        .resume         = rt2x00pci_resume,
index 6593059f9c7e5809dc5d7aaed2470acb0f4ac4d7..a6ce7d6cbdfae3c7e30b174cf1961b2940a4df51 100644 (file)
@@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
        switch (ant->rx) {
        case ANTENNA_HW_DIVERSITY:
                rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-               temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+               temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)
                       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
                rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
                break;
@@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
 
        rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
        rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-                         !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+                         !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
        /*
         * Configure the RX antenna.
@@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
 
        if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
                sel = antenna_sel_a;
-               lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+               lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
        } else {
                sel = antenna_sel_bg;
-               lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+               lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
        }
 
        for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
        short lna_gain = 0;
 
        if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
                        lna_gain += 14;
 
                rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
@@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
                low_bound = 0x28;
                up_bound = 0x48;
 
-               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
                        low_bound += 0x10;
                        up_bound += 0x10;
                }
@@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
                        up_bound = 0x1c;
                }
 
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
                        low_bound += 0x14;
                        up_bound += 0x10;
                }
@@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
        }
 
        if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+               if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
                        if (lna == 3 || lna == 2)
                                offset += 10;
                } else {
@@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Read the Frame type.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-               __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
        /*
         * Detect if this device has an hardware controlled radio.
         */
        if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
        /*
         * Read frequency offset.
@@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
        if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
-               __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-               __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
        }
 
        /*
@@ -2200,15 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
         * This device has multiple filters for control frames,
         * but has no a separate filter for PS Poll frames.
         */
-       __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
        /*
         * This device requires firmware.
         */
-       __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
        if (!modparam_nohwcrypt)
-               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-       __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
        /*
         * Set the rssi offset.
@@ -2310,6 +2310,9 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .get_tsf                = rt73usb_get_tsf,
        .rfkill_poll            = rt2x00mac_rfkill_poll,
        .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2388,113 +2391,113 @@ static const struct rt2x00_ops rt73usb_ops = {
  */
 static struct usb_device_id rt73usb_device_table[] = {
        /* AboCom */
-       { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21b) },
+       { USB_DEVICE(0x07b8, 0xb21c) },
+       { USB_DEVICE(0x07b8, 0xb21d) },
+       { USB_DEVICE(0x07b8, 0xb21e) },
+       { USB_DEVICE(0x07b8, 0xb21f) },
        /* AL */
-       { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x14b2, 0x3c10) },
        /* Amigo */
-       { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x148f, 0x9021) },
+       { USB_DEVICE(0x0eb0, 0x9021) },
        /* AMIT  */
-       { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x18c5, 0x0002) },
        /* Askey */
-       { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1690, 0x0722) },
        /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0b05, 0x1723) },
+       { USB_DEVICE(0x0b05, 0x1724) },
        /* Belkin */
-       { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x050d, 0x705a) },
+       { USB_DEVICE(0x050d, 0x905b) },
+       { USB_DEVICE(0x050d, 0x905c) },
        /* Billionton */
-       { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1631, 0xc019) },
+       { USB_DEVICE(0x08dd, 0x0120) },
        /* Buffalo */
-       { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0411, 0x00d8) },
+       { USB_DEVICE(0x0411, 0x00d9) },
+       { USB_DEVICE(0x0411, 0x00f4) },
+       { USB_DEVICE(0x0411, 0x0116) },
+       { USB_DEVICE(0x0411, 0x0119) },
+       { USB_DEVICE(0x0411, 0x0137) },
        /* CEIVA */
-       { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x178d, 0x02be) },
        /* CNet */
-       { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1371, 0x9022) },
+       { USB_DEVICE(0x1371, 0x9032) },
        /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x14b2, 0x3c22) },
        /* Corega */
-       { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07aa, 0x002e) },
        /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07d1, 0x3c03) },
+       { USB_DEVICE(0x07d1, 0x3c04) },
+       { USB_DEVICE(0x07d1, 0x3c06) },
+       { USB_DEVICE(0x07d1, 0x3c07) },
        /* Edimax */
-       { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x7392, 0x7318) },
+       { USB_DEVICE(0x7392, 0x7618) },
        /* EnGenius */
-       { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1740, 0x3701) },
        /* Gemtek */
-       { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x15a9, 0x0004) },
        /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1044, 0x8008) },
+       { USB_DEVICE(0x1044, 0x800a) },
        /* Huawei-3Com */
-       { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1472, 0x0009) },
        /* Hercules */
-       { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x06f8, 0xe002) },
+       { USB_DEVICE(0x06f8, 0xe010) },
+       { USB_DEVICE(0x06f8, 0xe020) },
        /* Linksys */
-       { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x13b1, 0x0020) },
+       { USB_DEVICE(0x13b1, 0x0023) },
+       { USB_DEVICE(0x13b1, 0x0028) },
        /* MSI */
-       { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0db0, 0x4600) },
+       { USB_DEVICE(0x0db0, 0x6877) },
+       { USB_DEVICE(0x0db0, 0x6874) },
+       { USB_DEVICE(0x0db0, 0xa861) },
+       { USB_DEVICE(0x0db0, 0xa874) },
        /* Ovislink */
-       { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1b75, 0x7318) },
        /* Ralink */
-       { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x04bb, 0x093d) },
+       { USB_DEVICE(0x148f, 0x2573) },
+       { USB_DEVICE(0x148f, 0x2671) },
+       { USB_DEVICE(0x0812, 0x3101) },
        /* Qcom */
-       { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x18e8, 0x6196) },
+       { USB_DEVICE(0x18e8, 0x6229) },
+       { USB_DEVICE(0x18e8, 0x6238) },
        /* Samsung */
-       { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x04e8, 0x4471) },
        /* Senao */
-       { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x1740, 0x7100) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0024) },
+       { USB_DEVICE(0x0df6, 0x0027) },
+       { USB_DEVICE(0x0df6, 0x002f) },
+       { USB_DEVICE(0x0df6, 0x90ac) },
+       { USB_DEVICE(0x0df6, 0x9712) },
        /* Surecom */
-       { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0769, 0x31f3) },
        /* Tilgin */
-       { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x6933, 0x5001) },
        /* Philips */
-       { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0471, 0x200a) },
        /* Planex */
-       { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
-       { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x2019, 0xab01) },
+       { USB_DEVICE(0x2019, 0xab50) },
        /* WideTell */
-       { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x7167, 0x3840) },
        /* Zcom */
-       { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0cde, 0x001c) },
        /* ZyXEL */
-       { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0586, 0x3415) },
        { 0, }
 };
 
@@ -2506,10 +2509,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
 MODULE_FIRMWARE(FIRMWARE_RT2571);
 MODULE_LICENSE("GPL");
 
+static int rt73usb_probe(struct usb_interface *usb_intf,
+                        const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
 static struct usb_driver rt73usb_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rt73usb_device_table,
-       .probe          = rt2x00usb_probe,
+       .probe          = rt73usb_probe,
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
index 4803f54842e4db9a36fa7e89fa4fb59be07eb006..b259f807ad27b461bd7dccc75ce3b4d9c25001fd 100644 (file)
@@ -251,14 +251,16 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)
        bool blocked;
        u8 valid = 0;
 
-       radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
+       /*set init state to on */
+       rtlpriv->rfkill.rfkill_state = 1;
+       wiphy_rfkill_set_hw_state(hw->wiphy, 0);
 
-       /*set init state to that of switch */
-       rtlpriv->rfkill.rfkill_state = radio_state;
-       printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
-              rtlpriv->rfkill.rfkill_state ? "on" : "off");
+       radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
 
        if (valid) {
+               printk(KERN_INFO "rtlwifi: wireless switch is %s\n",
+                               rtlpriv->rfkill.rfkill_state ? "on" : "off");
+
                rtlpriv->rfkill.rfkill_state = radio_state;
 
                blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
index fbde52d834245dfe18bbe327db176839c57d8ce5..c3dd4cc678ba52f326263768de28e19d7c5a4647 100644 (file)
@@ -1785,7 +1785,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 
        rtl_pci_deinit(hw);
        rtl_deinit_core(hw);
-       rtlpriv->cfg->ops->deinit_sw_leds(hw);
+       if (rtlpriv->cfg->ops->deinit_sw_leds)
+               rtlpriv->cfg->ops->deinit_sw_leds(hw);
        _rtl_pci_io_handler_release(hw);
        rtlpriv->cfg->ops->deinit_sw_vars(hw);
 
index bb023274414c9ee65587e45dcdb1e84b130c2e8b..c228b9ee37113a1b0098e34c9d69132b4a67dd33 100644 (file)
@@ -634,7 +634,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
        u8 thermalvalue, delta, delta_lck, delta_iqk;
        long ele_a, ele_d, temp_cck, val_x, value32;
        long val_y, ele_c;
-       u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old;
+       u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
        int i;
        bool is2t = IS_92C_SERIAL(rtlhal->version);
        u8 txpwr_level[2] = {0, 0};
index f107660f545dc71c92074a9b8a937971baee7406..bc9d24134ac4d155d6db882eb250fec29562a2f3 100644 (file)
@@ -293,7 +293,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        u8 boxnum;
-       u16 box_reg, box_extreg;
+       u16 box_reg = 0, box_extreg = 0;
        u8 u1b_tmp;
        bool isfw_read = false;
        bool bwrite_sucess = false;
index 7b1da8d7508f2416dce677bbe214d90f6b2011f0..d21b934b5c3373a68ca97086b973b53e1cd5718e 100644 (file)
 #include "reg.h"
 #include "led.h"
 
+static void _rtl92ce_init_led(struct ieee80211_hw *hw,
+                             struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+       pled->hw = hw;
+       pled->ledpin = ledpin;
+       pled->ledon = false;
+}
+
 void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
 {
        u8 ledcfg;
@@ -97,10 +105,10 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 
 void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
 {
-}
+       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 
-void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw)
-{
+       _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
+       _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
 }
 
 void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
index 10da3018f4b700eb6421d1cd2265b6c1d5b8a7de..94332b3af5b1e21cb951226a620432a833d01966 100644 (file)
@@ -31,7 +31,6 @@
 #define __RTL92CE_LED_H__
 
 void rtl92ce_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw);
 void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
 void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
 void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
index 669b1168dbec8d75ce57477569b6f26efcb01933..e301b12e281afa5505709f8e5f97a13deac8f8ec 100644 (file)
@@ -202,7 +202,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-       u8 i, chnlgroup, pwr_diff_limit[4];
+       u8 i, chnlgroup = 0, pwr_diff_limit[4];
        u32 writeVal, customer_limit, rf;
 
        for (rf = 0; rf < 2; rf++) {
@@ -447,7 +447,7 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
-       u32 u4_regvalue;
+       u32 u4_regvalue = 0;
        u8 rfpath;
        bool rtstatus;
        struct bb_reg_def *pphyreg;
index b1cc4d44f534b464198e63bfe7612b9da8b1ac1c..f4e2f3dcccaeb0efc1d245edea2a856bafe9a2c6 100644 (file)
@@ -131,7 +131,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
        .enable_hw_sec = rtl92ce_enable_hw_security_config,
        .set_key = rtl92ce_set_key,
        .init_sw_leds = rtl92ce_init_sw_leds,
-       .deinit_sw_leds = rtl92ce_deinit_sw_leds,
        .get_bbreg = rtl92c_phy_query_bb_reg,
        .set_bbreg = rtl92c_phy_set_bb_reg,
        .get_rfreg = rtl92ce_phy_query_rf_reg,
index 9444e76838cfe59fb95938c6a769d7af031c0980..e43be254782787e57b13fcabb9e77b13929baaf4 100644 (file)
@@ -921,7 +921,7 @@ static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw,
                                               u8 out_ep_num,
                                               u8 queue_sel)
 {
-       u8      hq_sele;
+       u8 hq_sele = 0;
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
        switch (out_ep_num) {
index 1832c27c520c4a865aa423195f84f0192b8abe30..216b1d8a862fcc56999cc3958144908d79c35599 100644 (file)
  *     notification. This event is used to indicate that an unprotected
  *     disassociation frame was dropped when MFP is in use.
  *
+ * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
+ *      beacon or probe response from a compatible mesh peer.  This is only
+ *      sent while no station information (sta_info) exists for the new peer
+ *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set.  On
+ *      reception of this notification, userspace may decide to create a new
+ *      station (@NL80211_CMD_NEW_STATION).  To stop this notification from
+ *      reoccurring, the userspace authentication daemon may want to create the
+ *      new station with the AUTHENTICATED flag unset and maybe change it later
+ *      depending on the authentication result.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -522,6 +532,8 @@ enum nl80211_commands {
        NL80211_CMD_UNPROT_DEAUTHENTICATE,
        NL80211_CMD_UNPROT_DISASSOCIATE,
 
+       NL80211_CMD_NEW_PEER_CANDIDATE,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -545,6 +557,7 @@ enum nl80211_commands {
 /* source-level API compatibility */
 #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG
 #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG
+#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE
 
 /**
  * enum nl80211_attrs - nl80211 netlink attributes
@@ -886,6 +899,9 @@ enum nl80211_commands {
  *     changed once the mesh is active.
  * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute
  *     containing attributes from &enum nl80211_meshconf_params.
+ * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
+ *     allows auth frames in a mesh to be passed to userspace for processing via
+ *     the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
  *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1074,6 +1090,8 @@ enum nl80211_attrs {
        NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
        NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
 
+       NL80211_ATTR_SUPPORT_MESH_AUTH,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -1168,6 +1186,7 @@ enum nl80211_iftype {
  *     with short barker preamble
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -1177,6 +1196,7 @@ enum nl80211_sta_flags {
        NL80211_STA_FLAG_SHORT_PREAMBLE,
        NL80211_STA_FLAG_WME,
        NL80211_STA_FLAG_MFP,
+       NL80211_STA_FLAG_AUTHENTICATED,
 
        /* keep last */
        __NL80211_STA_FLAG_AFTER_LAST,
@@ -1277,6 +1297,7 @@ enum nl80211_sta_bss_param {
  *     attribute, like NL80211_STA_INFO_TX_BITRATE.
  * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute
  *     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_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -1297,6 +1318,7 @@ enum nl80211_sta_info {
        NL80211_STA_INFO_SIGNAL_AVG,
        NL80211_STA_INFO_RX_BITRATE,
        NL80211_STA_INFO_BSS_PARAM,
+       NL80211_STA_INFO_CONNECTED_TIME,
 
        /* keep last */
        __NL80211_STA_INFO_AFTER_LAST,
@@ -1719,9 +1741,12 @@ enum nl80211_meshconf_params {
  * vendor specific path metric or disable it to use the default Airtime
  * metric.
  *
- * @NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE: A vendor specific information
- * element that vendors will use to identify the path selection methods and
- * metrics in use.
+ * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a
+ * robust security network ie, or a vendor specific information element that
+ * vendors will use to identify the path selection methods and metrics in use.
+ *
+ * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
+ * daemon will be authenticating mesh candidates.
  *
  * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
  * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -1730,7 +1755,8 @@ enum nl80211_mesh_setup_params {
        __NL80211_MESH_SETUP_INVALID,
        NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL,
        NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
-       NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE,
+       NL80211_MESH_SETUP_IE,
+       NL80211_MESH_SETUP_USERSPACE_AUTH,
 
        /* keep last */
        __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
diff --git a/include/linux/rfkill-regulator.h b/include/linux/rfkill-regulator.h
new file mode 100644 (file)
index 0000000..aca36bc
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * rfkill-regulator.c - Regulator consumer driver for rfkill
+ *
+ * Copyright (C) 2009  Guiming Zhuo <gmzhuo@gmail.com>
+ * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_RFKILL_REGULATOR_H
+#define __LINUX_RFKILL_REGULATOR_H
+
+/*
+ * Use "vrfkill" as supply id when declaring the regulator consumer:
+ *
+ * static struct regulator_consumer_supply pcap_regulator_V6_consumers [] = {
+ *     { .dev_name = "rfkill-regulator.0", .supply = "vrfkill" },
+ * };
+ *
+ * If you have several regulator driven rfkill, you can append a numerical id to
+ * .dev_name as done above, and use the same id when declaring the platform
+ * device:
+ *
+ * static struct rfkill_regulator_platform_data ezx_rfkill_bt_data = {
+ *     .name  = "ezx-bluetooth",
+ *     .type  = RFKILL_TYPE_BLUETOOTH,
+ * };
+ *
+ * static struct platform_device a910_rfkill = {
+ *     .name  = "rfkill-regulator",
+ *     .id    = 0,
+ *     .dev   = {
+ *             .platform_data = &ezx_rfkill_bt_data,
+ *     },
+ * };
+ */
+
+#include <linux/rfkill.h>
+
+struct rfkill_regulator_platform_data {
+       char *name;             /* the name for the rfkill switch */
+       enum rfkill_type type;  /* the type as specified in rfkill.h */
+};
+
+#endif /* __LINUX_RFKILL_REGULATOR_H */
index 2b9ca0d5c4a0fc831bb4ffa5e7f1a82b5d481322..7a215a7f9e391c3d9ef72651d3bb76a4c2f08309 100644 (file)
@@ -276,10 +276,52 @@ struct l2cap_conn_param_update_rsp {
 #define L2CAP_CONN_PARAM_ACCEPTED      0x0000
 #define L2CAP_CONN_PARAM_REJECTED      0x0001
 
-/* ----- L2CAP connections ----- */
-struct l2cap_chan_list {
-       struct sock     *head;
-       rwlock_t        lock;
+/* ----- L2CAP channels and connections ----- */
+struct srej_list {
+       __u8    tx_seq;
+       struct list_head list;
+};
+
+struct l2cap_chan {
+       struct sock *sk;
+       __u8            ident;
+
+       __u8            conf_req[64];
+       __u8            conf_len;
+       __u8            num_conf_req;
+       __u8            num_conf_rsp;
+
+       __u16           conn_state;
+
+       __u8            next_tx_seq;
+       __u8            expected_ack_seq;
+       __u8            expected_tx_seq;
+       __u8            buffer_seq;
+       __u8            buffer_seq_srej;
+       __u8            srej_save_reqseq;
+       __u8            frames_sent;
+       __u8            unacked_frames;
+       __u8            retry_count;
+       __u8            num_acked;
+       __u16           sdu_len;
+       __u16           partial_sdu_len;
+       struct sk_buff  *sdu;
+
+       __u8            remote_tx_win;
+       __u8            remote_max_tx;
+       __u16           remote_mps;
+
+       struct timer_list       retrans_timer;
+       struct timer_list       monitor_timer;
+       struct timer_list       ack_timer;
+       struct sk_buff          *tx_send_head;
+       struct sk_buff_head     tx_q;
+       struct sk_buff_head     srej_q;
+       struct sk_buff_head     busy_q;
+       struct work_struct      busy_work;
+       struct list_head        srej_l;
+
+       struct list_head list;
 };
 
 struct l2cap_conn {
@@ -305,29 +347,16 @@ struct l2cap_conn {
 
        __u8            disc_reason;
 
-       struct l2cap_chan_list chan_list;
-};
-
-struct sock_del_list {
-       struct sock *sk;
-       struct list_head list;
+       struct list_head chan_l;
+       rwlock_t        chan_lock;
 };
 
 #define L2CAP_INFO_CL_MTU_REQ_SENT     0x01
 #define L2CAP_INFO_FEAT_MASK_REQ_SENT  0x04
 #define L2CAP_INFO_FEAT_MASK_REQ_DONE  0x08
 
-/* ----- L2CAP channel and socket info ----- */
+/* ----- L2CAP socket info ----- */
 #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
-#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
-#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue)
-#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue)
-#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list)
-
-struct srej_list {
-       __u8    tx_seq;
-       struct list_head list;
-};
 
 struct l2cap_pinfo {
        struct bt_sock  bt;
@@ -339,8 +368,6 @@ struct l2cap_pinfo {
        __u16           omtu;
        __u16           flush_to;
        __u8            mode;
-       __u8            num_conf_req;
-       __u8            num_conf_rsp;
 
        __u8            fcs;
        __u8            sec_level;
@@ -348,49 +375,18 @@ struct l2cap_pinfo {
        __u8            force_reliable;
        __u8            flushable;
 
-       __u8            conf_req[64];
-       __u8            conf_len;
        __u8            conf_state;
-       __u16           conn_state;
-
-       __u8            next_tx_seq;
-       __u8            expected_ack_seq;
-       __u8            expected_tx_seq;
-       __u8            buffer_seq;
-       __u8            buffer_seq_srej;
-       __u8            srej_save_reqseq;
-       __u8            frames_sent;
-       __u8            unacked_frames;
-       __u8            retry_count;
-       __u8            num_acked;
-       __u16           sdu_len;
-       __u16           partial_sdu_len;
-       struct sk_buff  *sdu;
-
-       __u8            ident;
 
        __u8            tx_win;
        __u8            max_tx;
-       __u8            remote_tx_win;
-       __u8            remote_max_tx;
        __u16           retrans_timeout;
        __u16           monitor_timeout;
-       __u16           remote_mps;
        __u16           mps;
 
        __le16          sport;
 
-       struct timer_list       retrans_timer;
-       struct timer_list       monitor_timer;
-       struct timer_list       ack_timer;
-       struct sk_buff_head     tx_queue;
-       struct sk_buff_head     srej_queue;
-       struct sk_buff_head     busy_queue;
-       struct work_struct      busy_work;
-       struct srej_list        srej_l;
        struct l2cap_conn       *conn;
-       struct sock             *next_c;
-       struct sock             *prev_c;
+       struct l2cap_chan       *chan;
 };
 
 #define L2CAP_CONF_REQ_SENT       0x01
@@ -417,24 +413,23 @@ struct l2cap_pinfo {
 #define L2CAP_CONN_RNR_SENT        0x0200
 #define L2CAP_CONN_SAR_RETRY       0x0400
 
-#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
+#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \
                jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
-#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \
+#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \
                jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
-#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \
+#define __mod_ack_timer() mod_timer(&chan->ack_timer, \
                jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
 
-static inline int l2cap_tx_window_full(struct sock *sk)
+static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        int sub;
 
-       sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64;
+       sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64;
 
        if (sub < 0)
                sub += 64;
 
-       return sub == pi->remote_tx_win;
+       return sub == ch->remote_tx_win;
 }
 
 #define __get_txseq(ctrl)      (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
@@ -450,18 +445,17 @@ extern struct bt_sock_list l2cap_sk_list;
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 
-u8 l2cap_get_ident(struct l2cap_conn *conn);
 void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
-int l2cap_build_conf_req(struct sock *sk, void *data);
+void __l2cap_connect_rsp_defer(struct sock *sk);
 int __l2cap_wait_ack(struct sock *sk);
 
 struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
 struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
 struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
-int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len);
+int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
 void l2cap_do_send(struct sock *sk, struct sk_buff *skb);
-void l2cap_streaming_send(struct sock *sk);
-int l2cap_ertm_send(struct sock *sk);
+void l2cap_streaming_send(struct l2cap_chan *chan);
+int l2cap_ertm_send(struct l2cap_chan *chan);
 
 void l2cap_sock_set_timer(struct sock *sk, long timeout);
 void l2cap_sock_clear_timer(struct sock *sk);
@@ -470,8 +464,8 @@ void l2cap_sock_kill(struct sock *sk);
 void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
                                                        int proto, gfp_t prio);
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
-void l2cap_chan_del(struct sock *sk, int err);
+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
+void l2cap_chan_del(struct l2cap_chan *chan, int err);
 int l2cap_do_connect(struct sock *sk);
 
 #endif /* __L2CAP_H */
index ba7384acf4e0c6307a5976f308d8d692c791f8c3..d30eada7c6cd8e3dfab83cc065c59edf54eb7917 100644 (file)
@@ -423,6 +423,7 @@ struct station_parameters {
  * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
  * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
  * @STATION_INFO_BSS_PARAM: @bss_param filled
+ * @STATION_INFO_CONNECTED_TIME: @connected_time filled
  */
 enum station_info_flags {
        STATION_INFO_INACTIVE_TIME      = 1<<0,
@@ -441,6 +442,7 @@ enum station_info_flags {
        STATION_INFO_SIGNAL_AVG         = 1<<13,
        STATION_INFO_RX_BITRATE         = 1<<14,
        STATION_INFO_BSS_PARAM          = 1<<15,
+       STATION_INFO_CONNECTED_TIME     = 1<<16
 };
 
 /**
@@ -511,6 +513,7 @@ struct sta_bss_parameters {
  * Station information filled by driver for get_station() and dump_station.
  *
  * @filled: bitflag of flags from &enum station_info_flags
+ * @connected_time: time(in secs) since a station is last connected
  * @inactive_time: time since last station activity (tx/rx) in milliseconds
  * @rx_bytes: bytes received from this station
  * @tx_bytes: bytes transmitted to this station
@@ -533,6 +536,7 @@ struct sta_bss_parameters {
  */
 struct station_info {
        u32 filled;
+       u32 connected_time;
        u32 inactive_time;
        u32 rx_bytes;
        u32 tx_bytes;
@@ -689,8 +693,9 @@ struct mesh_config {
  * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
  * @path_sel_proto: which path selection protocol to use
  * @path_metric: which metric to use
- * @vendor_ie: vendor information elements (optional)
- * @vendor_ie_len: length of vendor information elements
+ * @ie: vendor information elements (optional)
+ * @ie_len: length of vendor information elements
+ * @is_secure: or not
  *
  * These parameters are fixed when the mesh is created.
  */
@@ -699,8 +704,9 @@ struct mesh_setup {
        u8 mesh_id_len;
        u8  path_sel_proto;
        u8  path_metric;
-       const u8 *vendor_ie;
-       u8 vendor_ie_len;
+       const u8 *ie;
+       u8 ie_len;
+       bool is_secure;
 };
 
 /**
@@ -1451,6 +1457,8 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
  * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate
  *     unicast and multicast TX keys.
+ * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
+ *     auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
  */
 enum wiphy_flags {
        WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
@@ -1463,6 +1471,7 @@ enum wiphy_flags {
        WIPHY_FLAG_CONTROL_PORT_PROTOCOL        = BIT(7),
        WIPHY_FLAG_IBSS_RSN                     = BIT(8),
        WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9),
+       WIPHY_FLAG_MESH_AUTH                    = BIT(10),
 };
 
 struct mac_address {
@@ -2483,6 +2492,22 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  */
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 
+/**
+ * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
+ *
+ * @dev: network device
+ * @macaddr: the MAC address of the new candidate
+ * @ie: information elements advertised by the peer candidate
+ * @ie_len: lenght of the information elements buffer
+ * @gfp: allocation flags
+ *
+ * This function notifies cfg80211 that the mesh peer candidate has been
+ * detected, most likely via a beacon or, less likely, via a probe response.
+ * cfg80211 then sends a notification to userspace.
+ */
+void cfg80211_notify_new_peer_candidate(struct net_device *dev,
+               const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp);
+
 /**
  * DOC: RFkill integration
  *
index 025d4cc7bbf800c846113496bfec7a375afa07c4..d23dd6c1329cf463d5eb5126a97aae94f207bd15 100644 (file)
@@ -1819,6 +1819,9 @@ enum ieee80211_ampdu_mlme_action {
  * @set_ringparam: Set tx and rx ring sizes.
  *
  * @get_ringparam: Get tx and rx ring current and maximum sizes.
+ *
+ * @tx_frames_pending: Check if there is any pending frame in the hardware
+ *     queues before entering power save.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1906,6 +1909,7 @@ struct ieee80211_ops {
        int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
        void (*get_ringparam)(struct ieee80211_hw *hw,
                              u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+       bool (*tx_frames_pending)(struct ieee80211_hw *hw);
 };
 
 /**
@@ -2222,6 +2226,18 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
  */
 #define IEEE80211_TX_STATUS_HEADROOM   13
 
+/**
+ * ieee80211_sta_set_tim - set the TIM bit for a sleeping station
+ *
+ * If a driver buffers frames for a powersave station instead of passing
+ * them back to mac80211 for retransmission, the station needs to be told
+ * to wake up using the TIM bitmap in the beacon.
+ *
+ * This function sets the station's TIM bit - it will be cleared when the
+ * station wakes up.
+ */
+void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
+
 /**
  * ieee80211_tx_status - transmit status callback
  *
index 7a3398d9cd65d45ec99a3e31b564e9c15145d39d..c7eb073fe633f2e99dc760ed6ad8c4079f8f2bd3 100644 (file)
@@ -2497,6 +2497,9 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 
        hci_dev_lock(hdev);
 
+       if (!test_bit(HCI_MGMT, &hdev->flags))
+               goto unlock;
+
        data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
        if (data) {
                struct hci_cp_remote_oob_data_reply cp;
@@ -2515,6 +2518,7 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
                                                                        &cp);
        }
 
+unlock:
        hci_dev_unlock(hdev);
 }
 
index c3cebed205ccfec22759191bb359b103e914f3e5..d47de2b04b2e70217f98c79693919547006fc34d 100644 (file)
@@ -70,108 +70,101 @@ static void l2cap_busy_work(struct work_struct *work);
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
                                u8 code, u8 ident, u16 dlen, void *data);
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
 
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP channels ---- */
-static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
 {
-       struct sock *s;
-       for (s = l->head; s; s = l2cap_pi(s)->next_c) {
+       struct l2cap_chan *c;
+
+       list_for_each_entry(c, &conn->chan_l, list) {
+               struct sock *s = c->sk;
                if (l2cap_pi(s)->dcid == cid)
-                       break;
+                       return c;
        }
-       return s;
+       return NULL;
+
 }
 
-static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
+static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
 {
-       struct sock *s;
-       for (s = l->head; s; s = l2cap_pi(s)->next_c) {
+       struct l2cap_chan *c;
+
+       list_for_each_entry(c, &conn->chan_l, list) {
+               struct sock *s = c->sk;
                if (l2cap_pi(s)->scid == cid)
-                       break;
+                       return c;
        }
-       return s;
+       return NULL;
 }
 
 /* Find channel with given SCID.
  * Returns locked socket */
-static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
+static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
 {
-       struct sock *s;
-       read_lock(&l->lock);
-       s = __l2cap_get_chan_by_scid(l, cid);
-       if (s)
-               bh_lock_sock(s);
-       read_unlock(&l->lock);
-       return s;
+       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);
+       return c;
 }
 
-static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
+static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
 {
-       struct sock *s;
-       for (s = l->head; s; s = l2cap_pi(s)->next_c) {
-               if (l2cap_pi(s)->ident == ident)
-                       break;
+       struct l2cap_chan *c;
+
+       list_for_each_entry(c, &conn->chan_l, list) {
+               if (c->ident == ident)
+                       return c;
        }
-       return s;
+       return NULL;
 }
 
-static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
+static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
 {
-       struct sock *s;
-       read_lock(&l->lock);
-       s = __l2cap_get_chan_by_ident(l, ident);
-       if (s)
-               bh_lock_sock(s);
-       read_unlock(&l->lock);
-       return s;
+       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);
+       return c;
 }
 
-static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
+static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 {
        u16 cid = L2CAP_CID_DYN_START;
 
        for (; cid < L2CAP_CID_DYN_END; cid++) {
-               if (!__l2cap_get_chan_by_scid(l, cid))
+               if (!__l2cap_get_chan_by_scid(conn, cid))
                        return cid;
        }
 
        return 0;
 }
 
-static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
+static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
 {
-       sock_hold(sk);
-
-       if (l->head)
-               l2cap_pi(l->head)->prev_c = sk;
+       struct l2cap_chan *chan;
 
-       l2cap_pi(sk)->next_c = l->head;
-       l2cap_pi(sk)->prev_c = NULL;
-       l->head = sk;
-}
-
-static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
-{
-       struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
-
-       write_lock_bh(&l->lock);
-       if (sk == l->head)
-               l->head = next;
+       chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
+       if (!chan)
+               return NULL;
 
-       if (next)
-               l2cap_pi(next)->prev_c = prev;
-       if (prev)
-               l2cap_pi(prev)->next_c = next;
-       write_unlock_bh(&l->lock);
+       chan->sk = sk;
 
-       __sock_put(sk);
+       return chan;
 }
 
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
+static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
+       struct sock *sk = chan->sk;
 
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
                        l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
@@ -188,7 +181,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
                        l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
                } else {
                        /* Alloc CID for connection-oriented socket */
-                       l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
+                       l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
                        l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
                }
        } else if (sk->sk_type == SOCK_DGRAM) {
@@ -203,23 +196,30 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
                l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
        }
 
-       __l2cap_chan_link(l, sk);
+       sock_hold(sk);
+
+       list_add(&chan->list, &conn->chan_l);
 }
 
 /* Delete channel.
  * Must be called on the locked socket. */
-void l2cap_chan_del(struct sock *sk, int err)
+void l2cap_chan_del(struct l2cap_chan *chan, int err)
 {
+       struct sock *sk = chan->sk;
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
        struct sock *parent = bt_sk(sk)->parent;
 
        l2cap_sock_clear_timer(sk);
 
-       BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
+       BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
        if (conn) {
-               /* Unlink from channel list */
-               l2cap_chan_unlink(&conn->chan_list, sk);
+               /* Delete from channel list */
+               write_lock_bh(&conn->chan_lock);
+               list_del(&chan->list);
+               write_unlock_bh(&conn->chan_lock);
+               __sock_put(sk);
+
                l2cap_pi(sk)->conn = NULL;
                hci_conn_put(conn->hcon);
        }
@@ -236,23 +236,30 @@ void l2cap_chan_del(struct sock *sk, int err)
        } else
                sk->sk_state_change(sk);
 
-       skb_queue_purge(TX_QUEUE(sk));
+       if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
+                       l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
+               goto free;
+
+       skb_queue_purge(&chan->tx_q);
 
        if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
                struct srej_list *l, *tmp;
 
-               del_timer(&l2cap_pi(sk)->retrans_timer);
-               del_timer(&l2cap_pi(sk)->monitor_timer);
-               del_timer(&l2cap_pi(sk)->ack_timer);
+               del_timer(&chan->retrans_timer);
+               del_timer(&chan->monitor_timer);
+               del_timer(&chan->ack_timer);
 
-               skb_queue_purge(SREJ_QUEUE(sk));
-               skb_queue_purge(BUSY_QUEUE(sk));
+               skb_queue_purge(&chan->srej_q);
+               skb_queue_purge(&chan->busy_q);
 
-               list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+               list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
                        list_del(&l->list);
                        kfree(l);
                }
        }
+
+free:
+       kfree(chan);
 }
 
 static inline u8 l2cap_get_auth_type(struct sock *sk)
@@ -338,10 +345,11 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d
        hci_send_acl(conn->hcon, skb, flags);
 }
 
-static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
+static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 {
        struct sk_buff *skb;
        struct l2cap_hdr *lh;
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct l2cap_conn *conn = pi->conn;
        struct sock *sk = (struct sock *)pi;
        int count, hlen = L2CAP_HDR_SIZE + 2;
@@ -353,19 +361,19 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
        if (pi->fcs == L2CAP_FCS_CRC16)
                hlen += 2;
 
-       BT_DBG("pi %p, control 0x%2.2x", pi, control);
+       BT_DBG("chan %p, control 0x%2.2x", chan, control);
 
        count = min_t(unsigned int, conn->mtu, hlen);
        control |= L2CAP_CTRL_FRAME_TYPE;
 
-       if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+       if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
                control |= L2CAP_CTRL_FINAL;
-               pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+               chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
        }
 
-       if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
+       if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
                control |= L2CAP_CTRL_POLL;
-               pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
+               chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
        }
 
        skb = bt_skb_alloc(count, GFP_ATOMIC);
@@ -390,17 +398,17 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
        hci_send_acl(pi->conn->hcon, skb, flags);
 }
 
-static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
+static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 {
-       if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
-               pi->conn_state |= L2CAP_CONN_RNR_SENT;
+               chan->conn_state |= L2CAP_CONN_RNR_SENT;
        } else
                control |= L2CAP_SUPER_RCV_READY;
 
-       control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+       control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       l2cap_send_sframe(pi, control);
+       l2cap_send_sframe(chan, control);
 }
 
 static inline int __l2cap_no_conn_pending(struct sock *sk)
@@ -408,8 +416,9 @@ static inline int __l2cap_no_conn_pending(struct sock *sk)
        return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
 }
 
-static void l2cap_do_start(struct sock *sk)
+static void l2cap_do_start(struct l2cap_chan *chan)
 {
+       struct sock *sk = chan->sk;
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
 
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
@@ -421,11 +430,11 @@ static void l2cap_do_start(struct sock *sk)
                        req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
 
-                       l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                       chan->ident = l2cap_get_ident(conn);
                        l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
-                       l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-                                       L2CAP_CONN_REQ, sizeof(req), &req);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
+                                                       sizeof(req), &req);
                }
        } else {
                struct l2cap_info_req req;
@@ -458,19 +467,20 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
        }
 }
 
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
 {
+       struct sock *sk;
        struct l2cap_disconn_req req;
 
        if (!conn)
                return;
 
-       skb_queue_purge(TX_QUEUE(sk));
+       sk = chan->sk;
 
        if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
-               del_timer(&l2cap_pi(sk)->retrans_timer);
-               del_timer(&l2cap_pi(sk)->monitor_timer);
-               del_timer(&l2cap_pi(sk)->ack_timer);
+               del_timer(&chan->retrans_timer);
+               del_timer(&chan->monitor_timer);
+               del_timer(&chan->ack_timer);
        }
 
        req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
@@ -485,17 +495,15 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
 /* ---- L2CAP connections ---- */
 static void l2cap_conn_start(struct l2cap_conn *conn)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
-       struct sock_del_list del, *tmp1, *tmp2;
-       struct sock *sk;
+       struct l2cap_chan *chan, *tmp;
 
        BT_DBG("conn %p", conn);
 
-       INIT_LIST_HEAD(&del.list);
+       read_lock(&conn->chan_lock);
 
-       read_lock(&l->lock);
+       list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+               struct sock *sk = chan->sk;
 
-       for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
                bh_lock_sock(sk);
 
                if (sk->sk_type != SOCK_SEQPACKET &&
@@ -517,10 +525,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                        conn->feat_mask)
                                        && l2cap_pi(sk)->conf_state &
                                        L2CAP_CONF_STATE2_DEVICE) {
-                               tmp1 = kzalloc(sizeof(struct sock_del_list),
-                                               GFP_ATOMIC);
-                               tmp1->sk = sk;
-                               list_add_tail(&tmp1->list, &del.list);
+                               /* __l2cap_sock_close() calls list_del(chan)
+                                * so release the lock */
+                               read_unlock_bh(&conn->chan_lock);
+                                __l2cap_sock_close(sk, ECONNRESET);
+                               read_lock_bh(&conn->chan_lock);
                                bh_unlock_sock(sk);
                                continue;
                        }
@@ -528,11 +537,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                        req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
 
-                       l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                       chan->ident = l2cap_get_ident(conn);
                        l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
-                       l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-                               L2CAP_CONN_REQ, sizeof(req), &req);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
+                                                       sizeof(req), &req);
 
                } else if (sk->sk_state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
@@ -557,8 +566,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
                        }
 
-                       l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-                                       L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+                                                       sizeof(rsp), &rsp);
 
                        if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
                                        rsp.result != L2CAP_CR_SUCCESS) {
@@ -568,22 +577,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 
                        l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
                        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                               l2cap_build_conf_req(sk, buf), buf);
-                       l2cap_pi(sk)->num_conf_req++;
+                                               l2cap_build_conf_req(chan, buf), buf);
+                       chan->num_conf_req++;
                }
 
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&l->lock);
-
-       list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
-               bh_lock_sock(tmp1->sk);
-               __l2cap_sock_close(tmp1->sk, ECONNRESET);
-               bh_unlock_sock(tmp1->sk);
-               list_del(&tmp1->list);
-               kfree(tmp1);
-       }
+       read_unlock(&conn->chan_lock);
 }
 
 /* Find socket with cid and source bdaddr.
@@ -591,7 +592,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
  */
 static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
 {
-       struct sock *s, *sk = NULL, *sk1 = NULL;
+       struct sock *sk = NULL, *sk1 = NULL;
        struct hlist_node *node;
 
        read_lock(&l2cap_sk_list.lock);
@@ -610,18 +611,16 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
                                sk1 = sk;
                }
        }
-       s = node ? sk : sk1;
-       if (s)
-               bh_lock_sock(s);
+
        read_unlock(&l2cap_sk_list.lock);
 
-       return s;
+       return node ? sk : sk1;
 }
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
-       struct l2cap_chan_list *list = &conn->chan_list;
-       struct sock *parent, *uninitialized_var(sk);
+       struct sock *parent, *sk;
+       struct l2cap_chan *chan;
 
        BT_DBG("");
 
@@ -631,6 +630,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
        if (!parent)
                return;
 
+       bh_lock_sock(parent);
+
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
                BT_DBG("backlog full %d", parent->sk_ack_backlog);
@@ -641,24 +642,33 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
        if (!sk)
                goto clean;
 
-       write_lock_bh(&list->lock);
+       chan = l2cap_chan_alloc(sk);
+       if (!chan) {
+               l2cap_sock_kill(sk);
+               goto clean;
+       }
+
+       write_lock_bh(&conn->chan_lock);
 
        hci_conn_hold(conn->hcon);
 
        l2cap_sock_init(sk, parent);
+
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
 
        bt_accept_enqueue(parent, sk);
 
-       __l2cap_chan_add(conn, sk);
+       __l2cap_chan_add(conn, chan);
+
+       l2cap_pi(sk)->chan = chan;
 
        l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
 
        sk->sk_state = BT_CONNECTED;
        parent->sk_data_ready(parent, 0);
 
-       write_unlock_bh(&list->lock);
+       write_unlock_bh(&conn->chan_lock);
 
 clean:
        bh_unlock_sock(parent);
@@ -666,17 +676,18 @@ clean:
 
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
-       struct sock *sk;
+       struct l2cap_chan *chan;
 
        BT_DBG("conn %p", conn);
 
        if (!conn->hcon->out && conn->hcon->type == LE_LINK)
                l2cap_le_conn_ready(conn);
 
-       read_lock(&l->lock);
+       read_lock(&conn->chan_lock);
+
+       list_for_each_entry(chan, &conn->chan_l, list) {
+               struct sock *sk = chan->sk;
 
-       for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
                bh_lock_sock(sk);
 
                if (conn->hcon->type == LE_LINK) {
@@ -691,30 +702,31 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                        sk->sk_state = BT_CONNECTED;
                        sk->sk_state_change(sk);
                } else if (sk->sk_state == BT_CONNECT)
-                       l2cap_do_start(sk);
+                       l2cap_do_start(chan);
 
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&l->lock);
+       read_unlock(&conn->chan_lock);
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
 static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
-       struct sock *sk;
+       struct l2cap_chan *chan;
 
        BT_DBG("conn %p", conn);
 
-       read_lock(&l->lock);
+       read_lock(&conn->chan_lock);
+
+       list_for_each_entry(chan, &conn->chan_l, list) {
+               struct sock *sk = chan->sk;
 
-       for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
                if (l2cap_pi(sk)->force_reliable)
                        sk->sk_err = err;
        }
 
-       read_unlock(&l->lock);
+       read_unlock(&conn->chan_lock);
 }
 
 static void l2cap_info_timeout(unsigned long arg)
@@ -754,7 +766,9 @@ 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_list.lock);
+       rwlock_init(&conn->chan_lock);
+
+       INIT_LIST_HEAD(&conn->chan_l);
 
        if (hcon->type != LE_LINK)
                setup_timer(&conn->info_timer, l2cap_info_timeout,
@@ -768,6 +782,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 static void l2cap_conn_del(struct hci_conn *hcon, int err)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
+       struct l2cap_chan *chan, *l;
        struct sock *sk;
 
        if (!conn)
@@ -778,9 +793,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        kfree_skb(conn->rx_skb);
 
        /* Kill channels */
-       while ((sk = conn->chan_list.head)) {
+       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+               sk = chan->sk;
                bh_lock_sock(sk);
-               l2cap_chan_del(sk, err);
+               l2cap_chan_del(chan, err);
                bh_unlock_sock(sk);
                l2cap_sock_kill(sk);
        }
@@ -792,12 +808,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
        kfree(conn);
 }
 
-static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
+static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
-       write_lock_bh(&l->lock);
-       __l2cap_chan_add(conn, sk);
-       write_unlock_bh(&l->lock);
+       write_lock_bh(&conn->chan_lock);
+       __l2cap_chan_add(conn, chan);
+       write_unlock_bh(&conn->chan_lock);
 }
 
 /* ---- Socket interface ---- */
@@ -837,6 +852,7 @@ int l2cap_do_connect(struct sock *sk)
        bdaddr_t *src = &bt_sk(sk)->src;
        bdaddr_t *dst = &bt_sk(sk)->dst;
        struct l2cap_conn *conn;
+       struct l2cap_chan *chan;
        struct hci_conn *hcon;
        struct hci_dev *hdev;
        __u8 auth_type;
@@ -872,10 +888,19 @@ int l2cap_do_connect(struct sock *sk)
                goto done;
        }
 
+       chan = l2cap_chan_alloc(sk);
+       if (!chan) {
+               hci_conn_put(hcon);
+               err = -ENOMEM;
+               goto done;
+       }
+
        /* Update source addr of the socket */
        bacpy(src, conn->src);
 
-       l2cap_chan_add(conn, sk);
+       l2cap_chan_add(conn, chan);
+
+       l2cap_pi(sk)->chan = chan;
 
        sk->sk_state = BT_CONNECT;
        l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
@@ -887,7 +912,7 @@ int l2cap_do_connect(struct sock *sk)
                        if (l2cap_check_security(sk))
                                sk->sk_state = BT_CONNECTED;
                } else
-                       l2cap_do_start(sk);
+                       l2cap_do_start(chan);
        }
 
        err = 0;
@@ -905,7 +930,7 @@ int __l2cap_wait_ack(struct sock *sk)
        int timeo = HZ/5;
 
        add_wait_queue(sk_sleep(sk), &wait);
-       while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
+       while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
                set_current_state(TASK_INTERRUPTIBLE);
 
                if (!timeo)
@@ -931,57 +956,59 @@ int __l2cap_wait_ack(struct sock *sk)
 
 static void l2cap_monitor_timeout(unsigned long arg)
 {
-       struct sock *sk = (void *) arg;
+       struct l2cap_chan *chan = (void *) arg;
+       struct sock *sk = chan->sk;
 
-       BT_DBG("sk %p", sk);
+       BT_DBG("chan %p", chan);
 
        bh_lock_sock(sk);
-       if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
-               l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
+       if (chan->retry_count >= chan->remote_max_tx) {
+               l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
                bh_unlock_sock(sk);
                return;
        }
 
-       l2cap_pi(sk)->retry_count++;
+       chan->retry_count++;
        __mod_monitor_timer();
 
-       l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
+       l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
        bh_unlock_sock(sk);
 }
 
 static void l2cap_retrans_timeout(unsigned long arg)
 {
-       struct sock *sk = (void *) arg;
+       struct l2cap_chan *chan = (void *) arg;
+       struct sock *sk = chan->sk;
 
-       BT_DBG("sk %p", sk);
+       BT_DBG("chan %p", chan);
 
        bh_lock_sock(sk);
-       l2cap_pi(sk)->retry_count = 1;
+       chan->retry_count = 1;
        __mod_monitor_timer();
 
-       l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+       chan->conn_state |= L2CAP_CONN_WAIT_F;
 
-       l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
+       l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
        bh_unlock_sock(sk);
 }
 
-static void l2cap_drop_acked_frames(struct sock *sk)
+static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
 {
        struct sk_buff *skb;
 
-       while ((skb = skb_peek(TX_QUEUE(sk))) &&
-                       l2cap_pi(sk)->unacked_frames) {
-               if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
+       while ((skb = skb_peek(&chan->tx_q)) &&
+                       chan->unacked_frames) {
+               if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
                        break;
 
-               skb = skb_dequeue(TX_QUEUE(sk));
+               skb = skb_dequeue(&chan->tx_q);
                kfree_skb(skb);
 
-               l2cap_pi(sk)->unacked_frames--;
+               chan->unacked_frames--;
        }
 
-       if (!l2cap_pi(sk)->unacked_frames)
-               del_timer(&l2cap_pi(sk)->retrans_timer);
+       if (!chan->unacked_frames)
+               del_timer(&chan->retrans_timer);
 }
 
 void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
@@ -1000,15 +1027,16 @@ void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
        hci_send_acl(hcon, skb, flags);
 }
 
-void l2cap_streaming_send(struct sock *sk)
+void l2cap_streaming_send(struct l2cap_chan *chan)
 {
+       struct sock *sk = chan->sk;
        struct sk_buff *skb;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        u16 control, fcs;
 
-       while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
+       while ((skb = skb_dequeue(&chan->tx_q))) {
                control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
-               control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+               control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
                put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
 
                if (pi->fcs == L2CAP_FCS_CRC16) {
@@ -1018,17 +1046,18 @@ void l2cap_streaming_send(struct sock *sk)
 
                l2cap_do_send(sk, skb);
 
-               pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+               chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
        }
 }
 
-static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
+static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 {
+       struct sock *sk = chan->sk;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        struct sk_buff *skb, *tx_skb;
        u16 control, fcs;
 
-       skb = skb_peek(TX_QUEUE(sk));
+       skb = skb_peek(&chan->tx_q);
        if (!skb)
                return;
 
@@ -1036,14 +1065,14 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
                if (bt_cb(skb)->tx_seq == tx_seq)
                        break;
 
-               if (skb_queue_is_last(TX_QUEUE(sk), skb))
+               if (skb_queue_is_last(&chan->tx_q, skb))
                        return;
 
-       } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
+       } while ((skb = skb_queue_next(&chan->tx_q, skb)));
 
-       if (pi->remote_max_tx &&
-                       bt_cb(skb)->retries == pi->remote_max_tx) {
-               l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
+       if (chan->remote_max_tx &&
+                       bt_cb(skb)->retries == chan->remote_max_tx) {
+               l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
                return;
        }
 
@@ -1051,12 +1080,12 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
        bt_cb(skb)->retries++;
        control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
 
-       if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+       if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
                control |= L2CAP_CTRL_FINAL;
-               pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+               chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
        }
 
-       control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+       control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
                        | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
 
        put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1069,9 +1098,10 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
        l2cap_do_send(sk, tx_skb);
 }
 
-int l2cap_ertm_send(struct sock *sk)
+int l2cap_ertm_send(struct l2cap_chan *chan)
 {
        struct sk_buff *skb, *tx_skb;
+       struct sock *sk = chan->sk;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        u16 control, fcs;
        int nsent = 0;
@@ -1079,11 +1109,11 @@ int l2cap_ertm_send(struct sock *sk)
        if (sk->sk_state != BT_CONNECTED)
                return -ENOTCONN;
 
-       while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
+       while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
 
-               if (pi->remote_max_tx &&
-                               bt_cb(skb)->retries == pi->remote_max_tx) {
-                       l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
+               if (chan->remote_max_tx &&
+                               bt_cb(skb)->retries == chan->remote_max_tx) {
+                       l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
                        break;
                }
 
@@ -1094,12 +1124,12 @@ int l2cap_ertm_send(struct sock *sk)
                control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
                control &= L2CAP_CTRL_SAR;
 
-               if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+               if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
                        control |= L2CAP_CTRL_FINAL;
-                       pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+                       chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
                }
-               control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
-                               | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+               control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+                               | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
                put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
 
@@ -1112,18 +1142,18 @@ int l2cap_ertm_send(struct sock *sk)
 
                __mod_retrans_timer();
 
-               bt_cb(skb)->tx_seq = pi->next_tx_seq;
-               pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+               bt_cb(skb)->tx_seq = chan->next_tx_seq;
+               chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
 
                if (bt_cb(skb)->retries == 1)
-                       pi->unacked_frames++;
+                       chan->unacked_frames++;
 
-               pi->frames_sent++;
+               chan->frames_sent++;
 
-               if (skb_queue_is_last(TX_QUEUE(sk), skb))
-                       sk->sk_send_head = NULL;
+               if (skb_queue_is_last(&chan->tx_q, skb))
+                       chan->tx_send_head = NULL;
                else
-                       sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
+                       chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
 
                nsent++;
        }
@@ -1131,41 +1161,39 @@ int l2cap_ertm_send(struct sock *sk)
        return nsent;
 }
 
-static int l2cap_retransmit_frames(struct sock *sk)
+static int l2cap_retransmit_frames(struct l2cap_chan *chan)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        int ret;
 
-       if (!skb_queue_empty(TX_QUEUE(sk)))
-               sk->sk_send_head = TX_QUEUE(sk)->next;
+       if (!skb_queue_empty(&chan->tx_q))
+               chan->tx_send_head = chan->tx_q.next;
 
-       pi->next_tx_seq = pi->expected_ack_seq;
-       ret = l2cap_ertm_send(sk);
+       chan->next_tx_seq = chan->expected_ack_seq;
+       ret = l2cap_ertm_send(chan);
        return ret;
 }
 
-static void l2cap_send_ack(struct l2cap_pinfo *pi)
+static void l2cap_send_ack(struct l2cap_chan *chan)
 {
-       struct sock *sk = (struct sock *)pi;
        u16 control = 0;
 
-       control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+       control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
-               pi->conn_state |= L2CAP_CONN_RNR_SENT;
-               l2cap_send_sframe(pi, control);
+               chan->conn_state |= L2CAP_CONN_RNR_SENT;
+               l2cap_send_sframe(chan, control);
                return;
        }
 
-       if (l2cap_ertm_send(sk) > 0)
+       if (l2cap_ertm_send(chan) > 0)
                return;
 
        control |= L2CAP_SUPER_RCV_READY;
-       l2cap_send_sframe(pi, control);
+       l2cap_send_sframe(chan, control);
 }
 
-static void l2cap_send_srejtail(struct sock *sk)
+static void l2cap_send_srejtail(struct l2cap_chan *chan)
 {
        struct srej_list *tail;
        u16 control;
@@ -1173,10 +1201,10 @@ static void l2cap_send_srejtail(struct sock *sk)
        control = L2CAP_SUPER_SELECT_REJECT;
        control |= L2CAP_CTRL_FINAL;
 
-       tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
+       tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
        control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       l2cap_send_sframe(l2cap_pi(sk), control);
+       l2cap_send_sframe(chan, control);
 }
 
 static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
@@ -1313,9 +1341,9 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
        return skb;
 }
 
-int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
+int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct sock *sk = chan->sk;
        struct sk_buff *skb;
        struct sk_buff_head sar_queue;
        u16 control;
@@ -1323,20 +1351,20 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
 
        skb_queue_head_init(&sar_queue);
        control = L2CAP_SDU_START;
-       skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
+       skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
        __skb_queue_tail(&sar_queue, skb);
-       len -= pi->remote_mps;
-       size += pi->remote_mps;
+       len -= chan->remote_mps;
+       size += chan->remote_mps;
 
        while (len > 0) {
                size_t buflen;
 
-               if (len > pi->remote_mps) {
+               if (len > chan->remote_mps) {
                        control = L2CAP_SDU_CONTINUE;
-                       buflen = pi->remote_mps;
+                       buflen = chan->remote_mps;
                } else {
                        control = L2CAP_SDU_END;
                        buflen = len;
@@ -1352,9 +1380,9 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
                len -= buflen;
                size += buflen;
        }
-       skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
-       if (sk->sk_send_head == NULL)
-               sk->sk_send_head = sar_queue.next;
+       skb_queue_splice_tail(&sar_queue, &chan->tx_q);
+       if (chan->tx_send_head == NULL)
+               chan->tx_send_head = sar_queue.next;
 
        return size;
 }
@@ -1385,14 +1413,14 @@ static void l2cap_chan_ready(struct sock *sk)
 /* Copy frame to all raw sockets on that connection */
 static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 {
-       struct l2cap_chan_list *l = &conn->chan_list;
        struct sk_buff *nskb;
-       struct sock *sk;
+       struct l2cap_chan *chan;
 
        BT_DBG("conn %p", conn);
 
-       read_lock(&l->lock);
-       for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+       read_lock(&conn->chan_lock);
+       list_for_each_entry(chan, &conn->chan_l, list) {
+               struct sock *sk = chan->sk;
                if (sk->sk_type != SOCK_RAW)
                        continue;
 
@@ -1406,7 +1434,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
                if (sock_queue_rcv_skb(sk, nskb))
                        kfree_skb(nskb);
        }
-       read_unlock(&l->lock);
+       read_unlock(&conn->chan_lock);
 }
 
 /* ---- L2CAP signalling commands ---- */
@@ -1538,32 +1566,35 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 
 static void l2cap_ack_timeout(unsigned long arg)
 {
-       struct sock *sk = (void *) arg;
+       struct l2cap_chan *chan = (void *) arg;
 
-       bh_lock_sock(sk);
-       l2cap_send_ack(l2cap_pi(sk));
-       bh_unlock_sock(sk);
+       bh_lock_sock(chan->sk);
+       l2cap_send_ack(chan);
+       bh_unlock_sock(chan->sk);
 }
 
-static inline void l2cap_ertm_init(struct sock *sk)
+static inline void l2cap_ertm_init(struct l2cap_chan *chan)
 {
-       l2cap_pi(sk)->expected_ack_seq = 0;
-       l2cap_pi(sk)->unacked_frames = 0;
-       l2cap_pi(sk)->buffer_seq = 0;
-       l2cap_pi(sk)->num_acked = 0;
-       l2cap_pi(sk)->frames_sent = 0;
+       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(&l2cap_pi(sk)->retrans_timer,
-                       l2cap_retrans_timeout, (unsigned long) sk);
-       setup_timer(&l2cap_pi(sk)->monitor_timer,
-                       l2cap_monitor_timeout, (unsigned long) sk);
-       setup_timer(&l2cap_pi(sk)->ack_timer,
-                       l2cap_ack_timeout, (unsigned long) sk);
+       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);
 
-       __skb_queue_head_init(SREJ_QUEUE(sk));
-       __skb_queue_head_init(BUSY_QUEUE(sk));
+       skb_queue_head_init(&chan->srej_q);
+       skb_queue_head_init(&chan->busy_q);
 
-       INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
+       INIT_LIST_HEAD(&chan->srej_l);
+
+       INIT_WORK(&chan->busy_work, l2cap_busy_work);
 
        sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
 }
@@ -1581,16 +1612,16 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
        }
 }
 
-int l2cap_build_conf_req(struct sock *sk, void *data)
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct l2cap_conf_req *req = data;
        struct l2cap_conf_rfc rfc = { .mode = pi->mode };
        void *ptr = req->data;
 
-       BT_DBG("sk %p", sk);
+       BT_DBG("chan %p", chan);
 
-       if (pi->num_conf_req || pi->num_conf_rsp)
+       if (chan->num_conf_req || chan->num_conf_rsp)
                goto done;
 
        switch (pi->mode) {
@@ -1679,20 +1710,20 @@ done:
        return ptr - data;
 }
 
-static int l2cap_parse_conf_req(struct sock *sk, void *data)
+static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct l2cap_conf_rsp *rsp = data;
        void *ptr = rsp->data;
-       void *req = pi->conf_req;
-       int len = pi->conf_len;
+       void *req = chan->conf_req;
+       int len = chan->conf_len;
        int type, hint, olen;
        unsigned long val;
        struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
        u16 mtu = L2CAP_DEFAULT_MTU;
        u16 result = L2CAP_CONF_SUCCESS;
 
-       BT_DBG("sk %p", sk);
+       BT_DBG("chan %p", chan);
 
        while (len >= L2CAP_CONF_OPT_SIZE) {
                len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
@@ -1733,7 +1764,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
                }
        }
 
-       if (pi->num_conf_rsp || pi->num_conf_req > 1)
+       if (chan->num_conf_rsp || chan->num_conf_req > 1)
                goto done;
 
        switch (pi->mode) {
@@ -1756,7 +1787,7 @@ done:
                result = L2CAP_CONF_UNACCEPT;
                rfc.mode = pi->mode;
 
-               if (pi->num_conf_rsp == 1)
+               if (chan->num_conf_rsp == 1)
                        return -ECONNREFUSED;
 
                l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
@@ -1783,13 +1814,13 @@ done:
                        break;
 
                case L2CAP_MODE_ERTM:
-                       pi->remote_tx_win = rfc.txwin_size;
-                       pi->remote_max_tx = rfc.max_transmit;
+                       chan->remote_tx_win = rfc.txwin_size;
+                       chan->remote_max_tx = rfc.max_transmit;
 
                        if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
                                rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
-                       pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+                       chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
                        rfc.retrans_timeout =
                                le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
@@ -1807,7 +1838,7 @@ done:
                        if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
                                rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
 
-                       pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+                       chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
                        pi->conf_state |= L2CAP_CONF_MODE_DONE;
 
@@ -1916,6 +1947,31 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla
        return ptr - data;
 }
 
+void __l2cap_connect_rsp_defer(struct sock *sk)
+{
+       struct l2cap_conn_rsp rsp;
+       struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       u8 buf[128];
+
+       sk->sk_state = BT_CONFIG;
+
+       rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+       rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+       rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+       l2cap_send_cmd(conn, chan->ident,
+                               L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+       if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
+               return;
+
+       l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+       l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+                       l2cap_build_conf_req(chan, buf), buf);
+       chan->num_conf_req++;
+}
+
 static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
 {
        struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -1973,9 +2029,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-       struct l2cap_chan_list *list = &conn->chan_list;
        struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
        struct l2cap_conn_rsp rsp;
+       struct l2cap_chan *chan = NULL;
        struct sock *parent, *sk = NULL;
        int result, status = L2CAP_CS_NO_INFO;
 
@@ -2013,11 +2069,17 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        if (!sk)
                goto response;
 
-       write_lock_bh(&list->lock);
+       chan = l2cap_chan_alloc(sk);
+       if (!chan) {
+               l2cap_sock_kill(sk);
+               goto response;
+       }
+
+       write_lock_bh(&conn->chan_lock);
 
        /* Check if we already have channel with that dcid */
-       if (__l2cap_get_chan_by_dcid(list, scid)) {
-               write_unlock_bh(&list->lock);
+       if (__l2cap_get_chan_by_dcid(conn, scid)) {
+               write_unlock_bh(&conn->chan_lock);
                sock_set_flag(sk, SOCK_ZAPPED);
                l2cap_sock_kill(sk);
                goto response;
@@ -2033,12 +2095,15 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        bt_accept_enqueue(parent, sk);
 
-       __l2cap_chan_add(conn, sk);
+       __l2cap_chan_add(conn, chan);
+
+       l2cap_pi(sk)->chan = chan;
+
        dcid = l2cap_pi(sk)->scid;
 
        l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
 
-       l2cap_pi(sk)->ident = cmd->ident;
+       chan->ident = cmd->ident;
 
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
                if (l2cap_check_security(sk)) {
@@ -2063,7 +2128,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                status = L2CAP_CS_NO_INFO;
        }
 
-       write_unlock_bh(&list->lock);
+       write_unlock_bh(&conn->chan_lock);
 
 response:
        bh_unlock_sock(parent);
@@ -2089,13 +2154,13 @@ sendresp:
                                        L2CAP_INFO_REQ, sizeof(info), &info);
        }
 
-       if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+       if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
                                result == L2CAP_CR_SUCCESS) {
                u8 buf[128];
                l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(sk, buf), buf);
-               l2cap_pi(sk)->num_conf_req++;
+                                       l2cap_build_conf_req(chan, buf), buf);
+               chan->num_conf_req++;
        }
 
        return 0;
@@ -2105,6 +2170,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 {
        struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
        u16 scid, dcid, result, status;
+       struct l2cap_chan *chan;
        struct sock *sk;
        u8 req[128];
 
@@ -2116,19 +2182,21 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
        BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
 
        if (scid) {
-               sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-               if (!sk)
+               chan = l2cap_get_chan_by_scid(conn, scid);
+               if (!chan)
                        return -EFAULT;
        } else {
-               sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
-               if (!sk)
+               chan = l2cap_get_chan_by_ident(conn, cmd->ident);
+               if (!chan)
                        return -EFAULT;
        }
 
+       sk = chan->sk;
+
        switch (result) {
        case L2CAP_CR_SUCCESS:
                sk->sk_state = BT_CONFIG;
-               l2cap_pi(sk)->ident = 0;
+               chan->ident = 0;
                l2cap_pi(sk)->dcid = dcid;
                l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
 
@@ -2138,8 +2206,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
 
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(sk, req), req);
-               l2cap_pi(sk)->num_conf_req++;
+                                       l2cap_build_conf_req(chan, req), req);
+               chan->num_conf_req++;
                break;
 
        case L2CAP_CR_PEND:
@@ -2155,7 +2223,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                        break;
                }
 
-               l2cap_chan_del(sk, ECONNREFUSED);
+               l2cap_chan_del(chan, ECONNREFUSED);
                break;
        }
 
@@ -2179,6 +2247,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
        u16 dcid, flags;
        u8 rsp[64];
+       struct l2cap_chan *chan;
        struct sock *sk;
        int len;
 
@@ -2187,10 +2256,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
 
-       sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
-       if (!sk)
+       chan = l2cap_get_chan_by_scid(conn, dcid);
+       if (!chan)
                return -ENOENT;
 
+       sk = chan->sk;
+
        if (sk->sk_state != BT_CONFIG) {
                struct l2cap_cmd_rej rej;
 
@@ -2202,7 +2273,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        /* Reject if config buffer is too small. */
        len = cmd_len - sizeof(*req);
-       if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
+       if (chan->conf_len + len > sizeof(chan->conf_req)) {
                l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
                                l2cap_build_conf_rsp(sk, rsp,
                                        L2CAP_CONF_REJECT, flags), rsp);
@@ -2210,8 +2281,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        }
 
        /* Store config. */
-       memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
-       l2cap_pi(sk)->conf_len += len;
+       memcpy(chan->conf_req + chan->conf_len, req->data, len);
+       chan->conf_len += len;
 
        if (flags & 0x0001) {
                /* Incomplete config. Send empty response. */
@@ -2222,17 +2293,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        }
 
        /* Complete config. */
-       len = l2cap_parse_conf_req(sk, rsp);
+       len = l2cap_parse_conf_req(chan, rsp);
        if (len < 0) {
-               l2cap_send_disconn_req(conn, sk, ECONNRESET);
+               l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto unlock;
        }
 
        l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
-       l2cap_pi(sk)->num_conf_rsp++;
+       chan->num_conf_rsp++;
 
        /* Reset config buffer. */
-       l2cap_pi(sk)->conf_len = 0;
+       chan->conf_len = 0;
 
        if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
                goto unlock;
@@ -2242,11 +2313,11 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
                sk->sk_state = BT_CONNECTED;
 
-               l2cap_pi(sk)->next_tx_seq = 0;
-               l2cap_pi(sk)->expected_tx_seq = 0;
-               __skb_queue_head_init(TX_QUEUE(sk));
+               chan->next_tx_seq = 0;
+               chan->expected_tx_seq = 0;
+               skb_queue_head_init(&chan->tx_q);
                if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
-                       l2cap_ertm_init(sk);
+                       l2cap_ertm_init(chan);
 
                l2cap_chan_ready(sk);
                goto unlock;
@@ -2256,8 +2327,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                u8 buf[64];
                l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                                       l2cap_build_conf_req(sk, buf), buf);
-               l2cap_pi(sk)->num_conf_req++;
+                                       l2cap_build_conf_req(chan, buf), buf);
+               chan->num_conf_req++;
        }
 
 unlock:
@@ -2269,6 +2340,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 {
        struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
        u16 scid, flags, result;
+       struct l2cap_chan *chan;
        struct sock *sk;
        int len = cmd->len - sizeof(*rsp);
 
@@ -2279,21 +2351,23 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
                        scid, flags, result);
 
-       sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-       if (!sk)
+       chan = l2cap_get_chan_by_scid(conn, scid);
+       if (!chan)
                return 0;
 
+       sk = chan->sk;
+
        switch (result) {
        case L2CAP_CONF_SUCCESS:
                l2cap_conf_rfc_get(sk, rsp->data, len);
                break;
 
        case L2CAP_CONF_UNACCEPT:
-               if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
+               if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
                        char req[64];
 
                        if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
-                               l2cap_send_disconn_req(conn, sk, ECONNRESET);
+                               l2cap_send_disconn_req(conn, chan, ECONNRESET);
                                goto done;
                        }
 
@@ -2302,13 +2376,13 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        len = l2cap_parse_conf_rsp(sk, rsp->data,
                                                        len, req, &result);
                        if (len < 0) {
-                               l2cap_send_disconn_req(conn, sk, ECONNRESET);
+                               l2cap_send_disconn_req(conn, chan, ECONNRESET);
                                goto done;
                        }
 
                        l2cap_send_cmd(conn, l2cap_get_ident(conn),
                                                L2CAP_CONF_REQ, len, req);
-                       l2cap_pi(sk)->num_conf_req++;
+                       chan->num_conf_req++;
                        if (result != L2CAP_CONF_SUCCESS)
                                goto done;
                        break;
@@ -2317,7 +2391,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        default:
                sk->sk_err = ECONNRESET;
                l2cap_sock_set_timer(sk, HZ * 5);
-               l2cap_send_disconn_req(conn, sk, ECONNRESET);
+               l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto done;
        }
 
@@ -2330,11 +2404,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                set_default_fcs(l2cap_pi(sk));
 
                sk->sk_state = BT_CONNECTED;
-               l2cap_pi(sk)->next_tx_seq = 0;
-               l2cap_pi(sk)->expected_tx_seq = 0;
-               __skb_queue_head_init(TX_QUEUE(sk));
+               chan->next_tx_seq = 0;
+               chan->expected_tx_seq = 0;
+               skb_queue_head_init(&chan->tx_q);
                if (l2cap_pi(sk)->mode ==  L2CAP_MODE_ERTM)
-                       l2cap_ertm_init(sk);
+                       l2cap_ertm_init(chan);
 
                l2cap_chan_ready(sk);
        }
@@ -2349,6 +2423,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
        struct l2cap_disconn_rsp rsp;
        u16 dcid, scid;
+       struct l2cap_chan *chan;
        struct sock *sk;
 
        scid = __le16_to_cpu(req->scid);
@@ -2356,10 +2431,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
        BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
 
-       sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
-       if (!sk)
+       chan = l2cap_get_chan_by_scid(conn, dcid);
+       if (!chan)
                return 0;
 
+       sk = chan->sk;
+
        rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
        rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
@@ -2375,7 +2452,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
                return 0;
        }
 
-       l2cap_chan_del(sk, ECONNRESET);
+       l2cap_chan_del(chan, ECONNRESET);
        bh_unlock_sock(sk);
 
        l2cap_sock_kill(sk);
@@ -2386,6 +2463,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 {
        struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
        u16 dcid, scid;
+       struct l2cap_chan *chan;
        struct sock *sk;
 
        scid = __le16_to_cpu(rsp->scid);
@@ -2393,10 +2471,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 
        BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
 
-       sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-       if (!sk)
+       chan = l2cap_get_chan_by_scid(conn, scid);
+       if (!chan)
                return 0;
 
+       sk = chan->sk;
+
        /* don't delete l2cap channel if sk is owned by user */
        if (sock_owned_by_user(sk)) {
                sk->sk_state = BT_DISCONN;
@@ -2406,7 +2486,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
                return 0;
        }
 
-       l2cap_chan_del(sk, 0);
+       l2cap_chan_del(chan, 0);
        bh_unlock_sock(sk);
 
        l2cap_sock_kill(sk);
@@ -2709,49 +2789,47 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi,  struct sk_buff *skb)
        return 0;
 }
 
-static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
+static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        u16 control = 0;
 
-       pi->frames_sent = 0;
+       chan->frames_sent = 0;
 
-       control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+       control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
-               l2cap_send_sframe(pi, control);
-               pi->conn_state |= L2CAP_CONN_RNR_SENT;
+               l2cap_send_sframe(chan, control);
+               chan->conn_state |= L2CAP_CONN_RNR_SENT;
        }
 
-       if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
-               l2cap_retransmit_frames(sk);
+       if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
+               l2cap_retransmit_frames(chan);
 
-       l2cap_ertm_send(sk);
+       l2cap_ertm_send(chan);
 
-       if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
-                       pi->frames_sent == 0) {
+       if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+                       chan->frames_sent == 0) {
                control |= L2CAP_SUPER_RCV_READY;
-               l2cap_send_sframe(pi, control);
+               l2cap_send_sframe(chan, control);
        }
 }
 
-static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
+static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
 {
        struct sk_buff *next_skb;
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        int tx_seq_offset, next_tx_seq_offset;
 
        bt_cb(skb)->tx_seq = tx_seq;
        bt_cb(skb)->sar = sar;
 
-       next_skb = skb_peek(SREJ_QUEUE(sk));
+       next_skb = skb_peek(&chan->srej_q);
        if (!next_skb) {
-               __skb_queue_tail(SREJ_QUEUE(sk), skb);
+               __skb_queue_tail(&chan->srej_q, skb);
                return 0;
        }
 
-       tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+       tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
        if (tx_seq_offset < 0)
                tx_seq_offset += 64;
 
@@ -2760,53 +2838,53 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s
                        return -EINVAL;
 
                next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
-                                               pi->buffer_seq) % 64;
+                                               chan->buffer_seq) % 64;
                if (next_tx_seq_offset < 0)
                        next_tx_seq_offset += 64;
 
                if (next_tx_seq_offset > tx_seq_offset) {
-                       __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
+                       __skb_queue_before(&chan->srej_q, next_skb, skb);
                        return 0;
                }
 
-               if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
+               if (skb_queue_is_last(&chan->srej_q, next_skb))
                        break;
 
-       } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
+       } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
 
-       __skb_queue_tail(SREJ_QUEUE(sk), skb);
+       __skb_queue_tail(&chan->srej_q, skb);
 
        return 0;
 }
 
-static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
+static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct sk_buff *_skb;
        int err;
 
        switch (control & L2CAP_CTRL_SAR) {
        case L2CAP_SDU_UNSEGMENTED:
-               if (pi->conn_state & L2CAP_CONN_SAR_SDU)
+               if (chan->conn_state & L2CAP_CONN_SAR_SDU)
                        goto drop;
 
-               err = sock_queue_rcv_skb(sk, skb);
+               err = sock_queue_rcv_skb(chan->sk, skb);
                if (!err)
                        return err;
 
                break;
 
        case L2CAP_SDU_START:
-               if (pi->conn_state & L2CAP_CONN_SAR_SDU)
+               if (chan->conn_state & L2CAP_CONN_SAR_SDU)
                        goto drop;
 
-               pi->sdu_len = get_unaligned_le16(skb->data);
+               chan->sdu_len = get_unaligned_le16(skb->data);
 
-               if (pi->sdu_len > pi->imtu)
+               if (chan->sdu_len > pi->imtu)
                        goto disconnect;
 
-               pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
-               if (!pi->sdu)
+               chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
+               if (!chan->sdu)
                        return -ENOMEM;
 
                /* pull sdu_len bytes only after alloc, because of Local Busy
@@ -2814,63 +2892,63 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
                 * only once, i.e., when alloc does not fail */
                skb_pull(skb, 2);
 
-               memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+               memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               pi->conn_state |= L2CAP_CONN_SAR_SDU;
-               pi->partial_sdu_len = skb->len;
+               chan->conn_state |= L2CAP_CONN_SAR_SDU;
+               chan->partial_sdu_len = skb->len;
                break;
 
        case L2CAP_SDU_CONTINUE:
-               if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
                        goto disconnect;
 
-               if (!pi->sdu)
+               if (!chan->sdu)
                        goto disconnect;
 
-               pi->partial_sdu_len += skb->len;
-               if (pi->partial_sdu_len > pi->sdu_len)
+               chan->partial_sdu_len += skb->len;
+               if (chan->partial_sdu_len > chan->sdu_len)
                        goto drop;
 
-               memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+               memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
                break;
 
        case L2CAP_SDU_END:
-               if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
                        goto disconnect;
 
-               if (!pi->sdu)
+               if (!chan->sdu)
                        goto disconnect;
 
-               if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
-                       pi->partial_sdu_len += skb->len;
+               if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
+                       chan->partial_sdu_len += skb->len;
 
-                       if (pi->partial_sdu_len > pi->imtu)
+                       if (chan->partial_sdu_len > pi->imtu)
                                goto drop;
 
-                       if (pi->partial_sdu_len != pi->sdu_len)
+                       if (chan->partial_sdu_len != chan->sdu_len)
                                goto drop;
 
-                       memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+                       memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
                }
 
-               _skb = skb_clone(pi->sdu, GFP_ATOMIC);
+               _skb = skb_clone(chan->sdu, GFP_ATOMIC);
                if (!_skb) {
-                       pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+                       chan->conn_state |= L2CAP_CONN_SAR_RETRY;
                        return -ENOMEM;
                }
 
-               err = sock_queue_rcv_skb(sk, _skb);
+               err = sock_queue_rcv_skb(chan->sk, _skb);
                if (err < 0) {
                        kfree_skb(_skb);
-                       pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+                       chan->conn_state |= L2CAP_CONN_SAR_RETRY;
                        return err;
                }
 
-               pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
-               pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
+               chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
+               chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
 
-               kfree_skb(pi->sdu);
+               kfree_skb(chan->sdu);
                break;
        }
 
@@ -2878,51 +2956,50 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
        return 0;
 
 drop:
-       kfree_skb(pi->sdu);
-       pi->sdu = NULL;
+       kfree_skb(chan->sdu);
+       chan->sdu = NULL;
 
 disconnect:
-       l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+       l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
        kfree_skb(skb);
        return 0;
 }
 
-static int l2cap_try_push_rx_skb(struct sock *sk)
+static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        struct sk_buff *skb;
        u16 control;
        int err;
 
-       while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
+       while ((skb = skb_dequeue(&chan->busy_q))) {
                control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-               err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+               err = l2cap_ertm_reassembly_sdu(chan, skb, control);
                if (err < 0) {
-                       skb_queue_head(BUSY_QUEUE(sk), skb);
+                       skb_queue_head(&chan->busy_q, skb);
                        return -EBUSY;
                }
 
-               pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+               chan->buffer_seq = (chan->buffer_seq + 1) % 64;
        }
 
-       if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
+       if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
                goto done;
 
-       control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+       control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
        control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
-       l2cap_send_sframe(pi, control);
-       l2cap_pi(sk)->retry_count = 1;
+       l2cap_send_sframe(chan, control);
+       chan->retry_count = 1;
 
-       del_timer(&pi->retrans_timer);
+       del_timer(&chan->retrans_timer);
        __mod_monitor_timer();
 
-       l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+       chan->conn_state |= L2CAP_CONN_WAIT_F;
 
 done:
-       pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
-       pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
+       chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
+       chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
 
-       BT_DBG("sk %p, Exit local busy", sk);
+       BT_DBG("chan %p, Exit local busy", chan);
 
        return 0;
 }
@@ -2930,21 +3007,21 @@ done:
 static void l2cap_busy_work(struct work_struct *work)
 {
        DECLARE_WAITQUEUE(wait, current);
-       struct l2cap_pinfo *pi =
-               container_of(work, struct l2cap_pinfo, busy_work);
-       struct sock *sk = (struct sock *)pi;
+       struct l2cap_chan *chan =
+               container_of(work, struct l2cap_chan, busy_work);
+       struct sock *sk = chan->sk;
        int n_tries = 0, timeo = HZ/5, err;
        struct sk_buff *skb;
 
        lock_sock(sk);
 
        add_wait_queue(sk_sleep(sk), &wait);
-       while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
+       while ((skb = skb_peek(&chan->busy_q))) {
                set_current_state(TASK_INTERRUPTIBLE);
 
                if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
                        err = -EBUSY;
-                       l2cap_send_disconn_req(pi->conn, sk, EBUSY);
+                       l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
                        break;
                }
 
@@ -2964,7 +3041,7 @@ static void l2cap_busy_work(struct work_struct *work)
                if (err)
                        break;
 
-               if (l2cap_try_push_rx_skb(sk) == 0)
+               if (l2cap_try_push_rx_skb(chan) == 0)
                        break;
        }
 
@@ -2974,48 +3051,47 @@ static void l2cap_busy_work(struct work_struct *work)
        release_sock(sk);
 }
 
-static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
+static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        int sctrl, err;
 
-       if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
                bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-               __skb_queue_tail(BUSY_QUEUE(sk), skb);
-               return l2cap_try_push_rx_skb(sk);
+               __skb_queue_tail(&chan->busy_q, skb);
+               return l2cap_try_push_rx_skb(chan);
 
 
        }
 
-       err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+       err = l2cap_ertm_reassembly_sdu(chan, skb, control);
        if (err >= 0) {
-               pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+               chan->buffer_seq = (chan->buffer_seq + 1) % 64;
                return err;
        }
 
        /* Busy Condition */
-       BT_DBG("sk %p, Enter local busy", sk);
+       BT_DBG("chan %p, Enter local busy", chan);
 
-       pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
+       chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
        bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-       __skb_queue_tail(BUSY_QUEUE(sk), skb);
+       __skb_queue_tail(&chan->busy_q, skb);
 
-       sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+       sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
        sctrl |= L2CAP_SUPER_RCV_NOT_READY;
-       l2cap_send_sframe(pi, sctrl);
+       l2cap_send_sframe(chan, sctrl);
 
-       pi->conn_state |= L2CAP_CONN_RNR_SENT;
+       chan->conn_state |= L2CAP_CONN_RNR_SENT;
 
-       del_timer(&pi->ack_timer);
+       del_timer(&chan->ack_timer);
 
-       queue_work(_busy_wq, &pi->busy_work);
+       queue_work(_busy_wq, &chan->busy_work);
 
        return err;
 }
 
-static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
+static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct sk_buff *_skb;
        int err = -EINVAL;
 
@@ -3026,80 +3102,80 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb,
 
        switch (control & L2CAP_CTRL_SAR) {
        case L2CAP_SDU_UNSEGMENTED:
-               if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
-                       kfree_skb(pi->sdu);
+               if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+                       kfree_skb(chan->sdu);
                        break;
                }
 
-               err = sock_queue_rcv_skb(sk, skb);
+               err = sock_queue_rcv_skb(chan->sk, skb);
                if (!err)
                        return 0;
 
                break;
 
        case L2CAP_SDU_START:
-               if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
-                       kfree_skb(pi->sdu);
+               if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+                       kfree_skb(chan->sdu);
                        break;
                }
 
-               pi->sdu_len = get_unaligned_le16(skb->data);
+               chan->sdu_len = get_unaligned_le16(skb->data);
                skb_pull(skb, 2);
 
-               if (pi->sdu_len > pi->imtu) {
+               if (chan->sdu_len > pi->imtu) {
                        err = -EMSGSIZE;
                        break;
                }
 
-               pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
-               if (!pi->sdu) {
+               chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
+               if (!chan->sdu) {
                        err = -ENOMEM;
                        break;
                }
 
-               memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+               memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               pi->conn_state |= L2CAP_CONN_SAR_SDU;
-               pi->partial_sdu_len = skb->len;
+               chan->conn_state |= L2CAP_CONN_SAR_SDU;
+               chan->partial_sdu_len = skb->len;
                err = 0;
                break;
 
        case L2CAP_SDU_CONTINUE:
-               if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
                        break;
 
-               memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+               memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               pi->partial_sdu_len += skb->len;
-               if (pi->partial_sdu_len > pi->sdu_len)
-                       kfree_skb(pi->sdu);
+               chan->partial_sdu_len += skb->len;
+               if (chan->partial_sdu_len > chan->sdu_len)
+                       kfree_skb(chan->sdu);
                else
                        err = 0;
 
                break;
 
        case L2CAP_SDU_END:
-               if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
                        break;
 
-               memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+               memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
-               pi->partial_sdu_len += skb->len;
+               chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+               chan->partial_sdu_len += skb->len;
 
-               if (pi->partial_sdu_len > pi->imtu)
+               if (chan->partial_sdu_len > pi->imtu)
                        goto drop;
 
-               if (pi->partial_sdu_len == pi->sdu_len) {
-                       _skb = skb_clone(pi->sdu, GFP_ATOMIC);
-                       err = sock_queue_rcv_skb(sk, _skb);
+               if (chan->partial_sdu_len == chan->sdu_len) {
+                       _skb = skb_clone(chan->sdu, GFP_ATOMIC);
+                       err = sock_queue_rcv_skb(chan->sk, _skb);
                        if (err < 0)
                                kfree_skb(_skb);
                }
                err = 0;
 
 drop:
-               kfree_skb(pi->sdu);
+               kfree_skb(chan->sdu);
                break;
        }
 
@@ -3107,31 +3183,30 @@ drop:
        return err;
 }
 
-static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
+static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
 {
        struct sk_buff *skb;
        u16 control;
 
-       while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
+       while ((skb = skb_peek(&chan->srej_q))) {
                if (bt_cb(skb)->tx_seq != tx_seq)
                        break;
 
-               skb = skb_dequeue(SREJ_QUEUE(sk));
+               skb = skb_dequeue(&chan->srej_q);
                control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-               l2cap_ertm_reassembly_sdu(sk, skb, control);
-               l2cap_pi(sk)->buffer_seq_srej =
-                       (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
+               l2cap_ertm_reassembly_sdu(chan, skb, control);
+               chan->buffer_seq_srej =
+                       (chan->buffer_seq_srej + 1) % 64;
                tx_seq = (tx_seq + 1) % 64;
        }
 }
 
-static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
+static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        struct srej_list *l, *tmp;
        u16 control;
 
-       list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+       list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
                if (l->tx_seq == tx_seq) {
                        list_del(&l->list);
                        kfree(l);
@@ -3139,34 +3214,33 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
                }
                control = L2CAP_SUPER_SELECT_REJECT;
                control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-               l2cap_send_sframe(pi, control);
+               l2cap_send_sframe(chan, control);
                list_del(&l->list);
-               list_add_tail(&l->list, SREJ_LIST(sk));
+               list_add_tail(&l->list, &chan->srej_l);
        }
 }
 
-static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
+static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        struct srej_list *new;
        u16 control;
 
-       while (tx_seq != pi->expected_tx_seq) {
+       while (tx_seq != chan->expected_tx_seq) {
                control = L2CAP_SUPER_SELECT_REJECT;
-               control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-               l2cap_send_sframe(pi, control);
+               control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+               l2cap_send_sframe(chan, control);
 
                new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
-               new->tx_seq = pi->expected_tx_seq;
-               pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-               list_add_tail(&new->list, SREJ_LIST(sk));
+               new->tx_seq = chan->expected_tx_seq;
+               chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
+               list_add_tail(&new->list, &chan->srej_l);
        }
-       pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+       chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
 }
 
-static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
+       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        u8 tx_seq = __get_txseq(rx_control);
        u8 req_seq = __get_reqseq(rx_control);
        u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
@@ -3174,72 +3248,72 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
        int num_to_ack = (pi->tx_win/6) + 1;
        int err = 0;
 
-       BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
-                                                               rx_control);
+       BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
+                                                       tx_seq, rx_control);
 
        if (L2CAP_CTRL_FINAL & rx_control &&
-                       l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
-               del_timer(&pi->monitor_timer);
-               if (pi->unacked_frames > 0)
+                       chan->conn_state & L2CAP_CONN_WAIT_F) {
+               del_timer(&chan->monitor_timer);
+               if (chan->unacked_frames > 0)
                        __mod_retrans_timer();
-               pi->conn_state &= ~L2CAP_CONN_WAIT_F;
+               chan->conn_state &= ~L2CAP_CONN_WAIT_F;
        }
 
-       pi->expected_ack_seq = req_seq;
-       l2cap_drop_acked_frames(sk);
+       chan->expected_ack_seq = req_seq;
+       l2cap_drop_acked_frames(chan);
 
-       if (tx_seq == pi->expected_tx_seq)
+       if (tx_seq == chan->expected_tx_seq)
                goto expected;
 
-       tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+       tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
        if (tx_seq_offset < 0)
                tx_seq_offset += 64;
 
        /* invalid tx_seq */
        if (tx_seq_offset >= pi->tx_win) {
-               l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+               l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
                goto drop;
        }
 
-       if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
+       if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
                goto drop;
 
-       if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+       if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
                struct srej_list *first;
 
-               first = list_first_entry(SREJ_LIST(sk),
+               first = list_first_entry(&chan->srej_l,
                                struct srej_list, list);
                if (tx_seq == first->tx_seq) {
-                       l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
-                       l2cap_check_srej_gap(sk, tx_seq);
+                       l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
+                       l2cap_check_srej_gap(chan, tx_seq);
 
                        list_del(&first->list);
                        kfree(first);
 
-                       if (list_empty(SREJ_LIST(sk))) {
-                               pi->buffer_seq = pi->buffer_seq_srej;
-                               pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
-                               l2cap_send_ack(pi);
-                               BT_DBG("sk %p, Exit SREJ_SENT", sk);
+                       if (list_empty(&chan->srej_l)) {
+                               chan->buffer_seq = chan->buffer_seq_srej;
+                               chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
+                               l2cap_send_ack(chan);
+                               BT_DBG("chan %p, Exit SREJ_SENT", chan);
                        }
                } else {
                        struct srej_list *l;
 
                        /* duplicated tx_seq */
-                       if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
+                       if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
                                goto drop;
 
-                       list_for_each_entry(l, SREJ_LIST(sk), list) {
+                       list_for_each_entry(l, &chan->srej_l, list) {
                                if (l->tx_seq == tx_seq) {
-                                       l2cap_resend_srejframe(sk, tx_seq);
+                                       l2cap_resend_srejframe(chan, tx_seq);
                                        return 0;
                                }
                        }
-                       l2cap_send_srejframe(sk, tx_seq);
+                       l2cap_send_srejframe(chan, tx_seq);
                }
        } else {
                expected_tx_seq_offset =
-                       (pi->expected_tx_seq - pi->buffer_seq) % 64;
+                       (chan->expected_tx_seq - chan->buffer_seq) % 64;
                if (expected_tx_seq_offset < 0)
                        expected_tx_seq_offset += 64;
 
@@ -3247,51 +3321,51 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
                if (tx_seq_offset < expected_tx_seq_offset)
                        goto drop;
 
-               pi->conn_state |= L2CAP_CONN_SREJ_SENT;
+               chan->conn_state |= L2CAP_CONN_SREJ_SENT;
 
-               BT_DBG("sk %p, Enter SREJ", sk);
+               BT_DBG("chan %p, Enter SREJ", chan);
 
-               INIT_LIST_HEAD(SREJ_LIST(sk));
-               pi->buffer_seq_srej = pi->buffer_seq;
+               INIT_LIST_HEAD(&chan->srej_l);
+               chan->buffer_seq_srej = chan->buffer_seq;
 
-               __skb_queue_head_init(SREJ_QUEUE(sk));
-               __skb_queue_head_init(BUSY_QUEUE(sk));
-               l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
+               __skb_queue_head_init(&chan->srej_q);
+               __skb_queue_head_init(&chan->busy_q);
+               l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
 
-               pi->conn_state |= L2CAP_CONN_SEND_PBIT;
+               chan->conn_state |= L2CAP_CONN_SEND_PBIT;
 
-               l2cap_send_srejframe(sk, tx_seq);
+               l2cap_send_srejframe(chan, tx_seq);
 
-               del_timer(&pi->ack_timer);
+               del_timer(&chan->ack_timer);
        }
        return 0;
 
 expected:
-       pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+       chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
 
-       if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+       if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
                bt_cb(skb)->tx_seq = tx_seq;
                bt_cb(skb)->sar = sar;
-               __skb_queue_tail(SREJ_QUEUE(sk), skb);
+               __skb_queue_tail(&chan->srej_q, skb);
                return 0;
        }
 
-       err = l2cap_push_rx_skb(sk, skb, rx_control);
+       err = l2cap_push_rx_skb(chan, skb, rx_control);
        if (err < 0)
                return 0;
 
        if (rx_control & L2CAP_CTRL_FINAL) {
-               if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-                       pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
+                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
                else
-                       l2cap_retransmit_frames(sk);
+                       l2cap_retransmit_frames(chan);
        }
 
        __mod_ack_timer();
 
-       pi->num_acked = (pi->num_acked + 1) % num_to_ack;
-       if (pi->num_acked == num_to_ack - 1)
-               l2cap_send_ack(pi);
+       chan->num_acked = (chan->num_acked + 1) % num_to_ack;
+       if (chan->num_acked == num_to_ack - 1)
+               l2cap_send_ack(chan);
 
        return 0;
 
@@ -3300,165 +3374,160 @@ drop:
        return 0;
 }
 
-static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
+static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-       BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
+       BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
                                                rx_control);
 
-       pi->expected_ack_seq = __get_reqseq(rx_control);
-       l2cap_drop_acked_frames(sk);
+       chan->expected_ack_seq = __get_reqseq(rx_control);
+       l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_POLL) {
-               pi->conn_state |= L2CAP_CONN_SEND_FBIT;
-               if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
-                       if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-                                       (pi->unacked_frames > 0))
+               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+               if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+                       if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+                                       (chan->unacked_frames > 0))
                                __mod_retrans_timer();
 
-                       pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-                       l2cap_send_srejtail(sk);
+                       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+                       l2cap_send_srejtail(chan);
                } else {
-                       l2cap_send_i_or_rr_or_rnr(sk);
+                       l2cap_send_i_or_rr_or_rnr(chan);
                }
 
        } else if (rx_control & L2CAP_CTRL_FINAL) {
-               pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+               chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
-               if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-                       pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
+                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
                else
-                       l2cap_retransmit_frames(sk);
+                       l2cap_retransmit_frames(chan);
 
        } else {
-               if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-                               (pi->unacked_frames > 0))
+               if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+                               (chan->unacked_frames > 0))
                        __mod_retrans_timer();
 
-               pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-               if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
-                       l2cap_send_ack(pi);
+               chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+               if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
+                       l2cap_send_ack(chan);
                else
-                       l2cap_ertm_send(sk);
+                       l2cap_ertm_send(chan);
        }
 }
 
-static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
+static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        u8 tx_seq = __get_reqseq(rx_control);
 
-       BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+       BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
-       pi->expected_ack_seq = tx_seq;
-       l2cap_drop_acked_frames(sk);
+       chan->expected_ack_seq = tx_seq;
+       l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_FINAL) {
-               if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-                       pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
+                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
                else
-                       l2cap_retransmit_frames(sk);
+                       l2cap_retransmit_frames(chan);
        } else {
-               l2cap_retransmit_frames(sk);
+               l2cap_retransmit_frames(chan);
 
-               if (pi->conn_state & L2CAP_CONN_WAIT_F)
-                       pi->conn_state |= L2CAP_CONN_REJ_ACT;
+               if (chan->conn_state & L2CAP_CONN_WAIT_F)
+                       chan->conn_state |= L2CAP_CONN_REJ_ACT;
        }
 }
-static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
+static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        u8 tx_seq = __get_reqseq(rx_control);
 
-       BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+       BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
        if (rx_control & L2CAP_CTRL_POLL) {
-               pi->expected_ack_seq = tx_seq;
-               l2cap_drop_acked_frames(sk);
+               chan->expected_ack_seq = tx_seq;
+               l2cap_drop_acked_frames(chan);
 
-               pi->conn_state |= L2CAP_CONN_SEND_FBIT;
-               l2cap_retransmit_one_frame(sk, tx_seq);
+               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+               l2cap_retransmit_one_frame(chan, tx_seq);
 
-               l2cap_ertm_send(sk);
+               l2cap_ertm_send(chan);
 
-               if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-                       pi->srej_save_reqseq = tx_seq;
-                       pi->conn_state |= L2CAP_CONN_SREJ_ACT;
+               if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+                       chan->srej_save_reqseq = tx_seq;
+                       chan->conn_state |= L2CAP_CONN_SREJ_ACT;
                }
        } else if (rx_control & L2CAP_CTRL_FINAL) {
-               if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
-                               pi->srej_save_reqseq == tx_seq)
-                       pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+               if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
+                               chan->srej_save_reqseq == tx_seq)
+                       chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
                else
-                       l2cap_retransmit_one_frame(sk, tx_seq);
+                       l2cap_retransmit_one_frame(chan, tx_seq);
        } else {
-               l2cap_retransmit_one_frame(sk, tx_seq);
-               if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-                       pi->srej_save_reqseq = tx_seq;
-                       pi->conn_state |= L2CAP_CONN_SREJ_ACT;
+               l2cap_retransmit_one_frame(chan, tx_seq);
+               if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+                       chan->srej_save_reqseq = tx_seq;
+                       chan->conn_state |= L2CAP_CONN_SREJ_ACT;
                }
        }
 }
 
-static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
+static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
        u8 tx_seq = __get_reqseq(rx_control);
 
-       BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+       BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
-       pi->expected_ack_seq = tx_seq;
-       l2cap_drop_acked_frames(sk);
+       chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+       chan->expected_ack_seq = tx_seq;
+       l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_POLL)
-               pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
 
-       if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
-               del_timer(&pi->retrans_timer);
+       if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
+               del_timer(&chan->retrans_timer);
                if (rx_control & L2CAP_CTRL_POLL)
-                       l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
+                       l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
                return;
        }
 
        if (rx_control & L2CAP_CTRL_POLL)
-               l2cap_send_srejtail(sk);
+               l2cap_send_srejtail(chan);
        else
-               l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
+               l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
 }
 
-static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
 {
-       BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+       BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
 
        if (L2CAP_CTRL_FINAL & rx_control &&
-                       l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
-               del_timer(&l2cap_pi(sk)->monitor_timer);
-               if (l2cap_pi(sk)->unacked_frames > 0)
+                       chan->conn_state & L2CAP_CONN_WAIT_F) {
+               del_timer(&chan->monitor_timer);
+               if (chan->unacked_frames > 0)
                        __mod_retrans_timer();
-               l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
+               chan->conn_state &= ~L2CAP_CONN_WAIT_F;
        }
 
        switch (rx_control & L2CAP_CTRL_SUPERVISE) {
        case L2CAP_SUPER_RCV_READY:
-               l2cap_data_channel_rrframe(sk, rx_control);
+               l2cap_data_channel_rrframe(chan, rx_control);
                break;
 
        case L2CAP_SUPER_REJECT:
-               l2cap_data_channel_rejframe(sk, rx_control);
+               l2cap_data_channel_rejframe(chan, rx_control);
                break;
 
        case L2CAP_SUPER_SELECT_REJECT:
-               l2cap_data_channel_srejframe(sk, rx_control);
+               l2cap_data_channel_srejframe(chan, rx_control);
                break;
 
        case L2CAP_SUPER_RCV_NOT_READY:
-               l2cap_data_channel_rnrframe(sk, rx_control);
+               l2cap_data_channel_rnrframe(chan, rx_control);
                break;
        }
 
@@ -3468,6 +3537,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 {
+       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        u16 control;
        u8 req_seq;
@@ -3492,41 +3562,41 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
                len -= 2;
 
        if (len > pi->mps) {
-               l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+               l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
                goto drop;
        }
 
        req_seq = __get_reqseq(control);
-       req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
+       req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
        if (req_seq_offset < 0)
                req_seq_offset += 64;
 
        next_tx_seq_offset =
-               (pi->next_tx_seq - pi->expected_ack_seq) % 64;
+               (chan->next_tx_seq - chan->expected_ack_seq) % 64;
        if (next_tx_seq_offset < 0)
                next_tx_seq_offset += 64;
 
        /* check for invalid req-seq */
        if (req_seq_offset > next_tx_seq_offset) {
-               l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+               l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
                goto drop;
        }
 
        if (__is_iframe(control)) {
                if (len < 0) {
-                       l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+                       l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
                        goto drop;
                }
 
-               l2cap_data_channel_iframe(sk, control, skb);
+               l2cap_data_channel_iframe(chan, control, skb);
        } else {
                if (len != 0) {
                        BT_ERR("%d", len);
-                       l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+                       l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
                        goto drop;
                }
 
-               l2cap_data_channel_sframe(sk, control, skb);
+               l2cap_data_channel_sframe(chan, control, skb);
        }
 
        return 0;
@@ -3538,21 +3608,23 @@ drop:
 
 static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
+       struct l2cap_chan *chan;
        struct sock *sk;
        struct l2cap_pinfo *pi;
        u16 control;
        u8 tx_seq;
        int len;
 
-       sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
-       if (!sk) {
+       chan = l2cap_get_chan_by_scid(conn, cid);
+       if (!chan) {
                BT_DBG("unknown cid 0x%4.4x", cid);
                goto drop;
        }
 
+       sk = chan->sk;
        pi = l2cap_pi(sk);
 
-       BT_DBG("sk %p, len %d", sk, skb->len);
+       BT_DBG("chan %p, len %d", chan, skb->len);
 
        if (sk->sk_state != BT_CONNECTED)
                goto drop;
@@ -3600,17 +3672,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 
                tx_seq = __get_txseq(control);
 
-               if (pi->expected_tx_seq == tx_seq)
-                       pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+               if (chan->expected_tx_seq == tx_seq)
+                       chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
                else
-                       pi->expected_tx_seq = (tx_seq + 1) % 64;
+                       chan->expected_tx_seq = (tx_seq + 1) % 64;
 
-               l2cap_streaming_reassembly_sdu(sk, skb, control);
+               l2cap_streaming_reassembly_sdu(chan, skb, control);
 
                goto done;
 
        default:
-               BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
+               BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
                break;
        }
 
@@ -3654,6 +3726,36 @@ done:
        return 0;
 }
 
+static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
+{
+       struct sock *sk;
+
+       sk = l2cap_get_sock_by_scid(0, cid, conn->src);
+       if (!sk)
+               goto drop;
+
+       bh_lock_sock(sk);
+
+       BT_DBG("sk %p, len %d", sk, skb->len);
+
+       if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+               goto drop;
+
+       if (l2cap_pi(sk)->imtu < skb->len)
+               goto drop;
+
+       if (!sock_queue_rcv_skb(sk, skb))
+               goto done;
+
+drop:
+       kfree_skb(skb);
+
+done:
+       if (sk)
+               bh_unlock_sock(sk);
+       return 0;
+}
+
 static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 {
        struct l2cap_hdr *lh = (void *) skb->data;
@@ -3683,6 +3785,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
                l2cap_conless_channel(conn, psm, skb);
                break;
 
+       case L2CAP_CID_LE_DATA:
+               l2cap_att_channel(conn, cid, skb);
+               break;
+
        default:
                l2cap_data_channel(conn, cid, skb);
                break;
@@ -3786,20 +3892,19 @@ static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
 
 static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 {
-       struct l2cap_chan_list *l;
        struct l2cap_conn *conn = hcon->l2cap_data;
-       struct sock *sk;
+       struct l2cap_chan *chan;
 
        if (!conn)
                return 0;
 
-       l = &conn->chan_list;
-
        BT_DBG("conn %p", conn);
 
-       read_lock(&l->lock);
+       read_lock(&conn->chan_lock);
+
+       list_for_each_entry(chan, &conn->chan_l, list) {
+               struct sock *sk = chan->sk;
 
-       for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
                bh_lock_sock(sk);
 
                if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
@@ -3820,10 +3925,10 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                                req.psm  = l2cap_pi(sk)->psm;
 
-                               l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                               chan->ident = l2cap_get_ident(conn);
                                l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
-                               l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+                               l2cap_send_cmd(conn, chan->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
                        } else {
                                l2cap_sock_clear_timer(sk);
@@ -3846,14 +3951,14 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
                        rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-                       l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-                                       L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+                                                       sizeof(rsp), &rsp);
                }
 
                bh_unlock_sock(sk);
        }
 
-       read_unlock(&l->lock);
+       read_unlock(&conn->chan_lock);
 
        return 0;
 }
@@ -3872,7 +3977,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
 
        if (!(flags & ACL_CONT)) {
                struct l2cap_hdr *hdr;
-               struct sock *sk;
+               struct l2cap_chan *chan;
                u16 cid;
                int len;
 
@@ -3910,18 +4015,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
                        goto drop;
                }
 
-               sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
+               chan = l2cap_get_chan_by_scid(conn, cid);
 
-               if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
-                       BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
-                                       len, l2cap_pi(sk)->imtu);
-                       bh_unlock_sock(sk);
-                       l2cap_conn_unreliable(conn, ECOMM);
-                       goto drop;
-               }
+               if (chan && chan->sk) {
+                       struct sock *sk = chan->sk;
 
-               if (sk)
+                       if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
+                               BT_ERR("Frame exceeding recv MTU (len %d, "
+                                                       "MTU %d)", len,
+                                                       l2cap_pi(sk)->imtu);
+                               bh_unlock_sock(sk);
+                               l2cap_conn_unreliable(conn, ECOMM);
+                               goto drop;
+                       }
                        bh_unlock_sock(sk);
+               }
 
                /* Allocate skb for the complete frame (with header) */
                conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
index 299fe56a9668e677457d23b691ac38521c61a1fe..47394a178bd5e0198a815e1e310dae7c88305ea6 100644 (file)
@@ -269,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
                goto done;
        }
 
-       if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) {
+       if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) {
                bdaddr_t *src = &bt_sk(sk)->src;
                u16 psm;
 
@@ -757,35 +757,37 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
        case L2CAP_MODE_ERTM:
        case L2CAP_MODE_STREAMING:
                /* Entire SDU fits into one PDU */
-               if (len <= pi->remote_mps) {
+               if (len <= pi->chan->remote_mps) {
                        control = L2CAP_SDU_UNSEGMENTED;
                        skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
                        if (IS_ERR(skb)) {
                                err = PTR_ERR(skb);
                                goto done;
                        }
-                       __skb_queue_tail(TX_QUEUE(sk), skb);
+                       __skb_queue_tail(&pi->chan->tx_q, skb);
 
-                       if (sk->sk_send_head == NULL)
-                               sk->sk_send_head = skb;
+                       if (pi->chan->tx_send_head == NULL)
+                               pi->chan->tx_send_head = skb;
 
                } else {
                /* Segment SDU into multiples PDUs */
-                       err = l2cap_sar_segment_sdu(sk, msg, len);
+                       err = l2cap_sar_segment_sdu(pi->chan, msg, len);
                        if (err < 0)
                                goto done;
                }
 
                if (pi->mode == L2CAP_MODE_STREAMING) {
-                       l2cap_streaming_send(sk);
-               } else {
-                       if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-                                       (pi->conn_state & L2CAP_CONN_WAIT_F)) {
-                               err = len;
-                               break;
-                       }
-                       err = l2cap_ertm_send(sk);
+                       l2cap_streaming_send(pi->chan);
+                       err = len;
+                       break;
+               }
+
+               if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+                               (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) {
+                       err = len;
+                       break;
                }
+               err = l2cap_ertm_send(pi->chan);
 
                if (err >= 0)
                        err = len;
@@ -808,29 +810,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
        lock_sock(sk);
 
        if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
-               struct l2cap_conn_rsp rsp;
-               struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-               u8 buf[128];
-
-               sk->sk_state = BT_CONFIG;
-
-               rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-               rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
-               rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
-               rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-               l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
-                                       L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-
-               if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
-                       release_sock(sk);
-                       return 0;
-               }
-
-               l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-               l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-                               l2cap_build_conf_req(sk, buf), buf);
-               l2cap_pi(sk)->num_conf_req++;
-
+               __l2cap_connect_rsp_defer(sk);
                release_sock(sk);
                return 0;
        }
@@ -886,6 +866,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
 void __l2cap_sock_close(struct sock *sk, int reason)
 {
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 
        BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
 
@@ -900,9 +881,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
                                        sk->sk_type == SOCK_STREAM) &&
                                        conn->hcon->type == ACL_LINK) {
                        l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-                       l2cap_send_disconn_req(conn, sk, reason);
+                       l2cap_send_disconn_req(conn, chan, reason);
                } else
-                       l2cap_chan_del(sk, reason);
+                       l2cap_chan_del(chan, reason);
                break;
 
        case BT_CONNECT2:
@@ -921,16 +902,16 @@ void __l2cap_sock_close(struct sock *sk, int reason)
                        rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
                        rsp.result = cpu_to_le16(result);
                        rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-                       l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-                                       L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+                                                       sizeof(rsp), &rsp);
                }
 
-               l2cap_chan_del(sk, reason);
+               l2cap_chan_del(chan, reason);
                break;
 
        case BT_CONNECT:
        case BT_DISCONN:
-               l2cap_chan_del(sk, reason);
+               l2cap_chan_del(chan, reason);
                break;
 
        default:
@@ -1035,12 +1016,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
        }
 
        /* Default config options */
-       pi->conf_len = 0;
        pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
-       skb_queue_head_init(TX_QUEUE(sk));
-       skb_queue_head_init(SREJ_QUEUE(sk));
-       skb_queue_head_init(BUSY_QUEUE(sk));
-       INIT_LIST_HEAD(SREJ_LIST(sk));
 }
 
 static struct proto l2cap_proto = {
index bf5d28da46e66487aeb1f0c320c188e646696175..a6d191f2a0fed2e0771c37185fec019690b6343e 100644 (file)
@@ -330,6 +330,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct timespec uptime;
 
        sinfo->generation = sdata->local->sta_generation;
 
@@ -343,7 +344,11 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                        STATION_INFO_TX_BITRATE |
                        STATION_INFO_RX_BITRATE |
                        STATION_INFO_RX_DROP_MISC |
-                       STATION_INFO_BSS_PARAM;
+                       STATION_INFO_BSS_PARAM |
+                       STATION_INFO_CONNECTED_TIME;
+
+       do_posix_clock_monotonic_gettime(&uptime);
+       sinfo->connected_time = uptime.tv_sec - sta->last_connected;
 
        sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
        sinfo->rx_bytes = sta->rx_bytes;
@@ -686,6 +691,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                if (set & BIT(NL80211_STA_FLAG_MFP))
                        sta->flags |= WLAN_STA_MFP;
        }
+
+       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+               sta->flags &= ~WLAN_STA_AUTH;
+               if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
+                       sta->flags |= WLAN_STA_AUTH;
+       }
        spin_unlock_irqrestore(&sta->flaglock, flags);
 
        /*
@@ -1034,26 +1045,26 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
        u8 *new_ie;
        const u8 *old_ie;
 
-       /* first allocate the new vendor information element */
+       /* allocate information elements */
        new_ie = NULL;
-       old_ie = ifmsh->vendor_ie;
+       old_ie = ifmsh->ie;
 
-       ifmsh->vendor_ie_len = setup->vendor_ie_len;
-       if (setup->vendor_ie_len) {
-               new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len,
+       if (setup->ie_len) {
+               new_ie = kmemdup(setup->ie, setup->ie_len,
                                GFP_KERNEL);
                if (!new_ie)
                        return -ENOMEM;
        }
+       ifmsh->ie_len = setup->ie_len;
+       ifmsh->ie = new_ie;
+       kfree(old_ie);
 
        /* now copy the rest of the setup parameters */
        ifmsh->mesh_id_len = setup->mesh_id_len;
        memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
        ifmsh->mesh_pp_id = setup->path_sel_proto;
        ifmsh->mesh_pm_id = setup->path_metric;
-       ifmsh->vendor_ie = new_ie;
-
-       kfree(old_ie);
+       ifmsh->is_secure = setup->is_secure;
 
        return 0;
 }
index c04a1396cf8d94e4ff6d467cb1f98a3a1133f5be..a01d2137fddca33f11bc89bda319c5d00937b98d 100644 (file)
@@ -92,6 +92,31 @@ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
 }
 STA_OPS(inactive_ms);
 
+
+static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf,
+                                       size_t count, loff_t *ppos)
+{
+       struct sta_info *sta = file->private_data;
+       struct timespec uptime;
+       struct tm result;
+       long connected_time_secs;
+       char buf[100];
+       int res;
+       do_posix_clock_monotonic_gettime(&uptime);
+       connected_time_secs = uptime.tv_sec - sta->last_connected;
+       time_to_tm(connected_time_secs, 0, &result);
+       result.tm_year -= 70;
+       result.tm_mday -= 1;
+       res = scnprintf(buf, sizeof(buf),
+               "years  - %ld\nmonths - %d\ndays   - %d\nclock  - %d:%d:%d\n\n",
+                       result.tm_year, result.tm_mon, result.tm_mday,
+                       result.tm_hour, result.tm_min, result.tm_sec);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(connected_time);
+
+
+
 static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
                                      size_t count, loff_t *ppos)
 {
@@ -324,6 +349,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
        DEBUGFS_ADD(flags);
        DEBUGFS_ADD(num_ps_buf_frames);
        DEBUGFS_ADD(inactive_ms);
+       DEBUGFS_ADD(connected_time);
        DEBUGFS_ADD(last_seq_ctrl);
        DEBUGFS_ADD(agg_status);
        DEBUGFS_ADD(dev);
index 9c0d62bb0ea3443d13edad25642ae7375a026293..00a0685f240355ea136301013a90597180117605 100644 (file)
@@ -552,4 +552,17 @@ static inline void drv_get_ringparam(struct ieee80211_local *local,
        trace_drv_return_void(local);
 }
 
+static inline bool drv_tx_frames_pending(struct ieee80211_local *local)
+{
+       bool ret = false;
+
+       might_sleep();
+
+       trace_drv_tx_frames_pending(local);
+       if (local->ops->tx_frames_pending)
+               ret = local->ops->tx_frames_pending(&local->hw);
+       trace_drv_return_bool(local, ret);
+
+       return ret;
+}
 #endif /* __MAC80211_DRIVER_OPS */
index 45aab80738e272c3b9b1a25c71bb14201b643c14..c8c934d48b7ad7c8111bd156c8b244b5c9f85038 100644 (file)
@@ -74,6 +74,21 @@ TRACE_EVENT(drv_return_int,
        TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret)
 );
 
+TRACE_EVENT(drv_return_bool,
+       TP_PROTO(struct ieee80211_local *local, bool ret),
+       TP_ARGS(local, ret),
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               __field(bool, ret)
+       ),
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               __entry->ret = ret;
+       ),
+       TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ?
+                 "true" : "false")
+);
+
 TRACE_EVENT(drv_return_u64,
        TP_PROTO(struct ieee80211_local *local, u64 ret),
        TP_ARGS(local, ret),
@@ -964,6 +979,11 @@ TRACE_EVENT(drv_get_ringparam,
        )
 );
 
+DEFINE_EVENT(local_only_evt, drv_tx_frames_pending,
+       TP_PROTO(struct ieee80211_local *local),
+       TP_ARGS(local)
+);
+
 DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
        TP_PROTO(struct ieee80211_local *local),
        TP_ARGS(local)
index 89ce1e329b5d64fe0430e0b4cf744c852ffa295d..a77849970914eb15634b8d23d8b30f6f75e8a2ef 100644 (file)
@@ -488,8 +488,9 @@ struct ieee80211_if_mesh {
        struct mesh_config mshcfg;
        u32 mesh_seqnum;
        bool accepting_plinks;
-       const u8 *vendor_ie;
-       u8 vendor_ie_len;
+       const u8 *ie;
+       u8 ie_len;
+       bool is_secure;
 };
 
 #ifdef CONFIG_MAC80211_MESH
index dc50fc3153e53d3e689570036cdea5e079ad9cbb..0ab2a8df312df03988a4293402743a7fe3ce2cb7 100644 (file)
@@ -545,7 +545,9 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
        },
        [NL80211_IFTYPE_MESH_POINT] = {
                .tx = 0xffff,
-               .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+                       BIT(IEEE80211_STYPE_AUTH >> 4) |
+                       BIT(IEEE80211_STYPE_DEAUTH >> 4),
        },
 };
 
@@ -760,6 +762,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
 #endif
 
+       /* if the underlying driver supports mesh, mac80211 will (at least)
+        * provide routing of mesh authentication frames to userspace */
+       if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
+               local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
+
        /* mac80211 supports control port protocol changing */
        local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
 
index 2a57cc02c6189415387cbba01585778a7ab1674a..11207979e2e29b7a07a6aedf927e527a9f7b01dd 100644 (file)
@@ -279,9 +279,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
            MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
        *pos++ = 0x00;
 
-       if (sdata->u.mesh.vendor_ie) {
-               int len = sdata->u.mesh.vendor_ie_len;
-               const u8 *data = sdata->u.mesh.vendor_ie;
+       if (sdata->u.mesh.ie) {
+               int len = sdata->u.mesh.ie_len;
+               const u8 *data = sdata->u.mesh.ie;
                if (skb_tailroom(skb) > len)
                        memcpy(skb_put(skb, len), data, len);
        }
@@ -573,6 +573,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
        ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
                               &elems);
 
+       /* ignore beacons from secure mesh peers if our security is off */
+       if (elems.rsn_len && !sdata->u.mesh.is_secure)
+               return;
+
        if (elems.ds_params && elems.ds_params_len == 1)
                freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
        else
@@ -586,9 +590,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
        if (elems.mesh_id && elems.mesh_config &&
            mesh_matches_local(&elems, sdata)) {
                supp_rates = ieee80211_sta_get_rates(local, &elems, band);
-
-               mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
-                                     mesh_peer_accepts_plinks(&elems));
+               mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);
        }
 }
 
index b99e230fe31c3eff6960c09c6d4b4e37b228518b..10acf1cc80824b0aa1165c20cab1bdbc7b1a0d38 100644 (file)
@@ -226,7 +226,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
 /* Mesh plinks */
 void mesh_neighbour_update(u8 *hw_addr, u32 rates,
-               struct ieee80211_sub_if_data *sdata, bool add);
+               struct ieee80211_sub_if_data *sdata,
+               struct ieee802_11_elems *ie);
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
 void mesh_plink_broken(struct sta_info *sta);
index 336ca9d0c5c44aac5c7f7eb88b42c18cfefaa5b8..35c715adaae2031ed9536e6ae257c1023f9c5d89 100644 (file)
@@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
        __mesh_table_free(tbl);
 }
 
-static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
+static int mesh_table_grow(struct mesh_table *oldtbl,
+               struct mesh_table *newtbl)
 {
-       struct mesh_table *newtbl;
        struct hlist_head *oldhash;
        struct hlist_node *p, *q;
        int i;
 
-       if (atomic_read(&tbl->entries)
-                       < tbl->mean_chain_len * (tbl->hash_mask + 1))
-               goto endgrow;
+       if (atomic_read(&oldtbl->entries)
+                       < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
+               return -EAGAIN;
 
-       newtbl = mesh_table_alloc(tbl->size_order + 1);
-       if (!newtbl)
-               goto endgrow;
 
-       newtbl->free_node = tbl->free_node;
-       newtbl->mean_chain_len = tbl->mean_chain_len;
-       newtbl->copy_node = tbl->copy_node;
-       atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
+       newtbl->free_node = oldtbl->free_node;
+       newtbl->mean_chain_len = oldtbl->mean_chain_len;
+       newtbl->copy_node = oldtbl->copy_node;
+       atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));
 
-       oldhash = tbl->hash_buckets;
-       for (i = 0; i <= tbl->hash_mask; i++)
+       oldhash = oldtbl->hash_buckets;
+       for (i = 0; i <= oldtbl->hash_mask; i++)
                hlist_for_each(p, &oldhash[i])
-                       if (tbl->copy_node(p, newtbl) < 0)
+                       if (oldtbl->copy_node(p, newtbl) < 0)
                                goto errcopy;
 
-       return newtbl;
+       return 0;
 
 errcopy:
        for (i = 0; i <= newtbl->hash_mask; i++) {
                hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
-                       tbl->free_node(p, 0);
+                       oldtbl->free_node(p, 0);
        }
-       __mesh_table_free(newtbl);
-endgrow:
-       return NULL;
+       return -ENOMEM;
 }
 
 
@@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void)
 {
        struct mesh_table *oldtbl, *newtbl;
 
+       newtbl = mesh_table_alloc(mesh_paths->size_order + 1);
+       if (!newtbl)
+               return;
        write_lock(&pathtbl_resize_lock);
        oldtbl = mesh_paths;
-       newtbl = mesh_table_grow(mesh_paths);
-       if (!newtbl) {
+       if (mesh_table_grow(mesh_paths, newtbl) < 0) {
+               __mesh_table_free(newtbl);
                write_unlock(&pathtbl_resize_lock);
                return;
        }
@@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void)
 {
        struct mesh_table *oldtbl, *newtbl;
 
+       newtbl = mesh_table_alloc(mpp_paths->size_order + 1);
+       if (!newtbl)
+               return;
        write_lock(&pathtbl_resize_lock);
        oldtbl = mpp_paths;
-       newtbl = mesh_table_grow(mpp_paths);
-       if (!newtbl) {
+       if (mesh_table_grow(mpp_paths, newtbl) < 0) {
+               __mesh_table_free(newtbl);
                write_unlock(&pathtbl_resize_lock);
                return;
        }
index 44b53931ba5e0e410def11e3b216f4944e29a9fd..84e5b056af022a33d3016ebc3b813c61a370ee22 100644 (file)
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return NULL;
 
-       sta->flags = WLAN_STA_AUTHORIZED;
+       sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH;
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
        rate_control_rate_init(sta);
 
@@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                __le16 reason) {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
-                       sdata->u.mesh.vendor_ie_len);
+                       sdata->u.mesh.ie_len);
        struct ieee80211_mgmt *mgmt;
        bool include_plid = false;
        static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A };
@@ -237,8 +237,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata,
-                          bool peer_accepting_plinks)
+void mesh_neighbour_update(u8 *hw_addr, u32 rates,
+               struct ieee80211_sub_if_data *sdata,
+               struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
@@ -248,8 +249,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
        sta = sta_info_get(sdata, hw_addr);
        if (!sta) {
                rcu_read_unlock();
-
-               sta = mesh_plink_alloc(sdata, hw_addr, rates);
+               /* Userspace handles peer allocation when security is enabled
+                * */
+               if (sdata->u.mesh.is_secure)
+                       cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
+                                       elems->ie_start, elems->total_len,
+                                       GFP_KERNEL);
+               else
+                       sta = mesh_plink_alloc(sdata, hw_addr, rates);
                if (!sta)
                        return;
                if (sta_info_insert_rcu(sta)) {
@@ -260,7 +267,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
 
        sta->last_rx = jiffies;
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
-       if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
+       if (mesh_peer_accepts_plinks(elems) &&
+                       sta->plink_state == PLINK_LISTEN &&
                        sdata->u.mesh.accepting_plinks &&
                        sdata->u.mesh.mshcfg.auto_open_plinks)
                mesh_plink_open(sta);
@@ -372,6 +380,9 @@ int mesh_plink_open(struct sta_info *sta)
        __le16 llid;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
 
+       if (!test_sta_flags(sta, WLAN_STA_AUTH))
+               return -EPERM;
+
        spin_lock_bh(&sta->lock);
        get_random_bytes(&llid, 2);
        sta->llid = llid;
@@ -449,6 +460,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                mpl_dbg("Mesh plink: missing necessary peer link ie\n");
                return;
        }
+       if (elems.rsn_len && !sdata->u.mesh.is_secure) {
+               mpl_dbg("Mesh plink: can't establish link with secure peer\n");
+               return;
+       }
 
        ftype = mgmt->u.action.u.plink_action.action_code;
        ie_len = elems.peer_link_len;
@@ -480,6 +495,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                return;
        }
 
+       if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) {
+               mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
+               rcu_read_unlock();
+               return;
+       }
+
        if (sta && sta->plink_state == PLINK_BLOCKED) {
                rcu_read_unlock();
                return;
index 865fed4cc18b6c88701607313c8822277adab0ad..a41f234bd4860b69a94f83ecc8334061bca2045a 100644 (file)
@@ -761,15 +761,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
        if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
            (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
                netif_tx_stop_all_queues(sdata->dev);
-               /*
-                * Flush all the frames queued in the driver before
-                * going to power save
-                */
-               drv_flush(local, false);
-               ieee80211_send_nullfunc(local, sdata, 1);
 
-               /* Flush once again to get the tx status of nullfunc frame */
-               drv_flush(local, false);
+               if (drv_tx_frames_pending(local))
+                       mod_timer(&local->dynamic_ps_timer, jiffies +
+                                 msecs_to_jiffies(
+                                 local->hw.conf.dynamic_ps_timeout));
+               else {
+                       ieee80211_send_nullfunc(local, sdata, 1);
+                       /* Flush to get the tx status of nullfunc frame */
+                       drv_flush(local, false);
+               }
        }
 
        if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
index 1f0b010904b85b66db447d8dacd6173fb95c0308..a864890e4d03753c3c50f7a4e8035ea8bdb035d4 100644 (file)
@@ -143,7 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        if (status->flag & RX_FLAG_HT) {
                /*
                 * MCS information is a separate field in radiotap,
-                * added below.
+                * added below. The byte here is needed as padding
+                * for the channel though, so initialise it to 0.
                 */
                *pos = 0;
        } else {
@@ -502,7 +503,8 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
                if (ieee80211_is_probe_req(hdr->frame_control) ||
                    ieee80211_is_probe_resp(hdr->frame_control) ||
-                   ieee80211_is_beacon(hdr->frame_control))
+                   ieee80211_is_beacon(hdr->frame_control) ||
+                   ieee80211_is_auth(hdr->frame_control))
                        return RX_CONTINUE;
 
                return RX_DROP_MONITOR;
@@ -1585,7 +1587,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
 }
 
 static int
-__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
 {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -1593,6 +1595,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
        struct ethhdr *ehdr;
        int ret;
 
+       *port_control = false;
        if (ieee80211_has_a4(hdr->frame_control) &&
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
                return -1;
@@ -1611,11 +1614,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                return -1;
 
        ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
-       if (ret < 0 || !check_port_control)
+       if (ret < 0)
                return ret;
 
        ehdr = (struct ethhdr *) rx->skb->data;
-       if (ehdr->h_proto != rx->sdata->control_port_protocol)
+       if (ehdr->h_proto == rx->sdata->control_port_protocol)
+               *port_control = true;
+       else if (check_port_control)
                return -1;
 
        return 0;
@@ -1916,6 +1921,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        struct net_device *dev = sdata->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        __le16 fc = hdr->frame_control;
+       bool port_control;
        int err;
 
        if (unlikely(!ieee80211_is_data(hdr->frame_control)))
@@ -1932,13 +1938,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
            sdata->vif.type == NL80211_IFTYPE_AP)
                return RX_DROP_MONITOR;
 
-       err = __ieee80211_data_to_8023(rx);
+       err = __ieee80211_data_to_8023(rx, &port_control);
        if (unlikely(err))
                return RX_DROP_UNUSABLE;
 
        if (!ieee80211_frame_allowed(rx, fc))
                return RX_DROP_MONITOR;
 
+       if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+           unlikely(port_control) && sdata->bss) {
+               sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+                                    u.ap);
+               dev = sdata->dev;
+               rx->sdata = sdata;
+       }
+
        rx->skb->dev = dev;
 
        dev->stats.rx_packets++;
index 52d4b1a695c93d5078ac15e06f604ad107908d61..a03d8a31287550d85e96467bc385e3eb291c35be 100644 (file)
@@ -228,6 +228,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
+       struct timespec uptime;
        int i;
 
        sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
@@ -245,6 +246,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        sta->sdata = sdata;
        sta->last_rx = jiffies;
 
+       do_posix_clock_monotonic_gettime(&uptime);
+       sta->last_connected = uptime.tv_sec;
        ewma_init(&sta->avg_signal, 1024, 8);
 
        if (sta_prepare_rate_control(local, sta, gfp)) {
@@ -609,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
 #endif
                dev_kfree_skb(skb);
 
-               if (skb_queue_empty(&sta->ps_tx_buf))
+               if (skb_queue_empty(&sta->ps_tx_buf) &&
+                   !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
                        sta_info_clear_tim_bit(sta);
        }
 
@@ -893,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        int sent, buffered;
 
+       clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
        if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
                drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
 
@@ -985,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
                ieee80211_queue_work(hw, &sta->drv_unblock_wk);
 }
 EXPORT_SYMBOL(ieee80211_sta_block_awake);
+
+void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta)
+{
+       struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+
+       set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
+       sta_info_set_tim_bit(sta);
+}
+EXPORT_SYMBOL(ieee80211_sta_set_tim);
index 87b18ba1e0e92483345f0e32c31a674829ef9eee..aa0adcbf3a938f50729c7cd969ad5358eb5e24c7 100644 (file)
@@ -43,6 +43,8 @@
  *     be in the queues
  * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
  *     station in power-save mode, reply when the driver unblocks.
+ * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
+ *     buffers. Automatically cleared on station wake-up.
  */
 enum ieee80211_sta_info_flags {
        WLAN_STA_AUTH           = 1<<0,
@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_BLOCK_BA       = 1<<11,
        WLAN_STA_PS_DRIVER      = 1<<12,
        WLAN_STA_PSPOLL         = 1<<13,
+       WLAN_STA_PS_DRIVER_BUF  = 1<<14,
 };
 
 #define STA_TID_NUM 16
@@ -226,6 +229,7 @@ enum plink_state {
  * @rx_bytes: Number of bytes received from this STA
  * @wep_weak_iv_count: number of weak WEP IVs received from this station
  * @last_rx: time (in jiffies) when last frame was received from this STA
+ * @last_connected: time (in seconds) when a station got connected
  * @num_duplicates: number of duplicate frames received from this STA
  * @rx_fragments: number of received MPDUs
  * @rx_dropped: number of dropped MPDUs from this STA
@@ -295,6 +299,7 @@ struct sta_info {
        unsigned long rx_packets, rx_bytes;
        unsigned long wep_weak_iv_count;
        unsigned long last_rx;
+       long last_connected;
        unsigned long num_duplicates;
        unsigned long rx_fragments;
        unsigned long rx_dropped;
index ce4596ed1268ca9039298f7a05c280a9e3fca190..17b10be31f5514a0a2713ca98ee1d404e0b742a4 100644 (file)
@@ -2262,7 +2262,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 
                /* headroom, head length, tail length and maximum TIM length */
                skb = dev_alloc_skb(local->tx_headroom + 400 +
-                               sdata->u.mesh.vendor_ie_len);
+                               sdata->u.mesh.ie_len);
                if (!skb)
                        goto out;
 
index 7fce6dfd2180af0ecaed0d3e82bb7afcc604001a..48464ca13b242c45a8825ed57e326affc5026455 100644 (file)
@@ -22,3 +22,14 @@ config RFKILL_INPUT
        depends on RFKILL
        depends on INPUT = y || RFKILL = INPUT
        default y if !EXPERT
+
+config RFKILL_REGULATOR
+       tristate "Generic rfkill regulator driver"
+       depends on RFKILL || !RFKILL
+       depends on REGULATOR
+       help
+          This options enable controlling radio transmitters connected to
+          voltage regulator using the regulator framework.
+
+          To compile this driver as a module, choose M here: the module will
+          be called rfkill-regulator.
index 662105352691d3737a4556906828a01c70d022c5..d9a5a58ffd8c8102553f18abdd7729d6d7e4c43c 100644 (file)
@@ -5,3 +5,4 @@
 rfkill-y                       += core.o
 rfkill-$(CONFIG_RFKILL_INPUT)  += input.o
 obj-$(CONFIG_RFKILL)           += rfkill.o
+obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
new file mode 100644 (file)
index 0000000..18dc512
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * rfkill-regulator.c - Regulator consumer driver for rfkill
+ *
+ * Copyright (C) 2009  Guiming Zhuo <gmzhuo@gmail.com>
+ * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * Implementation inspired by leds-regulator driver.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/rfkill.h>
+#include <linux/rfkill-regulator.h>
+
+struct rfkill_regulator_data {
+       struct rfkill *rf_kill;
+       bool reg_enabled;
+
+       struct regulator *vcc;
+};
+
+static int rfkill_regulator_set_block(void *data, bool blocked)
+{
+       struct rfkill_regulator_data *rfkill_data = data;
+
+       pr_debug("%s: blocked: %d\n", __func__, blocked);
+
+       if (blocked) {
+               if (rfkill_data->reg_enabled) {
+                       regulator_disable(rfkill_data->vcc);
+                       rfkill_data->reg_enabled = 0;
+               }
+       } else {
+               if (!rfkill_data->reg_enabled) {
+                       regulator_enable(rfkill_data->vcc);
+                       rfkill_data->reg_enabled = 1;
+               }
+       }
+
+       pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__,
+               regulator_is_enabled(rfkill_data->vcc));
+
+       return 0;
+}
+
+struct rfkill_ops rfkill_regulator_ops = {
+       .set_block = rfkill_regulator_set_block,
+};
+
+static int __devinit rfkill_regulator_probe(struct platform_device *pdev)
+{
+       struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data;
+       struct rfkill_regulator_data *rfkill_data;
+       struct regulator *vcc;
+       struct rfkill *rf_kill;
+       int ret = 0;
+
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "no platform data\n");
+               return -ENODEV;
+       }
+
+       if (pdata->name == NULL || pdata->type == 0) {
+               dev_err(&pdev->dev, "invalid name or type in platform data\n");
+               return -EINVAL;
+       }
+
+       vcc = regulator_get_exclusive(&pdev->dev, "vrfkill");
+       if (IS_ERR(vcc)) {
+               dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
+               ret = PTR_ERR(vcc);
+               goto out;
+       }
+
+       rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL);
+       if (rfkill_data == NULL) {
+               ret = -ENOMEM;
+               goto err_data_alloc;
+       }
+
+       rf_kill = rfkill_alloc(pdata->name, &pdev->dev,
+                               pdata->type,
+                               &rfkill_regulator_ops, rfkill_data);
+       if (rf_kill == NULL) {
+               dev_err(&pdev->dev, "Cannot alloc rfkill device\n");
+               ret = -ENOMEM;
+               goto err_rfkill_alloc;
+       }
+
+       if (regulator_is_enabled(vcc)) {
+               dev_dbg(&pdev->dev, "Regulator already enabled\n");
+               rfkill_data->reg_enabled = 1;
+       }
+       rfkill_data->vcc = vcc;
+       rfkill_data->rf_kill = rf_kill;
+
+       ret = rfkill_register(rf_kill);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot register rfkill device\n");
+               goto err_rfkill_register;
+       }
+
+       platform_set_drvdata(pdev, rfkill_data);
+       dev_info(&pdev->dev, "%s initialized\n", pdata->name);
+
+       return 0;
+
+err_rfkill_register:
+       rfkill_destroy(rf_kill);
+err_rfkill_alloc:
+       kfree(rfkill_data);
+err_data_alloc:
+       regulator_put(vcc);
+out:
+       return ret;
+}
+
+static int __devexit rfkill_regulator_remove(struct platform_device *pdev)
+{
+       struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev);
+       struct rfkill *rf_kill = rfkill_data->rf_kill;
+
+       rfkill_unregister(rf_kill);
+       rfkill_destroy(rf_kill);
+       regulator_put(rfkill_data->vcc);
+       kfree(rfkill_data);
+
+       return 0;
+}
+
+static struct platform_driver rfkill_regulator_driver = {
+       .probe = rfkill_regulator_probe,
+       .remove = __devexit_p(rfkill_regulator_remove),
+       .driver = {
+               .name = "rfkill-regulator",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init rfkill_regulator_init(void)
+{
+       return platform_driver_register(&rfkill_regulator_driver);
+}
+module_init(rfkill_regulator_init);
+
+static void __exit rfkill_regulator_exit(void)
+{
+       platform_driver_unregister(&rfkill_regulator_driver);
+}
+module_exit(rfkill_regulator_exit);
+
+MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("Regulator consumer driver for rfkill");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rfkill-regulator");
index 73e39c171ffb1a9d27bb011825ecc5cf8f83e24c..5c116083eeca7f99c28b9f8e9835a5d32e0e24db 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
+#include "nl80211.h"
 #include "core.h"
 
 /* Default values, timeouts in ms */
@@ -53,8 +54,9 @@ const struct mesh_config default_mesh_config = {
 const struct mesh_setup default_mesh_setup = {
        .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
        .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
-       .vendor_ie = NULL,
-       .vendor_ie_len = 0,
+       .ie = NULL,
+       .ie_len = 0,
+       .is_secure = false,
 };
 
 int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
@@ -72,6 +74,10 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
                return -EOPNOTSUPP;
 
+       if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
+             setup->is_secure)
+               return -EOPNOTSUPP;
+
        if (wdev->mesh_id_len)
                return -EALREADY;
 
@@ -105,6 +111,19 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        return err;
 }
 
+void cfg80211_notify_new_peer_candidate(struct net_device *dev,
+               const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+       if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+               return;
+
+       nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev,
+                       macaddr, ie, ie_len, gfp);
+}
+EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
+
 static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
                                 struct net_device *dev)
 {
index 297d7ce4117b99aec8cc358086ac0a956a2bb8ad..0efa7fd01150fef0a9a18030a53ff1b10d7ece14 100644 (file)
@@ -124,6 +124,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },
 
        [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
+       [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
 
        [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
                                         .len = NL80211_HT_CAPABILITY_LEN },
@@ -594,6 +595,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
        if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)
                NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN);
+       if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH)
+               NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH);
 
        NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
                sizeof(u32) * dev->wiphy.n_cipher_suites,
@@ -1922,6 +1925,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
        [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
+       [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
 };
 
 static int parse_station_flags(struct genl_info *info,
@@ -2016,6 +2020,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
        sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
        if (!sinfoattr)
                goto nla_put_failure;
+       if (sinfo->filled & STATION_INFO_CONNECTED_TIME)
+               NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME,
+                           sinfo->connected_time);
        if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
                NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
                            sinfo->inactive_time);
@@ -2281,7 +2288,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                        err = -EINVAL;
                if (params.supported_rates)
                        err = -EINVAL;
-               if (params.sta_flags_mask)
+               if (params.sta_flags_mask &
+                               ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+                                 BIT(NL80211_STA_FLAG_AUTHORIZED)))
                        err = -EINVAL;
                break;
        default:
@@ -2343,11 +2352,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                params.ht_capa =
                        nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
 
+       if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
+               params.plink_action =
+                   nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+
        if (parse_station_flags(info, &params))
                return -EINVAL;
 
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                return -EINVAL;
 
@@ -2823,7 +2837,8 @@ static const struct nla_policy
        nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
        [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
        [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
-       [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY,
+       [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
+       [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
                .len = IEEE80211_MAX_DATA_LEN },
 };
 
@@ -2925,14 +2940,16 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
                 IEEE80211_PATH_METRIC_VENDOR :
                 IEEE80211_PATH_METRIC_AIRTIME;
 
-       if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) {
+
+       if (tb[NL80211_MESH_SETUP_IE]) {
                struct nlattr *ieattr =
-                       tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE];
+                       tb[NL80211_MESH_SETUP_IE];
                if (!is_valid_ie_attr(ieattr))
                        return -EINVAL;
-               setup->vendor_ie = nla_data(ieattr);
-               setup->vendor_ie_len = nla_len(ieattr);
+               setup->ie = nla_data(ieattr);
+               setup->ie_len = nla_len(ieattr);
        }
+       setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
 
        return 0;
 }
@@ -5804,6 +5821,44 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
        nlmsg_free(msg);
 }
 
+void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
+               struct net_device *netdev,
+               const u8 *macaddr, const u8* ie, u8 ie_len,
+               gfp_t gfp)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
+       if (!hdr) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr);
+       if (ie_len && ie)
+               NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie);
+
+       if (genlmsg_end(msg, hdr) < 0) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+                               nl80211_mlme_mcgrp.id, gfp);
+       return;
+
+ nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+
 void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
                                 struct net_device *netdev, const u8 *addr,
                                 enum nl80211_key_type key_type, int key_id,
index dcac5cd6f0178694f70dbfc93558c5ccb43ef447..f2af6955a665654f498a29ce504574f999495763 100644 (file)
@@ -50,6 +50,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                               struct net_device *netdev, u16 reason,
                               const u8 *ie, size_t ie_len, bool from_ap);
 
+void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
+                                    struct net_device *netdev,
+                                    const u8 *macaddr, const u8* ie, u8 ie_len,
+                                    gfp_t gfp);
 void
 nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
                            struct net_device *netdev, const u8 *addr,