diff --git a/packages/linux/patches/linux-2.6.39-041-add_rtl8192se_driver-0.2.patch b/packages/linux/patches/linux-2.6.39-041-add_rtl8192se_driver-0.2.patch deleted file mode 100644 index 21aefadd88..0000000000 --- a/packages/linux/patches/linux-2.6.39-041-add_rtl8192se_driver-0.2.patch +++ /dev/null @@ -1,107576 +0,0 @@ -diff -Naur linux-2.6.39-rc6/Documentation/feature-removal-schedule.txt linux-2.6.39-rc6.rtl8192se/Documentation/feature-removal-schedule.txt ---- linux-2.6.39-rc6/Documentation/feature-removal-schedule.txt 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/Documentation/feature-removal-schedule.txt 2011-05-05 23:30:16.046811005 +0200 -@@ -35,17 +35,6 @@ - - --------------------------- - --What: AR9170USB --When: 2.6.40 -- --Why: This driver is deprecated and the firmware is no longer -- maintained. The replacement driver "carl9170" has been -- around for a while, so the devices are still supported. -- --Who: Christian Lamparter -- ----------------------------- -- - What: IRQF_SAMPLE_RANDOM - Check: IRQF_SAMPLE_RANDOM - When: July 2009 -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/ath3k.c linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/ath3k.c ---- linux-2.6.39-rc6/drivers/bluetooth/ath3k.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/ath3k.c 2011-05-05 23:29:49.570491221 +0200 -@@ -138,9 +138,6 @@ - count -= size; - } - -- kfree(send_buf); -- return 0; -- - error: - kfree(send_buf); - return err; -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/btmrvl_sdio.c linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/btmrvl_sdio.c ---- linux-2.6.39-rc6/drivers/bluetooth/btmrvl_sdio.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/btmrvl_sdio.c 2011-05-05 23:29:49.552491003 +0200 -@@ -49,15 +49,59 @@ - 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 @@ - 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 @@ - - *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 @@ - 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 @@ - { - 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 @@ - 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 @@ - 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 @@ - 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 @@ - - 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 @@ - 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 @@ - 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 @@ - - 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 @@ - - 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 @@ - 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 @@ - - 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 @@ - - 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 @@ - 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 @@ - 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); - -- if (btmrvl_sdio_download_fw_w_helper(card)) { -- BT_ERR("Failed to download firmware!"); -- ret = -EIO; -- goto done; -+ /* 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_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 @@ - - 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 @@ - - 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_LICENSE("GPL v2"); - MODULE_FIRMWARE("sd8688_helper.bin"); - MODULE_FIRMWARE("sd8688.bin"); -+MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/btmrvl_sdio.h linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/btmrvl_sdio.h ---- linux-2.6.39-rc6/drivers/bluetooth/btmrvl_sdio.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/btmrvl_sdio.h 2011-05-05 23:29:49.571491233 +0200 -@@ -47,44 +47,46 @@ - /* 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_device { - const char *helper; - const char *firmware; -+ const struct btmrvl_sdio_card_reg *reg; -+ u16 sd_blksz_fw_dl; - }; - - -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/hci_ath.c linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_ath.c ---- linux-2.6.39-rc6/drivers/bluetooth/hci_ath.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_ath.c 2011-05-05 23:29:49.554491027 +0200 -@@ -201,8 +201,13 @@ - /* 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; - } -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/hci_h4.c linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_h4.c ---- linux-2.6.39-rc6/drivers/bluetooth/hci_h4.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_h4.c 2011-05-05 23:29:49.566491173 +0200 -@@ -151,8 +151,13 @@ - /* 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; - } -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/hci_ldisc.c linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_ldisc.c ---- linux-2.6.39-rc6/drivers/bluetooth/hci_ldisc.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/hci_ldisc.c 2011-05-05 23:29:49.567491185 +0200 -@@ -359,6 +359,7 @@ - */ - 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 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/bluetooth/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/Kconfig ---- linux-2.6.39-rc6/drivers/bluetooth/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/bluetooth/Kconfig 2011-05-05 23:29:49.570491221 +0200 -@@ -188,7 +188,7 @@ - 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 @@ - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/ar9170.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/ar9170.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/ar9170.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/ar9170.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,258 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * Driver specific definitions -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 Atheros Communications, Inc. -- * -- * Permission to use, copy, modify, and/or distribute this software for any -- * purpose with or without fee is hereby granted, provided that the above -- * copyright notice and this permission notice appear in all copies. -- * -- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- */ --#ifndef __AR9170_H --#define __AR9170_H -- --#include --#include --#include --#include --#ifdef CONFIG_AR9170_LEDS --#include --#endif /* CONFIG_AR9170_LEDS */ --#include "eeprom.h" --#include "hw.h" -- --#include "../regd.h" -- --#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) -- --enum ar9170_bw { -- AR9170_BW_20, -- AR9170_BW_40_BELOW, -- AR9170_BW_40_ABOVE, -- -- __AR9170_NUM_BW, --}; -- --static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) --{ -- switch (type) { -- case NL80211_CHAN_NO_HT: -- case NL80211_CHAN_HT20: -- return AR9170_BW_20; -- case NL80211_CHAN_HT40MINUS: -- return AR9170_BW_40_BELOW; -- case NL80211_CHAN_HT40PLUS: -- return AR9170_BW_40_ABOVE; -- default: -- BUG(); -- } --} -- --enum ar9170_rf_init_mode { -- AR9170_RFI_NONE, -- AR9170_RFI_WARM, -- AR9170_RFI_COLD, --}; -- --#define AR9170_MAX_RX_BUFFER_SIZE 8192 -- --#ifdef CONFIG_AR9170_LEDS --struct ar9170; -- --struct ar9170_led { -- struct ar9170 *ar; -- struct led_classdev l; -- char name[32]; -- unsigned int toggled; -- bool last_state; -- bool registered; --}; -- --#endif /* CONFIG_AR9170_LEDS */ -- --enum ar9170_device_state { -- AR9170_UNKNOWN_STATE, -- AR9170_STOPPED, -- AR9170_IDLE, -- AR9170_STARTED, --}; -- --struct ar9170_rxstream_mpdu_merge { -- struct ar9170_rx_head plcp; -- bool has_plcp; --}; -- --struct ar9170_tx_queue_stats { -- unsigned int len; -- unsigned int limit; -- unsigned int count; --}; -- --#define AR9170_QUEUE_TIMEOUT 64 --#define AR9170_TX_TIMEOUT 8 --#define AR9170_JANITOR_DELAY 128 --#define AR9170_TX_INVALID_RATE 0xffffffff -- --#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH --#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) -- --struct ar9170 { -- struct ieee80211_hw *hw; -- struct ath_common common; -- struct mutex mutex; -- enum ar9170_device_state state; -- bool registered; -- unsigned long bad_hw_nagger; -- -- int (*open)(struct ar9170 *); -- void (*stop)(struct ar9170 *); -- int (*tx)(struct ar9170 *, struct sk_buff *); -- int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , -- void *, u32 , void *); -- void (*callback_cmd)(struct ar9170 *, u32 , void *); -- int (*flush)(struct ar9170 *); -- -- /* interface mode settings */ -- struct ieee80211_vif *vif; -- -- /* beaconing */ -- struct sk_buff *beacon; -- struct work_struct beacon_work; -- bool enable_beacon; -- -- /* cryptographic engine */ -- u64 usedkeys; -- bool rx_software_decryption; -- bool disable_offload; -- -- /* filter settings */ -- u64 cur_mc_hash; -- u32 cur_filter; -- unsigned int filter_state; -- bool sniffer_enabled; -- -- /* PHY */ -- struct ieee80211_channel *channel; -- int noise[4]; -- -- /* power calibration data */ -- u8 power_5G_leg[4]; -- u8 power_2G_cck[4]; -- u8 power_2G_ofdm[4]; -- u8 power_5G_ht20[8]; -- u8 power_5G_ht40[8]; -- u8 power_2G_ht20[8]; -- u8 power_2G_ht40[8]; -- -- u8 phy_heavy_clip; -- --#ifdef CONFIG_AR9170_LEDS -- struct delayed_work led_work; -- struct ar9170_led leds[AR9170_NUM_LEDS]; --#endif /* CONFIG_AR9170_LEDS */ -- -- /* qos queue settings */ -- spinlock_t tx_stats_lock; -- struct ar9170_tx_queue_stats tx_stats[5]; -- struct ieee80211_tx_queue_params edcf[5]; -- -- spinlock_t cmdlock; -- __le32 cmdbuf[PAYLOAD_MAX + 1]; -- -- /* MAC statistics */ -- struct ieee80211_low_level_stats stats; -- -- /* EEPROM */ -- struct ar9170_eeprom eeprom; -- -- /* tx queues - as seen by hw - */ -- struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; -- struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; -- struct delayed_work tx_janitor; -- -- /* rxstream mpdu merge */ -- struct ar9170_rxstream_mpdu_merge rx_mpdu; -- struct sk_buff *rx_failover; -- int rx_failover_missing; -- -- /* (cached) HW A-MPDU settings */ -- u8 global_ampdu_density; -- u8 global_ampdu_factor; --}; -- --struct ar9170_tx_info { -- unsigned long timeout; --}; -- --#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) --#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) -- --/* exported interface */ --void *ar9170_alloc(size_t priv_size); --int ar9170_register(struct ar9170 *ar, struct device *pdev); --void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); --void ar9170_unregister(struct ar9170 *ar); --void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); --void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); --int ar9170_nag_limiter(struct ar9170 *ar); -- --/* MAC */ --void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); --int ar9170_init_mac(struct ar9170 *ar); --int ar9170_set_qos(struct ar9170 *ar); --int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); --int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); --int ar9170_set_operating_mode(struct ar9170 *ar); --int ar9170_set_beacon_timers(struct ar9170 *ar); --int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); --int ar9170_set_slot_time(struct ar9170 *ar); --int ar9170_set_basic_rates(struct ar9170 *ar); --int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); --int ar9170_update_beacon(struct ar9170 *ar); --void ar9170_new_beacon(struct work_struct *work); --int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, -- u8 keyidx, u8 *keydata, int keylen); --int ar9170_disable_key(struct ar9170 *ar, u8 id); -- --/* LEDs */ --#ifdef CONFIG_AR9170_LEDS --int ar9170_register_leds(struct ar9170 *ar); --void ar9170_unregister_leds(struct ar9170 *ar); --#endif /* CONFIG_AR9170_LEDS */ --int ar9170_init_leds(struct ar9170 *ar); --int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); -- --/* PHY / RF */ --int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); --int ar9170_init_rf(struct ar9170 *ar); --int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, -- enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); -- --#endif /* __AR9170_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/cmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/cmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/cmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/cmd.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,127 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * Basic HW register/memory/command access functions -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 "ar9170.h" --#include "cmd.h" -- --int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) --{ -- int err; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return 0; -- -- err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); -- if (err) -- wiphy_debug(ar->hw->wiphy, "writing memory failed\n"); -- return err; --} -- --int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) --{ -- const __le32 buf[2] = { -- cpu_to_le32(reg), -- cpu_to_le32(val), -- }; -- int err; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return 0; -- -- err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), -- (u8 *) buf, 0, NULL); -- if (err) -- wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n", -- reg, val); -- return err; --} -- --int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) --{ -- int i, err; -- __le32 *offs, *res; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return 0; -- -- /* abuse "out" for the register offsets, must be same length */ -- offs = (__le32 *)out; -- for (i = 0; i < nregs; i++) -- offs[i] = cpu_to_le32(regs[i]); -- -- /* also use the same buffer for the input */ -- res = (__le32 *)out; -- -- err = ar->exec_cmd(ar, AR9170_CMD_RREG, -- 4 * nregs, (u8 *)offs, -- 4 * nregs, (u8 *)res); -- if (err) -- return err; -- -- /* convert result to cpu endian */ -- for (i = 0; i < nregs; i++) -- out[i] = le32_to_cpu(res[i]); -- -- return 0; --} -- --int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) --{ -- return ar9170_read_mreg(ar, 1, ®, val); --} -- --int ar9170_echo_test(struct ar9170 *ar, u32 v) --{ -- __le32 echobuf = cpu_to_le32(v); -- __le32 echores; -- int err; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return -ENODEV; -- -- err = ar->exec_cmd(ar, AR9170_CMD_ECHO, -- 4, (u8 *)&echobuf, -- 4, (u8 *)&echores); -- if (err) -- return err; -- -- if (echobuf != echores) -- return -EINVAL; -- -- return 0; --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/cmd.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/cmd.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/cmd.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/cmd.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,92 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * Basic HW register/memory/command access functions -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 Atheros Communications, Inc. -- * -- * Permission to use, copy, modify, and/or distribute this software for any -- * purpose with or without fee is hereby granted, provided that the above -- * copyright notice and this permission notice appear in all copies. -- * -- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- */ --#ifndef __CMD_H --#define __CMD_H -- --#include "ar9170.h" -- --/* basic HW access */ --int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); --int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); --int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); --int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); --int ar9170_echo_test(struct ar9170 *ar, u32 v); -- --/* -- * Macros to facilitate writing multiple registers in a single -- * write-combining USB command. Note that when the first group -- * fails the whole thing will fail without any others attempted, -- * but you won't know which write in the group failed. -- */ --#define ar9170_regwrite_begin(ar) \ --do { \ -- int __nreg = 0, __err = 0; \ -- struct ar9170 *__ar = ar; -- --#define ar9170_regwrite(r, v) do { \ -- __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ -- __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ -- __nreg++; \ -- if ((__nreg >= PAYLOAD_MAX/2)) { \ -- if (IS_ACCEPTING_CMD(__ar)) \ -- __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ -- 8 * __nreg, \ -- (u8 *) &__ar->cmdbuf[1], \ -- 0, NULL); \ -- __nreg = 0; \ -- if (__err) \ -- goto __regwrite_out; \ -- } \ --} while (0) -- --#define ar9170_regwrite_finish() \ --__regwrite_out : \ -- if (__nreg) { \ -- if (IS_ACCEPTING_CMD(__ar)) \ -- __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ -- 8 * __nreg, \ -- (u8 *) &__ar->cmdbuf[1], \ -- 0, NULL); \ -- __nreg = 0; \ -- } -- --#define ar9170_regwrite_result() \ -- __err; \ --} while (0); -- --#endif /* __CMD_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/eeprom.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/eeprom.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/eeprom.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/eeprom.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,179 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * EEPROM layout -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 Atheros Communications, Inc. -- * -- * Permission to use, copy, modify, and/or distribute this software for any -- * purpose with or without fee is hereby granted, provided that the above -- * copyright notice and this permission notice appear in all copies. -- * -- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- */ --#ifndef __AR9170_EEPROM_H --#define __AR9170_EEPROM_H -- --#define AR5416_MAX_CHAINS 2 --#define AR5416_MODAL_SPURS 5 -- --struct ar9170_eeprom_modal { -- __le32 antCtrlChain[AR5416_MAX_CHAINS]; -- __le32 antCtrlCommon; -- s8 antennaGainCh[AR5416_MAX_CHAINS]; -- u8 switchSettling; -- u8 txRxAttenCh[AR5416_MAX_CHAINS]; -- u8 rxTxMarginCh[AR5416_MAX_CHAINS]; -- s8 adcDesiredSize; -- s8 pgaDesiredSize; -- u8 xlnaGainCh[AR5416_MAX_CHAINS]; -- u8 txEndToXpaOff; -- u8 txEndToRxOn; -- u8 txFrameToXpaOn; -- u8 thresh62; -- s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; -- u8 xpdGain; -- u8 xpd; -- s8 iqCalICh[AR5416_MAX_CHAINS]; -- s8 iqCalQCh[AR5416_MAX_CHAINS]; -- u8 pdGainOverlap; -- u8 ob; -- u8 db; -- u8 xpaBiasLvl; -- u8 pwrDecreaseFor2Chain; -- u8 pwrDecreaseFor3Chain; -- u8 txFrameToDataStart; -- u8 txFrameToPaOn; -- u8 ht40PowerIncForPdadc; -- u8 bswAtten[AR5416_MAX_CHAINS]; -- u8 bswMargin[AR5416_MAX_CHAINS]; -- u8 swSettleHt40; -- u8 reserved[22]; -- struct spur_channel { -- __le16 spurChan; -- u8 spurRangeLow; -- u8 spurRangeHigh; -- } __packed spur_channels[AR5416_MODAL_SPURS]; --} __packed; -- --#define AR5416_NUM_PD_GAINS 4 --#define AR5416_PD_GAIN_ICEPTS 5 -- --struct ar9170_calibration_data_per_freq { -- u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; -- u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; --} __packed; -- --#define AR5416_NUM_5G_CAL_PIERS 8 --#define AR5416_NUM_2G_CAL_PIERS 4 -- --#define AR5416_NUM_5G_TARGET_PWRS 8 --#define AR5416_NUM_2G_CCK_TARGET_PWRS 3 --#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 --#define AR5416_MAX_NUM_TGT_PWRS 8 -- --struct ar9170_calibration_target_power_legacy { -- u8 freq; -- u8 power[4]; --} __packed; -- --struct ar9170_calibration_target_power_ht { -- u8 freq; -- u8 power[8]; --} __packed; -- --#define AR5416_NUM_CTLS 24 -- --struct ar9170_calctl_edges { -- u8 channel; --#define AR9170_CALCTL_EDGE_FLAGS 0xC0 -- u8 power_flags; --} __packed; -- --#define AR5416_NUM_BAND_EDGES 8 -- --struct ar9170_calctl_data { -- struct ar9170_calctl_edges -- control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; --} __packed; -- -- --struct ar9170_eeprom { -- __le16 length; -- __le16 checksum; -- __le16 version; -- u8 operating_flags; --#define AR9170_OPFLAG_5GHZ 1 --#define AR9170_OPFLAG_2GHZ 2 -- u8 misc; -- __le16 reg_domain[2]; -- u8 mac_address[6]; -- u8 rx_mask; -- u8 tx_mask; -- __le16 rf_silent; -- __le16 bluetooth_options; -- __le16 device_capabilities; -- __le32 build_number; -- u8 deviceType; -- u8 reserved[33]; -- -- u8 customer_data[64]; -- -- struct ar9170_eeprom_modal -- modal_header[2]; -- -- u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; -- u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; -- -- struct ar9170_calibration_data_per_freq -- cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], -- cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; -- -- /* power calibration data */ -- struct ar9170_calibration_target_power_legacy -- cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; -- struct ar9170_calibration_target_power_ht -- cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], -- cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; -- -- struct ar9170_calibration_target_power_legacy -- cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], -- cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; -- struct ar9170_calibration_target_power_ht -- cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], -- cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; -- -- /* conformance testing limits */ -- u8 ctl_index[AR5416_NUM_CTLS]; -- struct ar9170_calctl_data -- ctl_data[AR5416_NUM_CTLS]; -- -- u8 pad; -- __le16 subsystem_id; --} __packed; -- --#endif /* __AR9170_EEPROM_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/hw.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,430 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * Hardware-specific definitions -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 Atheros Communications, Inc. -- * -- * Permission to use, copy, modify, and/or distribute this software for any -- * purpose with or without fee is hereby granted, provided that the above -- * copyright notice and this permission notice appear in all copies. -- * -- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- */ --#ifndef __AR9170_HW_H --#define __AR9170_HW_H -- --#define AR9170_MAX_CMD_LEN 64 -- --enum ar9170_cmd { -- AR9170_CMD_RREG = 0x00, -- AR9170_CMD_WREG = 0x01, -- AR9170_CMD_RMEM = 0x02, -- AR9170_CMD_WMEM = 0x03, -- AR9170_CMD_BITAND = 0x04, -- AR9170_CMD_BITOR = 0x05, -- AR9170_CMD_EKEY = 0x28, -- AR9170_CMD_DKEY = 0x29, -- AR9170_CMD_FREQUENCY = 0x30, -- AR9170_CMD_RF_INIT = 0x31, -- AR9170_CMD_SYNTH = 0x32, -- AR9170_CMD_FREQ_START = 0x33, -- AR9170_CMD_ECHO = 0x80, -- AR9170_CMD_TALLY = 0x81, -- AR9170_CMD_TALLY_APD = 0x82, -- AR9170_CMD_CONFIG = 0x83, -- AR9170_CMD_RESET = 0x90, -- AR9170_CMD_DKRESET = 0x91, -- AR9170_CMD_DKTX_STATUS = 0x92, -- AR9170_CMD_FDC = 0xA0, -- AR9170_CMD_WREEPROM = 0xB0, -- AR9170_CMD_WFLASH = 0xB0, -- AR9170_CMD_FLASH_ERASE = 0xB1, -- AR9170_CMD_FLASH_PROG = 0xB2, -- AR9170_CMD_FLASH_CHKSUM = 0xB3, -- AR9170_CMD_FLASH_READ = 0xB4, -- AR9170_CMD_FW_DL_INIT = 0xB5, -- AR9170_CMD_MEM_WREEPROM = 0xBB, --}; -- --/* endpoints */ --#define AR9170_EP_TX 1 --#define AR9170_EP_RX 2 --#define AR9170_EP_IRQ 3 --#define AR9170_EP_CMD 4 -- --#define AR9170_EEPROM_START 0x1600 -- --#define AR9170_GPIO_REG_BASE 0x1d0100 --#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE --#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) --#define AR9170_NUM_LEDS 2 -- -- --#define AR9170_USB_REG_BASE 0x1e1000 --#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) --#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 --#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 --#define AR9170_DMA_CTL_HIGH_SPEED 0x4 --#define AR9170_DMA_CTL_PACKET_MODE 0x8 -- --#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) --#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) -- -- -- --#define AR9170_MAC_REG_BASE 0x1c3000 -- --#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) --#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) -- --#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) --#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) --#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) -- --#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) --#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) --#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) --#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) -- --#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) --#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) -- --#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) -- --#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) --#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) --#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) --#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) --#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) --#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) -- --#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) --#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) --#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) --#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 --#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) --#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) --#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 -- --#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) --#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) -- --#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) --#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) --#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) --#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) --#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) --#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) --#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) --#define AR9170_MAC_REG_FTF_BIT6 BIT(6) --#define AR9170_MAC_REG_FTF_BIT7 BIT(7) --#define AR9170_MAC_REG_FTF_BEACON BIT(8) --#define AR9170_MAC_REG_FTF_ATIM BIT(9) --#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) --#define AR9170_MAC_REG_FTF_AUTH BIT(11) --#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) --#define AR9170_MAC_REG_FTF_BIT13 BIT(13) --#define AR9170_MAC_REG_FTF_BIT14 BIT(14) --#define AR9170_MAC_REG_FTF_BIT15 BIT(15) --#define AR9170_MAC_REG_FTF_BAR BIT(24) --#define AR9170_MAC_REG_FTF_BA BIT(25) --#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) --#define AR9170_MAC_REG_FTF_RTS BIT(27) --#define AR9170_MAC_REG_FTF_CTS BIT(28) --#define AR9170_MAC_REG_FTF_ACK BIT(29) --#define AR9170_MAC_REG_FTF_CFE BIT(30) --#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) --#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff --#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff -- --#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) --#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) --#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) --#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) --#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) --#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) --#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) --#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) -- -- --#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) --#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) -- --#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) -- --#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) --#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 --#define AR9170_MAC_REG_POWERMGT_AP 0xa1 --#define AR9170_MAC_REG_POWERMGT_STA 0x2 --#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 --#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) -- --#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) --#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) -- --#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) --#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) --#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) --#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) --#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) --#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) --#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) -- --#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) -- --#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) --#define AR9170_MAC_FCS_SWFCS 0x1 --#define AR9170_MAC_FCS_FIFO_PROT 0x4 -- -- --#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) -- --#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) --#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) -- --#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) --#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) -- --#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) --#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) -- --#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) --#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f --#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 --#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 --#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 -- --#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) --#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) --#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) --#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) --#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) --#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) -- -- --#define AR9170_PWR_REG_BASE 0x1D4000 -- --#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) --#define AR9170_PWR_CLK_AHB_40MHZ 0 --#define AR9170_PWR_CLK_AHB_20_22MHZ 1 --#define AR9170_PWR_CLK_AHB_40_44MHZ 2 --#define AR9170_PWR_CLK_AHB_80_88MHZ 3 --#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 -- -- --/* put beacon here in memory */ --#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 -- -- --struct ar9170_tx_control { -- __le16 length; -- __le16 mac_control; -- __le32 phy_control; -- u8 frame_data[0]; --} __packed; -- --/* these are either-or */ --#define AR9170_TX_MAC_PROT_RTS 0x0001 --#define AR9170_TX_MAC_PROT_CTS 0x0002 -- --#define AR9170_TX_MAC_NO_ACK 0x0004 --/* if unset, MAC will only do SIFS space before frame */ --#define AR9170_TX_MAC_BACKOFF 0x0008 --#define AR9170_TX_MAC_BURST 0x0010 --#define AR9170_TX_MAC_AGGR 0x0020 -- --/* encryption is a two-bit field */ --#define AR9170_TX_MAC_ENCR_NONE 0x0000 --#define AR9170_TX_MAC_ENCR_RC4 0x0040 --#define AR9170_TX_MAC_ENCR_CENC 0x0080 --#define AR9170_TX_MAC_ENCR_AES 0x00c0 -- --#define AR9170_TX_MAC_MMIC 0x0100 --#define AR9170_TX_MAC_HW_DURATION 0x0200 --#define AR9170_TX_MAC_QOS_SHIFT 10 --#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) --#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 --#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 --#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 --#define AR9170_TX_MAC_TXOP_RIFS 0x2000 --#define AR9170_TX_MAC_IMM_AMPDU 0x4000 --#define AR9170_TX_MAC_RATE_PROBE 0x8000 -- --/* either-or */ --#define AR9170_TX_PHY_MOD_MASK 0x00000003 --#define AR9170_TX_PHY_MOD_CCK 0x00000000 --#define AR9170_TX_PHY_MOD_OFDM 0x00000001 --#define AR9170_TX_PHY_MOD_HT 0x00000002 -- --/* depends on modulation */ --#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 --#define AR9170_TX_PHY_GREENFIELD 0x00000004 -- --#define AR9170_TX_PHY_BW_SHIFT 3 --#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) --#define AR9170_TX_PHY_BW_20MHZ 0 --#define AR9170_TX_PHY_BW_40MHZ 2 --#define AR9170_TX_PHY_BW_40MHZ_DUP 3 -- --#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 --#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) -- --#define AR9170_TX_PHY_TX_PWR_SHIFT 9 --#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) -- --/* not part of the hw-spec */ --#define AR9170_TX_PHY_QOS_SHIFT 25 --#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) -- --#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 --#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) --#define AR9170_TX_PHY_TXCHAIN_1 1 --/* use for cck, ofdm 6/9/12/18/24 and HT if capable */ --#define AR9170_TX_PHY_TXCHAIN_2 5 -- --#define AR9170_TX_PHY_MCS_SHIFT 18 --#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) -- --#define AR9170_TX_PHY_SHORT_GI 0x80000000 -- --#define AR5416_MAX_RATE_POWER 63 -- --struct ar9170_rx_head { -- u8 plcp[12]; --} __packed; -- --struct ar9170_rx_phystatus { -- union { -- struct { -- u8 rssi_ant0, rssi_ant1, rssi_ant2, -- rssi_ant0x, rssi_ant1x, rssi_ant2x, -- rssi_combined; -- } __packed; -- u8 rssi[7]; -- } __packed; -- -- u8 evm_stream0[6], evm_stream1[6]; -- u8 phy_err; --} __packed; -- --struct ar9170_rx_macstatus { -- u8 SAidx, DAidx; -- u8 error; -- u8 status; --} __packed; -- --#define AR9170_ENC_ALG_NONE 0x0 --#define AR9170_ENC_ALG_WEP64 0x1 --#define AR9170_ENC_ALG_TKIP 0x2 --#define AR9170_ENC_ALG_AESCCMP 0x4 --#define AR9170_ENC_ALG_WEP128 0x5 --#define AR9170_ENC_ALG_WEP256 0x6 --#define AR9170_ENC_ALG_CENC 0x7 -- --#define AR9170_RX_ENC_SOFTWARE 0x8 -- --static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) --{ -- return (t->SAidx & 0xc0) >> 4 | -- (t->DAidx & 0xc0) >> 6; --} -- --#define AR9170_RX_STATUS_MODULATION_MASK 0x03 --#define AR9170_RX_STATUS_MODULATION_CCK 0x00 --#define AR9170_RX_STATUS_MODULATION_OFDM 0x01 --#define AR9170_RX_STATUS_MODULATION_HT 0x02 --#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 -- --/* depends on modulation */ --#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 --#define AR9170_RX_STATUS_GREENFIELD 0x08 -- --#define AR9170_RX_STATUS_MPDU_MASK 0x30 --#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 --#define AR9170_RX_STATUS_MPDU_FIRST 0x20 --#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 --#define AR9170_RX_STATUS_MPDU_LAST 0x10 -- --#define AR9170_RX_ERROR_RXTO 0x01 --#define AR9170_RX_ERROR_OVERRUN 0x02 --#define AR9170_RX_ERROR_DECRYPT 0x04 --#define AR9170_RX_ERROR_FCS 0x08 --#define AR9170_RX_ERROR_WRONG_RA 0x10 --#define AR9170_RX_ERROR_PLCP 0x20 --#define AR9170_RX_ERROR_MMIC 0x40 --#define AR9170_RX_ERROR_FATAL 0x80 -- --struct ar9170_cmd_tx_status { -- u8 dst[ETH_ALEN]; -- __le32 rate; -- __le16 status; --} __packed; -- --#define AR9170_TX_STATUS_COMPLETE 0x00 --#define AR9170_TX_STATUS_RETRY 0x01 --#define AR9170_TX_STATUS_FAILED 0x02 -- --struct ar9170_cmd_ba_failed_count { -- __le16 failed; -- __le16 rate; --} __packed; -- --struct ar9170_cmd_response { -- u8 flag; -- u8 type; -- __le16 padding; -- -- union { -- struct ar9170_cmd_tx_status tx_status; -- struct ar9170_cmd_ba_failed_count ba_fail_cnt; -- u8 data[0]; -- }; --} __packed; -- --/* QoS */ -- --/* mac80211 queue to HW/FW map */ --static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; -- --/* HW/FW queue to mac80211 map */ --static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; -- --enum ar9170_txq { -- AR9170_TXQ_BE, -- AR9170_TXQ_BK, -- AR9170_TXQ_VI, -- AR9170_TXQ_VO, -- -- __AR9170_NUM_TXQ, --}; -- --#define AR9170_TXQ_DEPTH 32 --#define AR9170_TX_MAX_PENDING 128 --#define AR9170_RX_STREAM_MAX_SIZE 65535 -- --#endif /* __AR9170_HW_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/Kconfig 1970-01-01 01:00:00.000000000 +0100 -@@ -1,20 +0,0 @@ --config AR9170_USB -- tristate "Atheros AR9170 802.11n USB support (OBSOLETE)" -- depends on USB && MAC80211 -- select FW_LOADER -- help -- This driver is going to get replaced by carl9170. -- -- This is a driver for the Atheros "otus" 802.11n USB devices. -- -- These devices require additional firmware (2 files). -- For now, these files can be downloaded from here: -- -- http://wireless.kernel.org/en/users/Drivers/ar9170 -- -- If you choose to build a module, it'll be called ar9170usb. -- --config AR9170_LEDS -- bool -- depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) -- default y -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/led.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/led.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/led.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/led.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,181 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * LED handling -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 "ar9170.h" --#include "cmd.h" -- --int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) --{ -- return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); --} -- --int ar9170_init_leds(struct ar9170 *ar) --{ -- int err; -- -- /* disable LEDs */ -- /* GPIO [0/1 mode: output, 2/3: input] */ -- err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); -- if (err) -- goto out; -- -- /* GPIO 0/1 value: off */ -- err = ar9170_set_leds_state(ar, 0); -- --out: -- return err; --} -- --#ifdef CONFIG_AR9170_LEDS --static void ar9170_update_leds(struct work_struct *work) --{ -- struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); -- int i, tmp, blink_delay = 1000; -- u32 led_val = 0; -- bool rerun = false; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return ; -- -- mutex_lock(&ar->mutex); -- for (i = 0; i < AR9170_NUM_LEDS; i++) -- if (ar->leds[i].registered && ar->leds[i].toggled) { -- led_val |= 1 << i; -- -- tmp = 70 + 200 / (ar->leds[i].toggled); -- if (tmp < blink_delay) -- blink_delay = tmp; -- -- if (ar->leds[i].toggled > 1) -- ar->leds[i].toggled = 0; -- -- rerun = true; -- } -- -- ar9170_set_leds_state(ar, led_val); -- mutex_unlock(&ar->mutex); -- -- if (!rerun) -- return; -- -- ieee80211_queue_delayed_work(ar->hw, -- &ar->led_work, -- msecs_to_jiffies(blink_delay)); --} -- --static void ar9170_led_brightness_set(struct led_classdev *led, -- enum led_brightness brightness) --{ -- struct ar9170_led *arl = container_of(led, struct ar9170_led, l); -- struct ar9170 *ar = arl->ar; -- -- if (unlikely(!arl->registered)) -- return ; -- -- if (arl->last_state != !!brightness) { -- arl->toggled++; -- arl->last_state = !!brightness; -- } -- -- if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) -- ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); --} -- --static int ar9170_register_led(struct ar9170 *ar, int i, char *name, -- char *trigger) --{ -- int err; -- -- snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), -- "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); -- -- ar->leds[i].ar = ar; -- ar->leds[i].l.name = ar->leds[i].name; -- ar->leds[i].l.brightness_set = ar9170_led_brightness_set; -- ar->leds[i].l.brightness = 0; -- ar->leds[i].l.default_trigger = trigger; -- -- err = led_classdev_register(wiphy_dev(ar->hw->wiphy), -- &ar->leds[i].l); -- if (err) -- wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n", -- ar->leds[i].name, err); -- else -- ar->leds[i].registered = true; -- -- return err; --} -- --void ar9170_unregister_leds(struct ar9170 *ar) --{ -- int i; -- -- for (i = 0; i < AR9170_NUM_LEDS; i++) -- if (ar->leds[i].registered) { -- led_classdev_unregister(&ar->leds[i].l); -- ar->leds[i].registered = false; -- ar->leds[i].toggled = 0; -- } -- -- cancel_delayed_work_sync(&ar->led_work); --} -- --int ar9170_register_leds(struct ar9170 *ar) --{ -- int err; -- -- INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); -- -- err = ar9170_register_led(ar, 0, "tx", -- ieee80211_get_tx_led_name(ar->hw)); -- if (err) -- goto fail; -- -- err = ar9170_register_led(ar, 1, "assoc", -- ieee80211_get_assoc_led_name(ar->hw)); -- if (err) -- goto fail; -- -- return 0; -- --fail: -- ar9170_unregister_leds(ar); -- return err; --} -- --#endif /* CONFIG_AR9170_LEDS */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/mac.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/mac.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/mac.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/mac.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,519 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * MAC programming -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 -- --#include "ar9170.h" --#include "cmd.h" -- --int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) --{ -- u32 val; -- -- if (conf_is_ht40(&ar->hw->conf)) -- val = 0x010a; -- else { -- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) -- val = 0x105; -- else -- val = 0x104; -- } -- -- return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); --} -- --int ar9170_set_slot_time(struct ar9170 *ar) --{ -- u32 slottime = 20; -- -- if (!ar->vif) -- return 0; -- -- if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || -- ar->vif->bss_conf.use_short_slot) -- slottime = 9; -- -- return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); --} -- --int ar9170_set_basic_rates(struct ar9170 *ar) --{ -- u8 cck, ofdm; -- -- if (!ar->vif) -- return 0; -- -- ofdm = ar->vif->bss_conf.basic_rates >> 4; -- -- /* FIXME: is still necessary? */ -- if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) -- cck = 0; -- else -- cck = ar->vif->bss_conf.basic_rates & 0xf; -- -- return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, -- ofdm << 8 | cck); --} -- --int ar9170_set_qos(struct ar9170 *ar) --{ -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | -- (ar->edcf[0].cw_max << 16)); -- ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | -- (ar->edcf[1].cw_max << 16)); -- ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | -- (ar->edcf[2].cw_max << 16)); -- ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | -- (ar->edcf[3].cw_max << 16)); -- ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | -- (ar->edcf[4].cw_max << 16)); -- -- ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, -- ((ar->edcf[0].aifs * 9 + 10)) | -- ((ar->edcf[1].aifs * 9 + 10) << 12) | -- ((ar->edcf[2].aifs * 9 + 10) << 24)); -- ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, -- ((ar->edcf[2].aifs * 9 + 10) >> 8) | -- ((ar->edcf[3].aifs * 9 + 10) << 4) | -- ((ar->edcf[4].aifs * 9 + 10) << 16)); -- -- ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, -- ar->edcf[0].txop | ar->edcf[1].txop << 16); -- ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, -- ar->edcf[2].txop | ar->edcf[3].txop << 16); -- -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) --{ -- u32 val; -- -- /* don't allow AMPDU density > 8us */ -- if (mpdudensity > 6) -- return -EINVAL; -- -- /* Watch out! Otus uses slightly different density values. */ -- val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); -- -- ar9170_regwrite_begin(ar); -- ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --int ar9170_init_mac(struct ar9170 *ar) --{ -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); -- -- ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); -- -- /* enable MMIC */ -- ar9170_regwrite(AR9170_MAC_REG_SNIFFER, -- AR9170_MAC_REG_SNIFFER_DEFAULTS); -- -- ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); -- -- ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); -- ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); -- ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); -- -- /* CF-END mode */ -- ar9170_regwrite(0x1c3b2c, 0x19000000); -- -- /* NAV protects ACK only (in TXOP) */ -- ar9170_regwrite(0x1c3b38, 0x201); -- -- /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ -- /* OTUS set AM to 0x1 */ -- ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); -- -- ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); -- -- /* AGG test code*/ -- /* Aggregation MAX number and timeout */ -- ar9170_regwrite(0x1c3b9c, 0x10000a); -- -- ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, -- AR9170_MAC_REG_FTF_DEFAULTS); -- -- /* Enable deaggregator, response in sniffer mode */ -- ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); -- -- /* rate sets */ -- ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); -- ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); -- ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); -- -- /* MIMO response control */ -- ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ -- -- /* switch MAC to OTUS interface */ -- ar9170_regwrite(0x1c3600, 0x3); -- -- ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); -- -- /* set PHY register read timeout (??) */ -- ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); -- -- /* Disable Rx TimeOut, workaround for BB. */ -- ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); -- -- /* Set CPU clock frequency to 88/80MHz */ -- ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, -- AR9170_PWR_CLK_AHB_80_88MHZ | -- AR9170_PWR_CLK_DAC_160_INV_DLY); -- -- /* Set WLAN DMA interrupt mode: generate int per packet */ -- ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); -- -- ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, -- AR9170_MAC_FCS_FIFO_PROT); -- -- /* Disables the CF_END frame, undocumented register */ -- ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, -- 0x141E0F48); -- -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) --{ -- static const u8 zero[ETH_ALEN] = { 0 }; -- -- if (!mac) -- mac = zero; -- -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(reg, get_unaligned_le32(mac)); -- ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); -- -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) --{ -- int err; -- -- ar9170_regwrite_begin(ar); -- ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); -- ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); -- ar9170_regwrite_finish(); -- err = ar9170_regwrite_result(); -- if (err) -- return err; -- -- ar->cur_mc_hash = mc_hash; -- return 0; --} -- --int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) --{ -- int err; -- -- err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); -- if (err) -- return err; -- -- ar->cur_filter = filter; -- return 0; --} -- --static int ar9170_set_promiscouous(struct ar9170 *ar) --{ -- u32 encr_mode, sniffer; -- int err; -- -- err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); -- if (err) -- return err; -- -- err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); -- if (err) -- return err; -- -- if (ar->sniffer_enabled) { -- sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; -- -- /* -- * Rx decryption works in place. -- * -- * If we don't disable it, the hardware will render all -- * encrypted frames which are encrypted with an unknown -- * key useless. -- */ -- -- encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; -- ar->sniffer_enabled = true; -- } else { -- sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; -- -- if (ar->rx_software_decryption) -- encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; -- else -- encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; -- } -- -- ar9170_regwrite_begin(ar); -- ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); -- ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --int ar9170_set_operating_mode(struct ar9170 *ar) --{ -- struct ath_common *common = &ar->common; -- u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; -- u8 *mac_addr, *bssid; -- int err; -- -- if (ar->vif) { -- mac_addr = common->macaddr; -- bssid = common->curbssid; -- -- switch (ar->vif->type) { -- case NL80211_IFTYPE_MESH_POINT: -- case NL80211_IFTYPE_ADHOC: -- pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; -- break; -- case NL80211_IFTYPE_AP: -- pm_mode |= AR9170_MAC_REG_POWERMGT_AP; -- break; -- case NL80211_IFTYPE_WDS: -- pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; -- break; -- case NL80211_IFTYPE_MONITOR: -- ar->sniffer_enabled = true; -- ar->rx_software_decryption = true; -- break; -- default: -- pm_mode |= AR9170_MAC_REG_POWERMGT_STA; -- break; -- } -- } else { -- mac_addr = NULL; -- bssid = NULL; -- } -- -- err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); -- if (err) -- return err; -- -- err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); -- if (err) -- return err; -- -- err = ar9170_set_promiscouous(ar); -- if (err) -- return err; -- -- /* set AMPDU density to 8us. */ -- err = ar9170_set_ampdu_density(ar, 6); -- if (err) -- return err; -- -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) --{ -- u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); -- -- return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); --} -- --int ar9170_set_beacon_timers(struct ar9170 *ar) --{ -- u32 v = 0; -- u32 pretbtt = 0; -- -- if (ar->vif) { -- v |= ar->vif->bss_conf.beacon_int; -- -- if (ar->enable_beacon) { -- switch (ar->vif->type) { -- case NL80211_IFTYPE_MESH_POINT: -- case NL80211_IFTYPE_ADHOC: -- v |= BIT(25); -- break; -- case NL80211_IFTYPE_AP: -- v |= BIT(24); -- pretbtt = (ar->vif->bss_conf.beacon_int - 6) << -- 16; -- break; -- default: -- break; -- } -- } -- -- v |= ar->vif->bss_conf.dtim_period << 16; -- } -- -- ar9170_regwrite_begin(ar); -- ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); -- ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); -- ar9170_regwrite_finish(); -- return ar9170_regwrite_result(); --} -- --int ar9170_update_beacon(struct ar9170 *ar) --{ -- struct sk_buff *skb; -- __le32 *data, *old = NULL; -- u32 word; -- int i; -- -- skb = ieee80211_beacon_get(ar->hw, ar->vif); -- if (!skb) -- return -ENOMEM; -- -- data = (__le32 *)skb->data; -- if (ar->beacon) -- old = (__le32 *)ar->beacon->data; -- -- ar9170_regwrite_begin(ar); -- for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { -- /* -- * XXX: This accesses beyond skb data for up -- * to the last 3 bytes!! -- */ -- -- if (old && (data[i] == old[i])) -- continue; -- -- word = le32_to_cpu(data[i]); -- ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); -- } -- -- /* XXX: use skb->cb info */ -- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) -- ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, -- ((skb->len + 4) << (3 + 16)) + 0x0400); -- else -- ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, -- ((skb->len + 4) << 16) + 0x001b); -- -- ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); -- ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); -- ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); -- -- ar9170_regwrite_finish(); -- -- dev_kfree_skb(ar->beacon); -- ar->beacon = skb; -- -- return ar9170_regwrite_result(); --} -- --void ar9170_new_beacon(struct work_struct *work) --{ -- struct ar9170 *ar = container_of(work, struct ar9170, -- beacon_work); -- struct sk_buff *skb; -- -- if (unlikely(!IS_STARTED(ar))) -- return ; -- -- mutex_lock(&ar->mutex); -- -- if (!ar->vif) -- goto out; -- -- ar9170_update_beacon(ar); -- -- rcu_read_lock(); -- while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) -- ar9170_op_tx(ar->hw, skb); -- -- rcu_read_unlock(); -- -- out: -- mutex_unlock(&ar->mutex); --} -- --int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, -- u8 keyidx, u8 *keydata, int keylen) --{ -- __le32 vals[7]; -- static const u8 bcast[ETH_ALEN] = -- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -- u8 dummy; -- -- mac = mac ? : bcast; -- -- vals[0] = cpu_to_le32((keyidx << 16) + id); -- vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); -- vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | -- mac[3] << 8 | mac[2]); -- memset(&vals[3], 0, 16); -- if (keydata) -- memcpy(&vals[3], keydata, keylen); -- -- return ar->exec_cmd(ar, AR9170_CMD_EKEY, -- sizeof(vals), (u8 *)vals, -- 1, &dummy); --} -- --int ar9170_disable_key(struct ar9170 *ar, u8 id) --{ -- __le32 val = cpu_to_le32(id); -- u8 dummy; -- -- return ar->exec_cmd(ar, AR9170_CMD_EKEY, -- sizeof(val), (u8 *)&val, -- 1, &dummy); --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/main.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,2190 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * mac80211 interaction code -- * -- * Copyright 2008, Johannes Berg -- * Copyright 2009, Christian Lamparter -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 --#include --#include --#include --#include --#include "ar9170.h" --#include "hw.h" --#include "cmd.h" -- --static int modparam_nohwcrypt; --module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); --MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -- --#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ -- .bitrate = (_bitrate), \ -- .flags = (_flags), \ -- .hw_value = (_hw_rate) | (_txpidx) << 4, \ --} -- --static struct ieee80211_rate __ar9170_ratetable[] = { -- RATE(10, 0, 0, 0), -- RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), -- RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), -- RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), -- RATE(60, 0xb, 0, 0), -- RATE(90, 0xf, 0, 0), -- RATE(120, 0xa, 0, 0), -- RATE(180, 0xe, 0, 0), -- RATE(240, 0x9, 0, 0), -- RATE(360, 0xd, 1, 0), -- RATE(480, 0x8, 2, 0), -- RATE(540, 0xc, 3, 0), --}; --#undef RATE -- --#define ar9170_g_ratetable (__ar9170_ratetable + 0) --#define ar9170_g_ratetable_size 12 --#define ar9170_a_ratetable (__ar9170_ratetable + 4) --#define ar9170_a_ratetable_size 8 -- --/* -- * NB: The hw_value is used as an index into the ar9170_phy_freq_params -- * array in phy.c so that we don't have to do frequency lookups! -- */ --#define CHAN(_freq, _idx) { \ -- .center_freq = (_freq), \ -- .hw_value = (_idx), \ -- .max_power = 18, /* XXX */ \ --} -- --static struct ieee80211_channel ar9170_2ghz_chantable[] = { -- CHAN(2412, 0), -- CHAN(2417, 1), -- CHAN(2422, 2), -- CHAN(2427, 3), -- CHAN(2432, 4), -- CHAN(2437, 5), -- CHAN(2442, 6), -- CHAN(2447, 7), -- CHAN(2452, 8), -- CHAN(2457, 9), -- CHAN(2462, 10), -- CHAN(2467, 11), -- CHAN(2472, 12), -- CHAN(2484, 13), --}; -- --static struct ieee80211_channel ar9170_5ghz_chantable[] = { -- CHAN(4920, 14), -- CHAN(4940, 15), -- CHAN(4960, 16), -- CHAN(4980, 17), -- CHAN(5040, 18), -- CHAN(5060, 19), -- CHAN(5080, 20), -- CHAN(5180, 21), -- CHAN(5200, 22), -- CHAN(5220, 23), -- CHAN(5240, 24), -- CHAN(5260, 25), -- CHAN(5280, 26), -- CHAN(5300, 27), -- CHAN(5320, 28), -- CHAN(5500, 29), -- CHAN(5520, 30), -- CHAN(5540, 31), -- CHAN(5560, 32), -- CHAN(5580, 33), -- CHAN(5600, 34), -- CHAN(5620, 35), -- CHAN(5640, 36), -- CHAN(5660, 37), -- CHAN(5680, 38), -- CHAN(5700, 39), -- CHAN(5745, 40), -- CHAN(5765, 41), -- CHAN(5785, 42), -- CHAN(5805, 43), -- CHAN(5825, 44), -- CHAN(5170, 45), -- CHAN(5190, 46), -- CHAN(5210, 47), -- CHAN(5230, 48), --}; --#undef CHAN -- --#define AR9170_HT_CAP \ --{ \ -- .ht_supported = true, \ -- .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ -- IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ -- IEEE80211_HT_CAP_SGI_40 | \ -- IEEE80211_HT_CAP_GRN_FLD | \ -- IEEE80211_HT_CAP_DSSSCCK40 | \ -- IEEE80211_HT_CAP_SM_PS, \ -- .ampdu_factor = 3, \ -- .ampdu_density = 6, \ -- .mcs = { \ -- .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ -- .rx_highest = cpu_to_le16(300), \ -- .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ -- }, \ --} -- --static struct ieee80211_supported_band ar9170_band_2GHz = { -- .channels = ar9170_2ghz_chantable, -- .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), -- .bitrates = ar9170_g_ratetable, -- .n_bitrates = ar9170_g_ratetable_size, -- .ht_cap = AR9170_HT_CAP, --}; -- --static struct ieee80211_supported_band ar9170_band_5GHz = { -- .channels = ar9170_5ghz_chantable, -- .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), -- .bitrates = ar9170_a_ratetable, -- .n_bitrates = ar9170_a_ratetable_size, -- .ht_cap = AR9170_HT_CAP, --}; -- --static void ar9170_tx(struct ar9170 *ar); -- --static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) --{ -- return le16_to_cpu(hdr->seq_ctrl) >> 4; --} -- --static inline u16 ar9170_get_seq(struct sk_buff *skb) --{ -- struct ar9170_tx_control *txc = (void *) skb->data; -- return ar9170_get_seq_h((void *) txc->frame_data); --} -- --#ifdef AR9170_QUEUE_DEBUG --static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) --{ -- struct ar9170_tx_control *txc = (void *) skb->data; -- struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); -- struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; -- struct ieee80211_hdr *hdr = (void *) txc->frame_data; -- -- wiphy_debug(ar->hw->wiphy, -- "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d " -- "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", -- skb, skb_get_queue_mapping(skb), -- ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), -- le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), -- jiffies_to_msecs(arinfo->timeout - jiffies)); --} -- --static void __ar9170_dump_txqueue(struct ar9170 *ar, -- struct sk_buff_head *queue) --{ -- struct sk_buff *skb; -- int i = 0; -- -- printk(KERN_DEBUG "---[ cut here ]---\n"); -- wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n", -- skb_queue_len(queue)); -- -- skb_queue_walk(queue, skb) { -- printk(KERN_DEBUG "index:%d =>\n", i++); -- ar9170_print_txheader(ar, skb); -- } -- if (i != skb_queue_len(queue)) -- printk(KERN_DEBUG "WARNING: queue frame counter " -- "mismatch %d != %d\n", skb_queue_len(queue), i); -- printk(KERN_DEBUG "---[ end ]---\n"); --} --#endif /* AR9170_QUEUE_DEBUG */ -- --#ifdef AR9170_QUEUE_DEBUG --static void ar9170_dump_txqueue(struct ar9170 *ar, -- struct sk_buff_head *queue) --{ -- unsigned long flags; -- -- spin_lock_irqsave(&queue->lock, flags); -- __ar9170_dump_txqueue(ar, queue); -- spin_unlock_irqrestore(&queue->lock, flags); --} --#endif /* AR9170_QUEUE_DEBUG */ -- --#ifdef AR9170_QUEUE_STOP_DEBUG --static void __ar9170_dump_txstats(struct ar9170 *ar) --{ -- int i; -- -- wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); -- -- for (i = 0; i < __AR9170_NUM_TXQ; i++) -- wiphy_debug(ar->hw->wiphy, -- "queue:%d limit:%d len:%d waitack:%d stopped:%d\n", -- i, ar->tx_stats[i].limit, ar->tx_stats[i].len, -- skb_queue_len(&ar->tx_status[i]), -- ieee80211_queue_stopped(ar->hw, i)); --} --#endif /* AR9170_QUEUE_STOP_DEBUG */ -- --/* caller must guarantee exclusive access for _bin_ queue. */ --static void ar9170_recycle_expired(struct ar9170 *ar, -- struct sk_buff_head *queue, -- struct sk_buff_head *bin) --{ -- struct sk_buff *skb, *old = NULL; -- unsigned long flags; -- -- spin_lock_irqsave(&queue->lock, flags); -- while ((skb = skb_peek(queue))) { -- struct ieee80211_tx_info *txinfo; -- struct ar9170_tx_info *arinfo; -- -- txinfo = IEEE80211_SKB_CB(skb); -- arinfo = (void *) txinfo->rate_driver_data; -- -- if (time_is_before_jiffies(arinfo->timeout)) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "[%ld > %ld] frame expired => recycle\n", -- jiffies, arinfo->timeout); -- ar9170_print_txheader(ar, skb); --#endif /* AR9170_QUEUE_DEBUG */ -- __skb_unlink(skb, queue); -- __skb_queue_tail(bin, skb); -- } else { -- break; -- } -- -- if (unlikely(old == skb)) { -- /* bail out - queue is shot. */ -- -- WARN_ON(1); -- break; -- } -- old = skb; -- } -- spin_unlock_irqrestore(&queue->lock, flags); --} -- --static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, -- u16 tx_status) --{ -- struct ieee80211_tx_info *txinfo; -- unsigned int retries = 0; -- -- txinfo = IEEE80211_SKB_CB(skb); -- ieee80211_tx_info_clear_status(txinfo); -- -- switch (tx_status) { -- case AR9170_TX_STATUS_RETRY: -- retries = 2; -- case AR9170_TX_STATUS_COMPLETE: -- txinfo->flags |= IEEE80211_TX_STAT_ACK; -- break; -- -- case AR9170_TX_STATUS_FAILED: -- retries = ar->hw->conf.long_frame_max_tx_count; -- break; -- -- default: -- wiphy_err(ar->hw->wiphy, -- "invalid tx_status response (%x)\n", tx_status); -- break; -- } -- -- txinfo->status.rates[0].count = retries + 1; -- skb_pull(skb, sizeof(struct ar9170_tx_control)); -- ieee80211_tx_status_irqsafe(ar->hw, skb); --} -- --void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) --{ -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; -- unsigned int queue = skb_get_queue_mapping(skb); -- unsigned long flags; -- -- spin_lock_irqsave(&ar->tx_stats_lock, flags); -- ar->tx_stats[queue].len--; -- -- if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { --#ifdef AR9170_QUEUE_STOP_DEBUG -- wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue); -- __ar9170_dump_txstats(ar); --#endif /* AR9170_QUEUE_STOP_DEBUG */ -- ieee80211_wake_queue(ar->hw, queue); -- } -- spin_unlock_irqrestore(&ar->tx_stats_lock, flags); -- -- if (info->flags & IEEE80211_TX_CTL_NO_ACK) { -- ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); -- } else { -- arinfo->timeout = jiffies + -- msecs_to_jiffies(AR9170_TX_TIMEOUT); -- -- skb_queue_tail(&ar->tx_status[queue], skb); -- } -- -- if (!ar->tx_stats[queue].len && -- !skb_queue_empty(&ar->tx_pending[queue])) { -- ar9170_tx(ar); -- } --} -- --static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, -- const u8 *mac, -- struct sk_buff_head *queue, -- const u32 rate) --{ -- unsigned long flags; -- struct sk_buff *skb; -- -- /* -- * Unfortunately, the firmware does not tell to which (queued) frame -- * this transmission status report belongs to. -- * -- * So we have to make risky guesses - with the scarce information -- * the firmware provided (-> destination MAC, and phy_control) - -- * and hope that we picked the right one... -- */ -- -- spin_lock_irqsave(&queue->lock, flags); -- skb_queue_walk(queue, skb) { -- struct ar9170_tx_control *txc = (void *) skb->data; -- struct ieee80211_hdr *hdr = (void *) txc->frame_data; -- u32 r; -- -- if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "skip frame => DA %pM != %pM\n", -- mac, ieee80211_get_DA(hdr)); -- ar9170_print_txheader(ar, skb); --#endif /* AR9170_QUEUE_DEBUG */ -- continue; -- } -- -- r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> -- AR9170_TX_PHY_MCS_SHIFT; -- -- if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "skip frame => rate %d != %d\n", rate, r); -- ar9170_print_txheader(ar, skb); --#endif /* AR9170_QUEUE_DEBUG */ -- continue; -- } -- -- __skb_unlink(skb, queue); -- spin_unlock_irqrestore(&queue->lock, flags); -- return skb; -- } -- --#ifdef AR9170_QUEUE_DEBUG -- wiphy_err(ar->hw->wiphy, -- "ESS:[%pM] does not have any outstanding frames in queue.\n", -- mac); -- __ar9170_dump_txqueue(ar, queue); --#endif /* AR9170_QUEUE_DEBUG */ -- spin_unlock_irqrestore(&queue->lock, flags); -- -- return NULL; --} -- --/* -- * This worker tries to keeps an maintain tx_status queues. -- * So we can guarantee that incoming tx_status reports are -- * actually for a pending frame. -- */ -- --static void ar9170_tx_janitor(struct work_struct *work) --{ -- struct ar9170 *ar = container_of(work, struct ar9170, -- tx_janitor.work); -- struct sk_buff_head waste; -- unsigned int i; -- bool resched = false; -- -- if (unlikely(!IS_STARTED(ar))) -- return ; -- -- skb_queue_head_init(&waste); -- -- for (i = 0; i < __AR9170_NUM_TXQ; i++) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n", -- i); -- ar9170_dump_txqueue(ar, &ar->tx_pending[i]); -- ar9170_dump_txqueue(ar, &ar->tx_status[i]); --#endif /* AR9170_QUEUE_DEBUG */ -- -- ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); -- ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); -- skb_queue_purge(&waste); -- -- if (!skb_queue_empty(&ar->tx_status[i]) || -- !skb_queue_empty(&ar->tx_pending[i])) -- resched = true; -- } -- -- if (!resched) -- return; -- -- ieee80211_queue_delayed_work(ar->hw, -- &ar->tx_janitor, -- msecs_to_jiffies(AR9170_JANITOR_DELAY)); --} -- --void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) --{ -- struct ar9170_cmd_response *cmd = (void *) buf; -- -- if ((cmd->type & 0xc0) != 0xc0) { -- ar->callback_cmd(ar, len, buf); -- return; -- } -- -- /* hardware event handlers */ -- switch (cmd->type) { -- case 0xc1: { -- /* -- * TX status notification: -- * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 -- * -- * XX always 81 -- * YY always 00 -- * M1-M6 is the MAC address -- * R1-R4 is the transmit rate -- * S1-S2 is the transmit status -- */ -- -- struct sk_buff *skb; -- u32 phy = le32_to_cpu(cmd->tx_status.rate); -- u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> -- AR9170_TX_PHY_QOS_SHIFT; --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "recv tx_status for %pm, p:%08x, q:%d\n", -- cmd->tx_status.dst, phy, q); --#endif /* AR9170_QUEUE_DEBUG */ -- -- skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, -- &ar->tx_status[q], -- AR9170_TX_INVALID_RATE); -- if (unlikely(!skb)) -- return ; -- -- ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); -- break; -- } -- -- case 0xc0: -- /* -- * pre-TBTT event -- */ -- if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) -- ieee80211_queue_work(ar->hw, &ar->beacon_work); -- break; -- -- case 0xc2: -- /* -- * (IBSS) beacon send notification -- * bytes: 04 c2 XX YY B4 B3 B2 B1 -- * -- * XX always 80 -- * YY always 00 -- * B1-B4 "should" be the number of send out beacons. -- */ -- break; -- -- case 0xc3: -- /* End of Atim Window */ -- break; -- -- case 0xc4: -- /* BlockACK bitmap */ -- break; -- -- case 0xc5: -- /* BlockACK events */ -- break; -- -- case 0xc6: -- /* Watchdog Interrupt */ -- break; -- -- case 0xc9: -- /* retransmission issue / SIFS/EIFS collision ?! */ -- break; -- -- /* firmware debug */ -- case 0xca: -- printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, -- (char *)buf + 4); -- break; -- case 0xcb: -- len -= 4; -- -- switch (len) { -- case 1: -- printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", -- *((char *)buf + 4)); -- break; -- case 2: -- printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", -- le16_to_cpup((__le16 *)((char *)buf + 4))); -- break; -- case 4: -- printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", -- le32_to_cpup((__le32 *)((char *)buf + 4))); -- break; -- case 8: -- printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", -- (unsigned long)le64_to_cpup( -- (__le64 *)((char *)buf + 4))); -- break; -- } -- break; -- case 0xcc: -- print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, -- (char *)buf + 4, len - 4); -- break; -- -- default: -- pr_info("received unhandled event %x\n", cmd->type); -- print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); -- break; -- } --} -- --static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) --{ -- memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); -- ar->rx_mpdu.has_plcp = false; --} -- --int ar9170_nag_limiter(struct ar9170 *ar) --{ -- bool print_message; -- -- /* -- * we expect all sorts of errors in promiscuous mode. -- * don't bother with it, it's OK! -- */ -- if (ar->sniffer_enabled) -- return false; -- -- /* -- * only go for frequent errors! The hardware tends to -- * do some stupid thing once in a while under load, in -- * noisy environments or just for fun! -- */ -- if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) -- print_message = true; -- else -- print_message = false; -- -- /* reset threshold for "once in a while" */ -- ar->bad_hw_nagger = jiffies + HZ / 4; -- return print_message; --} -- --static int ar9170_rx_mac_status(struct ar9170 *ar, -- struct ar9170_rx_head *head, -- struct ar9170_rx_macstatus *mac, -- struct ieee80211_rx_status *status) --{ -- u8 error, decrypt; -- -- BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); -- BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); -- -- error = mac->error; -- if (error & AR9170_RX_ERROR_MMIC) { -- status->flag |= RX_FLAG_MMIC_ERROR; -- error &= ~AR9170_RX_ERROR_MMIC; -- } -- -- if (error & AR9170_RX_ERROR_PLCP) { -- status->flag |= RX_FLAG_FAILED_PLCP_CRC; -- error &= ~AR9170_RX_ERROR_PLCP; -- -- if (!(ar->filter_state & FIF_PLCPFAIL)) -- return -EINVAL; -- } -- -- if (error & AR9170_RX_ERROR_FCS) { -- status->flag |= RX_FLAG_FAILED_FCS_CRC; -- error &= ~AR9170_RX_ERROR_FCS; -- -- if (!(ar->filter_state & FIF_FCSFAIL)) -- return -EINVAL; -- } -- -- decrypt = ar9170_get_decrypt_type(mac); -- if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && -- decrypt != AR9170_ENC_ALG_NONE) -- status->flag |= RX_FLAG_DECRYPTED; -- -- /* ignore wrong RA errors */ -- error &= ~AR9170_RX_ERROR_WRONG_RA; -- -- if (error & AR9170_RX_ERROR_DECRYPT) { -- error &= ~AR9170_RX_ERROR_DECRYPT; -- /* -- * Rx decryption is done in place, -- * the original data is lost anyway. -- */ -- -- return -EINVAL; -- } -- -- /* drop any other error frames */ -- if (unlikely(error)) { -- /* TODO: update netdevice's RX dropped/errors statistics */ -- -- if (ar9170_nag_limiter(ar)) -- wiphy_debug(ar->hw->wiphy, -- "received frame with suspicious error code (%#x).\n", -- error); -- -- return -EINVAL; -- } -- -- status->band = ar->channel->band; -- status->freq = ar->channel->center_freq; -- -- switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { -- case AR9170_RX_STATUS_MODULATION_CCK: -- if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) -- status->flag |= RX_FLAG_SHORTPRE; -- switch (head->plcp[0]) { -- case 0x0a: -- status->rate_idx = 0; -- break; -- case 0x14: -- status->rate_idx = 1; -- break; -- case 0x37: -- status->rate_idx = 2; -- break; -- case 0x6e: -- status->rate_idx = 3; -- break; -- default: -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, -- "invalid plcp cck rate (%x).\n", -- head->plcp[0]); -- return -EINVAL; -- } -- break; -- -- case AR9170_RX_STATUS_MODULATION_DUPOFDM: -- case AR9170_RX_STATUS_MODULATION_OFDM: -- switch (head->plcp[0] & 0xf) { -- case 0xb: -- status->rate_idx = 0; -- break; -- case 0xf: -- status->rate_idx = 1; -- break; -- case 0xa: -- status->rate_idx = 2; -- break; -- case 0xe: -- status->rate_idx = 3; -- break; -- case 0x9: -- status->rate_idx = 4; -- break; -- case 0xd: -- status->rate_idx = 5; -- break; -- case 0x8: -- status->rate_idx = 6; -- break; -- case 0xc: -- status->rate_idx = 7; -- break; -- default: -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, -- "invalid plcp ofdm rate (%x).\n", -- head->plcp[0]); -- return -EINVAL; -- } -- if (status->band == IEEE80211_BAND_2GHZ) -- status->rate_idx += 4; -- break; -- -- case AR9170_RX_STATUS_MODULATION_HT: -- if (head->plcp[3] & 0x80) -- status->flag |= RX_FLAG_40MHZ; -- if (head->plcp[6] & 0x80) -- status->flag |= RX_FLAG_SHORT_GI; -- -- status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); -- status->flag |= RX_FLAG_HT; -- break; -- -- default: -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, "invalid modulation\n"); -- return -EINVAL; -- } -- -- return 0; --} -- --static void ar9170_rx_phy_status(struct ar9170 *ar, -- struct ar9170_rx_phystatus *phy, -- struct ieee80211_rx_status *status) --{ -- int i; -- -- BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); -- -- for (i = 0; i < 3; i++) -- if (phy->rssi[i] != 0x80) -- status->antenna |= BIT(i); -- -- /* post-process RSSI */ -- for (i = 0; i < 7; i++) -- if (phy->rssi[i] & 0x80) -- phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; -- -- /* TODO: we could do something with phy_errors */ -- status->signal = ar->noise[0] + phy->rssi_combined; --} -- --static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) --{ -- struct sk_buff *skb; -- int reserved = 0; -- struct ieee80211_hdr *hdr = (void *) buf; -- -- if (ieee80211_is_data_qos(hdr->frame_control)) { -- u8 *qc = ieee80211_get_qos_ctl(hdr); -- reserved += NET_IP_ALIGN; -- -- if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) -- reserved += NET_IP_ALIGN; -- } -- -- if (ieee80211_has_a4(hdr->frame_control)) -- reserved += NET_IP_ALIGN; -- -- reserved = 32 + (reserved & NET_IP_ALIGN); -- -- skb = dev_alloc_skb(len + reserved); -- if (likely(skb)) { -- skb_reserve(skb, reserved); -- memcpy(skb_put(skb, len), buf, len); -- } -- -- return skb; --} -- --/* -- * If the frame alignment is right (or the kernel has -- * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there -- * is only a single MPDU in the USB frame, then we could -- * submit to mac80211 the SKB directly. However, since -- * there may be multiple packets in one SKB in stream -- * mode, and we need to observe the proper ordering, -- * this is non-trivial. -- */ -- --static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) --{ -- struct ar9170_rx_head *head; -- struct ar9170_rx_macstatus *mac; -- struct ar9170_rx_phystatus *phy = NULL; -- struct ieee80211_rx_status status; -- struct sk_buff *skb; -- int mpdu_len; -- -- if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) -- return ; -- -- /* Received MPDU */ -- mpdu_len = len - sizeof(*mac); -- -- mac = (void *)(buf + mpdu_len); -- if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { -- /* this frame is too damaged and can't be used - drop it */ -- -- return ; -- } -- -- switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { -- case AR9170_RX_STATUS_MPDU_FIRST: -- /* first mpdu packet has the plcp header */ -- if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { -- head = (void *) buf; -- memcpy(&ar->rx_mpdu.plcp, (void *) buf, -- sizeof(struct ar9170_rx_head)); -- -- mpdu_len -= sizeof(struct ar9170_rx_head); -- buf += sizeof(struct ar9170_rx_head); -- ar->rx_mpdu.has_plcp = true; -- } else { -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, -- "plcp info is clipped.\n"); -- return ; -- } -- break; -- -- case AR9170_RX_STATUS_MPDU_LAST: -- /* last mpdu has a extra tail with phy status information */ -- -- if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { -- mpdu_len -= sizeof(struct ar9170_rx_phystatus); -- phy = (void *)(buf + mpdu_len); -- } else { -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, -- "frame tail is clipped.\n"); -- return ; -- } -- -- case AR9170_RX_STATUS_MPDU_MIDDLE: -- /* middle mpdus are just data */ -- if (unlikely(!ar->rx_mpdu.has_plcp)) { -- if (!ar9170_nag_limiter(ar)) -- return ; -- -- wiphy_err(ar->hw->wiphy, -- "rx stream did not start with a first_mpdu frame tag.\n"); -- -- return ; -- } -- -- head = &ar->rx_mpdu.plcp; -- break; -- -- case AR9170_RX_STATUS_MPDU_SINGLE: -- /* single mpdu - has plcp (head) and phy status (tail) */ -- head = (void *) buf; -- -- mpdu_len -= sizeof(struct ar9170_rx_head); -- mpdu_len -= sizeof(struct ar9170_rx_phystatus); -- -- buf += sizeof(struct ar9170_rx_head); -- phy = (void *)(buf + mpdu_len); -- break; -- -- default: -- BUG_ON(1); -- break; -- } -- -- if (unlikely(mpdu_len < FCS_LEN)) -- return ; -- -- memset(&status, 0, sizeof(status)); -- if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) -- return ; -- -- if (phy) -- ar9170_rx_phy_status(ar, phy, &status); -- -- skb = ar9170_rx_copy_data(buf, mpdu_len); -- if (likely(skb)) { -- memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); -- ieee80211_rx_irqsafe(ar->hw, skb); -- } --} -- --void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) --{ -- unsigned int i, tlen, resplen, wlen = 0, clen = 0; -- u8 *tbuf, *respbuf; -- -- tbuf = skb->data; -- tlen = skb->len; -- -- while (tlen >= 4) { -- clen = tbuf[1] << 8 | tbuf[0]; -- wlen = ALIGN(clen, 4); -- -- /* check if this is stream has a valid tag.*/ -- if (tbuf[2] != 0 || tbuf[3] != 0x4e) { -- /* -- * TODO: handle the highly unlikely event that the -- * corrupted stream has the TAG at the right position. -- */ -- -- /* check if the frame can be repaired. */ -- if (!ar->rx_failover_missing) { -- /* this is no "short read". */ -- if (ar9170_nag_limiter(ar)) { -- wiphy_err(ar->hw->wiphy, -- "missing tag!\n"); -- goto err_telluser; -- } else -- goto err_silent; -- } -- -- if (ar->rx_failover_missing > tlen) { -- if (ar9170_nag_limiter(ar)) { -- wiphy_err(ar->hw->wiphy, -- "possible multi stream corruption!\n"); -- goto err_telluser; -- } else -- goto err_silent; -- } -- -- memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); -- ar->rx_failover_missing -= tlen; -- -- if (ar->rx_failover_missing <= 0) { -- /* -- * nested ar9170_rx call! -- * termination is guaranteed, even when the -- * combined frame also have a element with -- * a bad tag. -- */ -- -- ar->rx_failover_missing = 0; -- ar9170_rx(ar, ar->rx_failover); -- -- skb_reset_tail_pointer(ar->rx_failover); -- skb_trim(ar->rx_failover, 0); -- } -- -- return ; -- } -- -- /* check if stream is clipped */ -- if (wlen > tlen - 4) { -- if (ar->rx_failover_missing) { -- /* TODO: handle double stream corruption. */ -- if (ar9170_nag_limiter(ar)) { -- wiphy_err(ar->hw->wiphy, -- "double rx stream corruption!\n"); -- goto err_telluser; -- } else -- goto err_silent; -- } -- -- /* -- * save incomplete data set. -- * the firmware will resend the missing bits when -- * the rx - descriptor comes round again. -- */ -- -- memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); -- ar->rx_failover_missing = clen - tlen; -- return ; -- } -- resplen = clen; -- respbuf = tbuf + 4; -- tbuf += wlen + 4; -- tlen -= wlen + 4; -- -- i = 0; -- -- /* weird thing, but this is the same in the original driver */ -- while (resplen > 2 && i < 12 && -- respbuf[0] == 0xff && respbuf[1] == 0xff) { -- i += 2; -- resplen -= 2; -- respbuf += 2; -- } -- -- if (resplen < 4) -- continue; -- -- /* found the 6 * 0xffff marker? */ -- if (i == 12) -- ar9170_handle_command_response(ar, respbuf, resplen); -- else -- ar9170_handle_mpdu(ar, respbuf, clen); -- } -- -- if (tlen) { -- if (net_ratelimit()) -- wiphy_err(ar->hw->wiphy, -- "%d bytes of unprocessed data left in rx stream!\n", -- tlen); -- -- goto err_telluser; -- } -- -- return ; -- --err_telluser: -- wiphy_err(ar->hw->wiphy, -- "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n", -- clen, wlen, tlen, ar->rx_failover_missing); -- -- if (ar->rx_failover_missing) -- print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, -- ar->rx_failover->data, -- ar->rx_failover->len); -- -- print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, -- skb->data, skb->len); -- -- wiphy_err(ar->hw->wiphy, -- "If you see this message frequently, please check your hardware and cables.\n"); -- --err_silent: -- if (ar->rx_failover_missing) { -- skb_reset_tail_pointer(ar->rx_failover); -- skb_trim(ar->rx_failover, 0); -- ar->rx_failover_missing = 0; -- } --} -- --#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ --do { \ -- queue.aifs = ai_fs; \ -- queue.cw_min = cwmin; \ -- queue.cw_max = cwmax; \ -- queue.txop = _txop; \ --} while (0) -- --static int ar9170_op_start(struct ieee80211_hw *hw) --{ -- struct ar9170 *ar = hw->priv; -- int err, i; -- -- mutex_lock(&ar->mutex); -- -- /* reinitialize queues statistics */ -- memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); -- for (i = 0; i < __AR9170_NUM_TXQ; i++) -- ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; -- -- /* reset QoS defaults */ -- AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ -- AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ -- AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ -- AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ -- AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ -- -- /* set sane AMPDU defaults */ -- ar->global_ampdu_density = 6; -- ar->global_ampdu_factor = 3; -- -- ar->bad_hw_nagger = jiffies; -- -- err = ar->open(ar); -- if (err) -- goto out; -- -- err = ar9170_init_mac(ar); -- if (err) -- goto out; -- -- err = ar9170_set_qos(ar); -- if (err) -- goto out; -- -- err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); -- if (err) -- goto out; -- -- err = ar9170_init_rf(ar); -- if (err) -- goto out; -- -- /* start DMA */ -- err = ar9170_write_reg(ar, 0x1c3d30, 0x100); -- if (err) -- goto out; -- -- ar->state = AR9170_STARTED; -- --out: -- mutex_unlock(&ar->mutex); -- return err; --} -- --static void ar9170_op_stop(struct ieee80211_hw *hw) --{ -- struct ar9170 *ar = hw->priv; -- unsigned int i; -- -- if (IS_STARTED(ar)) -- ar->state = AR9170_IDLE; -- -- cancel_delayed_work_sync(&ar->tx_janitor); --#ifdef CONFIG_AR9170_LEDS -- cancel_delayed_work_sync(&ar->led_work); --#endif -- cancel_work_sync(&ar->beacon_work); -- -- mutex_lock(&ar->mutex); -- -- if (IS_ACCEPTING_CMD(ar)) { -- ar9170_set_leds_state(ar, 0); -- -- /* stop DMA */ -- ar9170_write_reg(ar, 0x1c3d30, 0); -- ar->stop(ar); -- } -- -- for (i = 0; i < __AR9170_NUM_TXQ; i++) { -- skb_queue_purge(&ar->tx_pending[i]); -- skb_queue_purge(&ar->tx_status[i]); -- } -- -- mutex_unlock(&ar->mutex); --} -- --static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) --{ -- struct ieee80211_hdr *hdr; -- struct ar9170_tx_control *txc; -- struct ieee80211_tx_info *info; -- struct ieee80211_tx_rate *txrate; -- struct ar9170_tx_info *arinfo; -- unsigned int queue = skb_get_queue_mapping(skb); -- u16 keytype = 0; -- u16 len, icv = 0; -- -- BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); -- -- hdr = (void *)skb->data; -- info = IEEE80211_SKB_CB(skb); -- len = skb->len; -- -- txc = (void *)skb_push(skb, sizeof(*txc)); -- -- if (info->control.hw_key) { -- icv = info->control.hw_key->icv_len; -- -- switch (info->control.hw_key->cipher) { -- case WLAN_CIPHER_SUITE_WEP40: -- case WLAN_CIPHER_SUITE_WEP104: -- case WLAN_CIPHER_SUITE_TKIP: -- keytype = AR9170_TX_MAC_ENCR_RC4; -- break; -- case WLAN_CIPHER_SUITE_CCMP: -- keytype = AR9170_TX_MAC_ENCR_AES; -- break; -- default: -- WARN_ON(1); -- goto err_out; -- } -- } -- -- /* Length */ -- txc->length = cpu_to_le16(len + icv + 4); -- -- txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | -- AR9170_TX_MAC_BACKOFF); -- txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << -- AR9170_TX_MAC_QOS_SHIFT); -- txc->mac_control |= cpu_to_le16(keytype); -- txc->phy_control = cpu_to_le32(0); -- -- if (info->flags & IEEE80211_TX_CTL_NO_ACK) -- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); -- -- txrate = &info->control.rates[0]; -- if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) -- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); -- else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) -- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); -- -- arinfo = (void *)info->rate_driver_data; -- arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); -- -- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && -- (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { -- /* -- * WARNING: -- * Putting the QoS queue bits into an unexplored territory is -- * certainly not elegant. -- * -- * In my defense: This idea provides a reasonable way to -- * smuggle valuable information to the tx_status callback. -- * Also, the idea behind this bit-abuse came straight from -- * the original driver code. -- */ -- -- txc->phy_control |= -- cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); -- -- txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); -- } -- -- return 0; -- --err_out: -- skb_pull(skb, sizeof(*txc)); -- return -EINVAL; --} -- --static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) --{ -- struct ar9170_tx_control *txc; -- struct ieee80211_tx_info *info; -- struct ieee80211_rate *rate = NULL; -- struct ieee80211_tx_rate *txrate; -- u32 power, chains; -- -- txc = (void *) skb->data; -- info = IEEE80211_SKB_CB(skb); -- txrate = &info->control.rates[0]; -- -- if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); -- -- if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); -- -- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); -- /* this works because 40 MHz is 2 and dup is 3 */ -- if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); -- -- if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); -- -- if (txrate->flags & IEEE80211_TX_RC_MCS) { -- u32 r = txrate->idx; -- u8 *txpower; -- -- /* heavy clip control */ -- txc->phy_control |= cpu_to_le32((r & 0x7) << 7); -- -- r <<= AR9170_TX_PHY_MCS_SHIFT; -- BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); -- -- txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); -- txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); -- -- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { -- if (info->band == IEEE80211_BAND_5GHZ) -- txpower = ar->power_5G_ht40; -- else -- txpower = ar->power_2G_ht40; -- } else { -- if (info->band == IEEE80211_BAND_5GHZ) -- txpower = ar->power_5G_ht20; -- else -- txpower = ar->power_2G_ht20; -- } -- -- power = txpower[(txrate->idx) & 7]; -- } else { -- u8 *txpower; -- u32 mod; -- u32 phyrate; -- u8 idx = txrate->idx; -- -- if (info->band != IEEE80211_BAND_2GHZ) { -- idx += 4; -- txpower = ar->power_5G_leg; -- mod = AR9170_TX_PHY_MOD_OFDM; -- } else { -- if (idx < 4) { -- txpower = ar->power_2G_cck; -- mod = AR9170_TX_PHY_MOD_CCK; -- } else { -- mod = AR9170_TX_PHY_MOD_OFDM; -- txpower = ar->power_2G_ofdm; -- } -- } -- -- rate = &__ar9170_ratetable[idx]; -- -- phyrate = rate->hw_value & 0xF; -- power = txpower[(rate->hw_value & 0x30) >> 4]; -- phyrate <<= AR9170_TX_PHY_MCS_SHIFT; -- -- txc->phy_control |= cpu_to_le32(mod); -- txc->phy_control |= cpu_to_le32(phyrate); -- } -- -- power <<= AR9170_TX_PHY_TX_PWR_SHIFT; -- power &= AR9170_TX_PHY_TX_PWR_MASK; -- txc->phy_control |= cpu_to_le32(power); -- -- /* set TX chains */ -- if (ar->eeprom.tx_mask == 1) { -- chains = AR9170_TX_PHY_TXCHAIN_1; -- } else { -- chains = AR9170_TX_PHY_TXCHAIN_2; -- -- /* >= 36M legacy OFDM - use only one chain */ -- if (rate && rate->bitrate >= 360) -- chains = AR9170_TX_PHY_TXCHAIN_1; -- } -- txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); --} -- --static void ar9170_tx(struct ar9170 *ar) --{ -- struct sk_buff *skb; -- unsigned long flags; -- struct ieee80211_tx_info *info; -- struct ar9170_tx_info *arinfo; -- unsigned int i, frames, frames_failed, remaining_space; -- int err; -- bool schedule_garbagecollector = false; -- -- BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); -- -- if (unlikely(!IS_STARTED(ar))) -- return ; -- -- remaining_space = AR9170_TX_MAX_PENDING; -- -- for (i = 0; i < __AR9170_NUM_TXQ; i++) { -- spin_lock_irqsave(&ar->tx_stats_lock, flags); -- frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, -- skb_queue_len(&ar->tx_pending[i])); -- -- if (remaining_space < frames) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "tx quota reached queue:%d, " -- "remaining slots:%d, needed:%d\n", -- i, remaining_space, frames); --#endif /* AR9170_QUEUE_DEBUG */ -- frames = remaining_space; -- } -- -- ar->tx_stats[i].len += frames; -- ar->tx_stats[i].count += frames; -- if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, "queue %d full\n", i); -- wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n"); -- ar9170_dump_txqueue(ar, &ar->tx_pending[i]); -- ar9170_dump_txqueue(ar, &ar->tx_status[i]); --#endif /* AR9170_QUEUE_DEBUG */ -- --#ifdef AR9170_QUEUE_STOP_DEBUG -- wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i); -- __ar9170_dump_txstats(ar); --#endif /* AR9170_QUEUE_STOP_DEBUG */ -- ieee80211_stop_queue(ar->hw, i); -- } -- -- spin_unlock_irqrestore(&ar->tx_stats_lock, flags); -- -- if (!frames) -- continue; -- -- frames_failed = 0; -- while (frames) { -- skb = skb_dequeue(&ar->tx_pending[i]); -- if (unlikely(!skb)) { -- frames_failed += frames; -- frames = 0; -- break; -- } -- -- info = IEEE80211_SKB_CB(skb); -- arinfo = (void *) info->rate_driver_data; -- -- /* TODO: cancel stuck frames */ -- arinfo->timeout = jiffies + -- msecs_to_jiffies(AR9170_TX_TIMEOUT); -- --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i); -- ar9170_print_txheader(ar, skb); --#endif /* AR9170_QUEUE_DEBUG */ -- -- err = ar->tx(ar, skb); -- if (unlikely(err)) { -- frames_failed++; -- dev_kfree_skb_any(skb); -- } else { -- remaining_space--; -- schedule_garbagecollector = true; -- } -- -- frames--; -- } -- --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "ar9170_tx report for queue %d\n", i); -- -- wiphy_debug(ar->hw->wiphy, -- "unprocessed pending frames left:\n"); -- ar9170_dump_txqueue(ar, &ar->tx_pending[i]); --#endif /* AR9170_QUEUE_DEBUG */ -- -- if (unlikely(frames_failed)) { --#ifdef AR9170_QUEUE_DEBUG -- wiphy_debug(ar->hw->wiphy, -- "frames failed %d =>\n", frames_failed); --#endif /* AR9170_QUEUE_DEBUG */ -- -- spin_lock_irqsave(&ar->tx_stats_lock, flags); -- ar->tx_stats[i].len -= frames_failed; -- ar->tx_stats[i].count -= frames_failed; --#ifdef AR9170_QUEUE_STOP_DEBUG -- wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i); -- __ar9170_dump_txstats(ar); --#endif /* AR9170_QUEUE_STOP_DEBUG */ -- ieee80211_wake_queue(ar->hw, i); -- spin_unlock_irqrestore(&ar->tx_stats_lock, flags); -- } -- } -- -- if (!schedule_garbagecollector) -- return; -- -- ieee80211_queue_delayed_work(ar->hw, -- &ar->tx_janitor, -- msecs_to_jiffies(AR9170_JANITOR_DELAY)); --} -- --void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) --{ -- struct ar9170 *ar = hw->priv; -- struct ieee80211_tx_info *info; -- unsigned int queue; -- -- if (unlikely(!IS_STARTED(ar))) -- goto err_free; -- -- if (unlikely(ar9170_tx_prepare(ar, skb))) -- goto err_free; -- -- queue = skb_get_queue_mapping(skb); -- info = IEEE80211_SKB_CB(skb); -- ar9170_tx_prepare_phy(ar, skb); -- skb_queue_tail(&ar->tx_pending[queue], skb); -- -- ar9170_tx(ar); -- return; -- --err_free: -- dev_kfree_skb_any(skb); --} -- --static int ar9170_op_add_interface(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif) --{ -- struct ar9170 *ar = hw->priv; -- struct ath_common *common = &ar->common; -- int err = 0; -- -- mutex_lock(&ar->mutex); -- -- if (ar->vif) { -- err = -EBUSY; -- goto unlock; -- } -- -- ar->vif = vif; -- memcpy(common->macaddr, vif->addr, ETH_ALEN); -- -- if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { -- ar->rx_software_decryption = true; -- ar->disable_offload = true; -- } -- -- ar->cur_filter = 0; -- err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); -- if (err) -- goto unlock; -- -- err = ar9170_set_operating_mode(ar); -- --unlock: -- mutex_unlock(&ar->mutex); -- return err; --} -- --static void ar9170_op_remove_interface(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif) --{ -- struct ar9170 *ar = hw->priv; -- -- mutex_lock(&ar->mutex); -- ar->vif = NULL; -- ar9170_update_frame_filter(ar, 0); -- ar9170_set_beacon_timers(ar); -- dev_kfree_skb(ar->beacon); -- ar->beacon = NULL; -- ar->sniffer_enabled = false; -- ar->rx_software_decryption = false; -- ar9170_set_operating_mode(ar); -- mutex_unlock(&ar->mutex); --} -- --static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) --{ -- struct ar9170 *ar = hw->priv; -- int err = 0; -- -- mutex_lock(&ar->mutex); -- -- if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { -- /* TODO */ -- err = 0; -- } -- -- if (changed & IEEE80211_CONF_CHANGE_PS) { -- /* TODO */ -- err = 0; -- } -- -- if (changed & IEEE80211_CONF_CHANGE_POWER) { -- /* TODO */ -- err = 0; -- } -- -- if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { -- /* -- * is it long_frame_max_tx_count or short_frame_max_tx_count? -- */ -- -- err = ar9170_set_hwretry_limit(ar, -- ar->hw->conf.long_frame_max_tx_count); -- if (err) -- goto out; -- } -- -- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { -- -- /* adjust slot time for 5 GHz */ -- err = ar9170_set_slot_time(ar); -- if (err) -- goto out; -- -- err = ar9170_set_dyn_sifs_ack(ar); -- if (err) -- goto out; -- -- err = ar9170_set_channel(ar, hw->conf.channel, -- AR9170_RFI_NONE, -- nl80211_to_ar9170(hw->conf.channel_type)); -- if (err) -- goto out; -- } -- --out: -- mutex_unlock(&ar->mutex); -- return err; --} -- --static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, -- struct netdev_hw_addr_list *mc_list) --{ -- u64 mchash; -- struct netdev_hw_addr *ha; -- -- /* always get broadcast frames */ -- mchash = 1ULL << (0xff >> 2); -- -- netdev_hw_addr_list_for_each(ha, mc_list) -- mchash |= 1ULL << (ha->addr[5] >> 2); -- -- return mchash; --} -- --static void ar9170_op_configure_filter(struct ieee80211_hw *hw, -- unsigned int changed_flags, -- unsigned int *new_flags, -- u64 multicast) --{ -- struct ar9170 *ar = hw->priv; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return ; -- -- mutex_lock(&ar->mutex); -- -- /* mask supported flags */ -- *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | -- FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; -- ar->filter_state = *new_flags; -- /* -- * We can support more by setting the sniffer bit and -- * then checking the error flags, later. -- */ -- -- if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) -- multicast = ~0ULL; -- -- if (multicast != ar->cur_mc_hash) -- ar9170_update_multicast(ar, multicast); -- -- if (changed_flags & FIF_CONTROL) { -- u32 filter = AR9170_MAC_REG_FTF_PSPOLL | -- AR9170_MAC_REG_FTF_RTS | -- AR9170_MAC_REG_FTF_CTS | -- AR9170_MAC_REG_FTF_ACK | -- AR9170_MAC_REG_FTF_CFE | -- AR9170_MAC_REG_FTF_CFE_ACK; -- -- if (*new_flags & FIF_CONTROL) -- filter |= ar->cur_filter; -- else -- filter &= (~ar->cur_filter); -- -- ar9170_update_frame_filter(ar, filter); -- } -- -- if (changed_flags & FIF_PROMISC_IN_BSS) { -- ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; -- ar9170_set_operating_mode(ar); -- } -- -- mutex_unlock(&ar->mutex); --} -- -- --static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_bss_conf *bss_conf, -- u32 changed) --{ -- struct ar9170 *ar = hw->priv; -- struct ath_common *common = &ar->common; -- int err = 0; -- -- mutex_lock(&ar->mutex); -- -- if (changed & BSS_CHANGED_BSSID) { -- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -- err = ar9170_set_operating_mode(ar); -- if (err) -- goto out; -- } -- -- if (changed & BSS_CHANGED_BEACON_ENABLED) -- ar->enable_beacon = bss_conf->enable_beacon; -- -- if (changed & BSS_CHANGED_BEACON) { -- err = ar9170_update_beacon(ar); -- if (err) -- goto out; -- } -- -- if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | -- BSS_CHANGED_BEACON_INT)) { -- err = ar9170_set_beacon_timers(ar); -- if (err) -- goto out; -- } -- -- if (changed & BSS_CHANGED_ASSOC) { --#ifndef CONFIG_AR9170_LEDS -- /* enable assoc LED. */ -- err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); --#endif /* CONFIG_AR9170_LEDS */ -- } -- -- if (changed & BSS_CHANGED_HT) { -- /* TODO */ -- err = 0; -- } -- -- if (changed & BSS_CHANGED_ERP_SLOT) { -- err = ar9170_set_slot_time(ar); -- if (err) -- goto out; -- } -- -- if (changed & BSS_CHANGED_BASIC_RATES) { -- err = ar9170_set_basic_rates(ar); -- if (err) -- goto out; -- } -- --out: -- mutex_unlock(&ar->mutex); --} -- --static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) --{ -- struct ar9170 *ar = hw->priv; -- int err; -- u64 tsf; --#define NR 3 -- static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, -- AR9170_MAC_REG_TSF_L, -- AR9170_MAC_REG_TSF_H }; -- u32 val[NR]; -- int loops = 0; -- -- mutex_lock(&ar->mutex); -- -- while (loops++ < 10) { -- err = ar9170_read_mreg(ar, NR, addr, val); -- if (err || val[0] == val[2]) -- break; -- } -- -- mutex_unlock(&ar->mutex); -- -- if (WARN_ON(err)) -- return 0; -- tsf = val[0]; -- tsf = (tsf << 32) | val[1]; -- return tsf; --#undef NR --} -- --static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, -- struct ieee80211_vif *vif, struct ieee80211_sta *sta, -- struct ieee80211_key_conf *key) --{ -- struct ar9170 *ar = hw->priv; -- int err = 0, i; -- u8 ktype; -- -- if ((!ar->vif) || (ar->disable_offload)) -- return -EOPNOTSUPP; -- -- switch (key->cipher) { -- case WLAN_CIPHER_SUITE_WEP40: -- ktype = AR9170_ENC_ALG_WEP64; -- break; -- case WLAN_CIPHER_SUITE_WEP104: -- ktype = AR9170_ENC_ALG_WEP128; -- break; -- case WLAN_CIPHER_SUITE_TKIP: -- ktype = AR9170_ENC_ALG_TKIP; -- break; -- case WLAN_CIPHER_SUITE_CCMP: -- ktype = AR9170_ENC_ALG_AESCCMP; -- break; -- default: -- return -EOPNOTSUPP; -- } -- -- mutex_lock(&ar->mutex); -- if (cmd == SET_KEY) { -- if (unlikely(!IS_STARTED(ar))) { -- err = -EOPNOTSUPP; -- goto out; -- } -- -- /* group keys need all-zeroes address */ -- if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) -- sta = NULL; -- -- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { -- for (i = 0; i < 64; i++) -- if (!(ar->usedkeys & BIT(i))) -- break; -- if (i == 64) { -- ar->rx_software_decryption = true; -- ar9170_set_operating_mode(ar); -- err = -ENOSPC; -- goto out; -- } -- } else { -- i = 64 + key->keyidx; -- } -- -- key->hw_key_idx = i; -- -- err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, -- key->key, min_t(u8, 16, key->keylen)); -- if (err) -- goto out; -- -- if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { -- err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, -- ktype, 1, key->key + 16, 16); -- if (err) -- goto out; -- -- /* -- * hardware is not capable generating the MMIC -- * for fragmented frames! -- */ -- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; -- } -- -- if (i < 64) -- ar->usedkeys |= BIT(i); -- -- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; -- } else { -- if (unlikely(!IS_STARTED(ar))) { -- /* The device is gone... together with the key ;-) */ -- err = 0; -- goto out; -- } -- -- err = ar9170_disable_key(ar, key->hw_key_idx); -- if (err) -- goto out; -- -- if (key->hw_key_idx < 64) { -- ar->usedkeys &= ~BIT(key->hw_key_idx); -- } else { -- err = ar9170_upload_key(ar, key->hw_key_idx, NULL, -- AR9170_ENC_ALG_NONE, 0, -- NULL, 0); -- if (err) -- goto out; -- -- if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { -- err = ar9170_upload_key(ar, key->hw_key_idx, -- NULL, -- AR9170_ENC_ALG_NONE, 1, -- NULL, 0); -- if (err) -- goto out; -- } -- -- } -- } -- -- ar9170_regwrite_begin(ar); -- ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); -- ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); -- ar9170_regwrite_finish(); -- err = ar9170_regwrite_result(); -- --out: -- mutex_unlock(&ar->mutex); -- -- return err; --} -- --static int ar9170_get_stats(struct ieee80211_hw *hw, -- struct ieee80211_low_level_stats *stats) --{ -- struct ar9170 *ar = hw->priv; -- u32 val; -- int err; -- -- mutex_lock(&ar->mutex); -- err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); -- ar->stats.dot11ACKFailureCount += val; -- -- memcpy(stats, &ar->stats, sizeof(*stats)); -- mutex_unlock(&ar->mutex); -- -- return 0; --} -- --static int ar9170_get_survey(struct ieee80211_hw *hw, int idx, -- struct survey_info *survey) --{ -- struct ar9170 *ar = hw->priv; -- struct ieee80211_conf *conf = &hw->conf; -- -- if (idx != 0) -- return -ENOENT; -- -- /* TODO: update noise value, e.g. call ar9170_set_channel */ -- -- survey->channel = conf->channel; -- survey->filled = SURVEY_INFO_NOISE_DBM; -- survey->noise = ar->noise[0]; -- -- return 0; --} -- --static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, -- const struct ieee80211_tx_queue_params *param) --{ -- struct ar9170 *ar = hw->priv; -- int ret; -- -- mutex_lock(&ar->mutex); -- if (queue < __AR9170_NUM_TXQ) { -- memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], -- param, sizeof(*param)); -- -- ret = ar9170_set_qos(ar); -- } else { -- ret = -EINVAL; -- } -- -- mutex_unlock(&ar->mutex); -- return ret; --} -- --static int ar9170_ampdu_action(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- enum ieee80211_ampdu_mlme_action action, -- struct ieee80211_sta *sta, u16 tid, u16 *ssn, -- u8 buf_size) --{ -- switch (action) { -- case IEEE80211_AMPDU_RX_START: -- case IEEE80211_AMPDU_RX_STOP: -- /* Handled by firmware */ -- break; -- -- default: -- return -EOPNOTSUPP; -- } -- -- return 0; --} -- --static const struct ieee80211_ops ar9170_ops = { -- .start = ar9170_op_start, -- .stop = ar9170_op_stop, -- .tx = ar9170_op_tx, -- .add_interface = ar9170_op_add_interface, -- .remove_interface = ar9170_op_remove_interface, -- .config = ar9170_op_config, -- .prepare_multicast = ar9170_op_prepare_multicast, -- .configure_filter = ar9170_op_configure_filter, -- .conf_tx = ar9170_conf_tx, -- .bss_info_changed = ar9170_op_bss_info_changed, -- .get_tsf = ar9170_op_get_tsf, -- .set_key = ar9170_set_key, -- .get_stats = ar9170_get_stats, -- .get_survey = ar9170_get_survey, -- .ampdu_action = ar9170_ampdu_action, --}; -- --void *ar9170_alloc(size_t priv_size) --{ -- struct ieee80211_hw *hw; -- struct ar9170 *ar; -- struct sk_buff *skb; -- int i; -- -- /* -- * this buffer is used for rx stream reconstruction. -- * Under heavy load this device (or the transport layer?) -- * tends to split the streams into separate rx descriptors. -- */ -- -- skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); -- if (!skb) -- goto err_nomem; -- -- hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); -- if (!hw) -- goto err_nomem; -- -- ar = hw->priv; -- ar->hw = hw; -- ar->rx_failover = skb; -- -- mutex_init(&ar->mutex); -- spin_lock_init(&ar->cmdlock); -- spin_lock_init(&ar->tx_stats_lock); -- for (i = 0; i < __AR9170_NUM_TXQ; i++) { -- skb_queue_head_init(&ar->tx_status[i]); -- skb_queue_head_init(&ar->tx_pending[i]); -- } -- ar9170_rx_reset_rx_mpdu(ar); -- INIT_WORK(&ar->beacon_work, ar9170_new_beacon); -- INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); -- -- /* all hw supports 2.4 GHz, so set channel to 1 by default */ -- ar->channel = &ar9170_2ghz_chantable[0]; -- -- /* first part of wiphy init */ -- ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | -- BIT(NL80211_IFTYPE_WDS) | -- BIT(NL80211_IFTYPE_ADHOC); -- ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | -- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | -- IEEE80211_HW_SIGNAL_DBM; -- -- ar->hw->queues = __AR9170_NUM_TXQ; -- ar->hw->extra_tx_headroom = 8; -- -- ar->hw->max_rates = 1; -- ar->hw->max_rate_tries = 3; -- -- for (i = 0; i < ARRAY_SIZE(ar->noise); i++) -- ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ -- -- return ar; -- --err_nomem: -- kfree_skb(skb); -- return ERR_PTR(-ENOMEM); --} -- --static int ar9170_read_eeprom(struct ar9170 *ar) --{ --#define RW 8 /* number of words to read at once */ --#define RB (sizeof(u32) * RW) -- struct ath_regulatory *regulatory = &ar->common.regulatory; -- u8 *eeprom = (void *)&ar->eeprom; -- u8 *addr = ar->eeprom.mac_address; -- __le32 offsets[RW]; -- unsigned int rx_streams, tx_streams, tx_params = 0; -- int i, j, err, bands = 0; -- -- BUILD_BUG_ON(sizeof(ar->eeprom) & 3); -- -- BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); --#ifndef __CHECKER__ -- /* don't want to handle trailing remains */ -- BUILD_BUG_ON(sizeof(ar->eeprom) % RB); --#endif -- -- for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { -- for (j = 0; j < RW; j++) -- offsets[j] = cpu_to_le32(AR9170_EEPROM_START + -- RB * i + 4 * j); -- -- err = ar->exec_cmd(ar, AR9170_CMD_RREG, -- RB, (u8 *) &offsets, -- RB, eeprom + RB * i); -- if (err) -- return err; -- } -- --#undef RW --#undef RB -- -- if (ar->eeprom.length == cpu_to_le16(0xFFFF)) -- return -ENODATA; -- -- if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { -- ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; -- bands++; -- } -- if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { -- ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; -- bands++; -- } -- -- rx_streams = hweight8(ar->eeprom.rx_mask); -- tx_streams = hweight8(ar->eeprom.tx_mask); -- -- if (rx_streams != tx_streams) -- tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; -- -- if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) -- tx_params = (tx_streams - 1) << -- IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; -- -- ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; -- ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; -- -- /* -- * I measured this, a bandswitch takes roughly -- * 135 ms and a frequency switch about 80. -- * -- * FIXME: measure these values again once EEPROM settings -- * are used, that will influence them! -- */ -- if (bands == 2) -- ar->hw->channel_change_time = 135 * 1000; -- else -- ar->hw->channel_change_time = 80 * 1000; -- -- regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); -- regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); -- -- /* second part of wiphy init */ -- SET_IEEE80211_PERM_ADDR(ar->hw, addr); -- -- return bands ? 0 : -EINVAL; --} -- --static int ar9170_reg_notifier(struct wiphy *wiphy, -- struct regulatory_request *request) --{ -- struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); -- struct ar9170 *ar = hw->priv; -- -- return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); --} -- --int ar9170_register(struct ar9170 *ar, struct device *pdev) --{ -- struct ath_regulatory *regulatory = &ar->common.regulatory; -- int err; -- -- /* try to read EEPROM, init MAC addr */ -- err = ar9170_read_eeprom(ar); -- if (err) -- goto err_out; -- -- err = ath_regd_init(regulatory, ar->hw->wiphy, -- ar9170_reg_notifier); -- if (err) -- goto err_out; -- -- err = ieee80211_register_hw(ar->hw); -- if (err) -- goto err_out; -- -- if (!ath_is_world_regd(regulatory)) -- regulatory_hint(ar->hw->wiphy, regulatory->alpha2); -- -- err = ar9170_init_leds(ar); -- if (err) -- goto err_unreg; -- --#ifdef CONFIG_AR9170_LEDS -- err = ar9170_register_leds(ar); -- if (err) -- goto err_unreg; --#endif /* CONFIG_AR9170_LEDS */ -- -- dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", -- wiphy_name(ar->hw->wiphy)); -- -- ar->registered = true; -- return 0; -- --err_unreg: -- ieee80211_unregister_hw(ar->hw); -- --err_out: -- return err; --} -- --void ar9170_unregister(struct ar9170 *ar) --{ -- if (ar->registered) { --#ifdef CONFIG_AR9170_LEDS -- ar9170_unregister_leds(ar); --#endif /* CONFIG_AR9170_LEDS */ -- -- ieee80211_unregister_hw(ar->hw); -- } -- -- kfree_skb(ar->rx_failover); -- mutex_destroy(&ar->mutex); --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/Makefile 1970-01-01 01:00:00.000000000 +0100 -@@ -1,3 +0,0 @@ --ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o -- --obj-$(CONFIG_AR9170_USB) += ar9170usb.o -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/phy.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/phy.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,1719 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * PHY and RF code -- * -- * Copyright 2008, Johannes Berg -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 --#include "ar9170.h" --#include "cmd.h" -- --static int ar9170_init_power_cal(struct ar9170 *ar) --{ -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); -- ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); -- ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); -- -- ar9170_regwrite_finish(); -- return ar9170_regwrite_result(); --} -- --struct ar9170_phy_init { -- u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; --}; -- --static struct ar9170_phy_init ar5416_phy_init[] = { -- { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, -- { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, -- { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, -- { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, -- { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, -- { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, -- { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, -- { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, -- { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, -- { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, -- { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, -- { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, -- { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, -- { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, -- { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, -- { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, -- { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, -- { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, -- { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, -- { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, -- { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, -- { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, -- { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, -- { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, -- { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, -- { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, -- { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, -- { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, -- { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, -- { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, -- { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, -- { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, -- { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, -- { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, -- { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, -- { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, -- { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, -- { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, -- { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, -- { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, -- { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, -- { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, -- { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, -- { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, -- { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, -- { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, -- { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, -- { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, -- { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, -- { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, -- { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, -- { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, -- { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, -- { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, -- { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, -- { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, -- { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, -- { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, -- { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, -- { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, -- { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, -- { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, -- { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, -- { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, -- { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, -- { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, -- { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, -- { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, -- { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, -- { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, -- { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, -- { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, -- { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, -- { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, -- { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, -- { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, -- { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, -- { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, -- { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, -- { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, -- { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, -- { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, -- { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, -- { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, -- { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, -- { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, -- { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, -- { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, -- { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, -- { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, -- { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, -- { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, -- { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, -- { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, -- { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, -- { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, -- { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, -- { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, -- { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, -- { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, -- { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, -- { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, -- { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, -- { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, -- { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, -- { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, -- { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, -- { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, -- { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, -- { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, -- { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, -- { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, -- { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, -- { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, -- { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, -- { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, -- { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, -- { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, -- { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, -- { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, -- { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, -- { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, -- { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, -- { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, -- { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, -- { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, -- { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, -- { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, -- { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, -- { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, -- { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, -- { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, -- { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, -- { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, -- { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, -- { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, -- { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, -- { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, -- { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, -- { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, -- { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, -- { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, -- { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, -- { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, -- { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, -- { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, -- { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, -- { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, -- { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, -- { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, -- { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, -- { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, -- { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, -- { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, -- { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, -- { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, -- { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, -- { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, -- { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, -- { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, -- { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, -- { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, -- { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, -- { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, -- { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, -- { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, -- { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, -- { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, -- { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, -- { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, -- { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, -- { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, -- { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, -- { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, -- { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, -- { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, -- { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, -- { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, -- { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, -- { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, -- { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, -- { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, -- { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, -- { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, -- { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, -- { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, -- { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, -- { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, -- { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, -- { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, -- { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, -- { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, -- { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, -- { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, -- { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, -- { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, -- { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, -- { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, -- { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, --/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ -- { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, -- { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, -- { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, -- { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, -- { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, -- { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, -- { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, -- { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, -- { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, -- { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, -- { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, -- { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, -- { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, -- { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, -- { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, -- { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } --}; -- --/* -- * look up a certain register in ar5416_phy_init[] and return the init. value -- * for the band and bandwidth given. Return 0 if register address not found. -- */ --static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) --{ -- unsigned int i; -- for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { -- if (ar5416_phy_init[i].reg != reg) -- continue; -- -- if (is_2ghz) { -- if (is_40mhz) -- return ar5416_phy_init[i]._2ghz_40; -- else -- return ar5416_phy_init[i]._2ghz_20; -- } else { -- if (is_40mhz) -- return ar5416_phy_init[i]._5ghz_40; -- else -- return ar5416_phy_init[i]._5ghz_20; -- } -- } -- return 0; --} -- --/* -- * initialize some phy regs from eeprom values in modal_header[] -- * acc. to band and bandwidth -- */ --static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, -- bool is_2ghz, bool is_40mhz) --{ -- static const u8 xpd2pd[16] = { -- 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, -- 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2 -- }; -- u32 defval, newval; -- /* pointer to the modal_header acc. to band */ -- struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; -- -- ar9170_regwrite_begin(ar); -- -- /* ant common control (index 0) */ -- newval = le32_to_cpu(m->antCtrlCommon); -- ar9170_regwrite(0x1c5964, newval); -- -- /* ant control chain 0 (index 1) */ -- newval = le32_to_cpu(m->antCtrlChain[0]); -- ar9170_regwrite(0x1c5960, newval); -- -- /* ant control chain 2 (index 2) */ -- newval = le32_to_cpu(m->antCtrlChain[1]); -- ar9170_regwrite(0x1c7960, newval); -- -- /* SwSettle (index 3) */ -- if (!is_40mhz) { -- defval = ar9170_get_default_phy_reg_val(0x1c5844, -- is_2ghz, is_40mhz); -- newval = (defval & ~0x3f80) | -- ((m->switchSettling & 0x7f) << 7); -- ar9170_regwrite(0x1c5844, newval); -- } -- -- /* adcDesired, pdaDesired (index 4) */ -- defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz); -- newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) | -- ((u8)m->adcDesiredSize); -- ar9170_regwrite(0x1c5850, newval); -- -- /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ -- defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz); -- newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) | -- (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn; -- ar9170_regwrite(0x1c5834, newval); -- -- /* TxEndToRxOn (index 6) */ -- defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz); -- newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16); -- ar9170_regwrite(0x1c5828, newval); -- -- /* thresh62 (index 7) */ -- defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz); -- newval = (defval & ~0x7f000) | (m->thresh62 << 12); -- ar9170_regwrite(0x1c8864, newval); -- -- /* tx/rx attenuation chain 0 (index 8) */ -- defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz); -- newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12); -- ar9170_regwrite(0x1c5848, newval); -- -- /* tx/rx attenuation chain 2 (index 9) */ -- defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz); -- newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12); -- ar9170_regwrite(0x1c7848, newval); -- -- /* tx/rx margin chain 0 (index 10) */ -- defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz); -- newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18); -- /* bsw margin chain 0 for 5GHz only */ -- if (!is_2ghz) -- newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10); -- ar9170_regwrite(0x1c620c, newval); -- -- /* tx/rx margin chain 2 (index 11) */ -- defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz); -- newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18); -- ar9170_regwrite(0x1c820c, newval); -- -- /* iqCall, iqCallq chain 0 (index 12) */ -- defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz); -- newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) | -- ((u8)m->iqCalQCh[0] & 0x1f); -- ar9170_regwrite(0x1c5920, newval); -- -- /* iqCall, iqCallq chain 2 (index 13) */ -- defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz); -- newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) | -- ((u8)m->iqCalQCh[1] & 0x1f); -- ar9170_regwrite(0x1c7920, newval); -- -- /* xpd gain mask (index 14) */ -- defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz); -- newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16); -- ar9170_regwrite(0x1c6258, newval); -- ar9170_regwrite_finish(); -- -- return ar9170_regwrite_result(); --} -- --int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) --{ -- int i, err; -- u32 val; -- bool is_2ghz = band == IEEE80211_BAND_2GHZ; -- bool is_40mhz = conf_is_ht40(&ar->hw->conf); -- -- ar9170_regwrite_begin(ar); -- -- for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { -- if (is_40mhz) { -- if (is_2ghz) -- val = ar5416_phy_init[i]._2ghz_40; -- else -- val = ar5416_phy_init[i]._5ghz_40; -- } else { -- if (is_2ghz) -- val = ar5416_phy_init[i]._2ghz_20; -- else -- val = ar5416_phy_init[i]._5ghz_20; -- } -- -- ar9170_regwrite(ar5416_phy_init[i].reg, val); -- } -- -- ar9170_regwrite_finish(); -- err = ar9170_regwrite_result(); -- if (err) -- return err; -- -- err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); -- if (err) -- return err; -- -- err = ar9170_init_power_cal(ar); -- if (err) -- return err; -- -- /* XXX: remove magic! */ -- if (is_2ghz) -- err = ar9170_write_reg(ar, 0x1d4014, 0x5163); -- else -- err = ar9170_write_reg(ar, 0x1d4014, 0x5143); -- -- return err; --} -- --struct ar9170_rf_init { -- u32 reg, _5ghz, _2ghz; --}; -- --static struct ar9170_rf_init ar9170_rf_init[] = { -- /* bank 0 */ -- { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, -- { 0x1c58e0, 0x02008020, 0x02008020}, -- /* bank 1 */ -- { 0x1c58b0, 0x02108421, 0x02108421}, -- { 0x1c58ec, 0x00000008, 0x00000008}, -- /* bank 2 */ -- { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, -- { 0x1c58e0, 0x00000420, 0x00000420}, -- /* bank 3 */ -- { 0x1c58f0, 0x01400018, 0x01c00018}, -- /* bank 4 */ -- { 0x1c58b0, 0x000001a1, 0x000001a1}, -- { 0x1c58e8, 0x00000001, 0x00000001}, -- /* bank 5 */ -- { 0x1c58b0, 0x00000013, 0x00000013}, -- { 0x1c58e4, 0x00000002, 0x00000002}, -- /* bank 6 */ -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00004000, 0x00004000}, -- { 0x1c58b0, 0x00006c00, 0x00006c00}, -- { 0x1c58b0, 0x00002c00, 0x00002c00}, -- { 0x1c58b0, 0x00004800, 0x00004800}, -- { 0x1c58b0, 0x00004000, 0x00004000}, -- { 0x1c58b0, 0x00006000, 0x00006000}, -- { 0x1c58b0, 0x00001000, 0x00001000}, -- { 0x1c58b0, 0x00004000, 0x00004000}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00087c00, 0x00087c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00005400, 0x00005400}, -- { 0x1c58b0, 0x00000c00, 0x00000c00}, -- { 0x1c58b0, 0x00001800, 0x00001800}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00006c00, 0x00006c00}, -- { 0x1c58b0, 0x00006c00, 0x00006c00}, -- { 0x1c58b0, 0x00007c00, 0x00007c00}, -- { 0x1c58b0, 0x00002c00, 0x00002c00}, -- { 0x1c58b0, 0x00003c00, 0x00003c00}, -- { 0x1c58b0, 0x00003800, 0x00003800}, -- { 0x1c58b0, 0x00001c00, 0x00001c00}, -- { 0x1c58b0, 0x00000800, 0x00000800}, -- { 0x1c58b0, 0x00000408, 0x00000408}, -- { 0x1c58b0, 0x00004c15, 0x00004c15}, -- { 0x1c58b0, 0x00004188, 0x00004188}, -- { 0x1c58b0, 0x0000201e, 0x0000201e}, -- { 0x1c58b0, 0x00010408, 0x00010408}, -- { 0x1c58b0, 0x00000801, 0x00000801}, -- { 0x1c58b0, 0x00000c08, 0x00000c08}, -- { 0x1c58b0, 0x0000181e, 0x0000181e}, -- { 0x1c58b0, 0x00001016, 0x00001016}, -- { 0x1c58b0, 0x00002800, 0x00002800}, -- { 0x1c58b0, 0x00004010, 0x00004010}, -- { 0x1c58b0, 0x0000081c, 0x0000081c}, -- { 0x1c58b0, 0x00000115, 0x00000115}, -- { 0x1c58b0, 0x00000015, 0x00000015}, -- { 0x1c58b0, 0x00000066, 0x00000066}, -- { 0x1c58b0, 0x0000001c, 0x0000001c}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000004, 0x00000004}, -- { 0x1c58b0, 0x00000015, 0x00000015}, -- { 0x1c58b0, 0x0000001f, 0x0000001f}, -- { 0x1c58e0, 0x00000000, 0x00000400}, -- /* bank 7 */ -- { 0x1c58b0, 0x000000a0, 0x000000a0}, -- { 0x1c58b0, 0x00000000, 0x00000000}, -- { 0x1c58b0, 0x00000040, 0x00000040}, -- { 0x1c58f0, 0x0000001c, 0x0000001c}, --}; -- --static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) --{ -- int err, i; -- -- ar9170_regwrite_begin(ar); -- -- for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) -- ar9170_regwrite(ar9170_rf_init[i].reg, -- band5ghz ? ar9170_rf_init[i]._5ghz -- : ar9170_rf_init[i]._2ghz); -- -- ar9170_regwrite_finish(); -- err = ar9170_regwrite_result(); -- if (err) -- wiphy_err(ar->hw->wiphy, "rf init failed\n"); -- return err; --} -- --static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, -- u32 freq, enum ar9170_bw bw) --{ -- int err; -- u32 d0, d1, td0, td1, fd0, fd1; -- u8 chansel; -- u8 refsel0 = 1, refsel1 = 0; -- u8 lf_synth = 0; -- -- switch (bw) { -- case AR9170_BW_40_ABOVE: -- freq += 10; -- break; -- case AR9170_BW_40_BELOW: -- freq -= 10; -- break; -- case AR9170_BW_20: -- break; -- case __AR9170_NUM_BW: -- BUG(); -- } -- -- if (band5ghz) { -- if (freq % 10) { -- chansel = (freq - 4800) / 5; -- } else { -- chansel = ((freq - 4800) / 10) * 2; -- refsel0 = 0; -- refsel1 = 1; -- } -- chansel = byte_rev_table[chansel]; -- } else { -- if (freq == 2484) { -- chansel = 10 + (freq - 2274) / 5; -- lf_synth = 1; -- } else -- chansel = 16 + (freq - 2272) / 5; -- chansel *= 4; -- chansel = byte_rev_table[chansel]; -- } -- -- d1 = chansel; -- d0 = 0x21 | -- refsel0 << 3 | -- refsel1 << 2 | -- lf_synth << 1; -- td0 = d0 & 0x1f; -- td1 = d1 & 0x1f; -- fd0 = td1 << 5 | td0; -- -- td0 = (d0 >> 5) & 0x7; -- td1 = (d1 >> 5) & 0x7; -- fd1 = td1 << 5 | td0; -- -- ar9170_regwrite_begin(ar); -- -- ar9170_regwrite(0x1c58b0, fd0); -- ar9170_regwrite(0x1c58e8, fd1); -- -- ar9170_regwrite_finish(); -- err = ar9170_regwrite_result(); -- if (err) -- return err; -- -- msleep(10); -- -- return 0; --} -- --struct ar9170_phy_freq_params { -- u8 coeff_exp; -- u16 coeff_man; -- u8 coeff_exp_shgi; -- u16 coeff_man_shgi; --}; -- --struct ar9170_phy_freq_entry { -- u16 freq; -- struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; --}; -- --/* NB: must be in sync with channel tables in main! */ --static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { --/* -- * freq, -- * 20MHz, -- * 40MHz (below), -- * 40Mhz (above), -- */ -- { 2412, { -- { 3, 21737, 3, 19563, }, -- { 3, 21827, 3, 19644, }, -- { 3, 21647, 3, 19482, }, -- } }, -- { 2417, { -- { 3, 21692, 3, 19523, }, -- { 3, 21782, 3, 19604, }, -- { 3, 21602, 3, 19442, }, -- } }, -- { 2422, { -- { 3, 21647, 3, 19482, }, -- { 3, 21737, 3, 19563, }, -- { 3, 21558, 3, 19402, }, -- } }, -- { 2427, { -- { 3, 21602, 3, 19442, }, -- { 3, 21692, 3, 19523, }, -- { 3, 21514, 3, 19362, }, -- } }, -- { 2432, { -- { 3, 21558, 3, 19402, }, -- { 3, 21647, 3, 19482, }, -- { 3, 21470, 3, 19323, }, -- } }, -- { 2437, { -- { 3, 21514, 3, 19362, }, -- { 3, 21602, 3, 19442, }, -- { 3, 21426, 3, 19283, }, -- } }, -- { 2442, { -- { 3, 21470, 3, 19323, }, -- { 3, 21558, 3, 19402, }, -- { 3, 21382, 3, 19244, }, -- } }, -- { 2447, { -- { 3, 21426, 3, 19283, }, -- { 3, 21514, 3, 19362, }, -- { 3, 21339, 3, 19205, }, -- } }, -- { 2452, { -- { 3, 21382, 3, 19244, }, -- { 3, 21470, 3, 19323, }, -- { 3, 21295, 3, 19166, }, -- } }, -- { 2457, { -- { 3, 21339, 3, 19205, }, -- { 3, 21426, 3, 19283, }, -- { 3, 21252, 3, 19127, }, -- } }, -- { 2462, { -- { 3, 21295, 3, 19166, }, -- { 3, 21382, 3, 19244, }, -- { 3, 21209, 3, 19088, }, -- } }, -- { 2467, { -- { 3, 21252, 3, 19127, }, -- { 3, 21339, 3, 19205, }, -- { 3, 21166, 3, 19050, }, -- } }, -- { 2472, { -- { 3, 21209, 3, 19088, }, -- { 3, 21295, 3, 19166, }, -- { 3, 21124, 3, 19011, }, -- } }, -- { 2484, { -- { 3, 21107, 3, 18996, }, -- { 3, 21192, 3, 19073, }, -- { 3, 21022, 3, 18920, }, -- } }, -- { 4920, { -- { 4, 21313, 4, 19181, }, -- { 4, 21356, 4, 19220, }, -- { 4, 21269, 4, 19142, }, -- } }, -- { 4940, { -- { 4, 21226, 4, 19104, }, -- { 4, 21269, 4, 19142, }, -- { 4, 21183, 4, 19065, }, -- } }, -- { 4960, { -- { 4, 21141, 4, 19027, }, -- { 4, 21183, 4, 19065, }, -- { 4, 21098, 4, 18988, }, -- } }, -- { 4980, { -- { 4, 21056, 4, 18950, }, -- { 4, 21098, 4, 18988, }, -- { 4, 21014, 4, 18912, }, -- } }, -- { 5040, { -- { 4, 20805, 4, 18725, }, -- { 4, 20846, 4, 18762, }, -- { 4, 20764, 4, 18687, }, -- } }, -- { 5060, { -- { 4, 20723, 4, 18651, }, -- { 4, 20764, 4, 18687, }, -- { 4, 20682, 4, 18614, }, -- } }, -- { 5080, { -- { 4, 20641, 4, 18577, }, -- { 4, 20682, 4, 18614, }, -- { 4, 20601, 4, 18541, }, -- } }, -- { 5180, { -- { 4, 20243, 4, 18219, }, -- { 4, 20282, 4, 18254, }, -- { 4, 20204, 4, 18183, }, -- } }, -- { 5200, { -- { 4, 20165, 4, 18148, }, -- { 4, 20204, 4, 18183, }, -- { 4, 20126, 4, 18114, }, -- } }, -- { 5220, { -- { 4, 20088, 4, 18079, }, -- { 4, 20126, 4, 18114, }, -- { 4, 20049, 4, 18044, }, -- } }, -- { 5240, { -- { 4, 20011, 4, 18010, }, -- { 4, 20049, 4, 18044, }, -- { 4, 19973, 4, 17976, }, -- } }, -- { 5260, { -- { 4, 19935, 4, 17941, }, -- { 4, 19973, 4, 17976, }, -- { 4, 19897, 4, 17907, }, -- } }, -- { 5280, { -- { 4, 19859, 4, 17873, }, -- { 4, 19897, 4, 17907, }, -- { 4, 19822, 4, 17840, }, -- } }, -- { 5300, { -- { 4, 19784, 4, 17806, }, -- { 4, 19822, 4, 17840, }, -- { 4, 19747, 4, 17772, }, -- } }, -- { 5320, { -- { 4, 19710, 4, 17739, }, -- { 4, 19747, 4, 17772, }, -- { 4, 19673, 4, 17706, }, -- } }, -- { 5500, { -- { 4, 19065, 4, 17159, }, -- { 4, 19100, 4, 17190, }, -- { 4, 19030, 4, 17127, }, -- } }, -- { 5520, { -- { 4, 18996, 4, 17096, }, -- { 4, 19030, 4, 17127, }, -- { 4, 18962, 4, 17065, }, -- } }, -- { 5540, { -- { 4, 18927, 4, 17035, }, -- { 4, 18962, 4, 17065, }, -- { 4, 18893, 4, 17004, }, -- } }, -- { 5560, { -- { 4, 18859, 4, 16973, }, -- { 4, 18893, 4, 17004, }, -- { 4, 18825, 4, 16943, }, -- } }, -- { 5580, { -- { 4, 18792, 4, 16913, }, -- { 4, 18825, 4, 16943, }, -- { 4, 18758, 4, 16882, }, -- } }, -- { 5600, { -- { 4, 18725, 4, 16852, }, -- { 4, 18758, 4, 16882, }, -- { 4, 18691, 4, 16822, }, -- } }, -- { 5620, { -- { 4, 18658, 4, 16792, }, -- { 4, 18691, 4, 16822, }, -- { 4, 18625, 4, 16762, }, -- } }, -- { 5640, { -- { 4, 18592, 4, 16733, }, -- { 4, 18625, 4, 16762, }, -- { 4, 18559, 4, 16703, }, -- } }, -- { 5660, { -- { 4, 18526, 4, 16673, }, -- { 4, 18559, 4, 16703, }, -- { 4, 18493, 4, 16644, }, -- } }, -- { 5680, { -- { 4, 18461, 4, 16615, }, -- { 4, 18493, 4, 16644, }, -- { 4, 18428, 4, 16586, }, -- } }, -- { 5700, { -- { 4, 18396, 4, 16556, }, -- { 4, 18428, 4, 16586, }, -- { 4, 18364, 4, 16527, }, -- } }, -- { 5745, { -- { 4, 18252, 4, 16427, }, -- { 4, 18284, 4, 16455, }, -- { 4, 18220, 4, 16398, }, -- } }, -- { 5765, { -- { 4, 18189, 5, 32740, }, -- { 4, 18220, 4, 16398, }, -- { 4, 18157, 5, 32683, }, -- } }, -- { 5785, { -- { 4, 18126, 5, 32626, }, -- { 4, 18157, 5, 32683, }, -- { 4, 18094, 5, 32570, }, -- } }, -- { 5805, { -- { 4, 18063, 5, 32514, }, -- { 4, 18094, 5, 32570, }, -- { 4, 18032, 5, 32458, }, -- } }, -- { 5825, { -- { 4, 18001, 5, 32402, }, -- { 4, 18032, 5, 32458, }, -- { 4, 17970, 5, 32347, }, -- } }, -- { 5170, { -- { 4, 20282, 4, 18254, }, -- { 4, 20321, 4, 18289, }, -- { 4, 20243, 4, 18219, }, -- } }, -- { 5190, { -- { 4, 20204, 4, 18183, }, -- { 4, 20243, 4, 18219, }, -- { 4, 20165, 4, 18148, }, -- } }, -- { 5210, { -- { 4, 20126, 4, 18114, }, -- { 4, 20165, 4, 18148, }, -- { 4, 20088, 4, 18079, }, -- } }, -- { 5230, { -- { 4, 20049, 4, 18044, }, -- { 4, 20088, 4, 18079, }, -- { 4, 20011, 4, 18010, }, -- } }, --}; -- --static const struct ar9170_phy_freq_params * --ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, -- enum ar9170_bw bw) --{ -- unsigned int chanidx = 0; -- u16 freq = 2412; -- -- if (channel) { -- chanidx = channel->hw_value; -- freq = channel->center_freq; -- } -- -- BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); -- -- BUILD_BUG_ON(__AR9170_NUM_BW != 3); -- -- WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); -- -- return &ar9170_phy_freq_params[chanidx].params[bw]; --} -- -- --int ar9170_init_rf(struct ar9170 *ar) --{ -- const struct ar9170_phy_freq_params *freqpar; -- __le32 cmd[7]; -- int err; -- -- err = ar9170_init_rf_banks_0_7(ar, false); -- if (err) -- return err; -- -- err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); -- if (err) -- return err; -- -- freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); -- -- cmd[0] = cpu_to_le32(2412 * 1000); -- cmd[1] = cpu_to_le32(0); -- cmd[2] = cpu_to_le32(1); -- cmd[3] = cpu_to_le32(freqpar->coeff_exp); -- cmd[4] = cpu_to_le32(freqpar->coeff_man); -- cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); -- cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); -- -- /* RF_INIT echoes the command back to us */ -- err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, -- sizeof(cmd), (u8 *)cmd, -- sizeof(cmd), (u8 *)cmd); -- if (err) -- return err; -- -- msleep(1000); -- -- return ar9170_echo_test(ar, 0xaabbccdd); --} -- --static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) --{ -- int idx = nfreqs - 2; -- -- while (idx >= 0) { -- if (f >= freqs[idx]) -- return idx; -- idx--; -- } -- -- return 0; --} -- --static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) --{ -- /* nothing to interpolate, it's horizontal */ -- if (y2 == y1) -- return y1; -- -- /* check if we hit one of the edges */ -- if (x == x1) -- return y1; -- if (x == x2) -- return y2; -- -- /* x1 == x2 is bad, hopefully == x */ -- if (x2 == x1) -- return y1; -- -- return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); --} -- --static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) --{ --#define SHIFT 8 -- s32 y; -- -- y = ar9170_interpolate_s32(x << SHIFT, -- x1 << SHIFT, y1 << SHIFT, -- x2 << SHIFT, y2 << SHIFT); -- -- /* -- * XXX: unwrap this expression -- * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); --#undef SHIFT --} -- --static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) --{ -- int i; -- -- for (i = 0; i < 3; i++) -- if (x <= x_array[i + 1]) -- break; -- -- return ar9170_interpolate_u8(x, -- x_array[i], -- y_array[i], -- x_array[i + 1], -- y_array[i + 1]); --} -- --static int ar9170_set_freq_cal_data(struct ar9170 *ar, -- struct ieee80211_channel *channel) --{ -- u8 *cal_freq_pier; -- u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; -- u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; -- int chain, idx, i; -- u32 phy_data = 0; -- u8 f, tmp; -- -- switch (channel->band) { -- case IEEE80211_BAND_2GHZ: -- f = channel->center_freq - 2300; -- cal_freq_pier = ar->eeprom.cal_freq_pier_2G; -- i = AR5416_NUM_2G_CAL_PIERS - 1; -- break; -- -- case IEEE80211_BAND_5GHZ: -- f = (channel->center_freq - 4800) / 5; -- cal_freq_pier = ar->eeprom.cal_freq_pier_5G; -- i = AR5416_NUM_5G_CAL_PIERS - 1; -- break; -- -- default: -- return -EINVAL; -- break; -- } -- -- for (; i >= 0; i--) { -- if (cal_freq_pier[i] != 0xff) -- break; -- } -- if (i < 0) -- return -EINVAL; -- -- idx = ar9170_find_freq_idx(i, cal_freq_pier, f); -- -- ar9170_regwrite_begin(ar); -- -- for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { -- for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { -- struct ar9170_calibration_data_per_freq *cal_pier_data; -- int j; -- -- switch (channel->band) { -- case IEEE80211_BAND_2GHZ: -- cal_pier_data = &ar->eeprom. -- cal_pier_data_2G[chain][idx]; -- break; -- -- case IEEE80211_BAND_5GHZ: -- cal_pier_data = &ar->eeprom. -- cal_pier_data_5G[chain][idx]; -- break; -- -- default: -- return -EINVAL; -- } -- -- for (j = 0; j < 2; j++) { -- vpds[j][i] = ar9170_interpolate_u8(f, -- cal_freq_pier[idx], -- cal_pier_data->vpd_pdg[j][i], -- cal_freq_pier[idx + 1], -- cal_pier_data[1].vpd_pdg[j][i]); -- -- pwrs[j][i] = ar9170_interpolate_u8(f, -- cal_freq_pier[idx], -- cal_pier_data->pwr_pdg[j][i], -- cal_freq_pier[idx + 1], -- cal_pier_data[1].pwr_pdg[j][i]) / 2; -- } -- } -- -- for (i = 0; i < 76; i++) { -- if (i < 25) { -- tmp = ar9170_interpolate_val(i, &pwrs[0][0], -- &vpds[0][0]); -- } else { -- tmp = ar9170_interpolate_val(i - 12, -- &pwrs[1][0], -- &vpds[1][0]); -- } -- -- phy_data |= tmp << ((i & 3) << 3); -- if ((i & 3) == 3) { -- ar9170_regwrite(0x1c6280 + chain * 0x1000 + -- (i & ~3), phy_data); -- phy_data = 0; -- } -- } -- -- for (i = 19; i < 32; i++) -- ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), -- 0x0); -- } -- -- ar9170_regwrite_finish(); -- return ar9170_regwrite_result(); --} -- --static u8 ar9170_get_max_edge_power(struct ar9170 *ar, -- struct ar9170_calctl_edges edges[], -- u32 freq) --{ -- int i; -- u8 rc = AR5416_MAX_RATE_POWER; -- u8 f; -- if (freq < 3000) -- f = freq - 2300; -- else -- f = (freq - 4800) / 5; -- -- for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { -- if (edges[i].channel == 0xff) -- break; -- if (f == edges[i].channel) { -- /* exact freq match */ -- rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; -- break; -- } -- if (i > 0 && f < edges[i].channel) { -- if (f > edges[i - 1].channel && -- edges[i - 1].power_flags & -- AR9170_CALCTL_EDGE_FLAGS) { -- /* lower channel has the inband flag set */ -- rc = edges[i - 1].power_flags & -- ~AR9170_CALCTL_EDGE_FLAGS; -- } -- break; -- } -- } -- -- if (i == AR5416_NUM_BAND_EDGES) { -- if (f > edges[i - 1].channel && -- edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { -- /* lower channel has the inband flag set */ -- rc = edges[i - 1].power_flags & -- ~AR9170_CALCTL_EDGE_FLAGS; -- } -- } -- return rc; --} -- --static u8 ar9170_get_heavy_clip(struct ar9170 *ar, -- struct ar9170_calctl_edges edges[], -- u32 freq, enum ar9170_bw bw) --{ -- u8 f; -- int i; -- u8 rc = 0; -- -- if (freq < 3000) -- f = freq - 2300; -- else -- f = (freq - 4800) / 5; -- -- if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) -- rc |= 0xf0; -- -- for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { -- if (edges[i].channel == 0xff) -- break; -- if (f == edges[i].channel) { -- if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) -- rc |= 0x0f; -- break; -- } -- } -- -- return rc; --} -- --/* -- * calculate the conformance test limits and the heavy clip parameter -- * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) -- */ --static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) --{ -- u8 ctl_grp; /* CTL group */ -- u8 ctl_idx; /* CTL index */ -- int i, j; -- struct ctl_modes { -- u8 ctl_mode; -- u8 max_power; -- u8 *pwr_cal_data; -- int pwr_cal_len; -- } *modes; -- -- /* -- * order is relevant in the mode_list_*: we fall back to the -- * lower indices if any mode is missed in the EEPROM. -- */ -- struct ctl_modes mode_list_2ghz[] = { -- { CTL_11B, 0, ar->power_2G_cck, 4 }, -- { CTL_11G, 0, ar->power_2G_ofdm, 4 }, -- { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, -- { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, -- }; -- struct ctl_modes mode_list_5ghz[] = { -- { CTL_11A, 0, ar->power_5G_leg, 4 }, -- { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, -- { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, -- }; -- int nr_modes; -- --#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) -- -- ar->phy_heavy_clip = 0; -- -- /* -- * TODO: investigate the differences between OTUS' -- * hpreg.c::zfHpGetRegulatoryDomain() and -- * ath/regd.c::ath_regd_get_band_ctl() - -- * e.g. for FCC3_WORLD the OTUS procedure -- * always returns CTL_FCC, while the one in ath/ delivers -- * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. -- */ -- ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, -- ar->hw->conf.channel->band); -- -- /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ -- if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) -- ctl_grp = CTL_FCC; -- -- if (ctl_grp != CTL_FCC) -- /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ -- return; -- -- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { -- modes = mode_list_2ghz; -- nr_modes = ARRAY_SIZE(mode_list_2ghz); -- } else { -- modes = mode_list_5ghz; -- nr_modes = ARRAY_SIZE(mode_list_5ghz); -- } -- -- for (i = 0; i < nr_modes; i++) { -- u8 c = ctl_grp | modes[i].ctl_mode; -- for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) -- if (c == ar->eeprom.ctl_index[ctl_idx]) -- break; -- if (ctl_idx < AR5416_NUM_CTLS) { -- int f_off = 0; -- -- /* determine heav clip parameter from -- the 11G edges array */ -- if (modes[i].ctl_mode == CTL_11G) { -- ar->phy_heavy_clip = -- ar9170_get_heavy_clip(ar, -- EDGES(ctl_idx, 1), -- freq, bw); -- } -- -- /* adjust freq for 40MHz */ -- if (modes[i].ctl_mode == CTL_2GHT40 || -- modes[i].ctl_mode == CTL_5GHT40) { -- if (bw == AR9170_BW_40_BELOW) -- f_off = -10; -- else -- f_off = 10; -- } -- -- modes[i].max_power = -- ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), -- freq+f_off); -- -- /* -- * TODO: check if the regulatory max. power is -- * controlled by cfg80211 for DFS -- * (hpmain applies it to max_power itself for DFS freq) -- */ -- -- } else { -- /* -- * Workaround in otus driver, hpmain.c, line 3906: -- * if no data for 5GHT20 are found, take the -- * legacy 5G value. -- * We extend this here to fallback from any other *HT or -- * 11G, too. -- */ -- int k = i; -- -- modes[i].max_power = AR5416_MAX_RATE_POWER; -- while (k-- > 0) { -- if (modes[k].max_power != -- AR5416_MAX_RATE_POWER) { -- modes[i].max_power = modes[k].max_power; -- break; -- } -- } -- } -- -- /* apply max power to pwr_cal_data (ar->power_*) */ -- for (j = 0; j < modes[i].pwr_cal_len; j++) { -- modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], -- modes[i].max_power); -- } -- } -- -- if (ar->phy_heavy_clip & 0xf0) { -- ar->power_2G_ht40[0]--; -- ar->power_2G_ht40[1]--; -- ar->power_2G_ht40[2]--; -- } -- if (ar->phy_heavy_clip & 0xf) { -- ar->power_2G_ht20[0]++; -- ar->power_2G_ht20[1]++; -- ar->power_2G_ht20[2]++; -- } -- -- --#undef EDGES --} -- --static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) --{ -- struct ar9170_calibration_target_power_legacy *ctpl; -- struct ar9170_calibration_target_power_ht *ctph; -- u8 *ctpres; -- int ntargets; -- int idx, i, n; -- u8 ackpower, ackchains, f; -- u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; -- -- if (freq < 3000) -- f = freq - 2300; -- else -- f = (freq - 4800)/5; -- -- /* -- * cycle through the various modes -- * -- * legacy modes first: 5G, 2G CCK, 2G OFDM -- */ -- for (i = 0; i < 3; i++) { -- switch (i) { -- case 0: /* 5 GHz legacy */ -- ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; -- ntargets = AR5416_NUM_5G_TARGET_PWRS; -- ctpres = ar->power_5G_leg; -- break; -- case 1: /* 2.4 GHz CCK */ -- ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; -- ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; -- ctpres = ar->power_2G_cck; -- break; -- case 2: /* 2.4 GHz OFDM */ -- ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; -- ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; -- ctpres = ar->power_2G_ofdm; -- break; -- default: -- BUG(); -- } -- -- for (n = 0; n < ntargets; n++) { -- if (ctpl[n].freq == 0xff) -- break; -- pwr_freqs[n] = ctpl[n].freq; -- } -- ntargets = n; -- idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); -- for (n = 0; n < 4; n++) -- ctpres[n] = ar9170_interpolate_u8( -- f, -- ctpl[idx + 0].freq, -- ctpl[idx + 0].power[n], -- ctpl[idx + 1].freq, -- ctpl[idx + 1].power[n]); -- } -- -- /* -- * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 -- */ -- for (i = 0; i < 4; i++) { -- switch (i) { -- case 0: /* 5 GHz HT 20 */ -- ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; -- ntargets = AR5416_NUM_5G_TARGET_PWRS; -- ctpres = ar->power_5G_ht20; -- break; -- case 1: /* 5 GHz HT 40 */ -- ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; -- ntargets = AR5416_NUM_5G_TARGET_PWRS; -- ctpres = ar->power_5G_ht40; -- break; -- case 2: /* 2.4 GHz HT 20 */ -- ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; -- ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; -- ctpres = ar->power_2G_ht20; -- break; -- case 3: /* 2.4 GHz HT 40 */ -- ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; -- ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; -- ctpres = ar->power_2G_ht40; -- break; -- default: -- BUG(); -- } -- -- for (n = 0; n < ntargets; n++) { -- if (ctph[n].freq == 0xff) -- break; -- pwr_freqs[n] = ctph[n].freq; -- } -- ntargets = n; -- idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); -- for (n = 0; n < 8; n++) -- ctpres[n] = ar9170_interpolate_u8( -- f, -- ctph[idx + 0].freq, -- ctph[idx + 0].power[n], -- ctph[idx + 1].freq, -- ctph[idx + 1].power[n]); -- } -- -- -- /* calc. conformance test limits and apply to ar->power*[] */ -- ar9170_calc_ctl(ar, freq, bw); -- -- /* set ACK/CTS TX power */ -- ar9170_regwrite_begin(ar); -- -- if (ar->eeprom.tx_mask != 1) -- ackchains = AR9170_TX_PHY_TXCHAIN_2; -- else -- ackchains = AR9170_TX_PHY_TXCHAIN_1; -- -- if (freq < 3000) -- ackpower = ar->power_2G_ofdm[0] & 0x3f; -- else -- ackpower = ar->power_5G_leg[0] & 0x3f; -- -- ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); -- ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | -- ackpower << 21 | ackchains << 27); -- -- ar9170_regwrite_finish(); -- return ar9170_regwrite_result(); --} -- --static int ar9170_calc_noise_dbm(u32 raw_noise) --{ -- if (raw_noise & 0x100) -- return ~((raw_noise & 0x0ff) >> 1); -- else -- return (raw_noise & 0xff) >> 1; --} -- --int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, -- enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) --{ -- const struct ar9170_phy_freq_params *freqpar; -- u32 cmd, tmp, offs; -- __le32 vals[8]; -- int i, err; -- bool bandswitch; -- -- /* clear BB heavy clip enable */ -- err = ar9170_write_reg(ar, 0x1c59e0, 0x200); -- if (err) -- return err; -- -- /* may be NULL at first setup */ -- if (ar->channel) -- bandswitch = ar->channel->band != channel->band; -- else -- bandswitch = true; -- -- /* HW workaround */ -- if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && -- channel->center_freq <= 2417) -- bandswitch = true; -- -- err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); -- if (err) -- return err; -- -- if (rfi != AR9170_RFI_NONE || bandswitch) { -- u32 val = 0x400; -- -- if (rfi == AR9170_RFI_COLD) -- val = 0x800; -- -- /* warm/cold reset BB/ADDA */ -- err = ar9170_write_reg(ar, 0x1d4004, val); -- if (err) -- return err; -- -- err = ar9170_write_reg(ar, 0x1d4004, 0x0); -- if (err) -- return err; -- -- err = ar9170_init_phy(ar, channel->band); -- if (err) -- return err; -- -- err = ar9170_init_rf_banks_0_7(ar, -- channel->band == IEEE80211_BAND_5GHZ); -- if (err) -- return err; -- -- cmd = AR9170_CMD_RF_INIT; -- } else { -- cmd = AR9170_CMD_FREQUENCY; -- } -- -- err = ar9170_init_rf_bank4_pwr(ar, -- channel->band == IEEE80211_BAND_5GHZ, -- channel->center_freq, bw); -- if (err) -- return err; -- -- switch (bw) { -- case AR9170_BW_20: -- tmp = 0x240; -- offs = 0; -- break; -- case AR9170_BW_40_BELOW: -- tmp = 0x2c4; -- offs = 3; -- break; -- case AR9170_BW_40_ABOVE: -- tmp = 0x2d4; -- offs = 1; -- break; -- default: -- BUG(); -- return -ENOSYS; -- } -- -- if (ar->eeprom.tx_mask != 1) -- tmp |= 0x100; -- -- err = ar9170_write_reg(ar, 0x1c5804, tmp); -- if (err) -- return err; -- -- err = ar9170_set_freq_cal_data(ar, channel); -- if (err) -- return err; -- -- err = ar9170_set_power_cal(ar, channel->center_freq, bw); -- if (err) -- return err; -- -- freqpar = ar9170_get_hw_dyn_params(channel, bw); -- -- vals[0] = cpu_to_le32(channel->center_freq * 1000); -- vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); -- vals[2] = cpu_to_le32(offs << 2 | 1); -- vals[3] = cpu_to_le32(freqpar->coeff_exp); -- vals[4] = cpu_to_le32(freqpar->coeff_man); -- vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); -- vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); -- vals[7] = cpu_to_le32(1000); -- -- err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, -- sizeof(vals), (u8 *)vals); -- if (err) -- return err; -- -- if (ar->phy_heavy_clip) { -- err = ar9170_write_reg(ar, 0x1c59e0, -- 0x200 | ar->phy_heavy_clip); -- if (err) { -- if (ar9170_nag_limiter(ar)) -- wiphy_err(ar->hw->wiphy, -- "failed to set heavy clip\n"); -- } -- } -- -- for (i = 0; i < 2; i++) { -- ar->noise[i] = ar9170_calc_noise_dbm( -- (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); -- -- ar->noise[i + 2] = ar9170_calc_noise_dbm( -- (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); -- } -- -- ar->channel = channel; -- return 0; --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/usb.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,1008 +0,0 @@ --/* -- * Atheros AR9170 driver -- * -- * USB - frontend -- * -- * Copyright 2008, Johannes Berg -- * Copyright 2009, Christian Lamparter -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 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 --#include --#include --#include --#include --#include --#include --#include "ar9170.h" --#include "cmd.h" --#include "hw.h" --#include "usb.h" -- --MODULE_AUTHOR("Johannes Berg "); --MODULE_AUTHOR("Christian Lamparter "); --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); --MODULE_FIRMWARE("ar9170.fw"); -- --enum ar9170_requirements { -- AR9170_REQ_FW1_ONLY = 1, --}; -- --static struct usb_device_id ar9170_usb_ids[] = { -- /* Atheros 9170 */ -- { USB_DEVICE(0x0cf3, 0x9170) }, -- /* Atheros TG121N */ -- { USB_DEVICE(0x0cf3, 0x1001) }, -- /* TP-Link TL-WN821N v2 */ -- { USB_DEVICE(0x0cf3, 0x1002) }, -- /* 3Com Dual Band 802.11n USB Adapter */ -- { USB_DEVICE(0x0cf3, 0x1010) }, -- /* H3C Dual Band 802.11n USB Adapter */ -- { USB_DEVICE(0x0cf3, 0x1011) }, -- /* Cace Airpcap NX */ -- { USB_DEVICE(0xcace, 0x0300) }, -- /* D-Link DWA 160 A1 */ -- { USB_DEVICE(0x07d1, 0x3c10) }, -- /* D-Link DWA 160 A2 */ -- { USB_DEVICE(0x07d1, 0x3a09) }, -- /* Netgear WNA1000 */ -- { USB_DEVICE(0x0846, 0x9040) }, -- /* Netgear WNDA3100 */ -- { USB_DEVICE(0x0846, 0x9010) }, -- /* Netgear WN111 v2 */ -- { USB_DEVICE(0x0846, 0x9001) }, -- /* Zydas ZD1221 */ -- { USB_DEVICE(0x0ace, 0x1221) }, -- /* Proxim ORiNOCO 802.11n USB */ -- { USB_DEVICE(0x1435, 0x0804) }, -- /* WNC Generic 11n USB Dongle */ -- { USB_DEVICE(0x1435, 0x0326) }, -- /* ZyXEL NWD271N */ -- { USB_DEVICE(0x0586, 0x3417) }, -- /* Z-Com UB81 BG */ -- { USB_DEVICE(0x0cde, 0x0023) }, -- /* Z-Com UB82 ABG */ -- { USB_DEVICE(0x0cde, 0x0026) }, -- /* Sphairon Homelink 1202 */ -- { USB_DEVICE(0x0cde, 0x0027) }, -- /* Arcadyan WN7512 */ -- { USB_DEVICE(0x083a, 0xf522) }, -- /* Planex GWUS300 */ -- { USB_DEVICE(0x2019, 0x5304) }, -- /* IO-Data WNGDNUS2 */ -- { USB_DEVICE(0x04bb, 0x093f) }, -- /* AVM FRITZ!WLAN USB Stick N */ -- { USB_DEVICE(0x057C, 0x8401) }, -- /* NEC WL300NU-G */ -- { USB_DEVICE(0x0409, 0x0249) }, -- /* AVM FRITZ!WLAN USB Stick N 2.4 */ -- { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, -- /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */ -- { USB_DEVICE(0x1668, 0x1200) }, -- -- /* terminate */ -- {} --}; --MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); -- --static void ar9170_usb_submit_urb(struct ar9170_usb *aru) --{ -- struct urb *urb; -- unsigned long flags; -- int err; -- -- if (unlikely(!IS_STARTED(&aru->common))) -- return ; -- -- spin_lock_irqsave(&aru->tx_urb_lock, flags); -- if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { -- spin_unlock_irqrestore(&aru->tx_urb_lock, flags); -- return ; -- } -- atomic_inc(&aru->tx_submitted_urbs); -- -- urb = usb_get_from_anchor(&aru->tx_pending); -- if (!urb) { -- atomic_dec(&aru->tx_submitted_urbs); -- spin_unlock_irqrestore(&aru->tx_urb_lock, flags); -- -- return ; -- } -- spin_unlock_irqrestore(&aru->tx_urb_lock, flags); -- -- aru->tx_pending_urbs--; -- usb_anchor_urb(urb, &aru->tx_submitted); -- -- err = usb_submit_urb(urb, GFP_ATOMIC); -- if (unlikely(err)) { -- if (ar9170_nag_limiter(&aru->common)) -- dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", -- err); -- -- usb_unanchor_urb(urb); -- atomic_dec(&aru->tx_submitted_urbs); -- ar9170_tx_callback(&aru->common, urb->context); -- } -- -- usb_free_urb(urb); --} -- --static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) --{ -- struct sk_buff *skb = urb->context; -- struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); -- -- if (unlikely(!aru)) { -- dev_kfree_skb_irq(skb); -- return ; -- } -- -- atomic_dec(&aru->tx_submitted_urbs); -- -- ar9170_tx_callback(&aru->common, skb); -- -- ar9170_usb_submit_urb(aru); --} -- --static void ar9170_usb_tx_urb_complete(struct urb *urb) --{ --} -- --static void ar9170_usb_irq_completed(struct urb *urb) --{ -- struct ar9170_usb *aru = urb->context; -- -- switch (urb->status) { -- /* everything is fine */ -- case 0: -- break; -- -- /* disconnect */ -- case -ENOENT: -- case -ECONNRESET: -- case -ENODEV: -- case -ESHUTDOWN: -- goto free; -- -- default: -- goto resubmit; -- } -- -- ar9170_handle_command_response(&aru->common, urb->transfer_buffer, -- urb->actual_length); -- --resubmit: -- usb_anchor_urb(urb, &aru->rx_submitted); -- if (usb_submit_urb(urb, GFP_ATOMIC)) { -- usb_unanchor_urb(urb); -- goto free; -- } -- -- return; -- --free: -- usb_free_coherent(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); --} -- --static void ar9170_usb_rx_completed(struct urb *urb) --{ -- struct sk_buff *skb = urb->context; -- struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); -- int err; -- -- if (!aru) -- goto free; -- -- switch (urb->status) { -- /* everything is fine */ -- case 0: -- break; -- -- /* disconnect */ -- case -ENOENT: -- case -ECONNRESET: -- case -ENODEV: -- case -ESHUTDOWN: -- goto free; -- -- default: -- goto resubmit; -- } -- -- skb_put(skb, urb->actual_length); -- ar9170_rx(&aru->common, skb); -- --resubmit: -- skb_reset_tail_pointer(skb); -- skb_trim(skb, 0); -- -- usb_anchor_urb(urb, &aru->rx_submitted); -- err = usb_submit_urb(urb, GFP_ATOMIC); -- if (unlikely(err)) { -- usb_unanchor_urb(urb); -- goto free; -- } -- -- return ; -- --free: -- dev_kfree_skb_irq(skb); --} -- --static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, -- struct urb *urb, gfp_t gfp) --{ -- struct sk_buff *skb; -- -- skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); -- if (!skb) -- return -ENOMEM; -- -- /* reserve some space for mac80211's radiotap */ -- skb_reserve(skb, 32); -- -- usb_fill_bulk_urb(urb, aru->udev, -- usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), -- skb->data, min(skb_tailroom(skb), -- AR9170_MAX_RX_BUFFER_SIZE), -- ar9170_usb_rx_completed, skb); -- -- return 0; --} -- --static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) --{ -- struct urb *urb = NULL; -- void *ibuf; -- int err = -ENOMEM; -- -- /* initialize interrupt endpoint */ -- urb = usb_alloc_urb(0, GFP_KERNEL); -- if (!urb) -- goto out; -- -- ibuf = usb_alloc_coherent(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); -- if (!ibuf) -- goto out; -- -- usb_fill_int_urb(urb, aru->udev, -- usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, -- 64, ar9170_usb_irq_completed, aru, 1); -- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -- -- usb_anchor_urb(urb, &aru->rx_submitted); -- err = usb_submit_urb(urb, GFP_KERNEL); -- if (err) { -- usb_unanchor_urb(urb); -- usb_free_coherent(aru->udev, 64, urb->transfer_buffer, -- urb->transfer_dma); -- } -- --out: -- usb_free_urb(urb); -- return err; --} -- --static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) --{ -- struct urb *urb; -- int i; -- int err = -EINVAL; -- -- for (i = 0; i < AR9170_NUM_RX_URBS; i++) { -- err = -ENOMEM; -- urb = usb_alloc_urb(0, GFP_KERNEL); -- if (!urb) -- goto err_out; -- -- err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); -- if (err) { -- usb_free_urb(urb); -- goto err_out; -- } -- -- usb_anchor_urb(urb, &aru->rx_submitted); -- err = usb_submit_urb(urb, GFP_KERNEL); -- if (err) { -- usb_unanchor_urb(urb); -- dev_kfree_skb_any((void *) urb->transfer_buffer); -- usb_free_urb(urb); -- goto err_out; -- } -- usb_free_urb(urb); -- } -- -- /* the device now waiting for a firmware. */ -- aru->common.state = AR9170_IDLE; -- return 0; -- --err_out: -- -- usb_kill_anchored_urbs(&aru->rx_submitted); -- return err; --} -- --static int ar9170_usb_flush(struct ar9170 *ar) --{ -- struct ar9170_usb *aru = (void *) ar; -- struct urb *urb; -- int ret, err = 0; -- -- if (IS_STARTED(ar)) -- aru->common.state = AR9170_IDLE; -- -- usb_wait_anchor_empty_timeout(&aru->tx_pending, -- msecs_to_jiffies(800)); -- while ((urb = usb_get_from_anchor(&aru->tx_pending))) { -- ar9170_tx_callback(&aru->common, (void *) urb->context); -- usb_free_urb(urb); -- } -- -- /* lets wait a while until the tx - queues are dried out */ -- ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, -- msecs_to_jiffies(100)); -- if (ret == 0) -- err = -ETIMEDOUT; -- -- usb_kill_anchored_urbs(&aru->tx_submitted); -- -- if (IS_ACCEPTING_CMD(ar)) -- aru->common.state = AR9170_STARTED; -- -- return err; --} -- --static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) --{ -- int err; -- -- aru->common.state = AR9170_UNKNOWN_STATE; -- -- err = ar9170_usb_flush(&aru->common); -- if (err) -- dev_err(&aru->udev->dev, "stuck tx urbs!\n"); -- -- usb_poison_anchored_urbs(&aru->tx_submitted); -- usb_poison_anchored_urbs(&aru->rx_submitted); --} -- --static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, -- unsigned int plen, void *payload, -- unsigned int outlen, void *out) --{ -- struct ar9170_usb *aru = (void *) ar; -- struct urb *urb = NULL; -- unsigned long flags; -- int err = -ENOMEM; -- -- if (unlikely(!IS_ACCEPTING_CMD(ar))) -- return -EPERM; -- -- if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) -- return -EINVAL; -- -- urb = usb_alloc_urb(0, GFP_ATOMIC); -- if (unlikely(!urb)) -- goto err_free; -- -- ar->cmdbuf[0] = cpu_to_le32(plen); -- ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); -- /* writing multiple regs fills this buffer already */ -- if (plen && payload != (u8 *)(&ar->cmdbuf[1])) -- memcpy(&ar->cmdbuf[1], payload, plen); -- -- spin_lock_irqsave(&aru->common.cmdlock, flags); -- aru->readbuf = (u8 *)out; -- aru->readlen = outlen; -- spin_unlock_irqrestore(&aru->common.cmdlock, flags); -- -- usb_fill_int_urb(urb, aru->udev, -- usb_sndintpipe(aru->udev, AR9170_EP_CMD), -- aru->common.cmdbuf, plen + 4, -- ar9170_usb_tx_urb_complete, NULL, 1); -- -- usb_anchor_urb(urb, &aru->tx_submitted); -- err = usb_submit_urb(urb, GFP_ATOMIC); -- if (unlikely(err)) { -- usb_unanchor_urb(urb); -- usb_free_urb(urb); -- goto err_unbuf; -- } -- usb_free_urb(urb); -- -- err = wait_for_completion_timeout(&aru->cmd_wait, HZ); -- if (err == 0) { -- err = -ETIMEDOUT; -- goto err_unbuf; -- } -- -- if (aru->readlen != outlen) { -- err = -EMSGSIZE; -- goto err_unbuf; -- } -- -- return 0; -- --err_unbuf: -- /* Maybe the device was removed in the second we were waiting? */ -- if (IS_STARTED(ar)) { -- dev_err(&aru->udev->dev, "no command feedback " -- "received (%d).\n", err); -- -- /* provide some maybe useful debug information */ -- print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, -- aru->common.cmdbuf, plen + 4); -- dump_stack(); -- } -- -- /* invalidate to avoid completing the next prematurely */ -- spin_lock_irqsave(&aru->common.cmdlock, flags); -- aru->readbuf = NULL; -- aru->readlen = 0; -- spin_unlock_irqrestore(&aru->common.cmdlock, flags); -- --err_free: -- -- return err; --} -- --static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) --{ -- struct ar9170_usb *aru = (struct ar9170_usb *) ar; -- struct urb *urb; -- -- if (unlikely(!IS_STARTED(ar))) { -- /* Seriously, what were you drink... err... thinking!? */ -- return -EPERM; -- } -- -- urb = usb_alloc_urb(0, GFP_ATOMIC); -- if (unlikely(!urb)) -- return -ENOMEM; -- -- usb_fill_bulk_urb(urb, aru->udev, -- usb_sndbulkpipe(aru->udev, AR9170_EP_TX), -- skb->data, skb->len, -- ar9170_usb_tx_urb_complete_frame, skb); -- urb->transfer_flags |= URB_ZERO_PACKET; -- -- usb_anchor_urb(urb, &aru->tx_pending); -- aru->tx_pending_urbs++; -- -- usb_free_urb(urb); -- -- ar9170_usb_submit_urb(aru); -- return 0; --} -- --static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) --{ -- struct ar9170_usb *aru = (void *) ar; -- unsigned long flags; -- u32 in, out; -- -- if (unlikely(!buffer)) -- return ; -- -- in = le32_to_cpup((__le32 *)buffer); -- out = le32_to_cpu(ar->cmdbuf[0]); -- -- /* mask off length byte */ -- out &= ~0xFF; -- -- if (aru->readlen >= 0) { -- /* add expected length */ -- out |= aru->readlen; -- } else { -- /* add obtained length */ -- out |= in & 0xFF; -- } -- -- /* -- * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response -- * length and we cannot predict the correct length in advance. -- * So we only check if we provided enough space for the data. -- */ -- if (unlikely(out < in)) { -- dev_warn(&aru->udev->dev, "received invalid command response " -- "got %d bytes, instead of %d bytes " -- "and the resp length is %d bytes\n", -- in, out, len); -- print_hex_dump_bytes("ar9170 invalid resp: ", -- DUMP_PREFIX_OFFSET, buffer, len); -- /* -- * Do not complete, then the command times out, -- * and we get a stack trace from there. -- */ -- return ; -- } -- -- spin_lock_irqsave(&aru->common.cmdlock, flags); -- if (aru->readbuf && len > 0) { -- memcpy(aru->readbuf, buffer + 4, len - 4); -- aru->readbuf = NULL; -- } -- complete(&aru->cmd_wait); -- spin_unlock_irqrestore(&aru->common.cmdlock, flags); --} -- --static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, -- size_t len, u32 addr, bool complete) --{ -- int transfer, err; -- u8 *buf = kmalloc(4096, GFP_KERNEL); -- -- if (!buf) -- return -ENOMEM; -- -- while (len) { -- transfer = min_t(int, len, 4096); -- memcpy(buf, data, transfer); -- -- err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), -- 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, -- addr >> 8, 0, buf, transfer, 1000); -- -- if (err < 0) { -- kfree(buf); -- return err; -- } -- -- len -= transfer; -- data += transfer; -- addr += transfer; -- } -- kfree(buf); -- -- if (complete) { -- err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), -- 0x31 /* FW DL COMPLETE */, -- 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); -- } -- -- return 0; --} -- --static int ar9170_usb_reset(struct ar9170_usb *aru) --{ -- int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); -- -- if (lock) { -- ret = usb_lock_device_for_reset(aru->udev, aru->intf); -- if (ret < 0) { -- dev_err(&aru->udev->dev, "unable to lock device " -- "for reset (%d).\n", ret); -- return ret; -- } -- } -- -- ret = usb_reset_device(aru->udev); -- if (lock) -- usb_unlock_device(aru->udev); -- -- /* let it rest - for a second - */ -- msleep(1000); -- -- return ret; --} -- --static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) --{ -- int err; -- -- if (!aru->init_values) -- goto upload_fw_start; -- -- /* First, upload initial values to device RAM */ -- err = ar9170_usb_upload(aru, aru->init_values->data, -- aru->init_values->size, 0x102800, false); -- if (err) { -- dev_err(&aru->udev->dev, "firmware part 1 " -- "upload failed (%d).\n", err); -- return err; -- } -- --upload_fw_start: -- -- /* Then, upload the firmware itself and start it */ -- return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, -- 0x200000, true); --} -- --static int ar9170_usb_init_transport(struct ar9170_usb *aru) --{ -- struct ar9170 *ar = (void *) &aru->common; -- int err; -- -- ar9170_regwrite_begin(ar); -- -- /* Set USB Rx stream mode MAX packet number to 2 */ -- ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); -- -- /* Set USB Rx stream mode timeout to 10us */ -- ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); -- -- ar9170_regwrite_finish(); -- -- err = ar9170_regwrite_result(); -- if (err) -- dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); -- -- return err; --} -- --static void ar9170_usb_stop(struct ar9170 *ar) --{ -- struct ar9170_usb *aru = (void *) ar; -- int ret; -- -- if (IS_ACCEPTING_CMD(ar)) -- aru->common.state = AR9170_STOPPED; -- -- ret = ar9170_usb_flush(ar); -- if (ret) -- dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); -- -- usb_poison_anchored_urbs(&aru->tx_submitted); -- -- /* -- * Note: -- * So far we freed all tx urbs, but we won't dare to touch any rx urbs. -- * Else we would end up with a unresponsive device... -- */ --} -- --static int ar9170_usb_open(struct ar9170 *ar) --{ -- struct ar9170_usb *aru = (void *) ar; -- int err; -- -- usb_unpoison_anchored_urbs(&aru->tx_submitted); -- err = ar9170_usb_init_transport(aru); -- if (err) { -- usb_poison_anchored_urbs(&aru->tx_submitted); -- return err; -- } -- -- aru->common.state = AR9170_IDLE; -- return 0; --} -- --static int ar9170_usb_init_device(struct ar9170_usb *aru) --{ -- int err; -- -- err = ar9170_usb_alloc_rx_irq_urb(aru); -- if (err) -- goto err_out; -- -- err = ar9170_usb_alloc_rx_bulk_urbs(aru); -- if (err) -- goto err_unrx; -- -- err = ar9170_usb_upload_firmware(aru); -- if (err) { -- err = ar9170_echo_test(&aru->common, 0x60d43110); -- if (err) { -- /* force user invention, by disabling the device */ -- err = usb_driver_set_configuration(aru->udev, -1); -- dev_err(&aru->udev->dev, "device is in a bad state. " -- "please reconnect it!\n"); -- goto err_unrx; -- } -- } -- -- return 0; -- --err_unrx: -- ar9170_usb_cancel_urbs(aru); -- --err_out: -- return err; --} -- --static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) --{ -- struct device *parent = aru->udev->dev.parent; -- struct usb_device *udev; -- -- /* -- * Store a copy of the usb_device pointer locally. -- * This is because device_release_driver initiates -- * ar9170_usb_disconnect, which in turn frees our -- * driver context (aru). -- */ -- udev = aru->udev; -- -- complete(&aru->firmware_loading_complete); -- -- /* unbind anything failed */ -- if (parent) -- device_lock(parent); -- -- device_release_driver(&udev->dev); -- if (parent) -- device_unlock(parent); -- -- usb_put_dev(udev); --} -- --static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) --{ -- struct ar9170_usb *aru = context; -- int err; -- -- aru->firmware = fw; -- -- if (!fw) { -- dev_err(&aru->udev->dev, "firmware file not found.\n"); -- goto err_freefw; -- } -- -- err = ar9170_usb_init_device(aru); -- if (err) -- goto err_freefw; -- -- err = ar9170_usb_open(&aru->common); -- if (err) -- goto err_unrx; -- -- err = ar9170_register(&aru->common, &aru->udev->dev); -- -- ar9170_usb_stop(&aru->common); -- if (err) -- goto err_unrx; -- -- complete(&aru->firmware_loading_complete); -- usb_put_dev(aru->udev); -- return; -- -- err_unrx: -- ar9170_usb_cancel_urbs(aru); -- -- err_freefw: -- ar9170_usb_firmware_failed(aru); --} -- --static void ar9170_usb_firmware_inits(const struct firmware *fw, -- void *context) --{ -- struct ar9170_usb *aru = context; -- int err; -- -- if (!fw) { -- dev_err(&aru->udev->dev, "file with init values not found.\n"); -- ar9170_usb_firmware_failed(aru); -- return; -- } -- -- aru->init_values = fw; -- -- /* ok so we have the init values -- get code for two-stage */ -- -- err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", -- &aru->udev->dev, GFP_KERNEL, aru, -- ar9170_usb_firmware_finish); -- if (err) -- ar9170_usb_firmware_failed(aru); --} -- --static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) --{ -- struct ar9170_usb *aru = context; -- int err; -- -- if (fw) { -- ar9170_usb_firmware_finish(fw, context); -- return; -- } -- -- if (aru->req_one_stage_fw) { -- dev_err(&aru->udev->dev, "ar9170.fw firmware file " -- "not found and is required for this device\n"); -- ar9170_usb_firmware_failed(aru); -- return; -- } -- -- dev_err(&aru->udev->dev, "ar9170.fw firmware file " -- "not found, trying old firmware...\n"); -- -- err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", -- &aru->udev->dev, GFP_KERNEL, aru, -- ar9170_usb_firmware_inits); -- if (err) -- ar9170_usb_firmware_failed(aru); --} -- --static bool ar9170_requires_one_stage(const struct usb_device_id *id) --{ -- if (!id->driver_info) -- return false; -- if (id->driver_info == AR9170_REQ_FW1_ONLY) -- return true; -- return false; --} -- --static int ar9170_usb_probe(struct usb_interface *intf, -- const struct usb_device_id *id) --{ -- struct ar9170_usb *aru; -- struct ar9170 *ar; -- struct usb_device *udev; -- int err; -- -- aru = ar9170_alloc(sizeof(*aru)); -- if (IS_ERR(aru)) { -- err = PTR_ERR(aru); -- goto out; -- } -- -- udev = interface_to_usbdev(intf); -- usb_get_dev(udev); -- aru->udev = udev; -- aru->intf = intf; -- ar = &aru->common; -- -- aru->req_one_stage_fw = ar9170_requires_one_stage(id); -- -- usb_set_intfdata(intf, aru); -- SET_IEEE80211_DEV(ar->hw, &intf->dev); -- -- init_usb_anchor(&aru->rx_submitted); -- init_usb_anchor(&aru->tx_pending); -- init_usb_anchor(&aru->tx_submitted); -- init_completion(&aru->cmd_wait); -- init_completion(&aru->firmware_loading_complete); -- spin_lock_init(&aru->tx_urb_lock); -- -- aru->tx_pending_urbs = 0; -- atomic_set(&aru->tx_submitted_urbs, 0); -- -- aru->common.stop = ar9170_usb_stop; -- aru->common.flush = ar9170_usb_flush; -- aru->common.open = ar9170_usb_open; -- aru->common.tx = ar9170_usb_tx; -- aru->common.exec_cmd = ar9170_usb_exec_cmd; -- aru->common.callback_cmd = ar9170_usb_callback_cmd; -- --#ifdef CONFIG_PM -- udev->reset_resume = 1; --#endif /* CONFIG_PM */ -- err = ar9170_usb_reset(aru); -- if (err) -- goto err_freehw; -- -- usb_get_dev(aru->udev); -- return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", -- &aru->udev->dev, GFP_KERNEL, aru, -- ar9170_usb_firmware_step2); --err_freehw: -- usb_set_intfdata(intf, NULL); -- usb_put_dev(udev); -- ieee80211_free_hw(ar->hw); --out: -- return err; --} -- --static void ar9170_usb_disconnect(struct usb_interface *intf) --{ -- struct ar9170_usb *aru = usb_get_intfdata(intf); -- -- if (!aru) -- return; -- -- aru->common.state = AR9170_IDLE; -- -- wait_for_completion(&aru->firmware_loading_complete); -- -- ar9170_unregister(&aru->common); -- ar9170_usb_cancel_urbs(aru); -- -- usb_put_dev(aru->udev); -- usb_set_intfdata(intf, NULL); -- ieee80211_free_hw(aru->common.hw); -- -- release_firmware(aru->init_values); -- release_firmware(aru->firmware); --} -- --#ifdef CONFIG_PM --static int ar9170_suspend(struct usb_interface *intf, -- pm_message_t message) --{ -- struct ar9170_usb *aru = usb_get_intfdata(intf); -- -- if (!aru) -- return -ENODEV; -- -- aru->common.state = AR9170_IDLE; -- ar9170_usb_cancel_urbs(aru); -- -- return 0; --} -- --static int ar9170_resume(struct usb_interface *intf) --{ -- struct ar9170_usb *aru = usb_get_intfdata(intf); -- int err; -- -- if (!aru) -- return -ENODEV; -- -- usb_unpoison_anchored_urbs(&aru->rx_submitted); -- usb_unpoison_anchored_urbs(&aru->tx_submitted); -- -- err = ar9170_usb_init_device(aru); -- if (err) -- goto err_unrx; -- -- err = ar9170_usb_open(&aru->common); -- if (err) -- goto err_unrx; -- -- return 0; -- --err_unrx: -- aru->common.state = AR9170_IDLE; -- ar9170_usb_cancel_urbs(aru); -- -- return err; --} --#endif /* CONFIG_PM */ -- --static struct usb_driver ar9170_driver = { -- .name = "ar9170usb", -- .probe = ar9170_usb_probe, -- .disconnect = ar9170_usb_disconnect, -- .id_table = ar9170_usb_ids, -- .soft_unbind = 1, --#ifdef CONFIG_PM -- .suspend = ar9170_suspend, -- .resume = ar9170_resume, -- .reset_resume = ar9170_resume, --#endif /* CONFIG_PM */ --}; -- --static int __init ar9170_init(void) --{ -- return usb_register(&ar9170_driver); --} -- --static void __exit ar9170_exit(void) --{ -- usb_deregister(&ar9170_driver); --} -- --module_init(ar9170_init); --module_exit(ar9170_exit); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ar9170/usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ar9170/usb.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,82 +0,0 @@ --/* -- * Atheros AR9170 USB driver -- * -- * Driver specific definitions -- * -- * Copyright 2008, Johannes Berg -- * Copyright 2009, Christian Lamparter -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; see the file COPYING. If not, see -- * http://www.gnu.org/licenses/. -- * -- * This file incorporates work covered by the following copyright and -- * permission notice: -- * Copyright (c) 2007-2008 Atheros Communications, Inc. -- * -- * Permission to use, copy, modify, and/or distribute this software for any -- * purpose with or without fee is hereby granted, provided that the above -- * copyright notice and this permission notice appear in all copies. -- * -- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- */ --#ifndef __USB_H --#define __USB_H -- --#include --#include --#include --#include --#include --#include --#include --#include "eeprom.h" --#include "hw.h" --#include "ar9170.h" -- --#define AR9170_NUM_RX_URBS 16 --#define AR9170_NUM_TX_URBS 8 -- --struct firmware; -- --struct ar9170_usb { -- struct ar9170 common; -- struct usb_device *udev; -- struct usb_interface *intf; -- -- struct usb_anchor rx_submitted; -- struct usb_anchor tx_pending; -- struct usb_anchor tx_submitted; -- -- bool req_one_stage_fw; -- -- spinlock_t tx_urb_lock; -- atomic_t tx_submitted_urbs; -- unsigned int tx_pending_urbs; -- -- struct completion cmd_wait; -- struct completion firmware_loading_complete; -- int readlen; -- u8 *readbuf; -- -- const struct firmware *init_values; -- const struct firmware *firmware; --}; -- --#endif /* __USB_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/ahb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/ahb.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/ahb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/ahb.c 2011-05-05 23:29:49.130485905 +0200 -@@ -18,6 +18,7 @@ - - #include - #include -+#include - #include - #include "ath5k.h" - #include "debug.h" -@@ -62,10 +63,27 @@ - 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 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/ath5k.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/ath5k.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/ath5k.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/ath5k.h 2011-05-05 23:29:49.133485941 +0200 -@@ -224,8 +224,7 @@ - - /* 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 @@ - 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 @@ - 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 @@ - 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_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 @@ - /* 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/attach.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/attach.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/attach.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/attach.c 2011-05-05 23:29:49.133485941 +0200 -@@ -313,12 +313,17 @@ - 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; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/base.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/base.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/base.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/base.c 2011-05-05 23:29:49.123485819 +0200 -@@ -1444,6 +1444,21 @@ - } - - 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) - { - struct ath5k_rx_status rs = {}; -@@ -1506,6 +1521,8 @@ - } 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 @@ - 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 @@ - } 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 @@ - 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 @@ - * 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 @@ - 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_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 @@ - - } 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 @@ - - 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 @@ - 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 @@ - * 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/base.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/base.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/base.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/base.h 2011-05-05 23:29:49.117485747 +0200 -@@ -193,12 +193,13 @@ - 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 @@ - - 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]; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/caps.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/caps.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/caps.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/caps.c 2011-05-05 23:29:49.128485881 +0200 -@@ -94,6 +94,9 @@ - } - } - -+ 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/debug.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/debug.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/debug.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/debug.c 2011-05-05 23:29:49.130485905 +0200 -@@ -888,64 +888,37 @@ - void - ath5k_debug_init_device(struct ath5k_softc *sc) - { -+ struct dentry *phydir; -+ - sc->debug.level = ath5k_debug; - -- sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", -- sc->hw->wiphy->debugfsdir); -+ phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); -+ if (!phydir) -+ return; - -- sc->debug.debugfs_debug = debugfs_create_file("debug", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, &fops_debug); -- -- sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, -- sc->debug.debugfs_phydir, sc, &fops_registers); -- -- sc->debug.debugfs_beacon = debugfs_create_file("beacon", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, &fops_beacon); -- -- sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, -- sc->debug.debugfs_phydir, sc, &fops_reset); -- -- sc->debug.debugfs_antenna = debugfs_create_file("antenna", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, &fops_antenna); -- -- sc->debug.debugfs_misc = debugfs_create_file("misc", -- S_IRUSR, -- sc->debug.debugfs_phydir, sc, &fops_misc); -- -- sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, -- &fops_frameerrors); -- -- sc->debug.debugfs_ani = debugfs_create_file("ani", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, -- &fops_ani); -- -- sc->debug.debugfs_queue = debugfs_create_file("queue", -- S_IWUSR | S_IRUSR, -- sc->debug.debugfs_phydir, sc, -- &fops_queue); --} -+ debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, -+ &fops_debug); - --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("registers", S_IRUSR, phydir, sc, &fops_registers); -+ -+ debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, -+ &fops_beacon); - -+ debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); -+ -+ debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, -+ &fops_antenna); -+ -+ debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); -+ -+ debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, -+ &fops_frameerrors); -+ -+ debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); -+ -+ debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, -+ &fops_queue); -+} - - /* functions used in other places */ - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/debug.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/debug.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/debug.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/debug.h 2011-05-05 23:29:49.132485929 +0200 -@@ -68,17 +68,6 @@ - - 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; - }; - - /** -@@ -141,9 +130,6 @@ - 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); - - void -@@ -167,9 +153,6 @@ - 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) {} - - static inline void -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/desc.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/desc.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/desc.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/desc.c 2011-05-05 23:29:49.126485857 +0200 -@@ -185,6 +185,12 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - * 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 @@ - 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 @@ - 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 @@ - 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 @@ - { - 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 @@ - 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 @@ - /* - * 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/eeprom.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/eeprom.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/eeprom.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/eeprom.c 2011-05-05 23:29:49.125485844 +0200 -@@ -660,6 +660,53 @@ - 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 @@ - 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 @@ - 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 @@ - } - - return 0; -+ -+err_out: -+ ath5k_eeprom_free_pcal_info(ah, mode); -+ return -ENOMEM; - } - - /* Parse EEPROM data */ -@@ -867,7 +918,7 @@ - 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 @@ - 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 @@ - 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 @@ - } - - return 0; -+ -+err_out: -+ ath5k_eeprom_free_pcal_info(ah, mode); -+ return -ENOMEM; - } - - /* Parse EEPROM data */ -@@ -1156,7 +1210,7 @@ - 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 @@ - 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 @@ - } - - return 0; -+ -+err_out: -+ ath5k_eeprom_free_pcal_info(ah, mode); -+ return -ENOMEM; - } - - /* Parse EEPROM data */ -@@ -1534,53 +1592,6 @@ - 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 @@ - 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 * -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/mac80211-ops.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/mac80211-ops.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/mac80211-ops.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/mac80211-ops.c 2011-05-05 23:29:49.126485857 +0200 -@@ -282,6 +282,15 @@ - 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) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/pci.c 2011-05-05 23:29:49.131485917 +0200 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include "../ath.h" - #include "ath5k.h" - #include "debug.h" -@@ -108,11 +109,42 @@ - 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, - }; - - /********************\ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/pcu.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/pcu.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/pcu.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/pcu.c 2011-05-05 23:29:49.133485941 +0200 -@@ -75,7 +75,7 @@ - * 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 @@ - - /* 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 @@ - 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 @@ - * 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)); - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/qcu.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/qcu.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/qcu.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/qcu.c 2011-05-05 23:29:49.129485893 +0200 -@@ -519,7 +519,7 @@ - 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 @@ - 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/reset.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/reset.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath5k/reset.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath5k/reset.c 2011-05-05 23:29:49.132485929 +0200 -@@ -159,6 +159,11 @@ - rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); - - /* -+ * Set default Tx frame to Tx data start delay -+ */ -+ txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; -+ -+ /* - * 5210 initvals don't include usec settings - * so we need to use magic values here for - * tx/rx latencies -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ahb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ahb.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ahb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ahb.c 2011-05-05 23:29:49.081485313 +0200 -@@ -21,6 +21,18 @@ - #include - #include "ath9k.h" - -+static const struct platform_device_id ath9k_platform_id_table[] = { -+ { -+ .name = "ath9k", -+ .driver_data = AR5416_AR9100_DEVID, -+ }, -+ { -+ .name = "ar934x_wmac", -+ .driver_data = AR9300_DEVID_AR9340, -+ }, -+ {}, -+}; -+ - /* return bus cachesize in 4B word units */ - static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) - { -@@ -57,6 +69,7 @@ - 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 +129,7 @@ - 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 +178,11 @@ - .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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ani.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ani.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ani.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ani.c 2011-05-05 23:29:49.073485215 +0200 -@@ -899,12 +899,6 @@ - * check here default level should not modify INI setting. - */ - if (use_new_ani(ah)) { -- const struct ani_ofdm_level_entry *entry_ofdm; -- const struct ani_cck_level_entry *entry_cck; -- -- entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; -- entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; -- - ah->aniperiod = ATH9K_ANI_PERIOD_NEW; - ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; - } else { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar5008_phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar5008_phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar5008_phy.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar5008_phy.c 2011-05-05 23:29:49.110485663 +0200 -@@ -44,6 +44,34 @@ - static const int m2ThreshExt_off = 127; - - -+static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array, -+ int col) -+{ -+ int i; -+ -+ for (i = 0; i < array->ia_rows; i++) -+ bank[i] = INI_RA(array, i, col); -+} -+ -+ -+#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \ -+ ar5008_write_rf_array(ah, iniarray, regData, &(regWr)) -+ -+static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array, -+ u32 *data, unsigned int *writecnt) -+{ -+ int r; -+ -+ ENABLE_REGWRITE_BUFFER(ah); -+ -+ for (r = 0; r < array->ia_rows; r++) { -+ REG_WRITE(ah, INI_RA(array, r, 0), data[r]); -+ DO_DELAY(*writecnt); -+ } -+ -+ REGWRITE_BUFFER_FLUSH(ah); -+} -+ - /** - * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters - * @rfbuf: -@@ -530,16 +558,16 @@ - eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - - /* Setup Bank 0 Write */ -- RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); -+ ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1); - - /* Setup Bank 1 Write */ -- RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); -+ ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1); - - /* Setup Bank 2 Write */ -- RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); -+ ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1); - - /* Setup Bank 6 Write */ -- RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, -+ ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3, - modesIndex); - { - int i; -@@ -569,7 +597,7 @@ - } - - /* Setup Bank 7 Setup */ -- RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); -+ ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1); - - /* Write Analog registers */ - REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, -@@ -729,6 +757,7 @@ - struct ath9k_channel *chan) - { - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); -+ struct ath_common *common = ath9k_hw_common(ah); - int i, regWrites = 0; - struct ieee80211_channel *channel = chan->chan; - u32 modesIndex, freqIndex; -@@ -805,7 +834,8 @@ - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 -- && ah->config.analog_shiftreg) { -+ && ah->config.analog_shiftreg -+ && (common->bus_ops->ath_bus_type != ATH_USB)) { - udelay(100); - } - -@@ -835,7 +865,8 @@ - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 -- && ah->config.analog_shiftreg) { -+ && ah->config.analog_shiftreg -+ && (common->bus_ops->ath_bus_type != ATH_USB)) { - udelay(100); - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_calib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_calib.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_calib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_calib.c 2011-05-05 23:29:49.076485252 +0200 -@@ -26,6 +26,27 @@ - IQ_MISMATCH_CAL = BIT(2), - }; - -+static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, -+ struct ath9k_channel *chan, -+ enum ar9002_cal_types cal_type) -+{ -+ bool supported = false; -+ switch (ah->supp_cals & cal_type) { -+ case IQ_MISMATCH_CAL: -+ /* Run IQ Mismatch for non-CCK only */ -+ if (!IS_CHAN_B(chan)) -+ supported = true; -+ break; -+ case ADC_GAIN_CAL: -+ case ADC_DC_CAL: -+ /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ -+ if (!IS_CHAN_B(chan) && -+ !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) -+ supported = true; -+ break; -+ } -+ return supported; -+} - - static void ar9002_hw_setup_calibration(struct ath_hw *ah, - struct ath9k_cal_list *currCal) -@@ -858,26 +879,32 @@ - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - ah->supp_cals = IQ_MISMATCH_CAL; - -- if (AR_SREV_9160_10_OR_LATER(ah) && -- !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) { -+ if (AR_SREV_9160_10_OR_LATER(ah)) - ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; - -+ if (AR_SREV_9287(ah)) -+ ah->supp_cals &= ~ADC_GAIN_CAL; - -+ if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { - INIT_CAL(&ah->adcgain_caldata); - INSERT_CAL(ah, &ah->adcgain_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, -- "enabling ADC Gain Calibration.\n"); -+ "enabling ADC Gain Calibration.\n"); -+ } - -+ if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { - INIT_CAL(&ah->adcdc_caldata); - INSERT_CAL(ah, &ah->adcdc_caldata); - ath_dbg(common, ATH_DBG_CALIBRATE, -- "enabling ADC DC Calibration.\n"); -+ "enabling ADC DC Calibration.\n"); - } - -- INIT_CAL(&ah->iq_caldata); -- INSERT_CAL(ah, &ah->iq_caldata); -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "enabling IQ Calibration.\n"); -+ if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { -+ INIT_CAL(&ah->iq_caldata); -+ INSERT_CAL(ah, &ah->iq_caldata); -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "enabling IQ Calibration.\n"); -+ } - - ah->cal_list_curr = ah->cal_list; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_mac.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_mac.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_mac.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_mac.c 2011-05-05 23:29:49.089485409 +0200 -@@ -290,7 +290,6 @@ - | (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_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, -@@ -415,17 +424,6 @@ - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); - } - --static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, -- u32 vmf) --{ -- struct ar5416_desc *ads = AR5416DESC(ds); -- -- if (vmf) -- ads->ds_ctl0 |= AR_VirtMoreFrag; -- else -- ads->ds_ctl0 &= ~AR_VirtMoreFrag; --} -- - void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags) - { -@@ -459,5 +457,5 @@ - ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; - ops->clr11n_aggr = ar9002_hw_clr11n_aggr; - ops->set11n_burstduration = ar9002_hw_set11n_burstduration; -- ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; -+ ops->set_clrdmask = ar9002_hw_set_clrdmask; - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9002_phy.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9002_phy.h 2011-05-05 23:29:49.007484419 +0200 -@@ -483,7 +483,11 @@ - #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 -@@ -495,6 +499,8 @@ - - #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 - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h 2011-05-05 23:29:49.075485239 +0200 -@@ -34,10 +34,10 @@ - - 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 @@ - {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 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 @@ - {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_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 @@ - {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 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 @@ - {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 @@ - {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}, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_calib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_calib.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_calib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_calib.c 2011-05-05 23:29:49.064485107 +0200 -@@ -18,13 +18,13 @@ - #include "hw-ops.h" - #include "ar9003_phy.h" - --#define MPASS 3 - #define MAX_MEASUREMENT 8 --#define MAX_DIFFERENCE 10 -+#define MAX_MAG_DELTA 11 -+#define MAX_PHS_DELTA 10 - - struct coeff { -- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; -- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; -+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; -+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; - int iqc_coeff[2]; - }; - -@@ -185,17 +185,19 @@ - - /* Accumulate IQ cal measures for active chains */ - for (i = 0; i < AR5416_MAX_CHAINS; i++) { -- ah->totalPowerMeasI[i] += -- REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); -- ah->totalPowerMeasQ[i] += -- REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); -- ah->totalIqCorrMeas[i] += -- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); -- ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, -- "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", -- ah->cal_samples, i, ah->totalPowerMeasI[i], -- ah->totalPowerMeasQ[i], -- ah->totalIqCorrMeas[i]); -+ if (ah->txchainmask & BIT(i)) { -+ ah->totalPowerMeasI[i] += -+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); -+ ah->totalPowerMeasQ[i] += -+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); -+ ah->totalIqCorrMeas[i] += -+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); -+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, -+ "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", -+ ah->cal_samples, i, ah->totalPowerMeasI[i], -+ ah->totalPowerMeasQ[i], -+ ah->totalIqCorrMeas[i]); -+ } - } - } - -@@ -608,36 +610,48 @@ - return true; - } - --static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) -+static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, -+ int max_delta) - { -- int diff[MPASS]; -- -- diff[0] = abs(mp_coeff[0] - mp_coeff[1]); -- diff[1] = abs(mp_coeff[1] - mp_coeff[2]); -- diff[2] = abs(mp_coeff[2] - mp_coeff[0]); -- -- if (diff[0] > MAX_DIFFERENCE && -- diff[1] > MAX_DIFFERENCE && -- diff[2] > MAX_DIFFERENCE) -- return false; -- -- if (diff[0] <= diff[1] && diff[0] <= diff[2]) -- *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; -- else if (diff[1] <= diff[2]) -- *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; -- else -- *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; -+ int mp_max = -64, max_idx = 0; -+ int mp_min = 63, min_idx = 0; -+ int mp_avg = 0, i, outlier_idx = 0; -+ -+ /* find min/max mismatch across all calibrated gains */ -+ for (i = 0; i < nmeasurement; i++) { -+ mp_avg += mp_coeff[i]; -+ if (mp_coeff[i] > mp_max) { -+ mp_max = mp_coeff[i]; -+ max_idx = i; -+ } else if (mp_coeff[i] < mp_min) { -+ mp_min = mp_coeff[i]; -+ min_idx = i; -+ } -+ } - -- return true; -+ /* find average (exclude max abs value) */ -+ for (i = 0; i < nmeasurement; i++) { -+ if ((abs(mp_coeff[i]) < abs(mp_max)) || -+ (abs(mp_coeff[i]) < abs(mp_min))) -+ mp_avg += mp_coeff[i]; -+ } -+ mp_avg /= (nmeasurement - 1); -+ -+ /* detect outlier */ -+ if (abs(mp_max - mp_min) > max_delta) { -+ if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) -+ outlier_idx = max_idx; -+ else -+ outlier_idx = min_idx; -+ } -+ mp_coeff[outlier_idx] = mp_avg; - } - - static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, - u8 num_chains, - struct coeff *coeff) - { -- struct ath_common *common = ath9k_hw_common(ah); - int i, im, nmeasurement; -- int magnitude, phase; - u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; - - memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); -@@ -657,37 +671,28 @@ - - /* Load the average of 2 passes */ - for (i = 0; i < num_chains; i++) { -- if (AR_SREV_9485(ah)) -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -- AR_PHY_CALIBRATED_GAINS_0); -- else -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_CALIBRATED_GAINS_0); -+ nmeasurement = REG_READ_FIELD(ah, -+ AR_PHY_TX_IQCAL_STATUS_B0, -+ AR_PHY_CALIBRATED_GAINS_0); - - if (nmeasurement > MAX_MEASUREMENT) - nmeasurement = MAX_MEASUREMENT; - -- for (im = 0; im < nmeasurement; im++) { -- /* -- * Determine which 2 passes are closest and compute avg -- * magnitude -- */ -- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], -- &magnitude)) -- goto disable_txiqcal; -+ /* detect outlier only if nmeasurement > 1 */ -+ if (nmeasurement > 1) { -+ /* Detect magnitude outlier */ -+ ar9003_hw_detect_outlier(coeff->mag_coeff[i], -+ nmeasurement, MAX_MAG_DELTA); -+ -+ /* Detect phase outlier */ -+ ar9003_hw_detect_outlier(coeff->phs_coeff[i], -+ nmeasurement, MAX_PHS_DELTA); -+ } - -- /* -- * Determine which 2 passes are closest and compute avg -- * phase -- */ -- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], -- &phase)) -- goto disable_txiqcal; -+ for (im = 0; im < nmeasurement; im++) { - -- coeff->iqc_coeff[0] = (magnitude & 0x7f) | -- ((phase & 0x7f) << 7); -+ coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | -+ ((coeff->phs_coeff[i][im] & 0x7f) << 7); - - if ((im % 2) == 0) - REG_RMW_FIELD(ah, tx_corr_coeff[im][i], -@@ -707,141 +712,37 @@ - - return; - --disable_txiqcal: -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, -- AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); -- REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, -- AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); -- -- ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); - } - --static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) -+static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -- static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { -- AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_TX_IQCAL_STATUS_B1, -- AR_PHY_TX_IQCAL_STATUS_B2, -- }; -- static const u32 chan_info_tab[] = { -- AR_PHY_CHAN_INFO_TAB_0, -- AR_PHY_CHAN_INFO_TAB_1, -- AR_PHY_CHAN_INFO_TAB_2, -- }; -- struct coeff coeff; -- s32 iq_res[6]; -- s32 i, j, ip, im, nmeasurement; -- u8 nchains = get_streams(common->tx_chainmask); -- -- for (ip = 0; ip < MPASS; ip++) { -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, -- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, -- DELPT); -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, -- AR_PHY_TX_IQCAL_START_DO_CAL, -- AR_PHY_TX_IQCAL_START_DO_CAL); -- -- if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, -- AR_PHY_TX_IQCAL_START_DO_CAL, -- 0, AH_WAIT_TIMEOUT)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Tx IQ Cal not complete.\n"); -- goto TX_IQ_CAL_FAILED; -- } -- -- nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, -- AR_PHY_CALIBRATED_GAINS_0); -- if (nmeasurement > MAX_MEASUREMENT) -- nmeasurement = MAX_MEASUREMENT; -- -- for (i = 0; i < nchains; i++) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Doing Tx IQ Cal for chain %d.\n", i); -- for (im = 0; im < nmeasurement; im++) { -- if (REG_READ(ah, txiqcal_status[i]) & -- AR_PHY_TX_IQCAL_STATUS_FAILED) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Tx IQ Cal failed for chain %d.\n", i); -- goto TX_IQ_CAL_FAILED; -- } -- -- for (j = 0; j < 3; j++) { -- u8 idx = 2 * j, -- offset = 4 * (3 * im + j); -- -- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, -- AR_PHY_CHAN_INFO_TAB_S2_READ, -- 0); -- -- /* 32 bits */ -- iq_res[idx] = REG_READ(ah, -- chan_info_tab[i] + -- offset); -- -- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, -- AR_PHY_CHAN_INFO_TAB_S2_READ, -- 1); -- -- /* 16 bits */ -- iq_res[idx+1] = 0xffff & REG_READ(ah, -- chan_info_tab[i] + -- offset); -- -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", -- idx, iq_res[idx], idx+1, iq_res[idx+1]); -- } -- -- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -- coeff.iqc_coeff)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Failed in calculation of IQ correction.\n"); -- goto TX_IQ_CAL_FAILED; -- } -- coeff.mag_coeff[i][im][ip] = -- coeff.iqc_coeff[0] & 0x7f; -- coeff.phs_coeff[i][im][ip] = -- (coeff.iqc_coeff[0] >> 7) & 0x7f; -- -- if (coeff.mag_coeff[i][im][ip] > 63) -- coeff.mag_coeff[i][im][ip] -= 128; -- if (coeff.phs_coeff[i][im][ip] > 63) -- coeff.phs_coeff[i][im][ip] -= 128; -- -- } -- } -- } -- -- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); -- -- return; -- --TX_IQ_CAL_FAILED: -- ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); --} -- --static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) --{ - u8 tx_gain_forced; - -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, -- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); - tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, - AR_PHY_TXGAIN_FORCE); - if (tx_gain_forced) - REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, - AR_PHY_TXGAIN_FORCE, 0); - -- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, -- AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); -+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, -+ AR_PHY_TX_IQCAL_START_DO_CAL, 1); -+ -+ if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, -+ AR_PHY_TX_IQCAL_START_DO_CAL, 0, -+ AH_WAIT_TIMEOUT)) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Tx IQ Cal is not completed.\n"); -+ return false; -+ } -+ return true; - } - - static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); - const u32 txiqcal_status[AR9300_MAX_CHAINS] = { -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -+ AR_PHY_TX_IQCAL_STATUS_B0, - AR_PHY_TX_IQCAL_STATUS_B1, - AR_PHY_TX_IQCAL_STATUS_B2, - }; -@@ -853,7 +754,7 @@ - struct coeff coeff; - s32 iq_res[6]; - u8 num_chains = 0; -- int i, ip, im, j; -+ int i, im, j; - int nmeasurement; - - for (i = 0; i < AR9300_MAX_CHAINS; i++) { -@@ -861,71 +762,69 @@ - num_chains++; - } - -- for (ip = 0; ip < MPASS; ip++) { -- for (i = 0; i < num_chains; i++) { -- nmeasurement = REG_READ_FIELD(ah, -- AR_PHY_TX_IQCAL_STATUS_B0_9485, -- AR_PHY_CALIBRATED_GAINS_0); -- if (nmeasurement > MAX_MEASUREMENT) -- nmeasurement = MAX_MEASUREMENT; -+ for (i = 0; i < num_chains; i++) { -+ nmeasurement = REG_READ_FIELD(ah, -+ AR_PHY_TX_IQCAL_STATUS_B0, -+ AR_PHY_CALIBRATED_GAINS_0); -+ if (nmeasurement > MAX_MEASUREMENT) -+ nmeasurement = MAX_MEASUREMENT; -+ -+ for (im = 0; im < nmeasurement; im++) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Doing Tx IQ Cal for chain %d.\n", i); - -- for (im = 0; im < nmeasurement; im++) { -+ if (REG_READ(ah, txiqcal_status[i]) & -+ AR_PHY_TX_IQCAL_STATUS_FAILED) { - ath_dbg(common, ATH_DBG_CALIBRATE, -- "Doing Tx IQ Cal for chain %d.\n", i); -- -- if (REG_READ(ah, txiqcal_status[i]) & -- AR_PHY_TX_IQCAL_STATUS_FAILED) { -- ath_dbg(common, ATH_DBG_CALIBRATE, - "Tx IQ Cal failed for chain %d.\n", i); -- goto tx_iqcal_fail; -- } -+ goto tx_iqcal_fail; -+ } - -- for (j = 0; j < 3; j++) { -- u32 idx = 2 * j, offset = 4 * (3 * im + j); -+ for (j = 0; j < 3; j++) { -+ u32 idx = 2 * j, offset = 4 * (3 * im + j); - -- REG_RMW_FIELD(ah, -+ REG_RMW_FIELD(ah, - AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 0); - -- /* 32 bits */ -- iq_res[idx] = REG_READ(ah, -- chan_info_tab[i] + -- offset); -+ /* 32 bits */ -+ iq_res[idx] = REG_READ(ah, -+ chan_info_tab[i] + -+ offset); - -- REG_RMW_FIELD(ah, -+ REG_RMW_FIELD(ah, - AR_PHY_CHAN_INFO_MEMORY, - AR_PHY_CHAN_INFO_TAB_S2_READ, - 1); - -- /* 16 bits */ -- iq_res[idx + 1] = 0xffff & REG_READ(ah, -- chan_info_tab[i] + offset); -- -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "IQ RES[%d]=0x%x" -- "IQ_RES[%d]=0x%x\n", -- idx, iq_res[idx], idx + 1, -- iq_res[idx + 1]); -- } -+ /* 16 bits */ -+ iq_res[idx + 1] = 0xffff & REG_READ(ah, -+ chan_info_tab[i] + offset); - -- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -- coeff.iqc_coeff)) { -- ath_dbg(common, ATH_DBG_CALIBRATE, -- "Failed in calculation of IQ correction.\n"); -- goto tx_iqcal_fail; -- } -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "IQ RES[%d]=0x%x" -+ "IQ_RES[%d]=0x%x\n", -+ idx, iq_res[idx], idx + 1, -+ iq_res[idx + 1]); -+ } - -- coeff.mag_coeff[i][im][ip] = -- coeff.iqc_coeff[0] & 0x7f; -- coeff.phs_coeff[i][im][ip] = -- (coeff.iqc_coeff[0] >> 7) & 0x7f; -- -- if (coeff.mag_coeff[i][im][ip] > 63) -- coeff.mag_coeff[i][im][ip] -= 128; -- if (coeff.phs_coeff[i][im][ip] > 63) -- coeff.phs_coeff[i][im][ip] -= 128; -+ if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, -+ coeff.iqc_coeff)) { -+ ath_dbg(common, ATH_DBG_CALIBRATE, -+ "Failed in calculation of \ -+ IQ correction.\n"); -+ goto tx_iqcal_fail; - } -+ -+ coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; -+ coeff.phs_coeff[i][im] = -+ (coeff.iqc_coeff[0] >> 7) & 0x7f; -+ -+ if (coeff.mag_coeff[i][im] > 63) -+ coeff.mag_coeff[i][im] -= 128; -+ if (coeff.phs_coeff[i][im] > 63) -+ coeff.phs_coeff[i][im] -= 128; - } - } - ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); -@@ -940,31 +839,37 @@ - struct ath9k_channel *chan) - { - struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_hw_capabilities *pCap = &ah->caps; - int val; -+ bool txiqcal_done = false; - - val = REG_READ(ah, AR_ENT_OTP); - ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); - -- if (AR_SREV_9485(ah)) -- ar9003_hw_set_chain_masks(ah, 0x1, 0x1); -- else if (val & AR_ENT_OTP_CHAIN2_DISABLE) -+ /* Configure rx/tx chains before running AGC/TxiQ cals */ -+ if (val & AR_ENT_OTP_CHAIN2_DISABLE) - ar9003_hw_set_chain_masks(ah, 0x3, 0x3); - else -- /* -- * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain -- * mode before running AGC/TxIQ cals -- */ -- ar9003_hw_set_chain_masks(ah, 0x7, 0x7); -+ ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, -+ pCap->tx_chainmask); - - /* Do Tx IQ Calibration */ -- if (AR_SREV_9485(ah)) -- ar9003_hw_tx_iq_cal_run(ah); -- else -- ar9003_hw_tx_iq_cal(ah); -+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, -+ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, -+ DELPT); - -- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -- udelay(5); -- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); -+ /* -+ * For AR9485 or later chips, TxIQ cal runs as part of -+ * AGC calibration -+ */ -+ if (AR_SREV_9485_OR_LATER(ah)) -+ txiqcal_done = true; -+ else { -+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -+ udelay(5); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); -+ } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, -@@ -979,7 +884,7 @@ - return false; - } - -- if (AR_SREV_9485(ah)) -+ if (txiqcal_done) - ar9003_hw_tx_iq_cal_post_proc(ah); - - /* Revert chainmasks to their original values before NF cal */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c 2011-05-05 23:29:49.096485493 +0200 -@@ -3217,7 +3217,6 @@ - u8 *word, int length, int mdata_size) - { - struct ath_common *common = ath9k_hw_common(ah); -- u8 *dptr; - const struct ar9300_eeprom *eep = NULL; - - switch (code) { -@@ -3235,7 +3234,6 @@ - break; - case _CompressBlock: - if (reference == 0) { -- dptr = mptr; - } else { - eep = ar9003_eeprom_struct_find_by_id(reference); - if (eep == NULL) { -@@ -3448,9 +3446,13 @@ - REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); - else { - REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); -- REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, -- bias >> 2); -- REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); -+ if (!AR_SREV_9340(ah)) { -+ REG_RMW_FIELD(ah, AR_CH0_THERM, -+ AR_CH0_THERM_XPABIASLVL_MSB, -+ bias >> 2); -+ REG_RMW_FIELD(ah, AR_CH0_THERM, -+ AR_CH0_THERM_XPASHORT2GND, 1); -+ } - } - } - -@@ -3497,23 +3499,28 @@ - - static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) - { -+ int chain; -+ static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { -+ AR_PHY_SWITCH_CHAIN_0, -+ AR_PHY_SWITCH_CHAIN_1, -+ AR_PHY_SWITCH_CHAIN_2, -+ }; -+ - u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); -+ - REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); - - value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); - -- value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); -- REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); -- -- if (!AR_SREV_9485(ah)) { -- value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); -- REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, -- value); -- -- value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); -- REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, -- value); -+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { -+ if ((ah->rxchainmask & BIT(chain)) || -+ (ah->txchainmask & BIT(chain))) { -+ value = ar9003_hw_ant_ctrl_chain_get(ah, chain, -+ is2ghz); -+ REG_RMW_FIELD(ah, switch_chain_reg[chain], -+ AR_SWITCH_TABLE_ALL, value); -+ } - } - - if (AR_SREV_9485(ah)) { -@@ -3634,13 +3641,16 @@ - - /* Test value. if 0 then attenuation is unused. Don't load anything. */ - for (i = 0; i < 3; i++) { -- value = ar9003_hw_atten_chain_get(ah, i, chan); -- REG_RMW_FIELD(ah, ext_atten_reg[i], -- AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); -- -- value = ar9003_hw_atten_chain_get_margin(ah, i, chan); -- REG_RMW_FIELD(ah, ext_atten_reg[i], -- AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); -+ if (ah->txchainmask & BIT(i)) { -+ value = ar9003_hw_atten_chain_get(ah, i, chan); -+ REG_RMW_FIELD(ah, ext_atten_reg[i], -+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); -+ -+ value = ar9003_hw_atten_chain_get_margin(ah, i, chan); -+ REG_RMW_FIELD(ah, ext_atten_reg[i], -+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, -+ value); -+ } - } - } - -@@ -3749,8 +3759,9 @@ - ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); - ar9003_hw_drive_strength_apply(ah); - ar9003_hw_atten_apply(ah, chan); -- ar9003_hw_internal_regulator_apply(ah); -- if (AR_SREV_9485(ah)) -+ if (!AR_SREV_9340(ah)) -+ ar9003_hw_internal_regulator_apply(ah); -+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) - ar9003_hw_apply_tuning_caps(ah); - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_hw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_hw.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_hw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_hw.c 2011-05-05 23:29:49.044484865 +0200 -@@ -18,6 +18,7 @@ - #include "ar9003_mac.h" - #include "ar9003_2p2_initvals.h" - #include "ar9485_initvals.h" -+#include "ar9340_initvals.h" - - /* General hardware code for the AR9003 hadware family */ - -@@ -28,109 +29,105 @@ - */ - static void ar9003_hw_init_mode_regs(struct ath_hw *ah) - { -- if (AR_SREV_9485_11(ah)) { -+ if (AR_SREV_9340(ah)) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], -- ar9485_1_1_mac_core, -- ARRAY_SIZE(ar9485_1_1_mac_core), 2); -+ ar9340_1p0_mac_core, -+ ARRAY_SIZE(ar9340_1p0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], -- ar9485_1_1_mac_postamble, -- ARRAY_SIZE(ar9485_1_1_mac_postamble), 5); -+ ar9340_1p0_mac_postamble, -+ ARRAY_SIZE(ar9340_1p0_mac_postamble), 5); - - /* bb */ -- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1, -- ARRAY_SIZE(ar9485_1_1), 2); -+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], -- ar9485_1_1_baseband_core, -- ARRAY_SIZE(ar9485_1_1_baseband_core), 2); -+ ar9340_1p0_baseband_core, -+ ARRAY_SIZE(ar9340_1p0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], -- ar9485_1_1_baseband_postamble, -- ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5); -+ ar9340_1p0_baseband_postamble, -+ ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], -- ar9485_1_1_radio_core, -- ARRAY_SIZE(ar9485_1_1_radio_core), 2); -+ ar9340_1p0_radio_core, -+ ARRAY_SIZE(ar9340_1p0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], -- ar9485_1_1_radio_postamble, -- ARRAY_SIZE(ar9485_1_1_radio_postamble), 2); -+ ar9340_1p0_radio_postamble, -+ ARRAY_SIZE(ar9340_1p0_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], -- ar9485_1_1_soc_preamble, -- ARRAY_SIZE(ar9485_1_1_soc_preamble), 2); -+ ar9340_1p0_soc_preamble, -+ ARRAY_SIZE(ar9340_1p0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); -- INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); -+ INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], -+ ar9340_1p0_soc_postamble, -+ ARRAY_SIZE(ar9340_1p0_soc_postamble), 5); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485_common_rx_gain_1_1, -- ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2); -+ ar9340Common_wo_xlna_rx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), -+ 5); - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485_modes_lowest_ob_db_tx_gain_1_1, -- ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), -+ ar9340Modes_high_ob_db_tx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0), - 5); - -- /* Load PCIE SERDES settings from INI */ -- -- /* Awake Setting */ -- -- INIT_INI_ARRAY(&ah->iniPcieSerdes, -- ar9485_1_1_pcie_phy_clkreq_disable_L1, -- ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), -- 2); -- -- /* Sleep Setting */ -+ INIT_INI_ARRAY(&ah->iniModesAdditional, -+ ar9340Modes_fast_clock_1p0, -+ ARRAY_SIZE(ar9340Modes_fast_clock_1p0), -+ 3); - -- INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, -- ar9485_1_1_pcie_phy_clkreq_disable_L1, -- ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), -+ INIT_INI_ARRAY(&ah->iniModesAdditional_40M, -+ ar9340_1p0_radio_core_40M, -+ ARRAY_SIZE(ar9340_1p0_radio_core_40M), - 2); -- } else if (AR_SREV_9485(ah)) { -+ } else if (AR_SREV_9485_11(ah)) { - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], -- ar9485_1_0_mac_core, -- ARRAY_SIZE(ar9485_1_0_mac_core), 2); -+ ar9485_1_1_mac_core, -+ ARRAY_SIZE(ar9485_1_1_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], -- ar9485_1_0_mac_postamble, -- ARRAY_SIZE(ar9485_1_0_mac_postamble), 5); -+ ar9485_1_1_mac_postamble, -+ ARRAY_SIZE(ar9485_1_1_mac_postamble), 5); - - /* bb */ -- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0, -- ARRAY_SIZE(ar9485_1_0), 2); -+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1, -+ ARRAY_SIZE(ar9485_1_1), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], -- ar9485_1_0_baseband_core, -- ARRAY_SIZE(ar9485_1_0_baseband_core), 2); -+ ar9485_1_1_baseband_core, -+ ARRAY_SIZE(ar9485_1_1_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], -- ar9485_1_0_baseband_postamble, -- ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5); -+ ar9485_1_1_baseband_postamble, -+ ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], -- ar9485_1_0_radio_core, -- ARRAY_SIZE(ar9485_1_0_radio_core), 2); -+ ar9485_1_1_radio_core, -+ ARRAY_SIZE(ar9485_1_1_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], -- ar9485_1_0_radio_postamble, -- ARRAY_SIZE(ar9485_1_0_radio_postamble), 2); -+ ar9485_1_1_radio_postamble, -+ ARRAY_SIZE(ar9485_1_1_radio_postamble), 2); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], -- ar9485_1_0_soc_preamble, -- ARRAY_SIZE(ar9485_1_0_soc_preamble), 2); -+ ar9485_1_1_soc_preamble, -+ ARRAY_SIZE(ar9485_1_1_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485Common_rx_gain_1_0, -- ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2); -+ ar9485Common_wo_xlna_rx_gain_1_1, -+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_lowest_ob_db_tx_gain_1_0, -- ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), -+ ar9485_modes_lowest_ob_db_tx_gain_1_1, -+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), - 5); - - /* Load PCIE SERDES settings from INI */ -@@ -138,15 +135,15 @@ - /* Awake Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdes, -- ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, -- ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), -+ ar9485_1_1_pcie_phy_clkreq_disable_L1, -+ ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), - 2); - - /* Sleep Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, -- ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1, -- ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1), -+ ar9485_1_1_pcie_phy_clkreq_disable_L1, -+ ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), - 2); - } else { - /* mac */ -@@ -223,15 +220,15 @@ - switch (ar9003_hw_get_tx_gain_idx(ah)) { - case 0: - default: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485_modes_lowest_ob_db_tx_gain_1_1, -- ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), -+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_lowest_ob_db_tx_gain_1_0, -- ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0), -+ ar9485_modes_lowest_ob_db_tx_gain_1_1, -+ ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, -@@ -240,15 +237,15 @@ - 5); - break; - case 1: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_high_ob_db_tx_gain_1_1, -- ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), -+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_high_ob_db_tx_gain_1_0, -- ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0), -+ ar9485Modes_high_ob_db_tx_gain_1_1, -+ ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, -@@ -257,15 +254,15 @@ - 5); - break; - case 2: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_low_ob_db_tx_gain_1_1, -- ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), -+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_low_ob_db_tx_gain_1_0, -- ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0), -+ ar9485Modes_low_ob_db_tx_gain_1_1, -+ ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, -@@ -274,15 +271,15 @@ - 5); - break; - case 3: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_high_power_tx_gain_1_1, -- ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), -+ ar9340Modes_lowest_ob_db_tx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), - 5); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, -- ar9485Modes_high_power_tx_gain_1_0, -- ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0), -+ ar9485Modes_high_power_tx_gain_1_1, -+ ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, -@@ -298,15 +295,15 @@ - switch (ar9003_hw_get_rx_gain_idx(ah)) { - case 0: - default: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485_common_rx_gain_1_1, -- ARRAY_SIZE(ar9485_common_rx_gain_1_1), -+ ar9340Common_rx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Common_rx_gain_table_1p0), - 2); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485Common_rx_gain_1_0, -- ARRAY_SIZE(ar9485Common_rx_gain_1_0), -+ ar9485Common_wo_xlna_rx_gain_1_1, -+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), - 2); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, -@@ -315,15 +312,15 @@ - 2); - break; - case 1: -- if (AR_SREV_9485_11(ah)) -+ if (AR_SREV_9340(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485Common_wo_xlna_rx_gain_1_1, -- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), -+ ar9340Common_wo_xlna_rx_gain_table_1p0, -+ ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), - 2); -- else if (AR_SREV_9485(ah)) -+ else if (AR_SREV_9485_11(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, -- ar9485Common_wo_xlna_rx_gain_1_0, -- ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0), -+ ar9485Common_wo_xlna_rx_gain_1_1, -+ ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), - 2); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_mac.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_mac.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_mac.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_mac.c 2011-05-05 23:29:49.081485313 +0200 -@@ -329,7 +329,6 @@ - | (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 @@ - 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, -@@ -485,17 +494,6 @@ - - } - --static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, -- u32 vmf) --{ -- struct ar9003_txc *ads = (struct ar9003_txc *) ds; -- -- if (vmf) -- ads->ctl11 |= AR_VirtMoreFrag; -- else -- ads->ctl11 &= ~AR_VirtMoreFrag; --} -- - void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) - { - struct ar9003_txc *ads = ds; -@@ -521,7 +519,7 @@ - ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; - ops->clr11n_aggr = ar9003_hw_clr11n_aggr; - ops->set11n_burstduration = ar9003_hw_set11n_burstduration; -- ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; -+ ops->set_clrdmask = ar9003_hw_set_clrdmask; - } - - void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_phy.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_phy.c 2011-05-05 23:29:49.076485252 +0200 -@@ -75,16 +75,42 @@ - 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 if (AR_SREV_9340(ah)) { -+ if (ah->is_clk_25mhz) { -+ u32 chan_frac; -+ -+ channelSel = (freq * 2) / 75; -+ chan_frac = (((freq * 2) % 75) * 0x20000) / 75; -+ channelSel = (channelSel << 17) | chan_frac; -+ } else -+ channelSel = CHANSEL_2G(freq) >> 1; -+ } else - channelSel = CHANSEL_2G(freq); - /* Set to 2G mode */ - bMode = 1; - } else { -- channelSel = CHANSEL_5G(freq); -- /* Doubler is ON, so, divide channelSel by 2. */ -- channelSel >>= 1; -+ if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { -+ u32 chan_frac; -+ -+ channelSel = (freq * 2) / 75; -+ chan_frac = ((freq % 75) * 0x20000) / 75; -+ channelSel = (channelSel << 17) | chan_frac; -+ } else { -+ channelSel = CHANSEL_5G(freq); -+ /* Doubler is ON, so, divide channelSel by 2. */ -+ channelSel >>= 1; -+ } - /* Set to 5G mode */ - bMode = 0; - } -@@ -142,7 +168,7 @@ - * is out-of-band and can be ignored. - */ - -- if (AR_SREV_9485(ah)) { -+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) { - spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, - IS_CHAN_2GHZ(chan)); - if (spur_fbin_ptr[0] == 0) /* No spur */ -@@ -167,7 +193,7 @@ - - for (i = 0; i < max_spur_cnts; i++) { - negative = 0; -- if (AR_SREV_9485(ah)) -+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) - cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], - IS_CHAN_2GHZ(chan)) - synth_freq; - else -@@ -401,7 +427,7 @@ - - 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); -@@ -590,29 +616,25 @@ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - unsigned int regWrites = 0, i; - struct ieee80211_channel *channel = chan->chan; -- u32 modesIndex, freqIndex; -+ u32 modesIndex; - - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - modesIndex = 1; -- freqIndex = 1; - break; - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - modesIndex = 2; -- freqIndex = 1; - break; - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_B: - modesIndex = 4; -- freqIndex = 2; - break; - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - modesIndex = 3; -- freqIndex = 2; - break; - - default: -@@ -637,6 +659,9 @@ - REG_WRITE_ARRAY(&ah->iniModesAdditional, - modesIndex, regWrites); - -+ if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) -+ REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); -+ - ar9003_hw_override_ini(ah); - ar9003_hw_set_channel_regs(ah, chan); - ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9003_phy.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9003_phy.h 2011-05-05 23:29:49.097485505 +0200 -@@ -548,15 +548,12 @@ - - #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) - --#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) --#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 --#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 --#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) --#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) -- --#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) --#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) --#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) -+#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3c8 : 0x448) -+#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3c4 : 0x440) -+#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ -+ 0x3f0 : 0x48c) - #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ - (AR_SREV_9485(ah) ? \ - 0x3d0 : 0x450) + ((_i) << 2)) -@@ -588,7 +585,7 @@ - #define AR_PHY_65NM_CH0_BIAS2 0x160c4 - #define AR_PHY_65NM_CH0_BIAS4 0x160cc - #define AR_PHY_65NM_CH0_RXTX4 0x1610c --#define AR_PHY_65NM_CH0_THERM (AR_SREV_9485(ah) ? 0x1628c : 0x16290) -+#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c) - - #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 - #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 -@@ -758,10 +755,10 @@ - #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 - #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 - #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 --#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 --#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 --#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 --#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 -+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 -+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 -+#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 -+#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 - - #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 - #define AR_PHY_CALIBRATED_GAINS_0 0x3e -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9340_initvals.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9340_initvals.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9340_initvals.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9340_initvals.h 2011-05-05 23:29:49.092485445 +0200 -@@ -0,0 +1,1525 @@ -+/* -+ * Copyright (c) 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. -+ */ -+ -+#ifndef INITVALS_9340_H -+#define INITVALS_9340_H -+ -+static const u32 ar9340_1p0_radio_postamble[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, -+ {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, -+ {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, -+ {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, -+ {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, -+}; -+ -+static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, -+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, -+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, -+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, -+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, -+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, -+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, -+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, -+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, -+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, -+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, -+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, -+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, -+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, -+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, -+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, -+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, -+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, -+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, -+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, -+ {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, -+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, -+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, -+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, -+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, -+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, -+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, -+ {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, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, -+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, -+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, -+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, -+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, -+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, -+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+}; -+ -+static const u32 ar9340Modes_fast_clock_1p0[][3] = { -+ /* Addr 5G_HT20 5G_HT40 */ -+ {0x00001030, 0x00000268, 0x000004d0}, -+ {0x00001070, 0x0000018c, 0x00000318}, -+ {0x000010b0, 0x00000fd0, 0x00001fa0}, -+ {0x00008014, 0x044c044c, 0x08980898}, -+ {0x0000801c, 0x148ec02b, 0x148ec057}, -+ {0x00008318, 0x000044c0, 0x00008980}, -+ {0x00009e00, 0x03721821, 0x03721821}, -+ {0x0000a230, 0x0000000b, 0x00000016}, -+ {0x0000a254, 0x00000898, 0x00001130}, -+}; -+ -+static const u32 ar9340_1p0_radio_core[][2] = { -+ /* Addr allmodes */ -+ {0x00016000, 0x36db6db6}, -+ {0x00016004, 0x6db6db40}, -+ {0x00016008, 0x73f00000}, -+ {0x0001600c, 0x00000000}, -+ {0x00016040, 0x7f80fff8}, -+ {0x00016044, 0x03b6d2db}, -+ {0x00016048, 0x24925266}, -+ {0x0001604c, 0x000f0278}, -+ {0x00016050, 0x6db6db6c}, -+ {0x00016054, 0x6db60000}, -+ {0x00016080, 0x00080000}, -+ {0x00016084, 0x0e48048c}, -+ {0x00016088, 0x14214514}, -+ {0x0001608c, 0x119f081c}, -+ {0x00016090, 0x24926490}, -+ {0x00016094, 0x00000000}, -+ {0x00016098, 0xd411eb84}, -+ {0x0001609c, 0x03e47f32}, -+ {0x000160a0, 0xc2108ffe}, -+ {0x000160a4, 0x812fc370}, -+ {0x000160a8, 0x423c8000}, -+ {0x000160ac, 0xa4646800}, -+ {0x000160b0, 0x00fe7f46}, -+ {0x000160b4, 0x92480000}, -+ {0x000160c0, 0x006db6db}, -+ {0x000160c4, 0x6db6db60}, -+ {0x000160c8, 0x6db6db6c}, -+ {0x000160cc, 0x6de6db6c}, -+ {0x000160d0, 0xb6da4924}, -+ {0x00016100, 0x04cb0001}, -+ {0x00016104, 0xfff80000}, -+ {0x00016108, 0x00080010}, -+ {0x0001610c, 0x00000000}, -+ {0x00016140, 0x50804008}, -+ {0x00016144, 0x01884080}, -+ {0x00016148, 0x000080c0}, -+ {0x00016280, 0x01000015}, -+ {0x00016284, 0x05530000}, -+ {0x00016288, 0x00318000}, -+ {0x0001628c, 0x50000000}, -+ {0x00016290, 0x4080294f}, -+ {0x00016380, 0x00000000}, -+ {0x00016384, 0x00000000}, -+ {0x00016388, 0x00800700}, -+ {0x0001638c, 0x00800700}, -+ {0x00016390, 0x00800700}, -+ {0x00016394, 0x00000000}, -+ {0x00016398, 0x00000000}, -+ {0x0001639c, 0x00000000}, -+ {0x000163a0, 0x00000001}, -+ {0x000163a4, 0x00000001}, -+ {0x000163a8, 0x00000000}, -+ {0x000163ac, 0x00000000}, -+ {0x000163b0, 0x00000000}, -+ {0x000163b4, 0x00000000}, -+ {0x000163b8, 0x00000000}, -+ {0x000163bc, 0x00000000}, -+ {0x000163c0, 0x000000a0}, -+ {0x000163c4, 0x000c0000}, -+ {0x000163c8, 0x14021402}, -+ {0x000163cc, 0x00001402}, -+ {0x000163d0, 0x00000000}, -+ {0x000163d4, 0x00000000}, -+ {0x00016400, 0x36db6db6}, -+ {0x00016404, 0x6db6db40}, -+ {0x00016408, 0x73f00000}, -+ {0x0001640c, 0x00000000}, -+ {0x00016440, 0x7f80fff8}, -+ {0x00016444, 0x03b6d2db}, -+ {0x00016448, 0x24927266}, -+ {0x0001644c, 0x000f0278}, -+ {0x00016450, 0x6db6db6c}, -+ {0x00016454, 0x6db60000}, -+ {0x00016500, 0x04cb0001}, -+ {0x00016504, 0xfff80000}, -+ {0x00016508, 0x00080010}, -+ {0x0001650c, 0x00000000}, -+ {0x00016540, 0x50804008}, -+ {0x00016544, 0x01884080}, -+ {0x00016548, 0x000080c0}, -+ {0x00016780, 0x00000000}, -+ {0x00016784, 0x00000000}, -+ {0x00016788, 0x00800700}, -+ {0x0001678c, 0x00800700}, -+ {0x00016790, 0x00800700}, -+ {0x00016794, 0x00000000}, -+ {0x00016798, 0x00000000}, -+ {0x0001679c, 0x00000000}, -+ {0x000167a0, 0x00000001}, -+ {0x000167a4, 0x00000001}, -+ {0x000167a8, 0x00000000}, -+ {0x000167ac, 0x00000000}, -+ {0x000167b0, 0x00000000}, -+ {0x000167b4, 0x00000000}, -+ {0x000167b8, 0x00000000}, -+ {0x000167bc, 0x00000000}, -+ {0x000167c0, 0x000000a0}, -+ {0x000167c4, 0x000c0000}, -+ {0x000167c8, 0x14021402}, -+ {0x000167cc, 0x00001402}, -+ {0x000167d0, 0x00000000}, -+ {0x000167d4, 0x00000000}, -+}; -+ -+static const u32 ar9340_1p0_radio_core_40M[][2] = { -+ {0x0001609c, 0x02566f3a}, -+ {0x000160ac, 0xa4647c00}, -+ {0x000160b0, 0x01885f5a}, -+}; -+ -+static const u32 ar9340_1p0_mac_postamble[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, -+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, -+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, -+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, -+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, -+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, -+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, -+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -+}; -+ -+static const u32 ar9340_1p0_soc_postamble[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -+}; -+ -+static const u32 ar9340_1p0_baseband_postamble[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, -+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, -+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, -+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, -+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, -+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, -+ {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, -+ {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, -+ {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, -+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, -+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e}, -+ {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, -+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, -+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, -+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, -+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, -+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, -+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, -+ {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, -+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, -+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, -+ {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, -+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, -+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, -+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, -+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, -+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, -+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, -+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, -+ {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, -+ {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, -+ {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, -+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, -+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, -+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, -+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, -+ {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000}, -+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, -+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, -+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, -+}; -+ -+static const u32 ar9340_1p0_baseband_core[][2] = { -+ /* Addr allmodes */ -+ {0x00009800, 0xafe68e30}, -+ {0x00009804, 0xfd14e000}, -+ {0x00009808, 0x9c0a9f6b}, -+ {0x0000980c, 0x04900000}, -+ {0x00009814, 0xb280c00a}, -+ {0x00009818, 0x00000000}, -+ {0x0000981c, 0x00020028}, -+ {0x00009834, 0x5f3ca3de}, -+ {0x00009838, 0x0108ecff}, -+ {0x0000983c, 0x14750600}, -+ {0x00009880, 0x201fff00}, -+ {0x00009884, 0x00001042}, -+ {0x000098a4, 0x00200400}, -+ {0x000098b0, 0x52440bbe}, -+ {0x000098d0, 0x004b6a8e}, -+ {0x000098d4, 0x00000820}, -+ {0x000098dc, 0x00000000}, -+ {0x000098f0, 0x00000000}, -+ {0x000098f4, 0x00000000}, -+ {0x00009c04, 0xff55ff55}, -+ {0x00009c08, 0x0320ff55}, -+ {0x00009c0c, 0x00000000}, -+ {0x00009c10, 0x00000000}, -+ {0x00009c14, 0x00046384}, -+ {0x00009c18, 0x05b6b440}, -+ {0x00009c1c, 0x00b6b440}, -+ {0x00009d00, 0xc080a333}, -+ {0x00009d04, 0x40206c10}, -+ {0x00009d08, 0x009c4060}, -+ {0x00009d0c, 0x9883800a}, -+ {0x00009d10, 0x01834061}, -+ {0x00009d14, 0x00c0040b}, -+ {0x00009d18, 0x00000000}, -+ {0x00009e08, 0x0038230c}, -+ {0x00009e24, 0x990bb515}, -+ {0x00009e28, 0x0c6f0000}, -+ {0x00009e30, 0x06336f77}, -+ {0x00009e34, 0x6af6532f}, -+ {0x00009e38, 0x0cc80c00}, -+ {0x00009e3c, 0xcf946222}, -+ {0x00009e40, 0x0d261820}, -+ {0x00009e4c, 0x00001004}, -+ {0x00009e50, 0x00ff03f1}, -+ {0x00009e54, 0x00000000}, -+ {0x00009fc0, 0x803e4788}, -+ {0x00009fc4, 0x0001efb5}, -+ {0x00009fcc, 0x40000014}, -+ {0x00009fd0, 0x01193b93}, -+ {0x0000a20c, 0x00000000}, -+ {0x0000a220, 0x00000000}, -+ {0x0000a224, 0x00000000}, -+ {0x0000a228, 0x10002310}, -+ {0x0000a22c, 0x01036a1e}, -+ {0x0000a234, 0x10000fff}, -+ {0x0000a23c, 0x00000000}, -+ {0x0000a244, 0x0c000000}, -+ {0x0000a2a0, 0x00000001}, -+ {0x0000a2c0, 0x00000001}, -+ {0x0000a2c8, 0x00000000}, -+ {0x0000a2cc, 0x18c43433}, -+ {0x0000a2d4, 0x00000000}, -+ {0x0000a2dc, 0x00000000}, -+ {0x0000a2e0, 0x00000000}, -+ {0x0000a2e4, 0x00000000}, -+ {0x0000a2e8, 0x00000000}, -+ {0x0000a2ec, 0x00000000}, -+ {0x0000a2f0, 0x00000000}, -+ {0x0000a2f4, 0x00000000}, -+ {0x0000a2f8, 0x00000000}, -+ {0x0000a344, 0x00000000}, -+ {0x0000a34c, 0x00000000}, -+ {0x0000a350, 0x0000a000}, -+ {0x0000a364, 0x00000000}, -+ {0x0000a370, 0x00000000}, -+ {0x0000a390, 0x00000001}, -+ {0x0000a394, 0x00000444}, -+ {0x0000a398, 0x001f0e0f}, -+ {0x0000a39c, 0x0075393f}, -+ {0x0000a3a0, 0xb79f6427}, -+ {0x0000a3a4, 0x00000000}, -+ {0x0000a3a8, 0xaaaaaaaa}, -+ {0x0000a3ac, 0x3c466478}, -+ {0x0000a3c0, 0x20202020}, -+ {0x0000a3c4, 0x22222220}, -+ {0x0000a3c8, 0x20200020}, -+ {0x0000a3cc, 0x20202020}, -+ {0x0000a3d0, 0x20202020}, -+ {0x0000a3d4, 0x20202020}, -+ {0x0000a3d8, 0x20202020}, -+ {0x0000a3dc, 0x20202020}, -+ {0x0000a3e0, 0x20202020}, -+ {0x0000a3e4, 0x20202020}, -+ {0x0000a3e8, 0x20202020}, -+ {0x0000a3ec, 0x20202020}, -+ {0x0000a3f0, 0x00000000}, -+ {0x0000a3f4, 0x00000246}, -+ {0x0000a3f8, 0x0cdbd380}, -+ {0x0000a3fc, 0x000f0f01}, -+ {0x0000a400, 0x8fa91f01}, -+ {0x0000a404, 0x00000000}, -+ {0x0000a408, 0x0e79e5c6}, -+ {0x0000a40c, 0x00820820}, -+ {0x0000a414, 0x1ce739ce}, -+ {0x0000a418, 0x2d001dce}, -+ {0x0000a41c, 0x1ce739ce}, -+ {0x0000a420, 0x000001ce}, -+ {0x0000a424, 0x1ce739ce}, -+ {0x0000a428, 0x000001ce}, -+ {0x0000a42c, 0x1ce739ce}, -+ {0x0000a430, 0x1ce739ce}, -+ {0x0000a434, 0x00000000}, -+ {0x0000a438, 0x00001801}, -+ {0x0000a43c, 0x00000000}, -+ {0x0000a440, 0x00000000}, -+ {0x0000a444, 0x00000000}, -+ {0x0000a448, 0x04000080}, -+ {0x0000a44c, 0x00000001}, -+ {0x0000a450, 0x00010000}, -+ {0x0000a458, 0x00000000}, -+ {0x0000a600, 0x00000000}, -+ {0x0000a604, 0x00000000}, -+ {0x0000a608, 0x00000000}, -+ {0x0000a60c, 0x00000000}, -+ {0x0000a610, 0x00000000}, -+ {0x0000a614, 0x00000000}, -+ {0x0000a618, 0x00000000}, -+ {0x0000a61c, 0x00000000}, -+ {0x0000a620, 0x00000000}, -+ {0x0000a624, 0x00000000}, -+ {0x0000a628, 0x00000000}, -+ {0x0000a62c, 0x00000000}, -+ {0x0000a630, 0x00000000}, -+ {0x0000a634, 0x00000000}, -+ {0x0000a638, 0x00000000}, -+ {0x0000a63c, 0x00000000}, -+ {0x0000a640, 0x00000000}, -+ {0x0000a644, 0x3fad9d74}, -+ {0x0000a648, 0x0048060a}, -+ {0x0000a64c, 0x00000637}, -+ {0x0000a670, 0x03020100}, -+ {0x0000a674, 0x09080504}, -+ {0x0000a678, 0x0d0c0b0a}, -+ {0x0000a67c, 0x13121110}, -+ {0x0000a680, 0x31301514}, -+ {0x0000a684, 0x35343332}, -+ {0x0000a688, 0x00000036}, -+ {0x0000a690, 0x00000838}, -+ {0x0000a7c0, 0x00000000}, -+ {0x0000a7c4, 0xfffffffc}, -+ {0x0000a7c8, 0x00000000}, -+ {0x0000a7cc, 0x00000000}, -+ {0x0000a7d0, 0x00000000}, -+ {0x0000a7d4, 0x00000004}, -+ {0x0000a7dc, 0x00000000}, -+ {0x0000a8d0, 0x004b6a8e}, -+ {0x0000a8d4, 0x00000820}, -+ {0x0000a8dc, 0x00000000}, -+ {0x0000a8f0, 0x00000000}, -+ {0x0000a8f4, 0x00000000}, -+ {0x0000b2d0, 0x00000080}, -+ {0x0000b2d4, 0x00000000}, -+ {0x0000b2dc, 0x00000000}, -+ {0x0000b2e0, 0x00000000}, -+ {0x0000b2e4, 0x00000000}, -+ {0x0000b2e8, 0x00000000}, -+ {0x0000b2ec, 0x00000000}, -+ {0x0000b2f0, 0x00000000}, -+ {0x0000b2f4, 0x00000000}, -+ {0x0000b2f8, 0x00000000}, -+ {0x0000b408, 0x0e79e5c0}, -+ {0x0000b40c, 0x00820820}, -+ {0x0000b420, 0x00000000}, -+}; -+ -+static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+}; -+ -+static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, -+ {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, -+}; -+static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, -+ {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, -+ {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, -+ {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, -+ {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, -+}; -+ -+ -+static const u32 ar9340Common_rx_gain_table_1p0[][2] = { -+ /* Addr allmodes */ -+ {0x0000a000, 0x00010000}, -+ {0x0000a004, 0x00030002}, -+ {0x0000a008, 0x00050004}, -+ {0x0000a00c, 0x00810080}, -+ {0x0000a010, 0x00830082}, -+ {0x0000a014, 0x01810180}, -+ {0x0000a018, 0x01830182}, -+ {0x0000a01c, 0x01850184}, -+ {0x0000a020, 0x01890188}, -+ {0x0000a024, 0x018b018a}, -+ {0x0000a028, 0x018d018c}, -+ {0x0000a02c, 0x01910190}, -+ {0x0000a030, 0x01930192}, -+ {0x0000a034, 0x01950194}, -+ {0x0000a038, 0x038a0196}, -+ {0x0000a03c, 0x038c038b}, -+ {0x0000a040, 0x0390038d}, -+ {0x0000a044, 0x03920391}, -+ {0x0000a048, 0x03940393}, -+ {0x0000a04c, 0x03960395}, -+ {0x0000a050, 0x00000000}, -+ {0x0000a054, 0x00000000}, -+ {0x0000a058, 0x00000000}, -+ {0x0000a05c, 0x00000000}, -+ {0x0000a060, 0x00000000}, -+ {0x0000a064, 0x00000000}, -+ {0x0000a068, 0x00000000}, -+ {0x0000a06c, 0x00000000}, -+ {0x0000a070, 0x00000000}, -+ {0x0000a074, 0x00000000}, -+ {0x0000a078, 0x00000000}, -+ {0x0000a07c, 0x00000000}, -+ {0x0000a080, 0x22222229}, -+ {0x0000a084, 0x1d1d1d1d}, -+ {0x0000a088, 0x1d1d1d1d}, -+ {0x0000a08c, 0x1d1d1d1d}, -+ {0x0000a090, 0x171d1d1d}, -+ {0x0000a094, 0x11111717}, -+ {0x0000a098, 0x00030311}, -+ {0x0000a09c, 0x00000000}, -+ {0x0000a0a0, 0x00000000}, -+ {0x0000a0a4, 0x00000000}, -+ {0x0000a0a8, 0x00000000}, -+ {0x0000a0ac, 0x00000000}, -+ {0x0000a0b0, 0x00000000}, -+ {0x0000a0b4, 0x00000000}, -+ {0x0000a0b8, 0x00000000}, -+ {0x0000a0bc, 0x00000000}, -+ {0x0000a0c0, 0x001f0000}, -+ {0x0000a0c4, 0x01000101}, -+ {0x0000a0c8, 0x011e011f}, -+ {0x0000a0cc, 0x011c011d}, -+ {0x0000a0d0, 0x02030204}, -+ {0x0000a0d4, 0x02010202}, -+ {0x0000a0d8, 0x021f0200}, -+ {0x0000a0dc, 0x0302021e}, -+ {0x0000a0e0, 0x03000301}, -+ {0x0000a0e4, 0x031e031f}, -+ {0x0000a0e8, 0x0402031d}, -+ {0x0000a0ec, 0x04000401}, -+ {0x0000a0f0, 0x041e041f}, -+ {0x0000a0f4, 0x0502041d}, -+ {0x0000a0f8, 0x05000501}, -+ {0x0000a0fc, 0x051e051f}, -+ {0x0000a100, 0x06010602}, -+ {0x0000a104, 0x061f0600}, -+ {0x0000a108, 0x061d061e}, -+ {0x0000a10c, 0x07020703}, -+ {0x0000a110, 0x07000701}, -+ {0x0000a114, 0x00000000}, -+ {0x0000a118, 0x00000000}, -+ {0x0000a11c, 0x00000000}, -+ {0x0000a120, 0x00000000}, -+ {0x0000a124, 0x00000000}, -+ {0x0000a128, 0x00000000}, -+ {0x0000a12c, 0x00000000}, -+ {0x0000a130, 0x00000000}, -+ {0x0000a134, 0x00000000}, -+ {0x0000a138, 0x00000000}, -+ {0x0000a13c, 0x00000000}, -+ {0x0000a140, 0x001f0000}, -+ {0x0000a144, 0x01000101}, -+ {0x0000a148, 0x011e011f}, -+ {0x0000a14c, 0x011c011d}, -+ {0x0000a150, 0x02030204}, -+ {0x0000a154, 0x02010202}, -+ {0x0000a158, 0x021f0200}, -+ {0x0000a15c, 0x0302021e}, -+ {0x0000a160, 0x03000301}, -+ {0x0000a164, 0x031e031f}, -+ {0x0000a168, 0x0402031d}, -+ {0x0000a16c, 0x04000401}, -+ {0x0000a170, 0x041e041f}, -+ {0x0000a174, 0x0502041d}, -+ {0x0000a178, 0x05000501}, -+ {0x0000a17c, 0x051e051f}, -+ {0x0000a180, 0x06010602}, -+ {0x0000a184, 0x061f0600}, -+ {0x0000a188, 0x061d061e}, -+ {0x0000a18c, 0x07020703}, -+ {0x0000a190, 0x07000701}, -+ {0x0000a194, 0x00000000}, -+ {0x0000a198, 0x00000000}, -+ {0x0000a19c, 0x00000000}, -+ {0x0000a1a0, 0x00000000}, -+ {0x0000a1a4, 0x00000000}, -+ {0x0000a1a8, 0x00000000}, -+ {0x0000a1ac, 0x00000000}, -+ {0x0000a1b0, 0x00000000}, -+ {0x0000a1b4, 0x00000000}, -+ {0x0000a1b8, 0x00000000}, -+ {0x0000a1bc, 0x00000000}, -+ {0x0000a1c0, 0x00000000}, -+ {0x0000a1c4, 0x00000000}, -+ {0x0000a1c8, 0x00000000}, -+ {0x0000a1cc, 0x00000000}, -+ {0x0000a1d0, 0x00000000}, -+ {0x0000a1d4, 0x00000000}, -+ {0x0000a1d8, 0x00000000}, -+ {0x0000a1dc, 0x00000000}, -+ {0x0000a1e0, 0x00000000}, -+ {0x0000a1e4, 0x00000000}, -+ {0x0000a1e8, 0x00000000}, -+ {0x0000a1ec, 0x00000000}, -+ {0x0000a1f0, 0x00000396}, -+ {0x0000a1f4, 0x00000396}, -+ {0x0000a1f8, 0x00000396}, -+ {0x0000a1fc, 0x00000196}, -+ {0x0000b000, 0x00010000}, -+ {0x0000b004, 0x00030002}, -+ {0x0000b008, 0x00050004}, -+ {0x0000b00c, 0x00810080}, -+ {0x0000b010, 0x00830082}, -+ {0x0000b014, 0x01810180}, -+ {0x0000b018, 0x01830182}, -+ {0x0000b01c, 0x01850184}, -+ {0x0000b020, 0x02810280}, -+ {0x0000b024, 0x02830282}, -+ {0x0000b028, 0x02850284}, -+ {0x0000b02c, 0x02890288}, -+ {0x0000b030, 0x028b028a}, -+ {0x0000b034, 0x0388028c}, -+ {0x0000b038, 0x038a0389}, -+ {0x0000b03c, 0x038c038b}, -+ {0x0000b040, 0x0390038d}, -+ {0x0000b044, 0x03920391}, -+ {0x0000b048, 0x03940393}, -+ {0x0000b04c, 0x03960395}, -+ {0x0000b050, 0x00000000}, -+ {0x0000b054, 0x00000000}, -+ {0x0000b058, 0x00000000}, -+ {0x0000b05c, 0x00000000}, -+ {0x0000b060, 0x00000000}, -+ {0x0000b064, 0x00000000}, -+ {0x0000b068, 0x00000000}, -+ {0x0000b06c, 0x00000000}, -+ {0x0000b070, 0x00000000}, -+ {0x0000b074, 0x00000000}, -+ {0x0000b078, 0x00000000}, -+ {0x0000b07c, 0x00000000}, -+ {0x0000b080, 0x32323232}, -+ {0x0000b084, 0x2f2f3232}, -+ {0x0000b088, 0x23282a2d}, -+ {0x0000b08c, 0x1c1e2123}, -+ {0x0000b090, 0x14171919}, -+ {0x0000b094, 0x0e0e1214}, -+ {0x0000b098, 0x03050707}, -+ {0x0000b09c, 0x00030303}, -+ {0x0000b0a0, 0x00000000}, -+ {0x0000b0a4, 0x00000000}, -+ {0x0000b0a8, 0x00000000}, -+ {0x0000b0ac, 0x00000000}, -+ {0x0000b0b0, 0x00000000}, -+ {0x0000b0b4, 0x00000000}, -+ {0x0000b0b8, 0x00000000}, -+ {0x0000b0bc, 0x00000000}, -+ {0x0000b0c0, 0x003f0020}, -+ {0x0000b0c4, 0x00400041}, -+ {0x0000b0c8, 0x0140005f}, -+ {0x0000b0cc, 0x0160015f}, -+ {0x0000b0d0, 0x017e017f}, -+ {0x0000b0d4, 0x02410242}, -+ {0x0000b0d8, 0x025f0240}, -+ {0x0000b0dc, 0x027f0260}, -+ {0x0000b0e0, 0x0341027e}, -+ {0x0000b0e4, 0x035f0340}, -+ {0x0000b0e8, 0x037f0360}, -+ {0x0000b0ec, 0x04400441}, -+ {0x0000b0f0, 0x0460045f}, -+ {0x0000b0f4, 0x0541047f}, -+ {0x0000b0f8, 0x055f0540}, -+ {0x0000b0fc, 0x057f0560}, -+ {0x0000b100, 0x06400641}, -+ {0x0000b104, 0x0660065f}, -+ {0x0000b108, 0x067e067f}, -+ {0x0000b10c, 0x07410742}, -+ {0x0000b110, 0x075f0740}, -+ {0x0000b114, 0x077f0760}, -+ {0x0000b118, 0x07800781}, -+ {0x0000b11c, 0x07a0079f}, -+ {0x0000b120, 0x07c107bf}, -+ {0x0000b124, 0x000007c0}, -+ {0x0000b128, 0x00000000}, -+ {0x0000b12c, 0x00000000}, -+ {0x0000b130, 0x00000000}, -+ {0x0000b134, 0x00000000}, -+ {0x0000b138, 0x00000000}, -+ {0x0000b13c, 0x00000000}, -+ {0x0000b140, 0x003f0020}, -+ {0x0000b144, 0x00400041}, -+ {0x0000b148, 0x0140005f}, -+ {0x0000b14c, 0x0160015f}, -+ {0x0000b150, 0x017e017f}, -+ {0x0000b154, 0x02410242}, -+ {0x0000b158, 0x025f0240}, -+ {0x0000b15c, 0x027f0260}, -+ {0x0000b160, 0x0341027e}, -+ {0x0000b164, 0x035f0340}, -+ {0x0000b168, 0x037f0360}, -+ {0x0000b16c, 0x04400441}, -+ {0x0000b170, 0x0460045f}, -+ {0x0000b174, 0x0541047f}, -+ {0x0000b178, 0x055f0540}, -+ {0x0000b17c, 0x057f0560}, -+ {0x0000b180, 0x06400641}, -+ {0x0000b184, 0x0660065f}, -+ {0x0000b188, 0x067e067f}, -+ {0x0000b18c, 0x07410742}, -+ {0x0000b190, 0x075f0740}, -+ {0x0000b194, 0x077f0760}, -+ {0x0000b198, 0x07800781}, -+ {0x0000b19c, 0x07a0079f}, -+ {0x0000b1a0, 0x07c107bf}, -+ {0x0000b1a4, 0x000007c0}, -+ {0x0000b1a8, 0x00000000}, -+ {0x0000b1ac, 0x00000000}, -+ {0x0000b1b0, 0x00000000}, -+ {0x0000b1b4, 0x00000000}, -+ {0x0000b1b8, 0x00000000}, -+ {0x0000b1bc, 0x00000000}, -+ {0x0000b1c0, 0x00000000}, -+ {0x0000b1c4, 0x00000000}, -+ {0x0000b1c8, 0x00000000}, -+ {0x0000b1cc, 0x00000000}, -+ {0x0000b1d0, 0x00000000}, -+ {0x0000b1d4, 0x00000000}, -+ {0x0000b1d8, 0x00000000}, -+ {0x0000b1dc, 0x00000000}, -+ {0x0000b1e0, 0x00000000}, -+ {0x0000b1e4, 0x00000000}, -+ {0x0000b1e8, 0x00000000}, -+ {0x0000b1ec, 0x00000000}, -+ {0x0000b1f0, 0x00000396}, -+ {0x0000b1f4, 0x00000396}, -+ {0x0000b1f8, 0x00000396}, -+ {0x0000b1fc, 0x00000196}, -+}; -+ -+static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, -+ {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, -+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, -+ {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, -+ {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, -+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, -+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, -+ {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, -+ {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, -+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, -+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, -+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, -+ {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, -+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, -+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, -+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, -+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, -+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, -+ {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, -+ {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, -+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, -+ {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, -+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, -+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, -+ {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, -+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, -+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, -+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, -+ {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, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, -+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, -+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, -+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, -+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, -+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, -+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, -+ {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+ {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, -+ {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, -+}; -+ -+static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266}, -+ {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266}, -+}; -+ -+static const u32 ar9340_1p0_mac_core[][2] = { -+ /* Addr allmodes */ -+ {0x00000008, 0x00000000}, -+ {0x00000030, 0x00020085}, -+ {0x00000034, 0x00000005}, -+ {0x00000040, 0x00000000}, -+ {0x00000044, 0x00000000}, -+ {0x00000048, 0x00000008}, -+ {0x0000004c, 0x00000010}, -+ {0x00000050, 0x00000000}, -+ {0x00001040, 0x002ffc0f}, -+ {0x00001044, 0x002ffc0f}, -+ {0x00001048, 0x002ffc0f}, -+ {0x0000104c, 0x002ffc0f}, -+ {0x00001050, 0x002ffc0f}, -+ {0x00001054, 0x002ffc0f}, -+ {0x00001058, 0x002ffc0f}, -+ {0x0000105c, 0x002ffc0f}, -+ {0x00001060, 0x002ffc0f}, -+ {0x00001064, 0x002ffc0f}, -+ {0x000010f0, 0x00000100}, -+ {0x00001270, 0x00000000}, -+ {0x000012b0, 0x00000000}, -+ {0x000012f0, 0x00000000}, -+ {0x0000143c, 0x00000000}, -+ {0x0000147c, 0x00000000}, -+ {0x00008000, 0x00000000}, -+ {0x00008004, 0x00000000}, -+ {0x00008008, 0x00000000}, -+ {0x0000800c, 0x00000000}, -+ {0x00008018, 0x00000000}, -+ {0x00008020, 0x00000000}, -+ {0x00008038, 0x00000000}, -+ {0x0000803c, 0x00000000}, -+ {0x00008040, 0x00000000}, -+ {0x00008044, 0x00000000}, -+ {0x00008048, 0x00000000}, -+ {0x0000804c, 0xffffffff}, -+ {0x00008054, 0x00000000}, -+ {0x00008058, 0x00000000}, -+ {0x0000805c, 0x000fc78f}, -+ {0x00008060, 0x0000000f}, -+ {0x00008064, 0x00000000}, -+ {0x00008070, 0x00000310}, -+ {0x00008074, 0x00000020}, -+ {0x00008078, 0x00000000}, -+ {0x0000809c, 0x0000000f}, -+ {0x000080a0, 0x00000000}, -+ {0x000080a4, 0x02ff0000}, -+ {0x000080a8, 0x0e070605}, -+ {0x000080ac, 0x0000000d}, -+ {0x000080b0, 0x00000000}, -+ {0x000080b4, 0x00000000}, -+ {0x000080b8, 0x00000000}, -+ {0x000080bc, 0x00000000}, -+ {0x000080c0, 0x2a800000}, -+ {0x000080c4, 0x06900168}, -+ {0x000080c8, 0x13881c20}, -+ {0x000080cc, 0x01f40000}, -+ {0x000080d0, 0x00252500}, -+ {0x000080d4, 0x00a00000}, -+ {0x000080d8, 0x00400000}, -+ {0x000080dc, 0x00000000}, -+ {0x000080e0, 0xffffffff}, -+ {0x000080e4, 0x0000ffff}, -+ {0x000080e8, 0x3f3f3f3f}, -+ {0x000080ec, 0x00000000}, -+ {0x000080f0, 0x00000000}, -+ {0x000080f4, 0x00000000}, -+ {0x000080fc, 0x00020000}, -+ {0x00008100, 0x00000000}, -+ {0x00008108, 0x00000052}, -+ {0x0000810c, 0x00000000}, -+ {0x00008110, 0x00000000}, -+ {0x00008114, 0x000007ff}, -+ {0x00008118, 0x000000aa}, -+ {0x0000811c, 0x00003210}, -+ {0x00008124, 0x00000000}, -+ {0x00008128, 0x00000000}, -+ {0x0000812c, 0x00000000}, -+ {0x00008130, 0x00000000}, -+ {0x00008134, 0x00000000}, -+ {0x00008138, 0x00000000}, -+ {0x0000813c, 0x0000ffff}, -+ {0x00008144, 0xffffffff}, -+ {0x00008168, 0x00000000}, -+ {0x0000816c, 0x00000000}, -+ {0x00008170, 0x18486200}, -+ {0x00008174, 0x33332210}, -+ {0x00008178, 0x00000000}, -+ {0x0000817c, 0x00020000}, -+ {0x000081c0, 0x00000000}, -+ {0x000081c4, 0x33332210}, -+ {0x000081c8, 0x00000000}, -+ {0x000081cc, 0x00000000}, -+ {0x000081d4, 0x00000000}, -+ {0x000081ec, 0x00000000}, -+ {0x000081f0, 0x00000000}, -+ {0x000081f4, 0x00000000}, -+ {0x000081f8, 0x00000000}, -+ {0x000081fc, 0x00000000}, -+ {0x00008240, 0x00100000}, -+ {0x00008244, 0x0010f424}, -+ {0x00008248, 0x00000800}, -+ {0x0000824c, 0x0001e848}, -+ {0x00008250, 0x00000000}, -+ {0x00008254, 0x00000000}, -+ {0x00008258, 0x00000000}, -+ {0x0000825c, 0x40000000}, -+ {0x00008260, 0x00080922}, -+ {0x00008264, 0x9d400010}, -+ {0x00008268, 0xffffffff}, -+ {0x0000826c, 0x0000ffff}, -+ {0x00008270, 0x00000000}, -+ {0x00008274, 0x40000000}, -+ {0x00008278, 0x003e4180}, -+ {0x0000827c, 0x00000004}, -+ {0x00008284, 0x0000002c}, -+ {0x00008288, 0x0000002c}, -+ {0x0000828c, 0x000000ff}, -+ {0x00008294, 0x00000000}, -+ {0x00008298, 0x00000000}, -+ {0x0000829c, 0x00000000}, -+ {0x00008300, 0x00000140}, -+ {0x00008314, 0x00000000}, -+ {0x0000831c, 0x0000010d}, -+ {0x00008328, 0x00000000}, -+ {0x0000832c, 0x00000007}, -+ {0x00008330, 0x00000302}, -+ {0x00008334, 0x00000700}, -+ {0x00008338, 0x00ff0000}, -+ {0x0000833c, 0x02400000}, -+ {0x00008340, 0x000107ff}, -+ {0x00008344, 0xaa48105b}, -+ {0x00008348, 0x008f0000}, -+ {0x0000835c, 0x00000000}, -+ {0x00008360, 0xffffffff}, -+ {0x00008364, 0xffffffff}, -+ {0x00008368, 0x00000000}, -+ {0x00008370, 0x00000000}, -+ {0x00008374, 0x000000ff}, -+ {0x00008378, 0x00000000}, -+ {0x0000837c, 0x00000000}, -+ {0x00008380, 0xffffffff}, -+ {0x00008384, 0xffffffff}, -+ {0x00008390, 0xffffffff}, -+ {0x00008394, 0xffffffff}, -+ {0x00008398, 0x00000000}, -+ {0x0000839c, 0x00000000}, -+ {0x000083a0, 0x00000000}, -+ {0x000083a4, 0x0000fa14}, -+ {0x000083a8, 0x000f0c00}, -+ {0x000083ac, 0x33332210}, -+ {0x000083b0, 0x33332210}, -+ {0x000083b4, 0x33332210}, -+ {0x000083b8, 0x33332210}, -+ {0x000083bc, 0x00000000}, -+ {0x000083c0, 0x00000000}, -+ {0x000083c4, 0x00000000}, -+ {0x000083c8, 0x00000000}, -+ {0x000083cc, 0x00000200}, -+ {0x000083d0, 0x000301ff}, -+}; -+ -+static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { -+ /* Addr allmodes */ -+ {0x0000a000, 0x00010000}, -+ {0x0000a004, 0x00030002}, -+ {0x0000a008, 0x00050004}, -+ {0x0000a00c, 0x00810080}, -+ {0x0000a010, 0x00830082}, -+ {0x0000a014, 0x01810180}, -+ {0x0000a018, 0x01830182}, -+ {0x0000a01c, 0x01850184}, -+ {0x0000a020, 0x01890188}, -+ {0x0000a024, 0x018b018a}, -+ {0x0000a028, 0x018d018c}, -+ {0x0000a02c, 0x03820190}, -+ {0x0000a030, 0x03840383}, -+ {0x0000a034, 0x03880385}, -+ {0x0000a038, 0x038a0389}, -+ {0x0000a03c, 0x038c038b}, -+ {0x0000a040, 0x0390038d}, -+ {0x0000a044, 0x03920391}, -+ {0x0000a048, 0x03940393}, -+ {0x0000a04c, 0x03960395}, -+ {0x0000a050, 0x00000000}, -+ {0x0000a054, 0x00000000}, -+ {0x0000a058, 0x00000000}, -+ {0x0000a05c, 0x00000000}, -+ {0x0000a060, 0x00000000}, -+ {0x0000a064, 0x00000000}, -+ {0x0000a068, 0x00000000}, -+ {0x0000a06c, 0x00000000}, -+ {0x0000a070, 0x00000000}, -+ {0x0000a074, 0x00000000}, -+ {0x0000a078, 0x00000000}, -+ {0x0000a07c, 0x00000000}, -+ {0x0000a080, 0x29292929}, -+ {0x0000a084, 0x29292929}, -+ {0x0000a088, 0x29292929}, -+ {0x0000a08c, 0x29292929}, -+ {0x0000a090, 0x22292929}, -+ {0x0000a094, 0x1d1d2222}, -+ {0x0000a098, 0x0c111117}, -+ {0x0000a09c, 0x00030303}, -+ {0x0000a0a0, 0x00000000}, -+ {0x0000a0a4, 0x00000000}, -+ {0x0000a0a8, 0x00000000}, -+ {0x0000a0ac, 0x00000000}, -+ {0x0000a0b0, 0x00000000}, -+ {0x0000a0b4, 0x00000000}, -+ {0x0000a0b8, 0x00000000}, -+ {0x0000a0bc, 0x00000000}, -+ {0x0000a0c0, 0x001f0000}, -+ {0x0000a0c4, 0x01000101}, -+ {0x0000a0c8, 0x011e011f}, -+ {0x0000a0cc, 0x011c011d}, -+ {0x0000a0d0, 0x02030204}, -+ {0x0000a0d4, 0x02010202}, -+ {0x0000a0d8, 0x021f0200}, -+ {0x0000a0dc, 0x0302021e}, -+ {0x0000a0e0, 0x03000301}, -+ {0x0000a0e4, 0x031e031f}, -+ {0x0000a0e8, 0x0402031d}, -+ {0x0000a0ec, 0x04000401}, -+ {0x0000a0f0, 0x041e041f}, -+ {0x0000a0f4, 0x0502041d}, -+ {0x0000a0f8, 0x05000501}, -+ {0x0000a0fc, 0x051e051f}, -+ {0x0000a100, 0x06010602}, -+ {0x0000a104, 0x061f0600}, -+ {0x0000a108, 0x061d061e}, -+ {0x0000a10c, 0x07020703}, -+ {0x0000a110, 0x07000701}, -+ {0x0000a114, 0x00000000}, -+ {0x0000a118, 0x00000000}, -+ {0x0000a11c, 0x00000000}, -+ {0x0000a120, 0x00000000}, -+ {0x0000a124, 0x00000000}, -+ {0x0000a128, 0x00000000}, -+ {0x0000a12c, 0x00000000}, -+ {0x0000a130, 0x00000000}, -+ {0x0000a134, 0x00000000}, -+ {0x0000a138, 0x00000000}, -+ {0x0000a13c, 0x00000000}, -+ {0x0000a140, 0x001f0000}, -+ {0x0000a144, 0x01000101}, -+ {0x0000a148, 0x011e011f}, -+ {0x0000a14c, 0x011c011d}, -+ {0x0000a150, 0x02030204}, -+ {0x0000a154, 0x02010202}, -+ {0x0000a158, 0x021f0200}, -+ {0x0000a15c, 0x0302021e}, -+ {0x0000a160, 0x03000301}, -+ {0x0000a164, 0x031e031f}, -+ {0x0000a168, 0x0402031d}, -+ {0x0000a16c, 0x04000401}, -+ {0x0000a170, 0x041e041f}, -+ {0x0000a174, 0x0502041d}, -+ {0x0000a178, 0x05000501}, -+ {0x0000a17c, 0x051e051f}, -+ {0x0000a180, 0x06010602}, -+ {0x0000a184, 0x061f0600}, -+ {0x0000a188, 0x061d061e}, -+ {0x0000a18c, 0x07020703}, -+ {0x0000a190, 0x07000701}, -+ {0x0000a194, 0x00000000}, -+ {0x0000a198, 0x00000000}, -+ {0x0000a19c, 0x00000000}, -+ {0x0000a1a0, 0x00000000}, -+ {0x0000a1a4, 0x00000000}, -+ {0x0000a1a8, 0x00000000}, -+ {0x0000a1ac, 0x00000000}, -+ {0x0000a1b0, 0x00000000}, -+ {0x0000a1b4, 0x00000000}, -+ {0x0000a1b8, 0x00000000}, -+ {0x0000a1bc, 0x00000000}, -+ {0x0000a1c0, 0x00000000}, -+ {0x0000a1c4, 0x00000000}, -+ {0x0000a1c8, 0x00000000}, -+ {0x0000a1cc, 0x00000000}, -+ {0x0000a1d0, 0x00000000}, -+ {0x0000a1d4, 0x00000000}, -+ {0x0000a1d8, 0x00000000}, -+ {0x0000a1dc, 0x00000000}, -+ {0x0000a1e0, 0x00000000}, -+ {0x0000a1e4, 0x00000000}, -+ {0x0000a1e8, 0x00000000}, -+ {0x0000a1ec, 0x00000000}, -+ {0x0000a1f0, 0x00000396}, -+ {0x0000a1f4, 0x00000396}, -+ {0x0000a1f8, 0x00000396}, -+ {0x0000a1fc, 0x00000196}, -+ {0x0000b000, 0x00010000}, -+ {0x0000b004, 0x00030002}, -+ {0x0000b008, 0x00050004}, -+ {0x0000b00c, 0x00810080}, -+ {0x0000b010, 0x00830082}, -+ {0x0000b014, 0x01810180}, -+ {0x0000b018, 0x01830182}, -+ {0x0000b01c, 0x01850184}, -+ {0x0000b020, 0x02810280}, -+ {0x0000b024, 0x02830282}, -+ {0x0000b028, 0x02850284}, -+ {0x0000b02c, 0x02890288}, -+ {0x0000b030, 0x028b028a}, -+ {0x0000b034, 0x0388028c}, -+ {0x0000b038, 0x038a0389}, -+ {0x0000b03c, 0x038c038b}, -+ {0x0000b040, 0x0390038d}, -+ {0x0000b044, 0x03920391}, -+ {0x0000b048, 0x03940393}, -+ {0x0000b04c, 0x03960395}, -+ {0x0000b050, 0x00000000}, -+ {0x0000b054, 0x00000000}, -+ {0x0000b058, 0x00000000}, -+ {0x0000b05c, 0x00000000}, -+ {0x0000b060, 0x00000000}, -+ {0x0000b064, 0x00000000}, -+ {0x0000b068, 0x00000000}, -+ {0x0000b06c, 0x00000000}, -+ {0x0000b070, 0x00000000}, -+ {0x0000b074, 0x00000000}, -+ {0x0000b078, 0x00000000}, -+ {0x0000b07c, 0x00000000}, -+ {0x0000b080, 0x32323232}, -+ {0x0000b084, 0x2f2f3232}, -+ {0x0000b088, 0x23282a2d}, -+ {0x0000b08c, 0x1c1e2123}, -+ {0x0000b090, 0x14171919}, -+ {0x0000b094, 0x0e0e1214}, -+ {0x0000b098, 0x03050707}, -+ {0x0000b09c, 0x00030303}, -+ {0x0000b0a0, 0x00000000}, -+ {0x0000b0a4, 0x00000000}, -+ {0x0000b0a8, 0x00000000}, -+ {0x0000b0ac, 0x00000000}, -+ {0x0000b0b0, 0x00000000}, -+ {0x0000b0b4, 0x00000000}, -+ {0x0000b0b8, 0x00000000}, -+ {0x0000b0bc, 0x00000000}, -+ {0x0000b0c0, 0x003f0020}, -+ {0x0000b0c4, 0x00400041}, -+ {0x0000b0c8, 0x0140005f}, -+ {0x0000b0cc, 0x0160015f}, -+ {0x0000b0d0, 0x017e017f}, -+ {0x0000b0d4, 0x02410242}, -+ {0x0000b0d8, 0x025f0240}, -+ {0x0000b0dc, 0x027f0260}, -+ {0x0000b0e0, 0x0341027e}, -+ {0x0000b0e4, 0x035f0340}, -+ {0x0000b0e8, 0x037f0360}, -+ {0x0000b0ec, 0x04400441}, -+ {0x0000b0f0, 0x0460045f}, -+ {0x0000b0f4, 0x0541047f}, -+ {0x0000b0f8, 0x055f0540}, -+ {0x0000b0fc, 0x057f0560}, -+ {0x0000b100, 0x06400641}, -+ {0x0000b104, 0x0660065f}, -+ {0x0000b108, 0x067e067f}, -+ {0x0000b10c, 0x07410742}, -+ {0x0000b110, 0x075f0740}, -+ {0x0000b114, 0x077f0760}, -+ {0x0000b118, 0x07800781}, -+ {0x0000b11c, 0x07a0079f}, -+ {0x0000b120, 0x07c107bf}, -+ {0x0000b124, 0x000007c0}, -+ {0x0000b128, 0x00000000}, -+ {0x0000b12c, 0x00000000}, -+ {0x0000b130, 0x00000000}, -+ {0x0000b134, 0x00000000}, -+ {0x0000b138, 0x00000000}, -+ {0x0000b13c, 0x00000000}, -+ {0x0000b140, 0x003f0020}, -+ {0x0000b144, 0x00400041}, -+ {0x0000b148, 0x0140005f}, -+ {0x0000b14c, 0x0160015f}, -+ {0x0000b150, 0x017e017f}, -+ {0x0000b154, 0x02410242}, -+ {0x0000b158, 0x025f0240}, -+ {0x0000b15c, 0x027f0260}, -+ {0x0000b160, 0x0341027e}, -+ {0x0000b164, 0x035f0340}, -+ {0x0000b168, 0x037f0360}, -+ {0x0000b16c, 0x04400441}, -+ {0x0000b170, 0x0460045f}, -+ {0x0000b174, 0x0541047f}, -+ {0x0000b178, 0x055f0540}, -+ {0x0000b17c, 0x057f0560}, -+ {0x0000b180, 0x06400641}, -+ {0x0000b184, 0x0660065f}, -+ {0x0000b188, 0x067e067f}, -+ {0x0000b18c, 0x07410742}, -+ {0x0000b190, 0x075f0740}, -+ {0x0000b194, 0x077f0760}, -+ {0x0000b198, 0x07800781}, -+ {0x0000b19c, 0x07a0079f}, -+ {0x0000b1a0, 0x07c107bf}, -+ {0x0000b1a4, 0x000007c0}, -+ {0x0000b1a8, 0x00000000}, -+ {0x0000b1ac, 0x00000000}, -+ {0x0000b1b0, 0x00000000}, -+ {0x0000b1b4, 0x00000000}, -+ {0x0000b1b8, 0x00000000}, -+ {0x0000b1bc, 0x00000000}, -+ {0x0000b1c0, 0x00000000}, -+ {0x0000b1c4, 0x00000000}, -+ {0x0000b1c8, 0x00000000}, -+ {0x0000b1cc, 0x00000000}, -+ {0x0000b1d0, 0x00000000}, -+ {0x0000b1d4, 0x00000000}, -+ {0x0000b1d8, 0x00000000}, -+ {0x0000b1dc, 0x00000000}, -+ {0x0000b1e0, 0x00000000}, -+ {0x0000b1e4, 0x00000000}, -+ {0x0000b1e8, 0x00000000}, -+ {0x0000b1ec, 0x00000000}, -+ {0x0000b1f0, 0x00000396}, -+ {0x0000b1f4, 0x00000396}, -+ {0x0000b1f8, 0x00000396}, -+ {0x0000b1fc, 0x00000196}, -+}; -+ -+static const u32 ar9340_1p0_soc_preamble[][2] = { -+ /* Addr allmodes */ -+ {0x000040a4, 0x00a0c1c9}, -+ {0x00007008, 0x00000000}, -+ {0x00007020, 0x00000000}, -+ {0x00007034, 0x00000002}, -+ {0x00007038, 0x000004c2}, -+}; -+ -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9485_initvals.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9485_initvals.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ar9485_initvals.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ar9485_initvals.h 2011-05-05 23:29:49.080485301 +0200 -@@ -17,931 +17,6 @@ - #ifndef INITVALS_9485_H - #define INITVALS_9485_H - --static const u32 ar9485Common_1_0[][2] = { -- /* Addr allmodes */ -- {0x00007010, 0x00000022}, -- {0x00007020, 0x00000000}, -- {0x00007034, 0x00000002}, -- {0x00007038, 0x000004c2}, --}; -- --static const u32 ar9485_1_0_mac_postamble[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, -- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, -- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, -- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, -- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, -- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, -- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, -- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, --}; -- --static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1[][2] = { -- /* Addr allmodes */ -- {0x00018c00, 0x10212e5e}, -- {0x00018c04, 0x000801d8}, -- {0x00018c08, 0x0000580c}, --}; -- --static const u32 ar9485Common_wo_xlna_rx_gain_1_0[][2] = { -- /* Addr allmodes */ -- {0x0000a000, 0x00010000}, -- {0x0000a004, 0x00030002}, -- {0x0000a008, 0x00050004}, -- {0x0000a00c, 0x00810080}, -- {0x0000a010, 0x01800082}, -- {0x0000a014, 0x01820181}, -- {0x0000a018, 0x01840183}, -- {0x0000a01c, 0x01880185}, -- {0x0000a020, 0x018a0189}, -- {0x0000a024, 0x02850284}, -- {0x0000a028, 0x02890288}, -- {0x0000a02c, 0x03850384}, -- {0x0000a030, 0x03890388}, -- {0x0000a034, 0x038b038a}, -- {0x0000a038, 0x038d038c}, -- {0x0000a03c, 0x03910390}, -- {0x0000a040, 0x03930392}, -- {0x0000a044, 0x03950394}, -- {0x0000a048, 0x00000396}, -- {0x0000a04c, 0x00000000}, -- {0x0000a050, 0x00000000}, -- {0x0000a054, 0x00000000}, -- {0x0000a058, 0x00000000}, -- {0x0000a05c, 0x00000000}, -- {0x0000a060, 0x00000000}, -- {0x0000a064, 0x00000000}, -- {0x0000a068, 0x00000000}, -- {0x0000a06c, 0x00000000}, -- {0x0000a070, 0x00000000}, -- {0x0000a074, 0x00000000}, -- {0x0000a078, 0x00000000}, -- {0x0000a07c, 0x00000000}, -- {0x0000a080, 0x28282828}, -- {0x0000a084, 0x28282828}, -- {0x0000a088, 0x28282828}, -- {0x0000a08c, 0x28282828}, -- {0x0000a090, 0x28282828}, -- {0x0000a094, 0x21212128}, -- {0x0000a098, 0x171c1c1c}, -- {0x0000a09c, 0x02020212}, -- {0x0000a0a0, 0x00000202}, -- {0x0000a0a4, 0x00000000}, -- {0x0000a0a8, 0x00000000}, -- {0x0000a0ac, 0x00000000}, -- {0x0000a0b0, 0x00000000}, -- {0x0000a0b4, 0x00000000}, -- {0x0000a0b8, 0x00000000}, -- {0x0000a0bc, 0x00000000}, -- {0x0000a0c0, 0x001f0000}, -- {0x0000a0c4, 0x111f1100}, -- {0x0000a0c8, 0x111d111e}, -- {0x0000a0cc, 0x111b111c}, -- {0x0000a0d0, 0x22032204}, -- {0x0000a0d4, 0x22012202}, -- {0x0000a0d8, 0x221f2200}, -- {0x0000a0dc, 0x221d221e}, -- {0x0000a0e0, 0x33013302}, -- {0x0000a0e4, 0x331f3300}, -- {0x0000a0e8, 0x4402331e}, -- {0x0000a0ec, 0x44004401}, -- {0x0000a0f0, 0x441e441f}, -- {0x0000a0f4, 0x55015502}, -- {0x0000a0f8, 0x551f5500}, -- {0x0000a0fc, 0x6602551e}, -- {0x0000a100, 0x66006601}, -- {0x0000a104, 0x661e661f}, -- {0x0000a108, 0x7703661d}, -- {0x0000a10c, 0x77017702}, -- {0x0000a110, 0x00007700}, -- {0x0000a114, 0x00000000}, -- {0x0000a118, 0x00000000}, -- {0x0000a11c, 0x00000000}, -- {0x0000a120, 0x00000000}, -- {0x0000a124, 0x00000000}, -- {0x0000a128, 0x00000000}, -- {0x0000a12c, 0x00000000}, -- {0x0000a130, 0x00000000}, -- {0x0000a134, 0x00000000}, -- {0x0000a138, 0x00000000}, -- {0x0000a13c, 0x00000000}, -- {0x0000a140, 0x001f0000}, -- {0x0000a144, 0x111f1100}, -- {0x0000a148, 0x111d111e}, -- {0x0000a14c, 0x111b111c}, -- {0x0000a150, 0x22032204}, -- {0x0000a154, 0x22012202}, -- {0x0000a158, 0x221f2200}, -- {0x0000a15c, 0x221d221e}, -- {0x0000a160, 0x33013302}, -- {0x0000a164, 0x331f3300}, -- {0x0000a168, 0x4402331e}, -- {0x0000a16c, 0x44004401}, -- {0x0000a170, 0x441e441f}, -- {0x0000a174, 0x55015502}, -- {0x0000a178, 0x551f5500}, -- {0x0000a17c, 0x6602551e}, -- {0x0000a180, 0x66006601}, -- {0x0000a184, 0x661e661f}, -- {0x0000a188, 0x7703661d}, -- {0x0000a18c, 0x77017702}, -- {0x0000a190, 0x00007700}, -- {0x0000a194, 0x00000000}, -- {0x0000a198, 0x00000000}, -- {0x0000a19c, 0x00000000}, -- {0x0000a1a0, 0x00000000}, -- {0x0000a1a4, 0x00000000}, -- {0x0000a1a8, 0x00000000}, -- {0x0000a1ac, 0x00000000}, -- {0x0000a1b0, 0x00000000}, -- {0x0000a1b4, 0x00000000}, -- {0x0000a1b8, 0x00000000}, -- {0x0000a1bc, 0x00000000}, -- {0x0000a1c0, 0x00000000}, -- {0x0000a1c4, 0x00000000}, -- {0x0000a1c8, 0x00000000}, -- {0x0000a1cc, 0x00000000}, -- {0x0000a1d0, 0x00000000}, -- {0x0000a1d4, 0x00000000}, -- {0x0000a1d8, 0x00000000}, -- {0x0000a1dc, 0x00000000}, -- {0x0000a1e0, 0x00000000}, -- {0x0000a1e4, 0x00000000}, -- {0x0000a1e8, 0x00000000}, -- {0x0000a1ec, 0x00000000}, -- {0x0000a1f0, 0x00000396}, -- {0x0000a1f4, 0x00000396}, -- {0x0000a1f8, 0x00000396}, -- {0x0000a1fc, 0x00000296}, --}; -- --static const u32 ar9485Modes_high_power_tx_gain_1_0[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, -- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, -- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, -- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, -- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, -- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, -- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, -- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, -- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, -- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, -- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, -- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, -- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, -- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, -- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, -- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, -- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, -- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, -- {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, -- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, -- {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, -- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, -- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, -- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, -- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, -- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, -- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, -- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, --}; -- --static const u32 ar9485_1_0[][2] = { -- /* Addr allmodes */ -- {0x0000a580, 0x00000000}, -- {0x0000a584, 0x00000000}, -- {0x0000a588, 0x00000000}, -- {0x0000a58c, 0x00000000}, -- {0x0000a590, 0x00000000}, -- {0x0000a594, 0x00000000}, -- {0x0000a598, 0x00000000}, -- {0x0000a59c, 0x00000000}, -- {0x0000a5a0, 0x00000000}, -- {0x0000a5a4, 0x00000000}, -- {0x0000a5a8, 0x00000000}, -- {0x0000a5ac, 0x00000000}, -- {0x0000a5b0, 0x00000000}, -- {0x0000a5b4, 0x00000000}, -- {0x0000a5b8, 0x00000000}, -- {0x0000a5bc, 0x00000000}, --}; -- --static const u32 ar9485_1_0_radio_core[][2] = { -- /* Addr allmodes */ -- {0x00016000, 0x36db6db6}, -- {0x00016004, 0x6db6db40}, -- {0x00016008, 0x73800000}, -- {0x0001600c, 0x00000000}, -- {0x00016040, 0x7f80fff8}, -- {0x00016048, 0x6c92426e}, -- {0x0001604c, 0x000f0278}, -- {0x00016050, 0x6db6db6c}, -- {0x00016054, 0x6db60000}, -- {0x00016080, 0x00080000}, -- {0x00016084, 0x0e48048c}, -- {0x00016088, 0x14214514}, -- {0x0001608c, 0x119f081e}, -- {0x00016090, 0x24926490}, -- {0x00016098, 0xd28b3330}, -- {0x000160a0, 0xc2108ffe}, -- {0x000160a4, 0x812fc370}, -- {0x000160a8, 0x423c8000}, -- {0x000160b4, 0x92480040}, -- {0x000160c0, 0x006db6db}, -- {0x000160c4, 0x0186db60}, -- {0x000160c8, 0x6db6db6c}, -- {0x000160cc, 0x6de6fbe0}, -- {0x000160d0, 0xf7dfcf3c}, -- {0x00016100, 0x04cb0001}, -- {0x00016104, 0xfff80015}, -- {0x00016108, 0x00080010}, -- {0x00016144, 0x01884080}, -- {0x00016148, 0x00008040}, -- {0x00016180, 0x08453333}, -- {0x00016184, 0x18e82f01}, -- {0x00016188, 0x00000000}, -- {0x0001618c, 0x00000000}, -- {0x00016240, 0x08400000}, -- {0x00016244, 0x1bf90f00}, -- {0x00016248, 0x00000000}, -- {0x0001624c, 0x00000000}, -- {0x00016280, 0x01000015}, -- {0x00016284, 0x00d30000}, -- {0x00016288, 0x00318000}, -- {0x0001628c, 0x50000000}, -- {0x00016290, 0x4b96210f}, -- {0x00016380, 0x00000000}, -- {0x00016384, 0x00000000}, -- {0x00016388, 0x00800700}, -- {0x0001638c, 0x00800700}, -- {0x00016390, 0x00800700}, -- {0x00016394, 0x00000000}, -- {0x00016398, 0x00000000}, -- {0x0001639c, 0x00000000}, -- {0x000163a0, 0x00000001}, -- {0x000163a4, 0x00000001}, -- {0x000163a8, 0x00000000}, -- {0x000163ac, 0x00000000}, -- {0x000163b0, 0x00000000}, -- {0x000163b4, 0x00000000}, -- {0x000163b8, 0x00000000}, -- {0x000163bc, 0x00000000}, -- {0x000163c0, 0x000000a0}, -- {0x000163c4, 0x000c0000}, -- {0x000163c8, 0x14021402}, -- {0x000163cc, 0x00001402}, -- {0x000163d0, 0x00000000}, -- {0x000163d4, 0x00000000}, -- {0x00016c40, 0x1319c178}, -- {0x00016c44, 0x10000000}, --}; -- --static const u32 ar9485Modes_lowest_ob_db_tx_gain_1_0[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, -- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, -- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, -- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, -- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, -- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, -- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, -- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, -- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, -- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, -- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, -- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, -- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, -- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, -- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, -- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, -- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, -- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, -- {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, -- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, -- {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, -- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, -- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, -- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, -- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, -- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, -- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, -- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, --}; -- --static const u32 ar9485_1_0_baseband_core[][2] = { -- /* Addr allmodes */ -- {0x00009800, 0xafe68e30}, -- {0x00009804, 0xfd14e000}, -- {0x00009808, 0x9c0a8f6b}, -- {0x0000980c, 0x04800000}, -- {0x00009814, 0x9280c00a}, -- {0x00009818, 0x00000000}, -- {0x0000981c, 0x00020028}, -- {0x00009834, 0x5f3ca3de}, -- {0x00009838, 0x0108ecff}, -- {0x0000983c, 0x14750600}, -- {0x00009880, 0x201fff00}, -- {0x00009884, 0x00001042}, -- {0x000098a4, 0x00200400}, -- {0x000098b0, 0x52440bbe}, -- {0x000098bc, 0x00000002}, -- {0x000098d0, 0x004b6a8e}, -- {0x000098d4, 0x00000820}, -- {0x000098dc, 0x00000000}, -- {0x000098f0, 0x00000000}, -- {0x000098f4, 0x00000000}, -- {0x00009c04, 0x00000000}, -- {0x00009c08, 0x03200000}, -- {0x00009c0c, 0x00000000}, -- {0x00009c10, 0x00000000}, -- {0x00009c14, 0x00046384}, -- {0x00009c18, 0x05b6b440}, -- {0x00009c1c, 0x00b6b440}, -- {0x00009d00, 0xc080a333}, -- {0x00009d04, 0x40206c10}, -- {0x00009d08, 0x009c4060}, -- {0x00009d0c, 0x1883800a}, -- {0x00009d10, 0x01834061}, -- {0x00009d14, 0x00c00400}, -- {0x00009d18, 0x00000000}, -- {0x00009d1c, 0x00000000}, -- {0x00009e08, 0x0038233c}, -- {0x00009e24, 0x990bb515}, -- {0x00009e28, 0x0a6f0000}, -- {0x00009e30, 0x06336f77}, -- {0x00009e34, 0x6af6532f}, -- {0x00009e38, 0x0cc80c00}, -- {0x00009e40, 0x0d261820}, -- {0x00009e4c, 0x00001004}, -- {0x00009e50, 0x00ff03f1}, -- {0x00009fc0, 0x80be4788}, -- {0x00009fc4, 0x0001efb5}, -- {0x00009fcc, 0x40000014}, -- {0x0000a20c, 0x00000000}, -- {0x0000a210, 0x00000000}, -- {0x0000a220, 0x00000000}, -- {0x0000a224, 0x00000000}, -- {0x0000a228, 0x10002310}, -- {0x0000a23c, 0x00000000}, -- {0x0000a244, 0x0c000000}, -- {0x0000a2a0, 0x00000001}, -- {0x0000a2c0, 0x00000001}, -- {0x0000a2c8, 0x00000000}, -- {0x0000a2cc, 0x18c43433}, -- {0x0000a2d4, 0x00000000}, -- {0x0000a2dc, 0x00000000}, -- {0x0000a2e0, 0x00000000}, -- {0x0000a2e4, 0x00000000}, -- {0x0000a2e8, 0x00000000}, -- {0x0000a2ec, 0x00000000}, -- {0x0000a2f0, 0x00000000}, -- {0x0000a2f4, 0x00000000}, -- {0x0000a2f8, 0x00000000}, -- {0x0000a344, 0x00000000}, -- {0x0000a34c, 0x00000000}, -- {0x0000a350, 0x0000a000}, -- {0x0000a364, 0x00000000}, -- {0x0000a370, 0x00000000}, -- {0x0000a390, 0x00000001}, -- {0x0000a394, 0x00000444}, -- {0x0000a398, 0x001f0e0f}, -- {0x0000a39c, 0x0075393f}, -- {0x0000a3a0, 0xb79f6427}, -- {0x0000a3a4, 0x00000000}, -- {0x0000a3a8, 0xaaaaaaaa}, -- {0x0000a3ac, 0x3c466478}, -- {0x0000a3c0, 0x20202020}, -- {0x0000a3c4, 0x22222220}, -- {0x0000a3c8, 0x20200020}, -- {0x0000a3cc, 0x20202020}, -- {0x0000a3d0, 0x20202020}, -- {0x0000a3d4, 0x20202020}, -- {0x0000a3d8, 0x20202020}, -- {0x0000a3dc, 0x20202020}, -- {0x0000a3e0, 0x20202020}, -- {0x0000a3e4, 0x20202020}, -- {0x0000a3e8, 0x20202020}, -- {0x0000a3ec, 0x20202020}, -- {0x0000a3f0, 0x00000000}, -- {0x0000a3f4, 0x00000006}, -- {0x0000a3f8, 0x0cdbd380}, -- {0x0000a3fc, 0x000f0f01}, -- {0x0000a400, 0x8fa91f01}, -- {0x0000a404, 0x00000000}, -- {0x0000a408, 0x0e79e5c6}, -- {0x0000a40c, 0x00820820}, -- {0x0000a414, 0x1ce739ce}, -- {0x0000a418, 0x2d0011ce}, -- {0x0000a41c, 0x1ce739ce}, -- {0x0000a420, 0x000001ce}, -- {0x0000a424, 0x1ce739ce}, -- {0x0000a428, 0x000001ce}, -- {0x0000a42c, 0x1ce739ce}, -- {0x0000a430, 0x1ce739ce}, -- {0x0000a434, 0x00000000}, -- {0x0000a438, 0x00001801}, -- {0x0000a43c, 0x00000000}, -- {0x0000a440, 0x00000000}, -- {0x0000a444, 0x00000000}, -- {0x0000a448, 0x04000000}, -- {0x0000a44c, 0x00000001}, -- {0x0000a450, 0x00010000}, -- {0x0000a458, 0x00000000}, -- {0x0000a5c4, 0x3fad9d74}, -- {0x0000a5c8, 0x0048060a}, -- {0x0000a5cc, 0x00000637}, -- {0x0000a760, 0x03020100}, -- {0x0000a764, 0x09080504}, -- {0x0000a768, 0x0d0c0b0a}, -- {0x0000a76c, 0x13121110}, -- {0x0000a770, 0x31301514}, -- {0x0000a774, 0x35343332}, -- {0x0000a778, 0x00000036}, -- {0x0000a780, 0x00000838}, -- {0x0000a7c0, 0x00000000}, -- {0x0000a7c4, 0xfffffffc}, -- {0x0000a7c8, 0x00000000}, -- {0x0000a7cc, 0x00000000}, -- {0x0000a7d0, 0x00000000}, -- {0x0000a7d4, 0x00000004}, -- {0x0000a7dc, 0x00000001}, --}; -- --static const u32 ar9485Modes_high_ob_db_tx_gain_1_0[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, -- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, -- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, -- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, -- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, -- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, -- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, -- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, -- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, -- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, -- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, -- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, -- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, -- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, -- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, -- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, -- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, -- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, -- {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, -- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, -- {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, -- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, -- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, -- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, -- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, -- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, -- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, -- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, --}; -- --static const u32 ar9485Common_rx_gain_1_0[][2] = { -- /* Addr allmodes */ -- {0x0000a000, 0x00010000}, -- {0x0000a004, 0x00030002}, -- {0x0000a008, 0x00050004}, -- {0x0000a00c, 0x00810080}, -- {0x0000a010, 0x01800082}, -- {0x0000a014, 0x01820181}, -- {0x0000a018, 0x01840183}, -- {0x0000a01c, 0x01880185}, -- {0x0000a020, 0x018a0189}, -- {0x0000a024, 0x02850284}, -- {0x0000a028, 0x02890288}, -- {0x0000a02c, 0x03850384}, -- {0x0000a030, 0x03890388}, -- {0x0000a034, 0x038b038a}, -- {0x0000a038, 0x038d038c}, -- {0x0000a03c, 0x03910390}, -- {0x0000a040, 0x03930392}, -- {0x0000a044, 0x03950394}, -- {0x0000a048, 0x00000396}, -- {0x0000a04c, 0x00000000}, -- {0x0000a050, 0x00000000}, -- {0x0000a054, 0x00000000}, -- {0x0000a058, 0x00000000}, -- {0x0000a05c, 0x00000000}, -- {0x0000a060, 0x00000000}, -- {0x0000a064, 0x00000000}, -- {0x0000a068, 0x00000000}, -- {0x0000a06c, 0x00000000}, -- {0x0000a070, 0x00000000}, -- {0x0000a074, 0x00000000}, -- {0x0000a078, 0x00000000}, -- {0x0000a07c, 0x00000000}, -- {0x0000a080, 0x28282828}, -- {0x0000a084, 0x28282828}, -- {0x0000a088, 0x28282828}, -- {0x0000a08c, 0x28282828}, -- {0x0000a090, 0x28282828}, -- {0x0000a094, 0x21212128}, -- {0x0000a098, 0x171c1c1c}, -- {0x0000a09c, 0x02020212}, -- {0x0000a0a0, 0x00000202}, -- {0x0000a0a4, 0x00000000}, -- {0x0000a0a8, 0x00000000}, -- {0x0000a0ac, 0x00000000}, -- {0x0000a0b0, 0x00000000}, -- {0x0000a0b4, 0x00000000}, -- {0x0000a0b8, 0x00000000}, -- {0x0000a0bc, 0x00000000}, -- {0x0000a0c0, 0x001f0000}, -- {0x0000a0c4, 0x111f1100}, -- {0x0000a0c8, 0x111d111e}, -- {0x0000a0cc, 0x111b111c}, -- {0x0000a0d0, 0x22032204}, -- {0x0000a0d4, 0x22012202}, -- {0x0000a0d8, 0x221f2200}, -- {0x0000a0dc, 0x221d221e}, -- {0x0000a0e0, 0x33013302}, -- {0x0000a0e4, 0x331f3300}, -- {0x0000a0e8, 0x4402331e}, -- {0x0000a0ec, 0x44004401}, -- {0x0000a0f0, 0x441e441f}, -- {0x0000a0f4, 0x55015502}, -- {0x0000a0f8, 0x551f5500}, -- {0x0000a0fc, 0x6602551e}, -- {0x0000a100, 0x66006601}, -- {0x0000a104, 0x661e661f}, -- {0x0000a108, 0x7703661d}, -- {0x0000a10c, 0x77017702}, -- {0x0000a110, 0x00007700}, -- {0x0000a114, 0x00000000}, -- {0x0000a118, 0x00000000}, -- {0x0000a11c, 0x00000000}, -- {0x0000a120, 0x00000000}, -- {0x0000a124, 0x00000000}, -- {0x0000a128, 0x00000000}, -- {0x0000a12c, 0x00000000}, -- {0x0000a130, 0x00000000}, -- {0x0000a134, 0x00000000}, -- {0x0000a138, 0x00000000}, -- {0x0000a13c, 0x00000000}, -- {0x0000a140, 0x001f0000}, -- {0x0000a144, 0x111f1100}, -- {0x0000a148, 0x111d111e}, -- {0x0000a14c, 0x111b111c}, -- {0x0000a150, 0x22032204}, -- {0x0000a154, 0x22012202}, -- {0x0000a158, 0x221f2200}, -- {0x0000a15c, 0x221d221e}, -- {0x0000a160, 0x33013302}, -- {0x0000a164, 0x331f3300}, -- {0x0000a168, 0x4402331e}, -- {0x0000a16c, 0x44004401}, -- {0x0000a170, 0x441e441f}, -- {0x0000a174, 0x55015502}, -- {0x0000a178, 0x551f5500}, -- {0x0000a17c, 0x6602551e}, -- {0x0000a180, 0x66006601}, -- {0x0000a184, 0x661e661f}, -- {0x0000a188, 0x7703661d}, -- {0x0000a18c, 0x77017702}, -- {0x0000a190, 0x00007700}, -- {0x0000a194, 0x00000000}, -- {0x0000a198, 0x00000000}, -- {0x0000a19c, 0x00000000}, -- {0x0000a1a0, 0x00000000}, -- {0x0000a1a4, 0x00000000}, -- {0x0000a1a8, 0x00000000}, -- {0x0000a1ac, 0x00000000}, -- {0x0000a1b0, 0x00000000}, -- {0x0000a1b4, 0x00000000}, -- {0x0000a1b8, 0x00000000}, -- {0x0000a1bc, 0x00000000}, -- {0x0000a1c0, 0x00000000}, -- {0x0000a1c4, 0x00000000}, -- {0x0000a1c8, 0x00000000}, -- {0x0000a1cc, 0x00000000}, -- {0x0000a1d0, 0x00000000}, -- {0x0000a1d4, 0x00000000}, -- {0x0000a1d8, 0x00000000}, -- {0x0000a1dc, 0x00000000}, -- {0x0000a1e0, 0x00000000}, -- {0x0000a1e4, 0x00000000}, -- {0x0000a1e8, 0x00000000}, -- {0x0000a1ec, 0x00000000}, -- {0x0000a1f0, 0x00000396}, -- {0x0000a1f4, 0x00000396}, -- {0x0000a1f8, 0x00000396}, -- {0x0000a1fc, 0x00000296}, --}; -- --static const u32 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1[][2] = { -- /* Addr allmodes */ -- {0x00018c00, 0x10252e5e}, -- {0x00018c04, 0x000801d8}, -- {0x00018c08, 0x0000580c}, --}; -- --static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = { -- /* Addr allmodes */ -- {0x00018c00, 0x10253e5e}, -- {0x00018c04, 0x000801d8}, -- {0x00018c08, 0x0000580c}, --}; -- --static const u32 ar9485_1_0_soc_preamble[][2] = { -- /* Addr allmodes */ -- {0x00004090, 0x00aa10aa}, -- {0x000040a4, 0x00a0c9c9}, -- {0x00007048, 0x00000004}, --}; -- --static const u32 ar9485_fast_clock_1_0_baseband_postamble[][3] = { -- /* Addr 5G_HT20 5G_HT40 */ -- {0x00009e00, 0x03721821, 0x03721821}, -- {0x0000a230, 0x0000400b, 0x00004016}, -- {0x0000a254, 0x00000898, 0x00001130}, --}; -- --static const u32 ar9485_1_0_baseband_postamble[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, -- {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, -- {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, -- {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, -- {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, -- {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, -- {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, -- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, -- {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, -- {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, -- {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, -- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, -- {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, -- {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, -- {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, -- {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, -- {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, -- {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, -- {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, -- {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, -- {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, -- {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, -- {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff}, -- {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, -- {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, -- {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, -- {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, -- {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, -- {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, -- {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, -- {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, -- {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, -- {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, -- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, -- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, -- {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, -- {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, --}; -- --static const u32 ar9485Modes_low_ob_db_tx_gain_1_0[][5] = { -- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, -- {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, -- {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, -- {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, -- {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, -- {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, -- {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, -- {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, -- {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, -- {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, -- {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, -- {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, -- {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, -- {0x0000a530, 0x48023ec6, 0x48023ec6, 0x2e000a20, 0x2e000a20}, -- {0x0000a534, 0x4d023f01, 0x4d023f01, 0x34000e20, 0x34000e20}, -- {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000e22, 0x38000e22}, -- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3c000e24, 0x3c000e24}, -- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x40000e26, 0x40000e26}, -- {0x0000a544, 0x6502feca, 0x6502feca, 0x43001640, 0x43001640}, -- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46001660, 0x46001660}, -- {0x0000a54c, 0x7203feca, 0x7203feca, 0x49001861, 0x49001861}, -- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4c001a81, 0x4c001a81}, -- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4f001a83, 0x4f001a83}, -- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x54001c85, 0x54001c85}, -- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x58001ce5, 0x58001ce5}, -- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5b001ce9, 0x5b001ce9}, -- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x60001eeb, 0x60001eeb}, -- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x60001eeb, 0x60001eeb}, -- {0x00016044, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db, 0x05b6b2db}, --}; -- --static const u32 ar9485_1_0_pcie_phy_clkreq_disable_L1[][2] = { -- /* Addr allmodes */ -- {0x00018c00, 0x10213e5e}, -- {0x00018c04, 0x000801d8}, -- {0x00018c08, 0x0000580c}, --}; -- --static const u32 ar9485_1_0_radio_postamble[][2] = { -- /* Addr allmodes */ -- {0x0001609c, 0x0b283f31}, -- {0x000160ac, 0x24611800}, -- {0x000160b0, 0x03284f3e}, -- {0x0001610c, 0x00170000}, -- {0x00016140, 0x10804008}, --}; -- --static const u32 ar9485_1_0_mac_core[][2] = { -- /* Addr allmodes */ -- {0x00000008, 0x00000000}, -- {0x00000030, 0x00020085}, -- {0x00000034, 0x00000005}, -- {0x00000040, 0x00000000}, -- {0x00000044, 0x00000000}, -- {0x00000048, 0x00000008}, -- {0x0000004c, 0x00000010}, -- {0x00000050, 0x00000000}, -- {0x00001040, 0x002ffc0f}, -- {0x00001044, 0x002ffc0f}, -- {0x00001048, 0x002ffc0f}, -- {0x0000104c, 0x002ffc0f}, -- {0x00001050, 0x002ffc0f}, -- {0x00001054, 0x002ffc0f}, -- {0x00001058, 0x002ffc0f}, -- {0x0000105c, 0x002ffc0f}, -- {0x00001060, 0x002ffc0f}, -- {0x00001064, 0x002ffc0f}, -- {0x000010f0, 0x00000100}, -- {0x00001270, 0x00000000}, -- {0x000012b0, 0x00000000}, -- {0x000012f0, 0x00000000}, -- {0x0000143c, 0x00000000}, -- {0x0000147c, 0x00000000}, -- {0x00008000, 0x00000000}, -- {0x00008004, 0x00000000}, -- {0x00008008, 0x00000000}, -- {0x0000800c, 0x00000000}, -- {0x00008018, 0x00000000}, -- {0x00008020, 0x00000000}, -- {0x00008038, 0x00000000}, -- {0x0000803c, 0x00000000}, -- {0x00008040, 0x00000000}, -- {0x00008044, 0x00000000}, -- {0x00008048, 0x00000000}, -- {0x0000804c, 0xffffffff}, -- {0x00008054, 0x00000000}, -- {0x00008058, 0x00000000}, -- {0x0000805c, 0x000fc78f}, -- {0x00008060, 0x0000000f}, -- {0x00008064, 0x00000000}, -- {0x00008070, 0x00000310}, -- {0x00008074, 0x00000020}, -- {0x00008078, 0x00000000}, -- {0x0000809c, 0x0000000f}, -- {0x000080a0, 0x00000000}, -- {0x000080a4, 0x02ff0000}, -- {0x000080a8, 0x0e070605}, -- {0x000080ac, 0x0000000d}, -- {0x000080b0, 0x00000000}, -- {0x000080b4, 0x00000000}, -- {0x000080b8, 0x00000000}, -- {0x000080bc, 0x00000000}, -- {0x000080c0, 0x2a800000}, -- {0x000080c4, 0x06900168}, -- {0x000080c8, 0x13881c20}, -- {0x000080cc, 0x01f40000}, -- {0x000080d0, 0x00252500}, -- {0x000080d4, 0x00a00000}, -- {0x000080d8, 0x00400000}, -- {0x000080dc, 0x00000000}, -- {0x000080e0, 0xffffffff}, -- {0x000080e4, 0x0000ffff}, -- {0x000080e8, 0x3f3f3f3f}, -- {0x000080ec, 0x00000000}, -- {0x000080f0, 0x00000000}, -- {0x000080f4, 0x00000000}, -- {0x000080fc, 0x00020000}, -- {0x00008100, 0x00000000}, -- {0x00008108, 0x00000052}, -- {0x0000810c, 0x00000000}, -- {0x00008110, 0x00000000}, -- {0x00008114, 0x000007ff}, -- {0x00008118, 0x000000aa}, -- {0x0000811c, 0x00003210}, -- {0x00008124, 0x00000000}, -- {0x00008128, 0x00000000}, -- {0x0000812c, 0x00000000}, -- {0x00008130, 0x00000000}, -- {0x00008134, 0x00000000}, -- {0x00008138, 0x00000000}, -- {0x0000813c, 0x0000ffff}, -- {0x00008144, 0xffffffff}, -- {0x00008168, 0x00000000}, -- {0x0000816c, 0x00000000}, -- {0x00008170, 0x18486200}, -- {0x00008174, 0x33332210}, -- {0x00008178, 0x00000000}, -- {0x0000817c, 0x00020000}, -- {0x000081c0, 0x00000000}, -- {0x000081c4, 0x33332210}, -- {0x000081c8, 0x00000000}, -- {0x000081cc, 0x00000000}, -- {0x000081d4, 0x00000000}, -- {0x000081ec, 0x00000000}, -- {0x000081f0, 0x00000000}, -- {0x000081f4, 0x00000000}, -- {0x000081f8, 0x00000000}, -- {0x000081fc, 0x00000000}, -- {0x00008240, 0x00100000}, -- {0x00008244, 0x0010f400}, -- {0x00008248, 0x00000800}, -- {0x0000824c, 0x0001e800}, -- {0x00008250, 0x00000000}, -- {0x00008254, 0x00000000}, -- {0x00008258, 0x00000000}, -- {0x0000825c, 0x40000000}, -- {0x00008260, 0x00080922}, -- {0x00008264, 0x9ca00010}, -- {0x00008268, 0xffffffff}, -- {0x0000826c, 0x0000ffff}, -- {0x00008270, 0x00000000}, -- {0x00008274, 0x40000000}, -- {0x00008278, 0x003e4180}, -- {0x0000827c, 0x00000004}, -- {0x00008284, 0x0000002c}, -- {0x00008288, 0x0000002c}, -- {0x0000828c, 0x000000ff}, -- {0x00008294, 0x00000000}, -- {0x00008298, 0x00000000}, -- {0x0000829c, 0x00000000}, -- {0x00008300, 0x00000140}, -- {0x00008314, 0x00000000}, -- {0x0000831c, 0x0000010d}, -- {0x00008328, 0x00000000}, -- {0x0000832c, 0x00000007}, -- {0x00008330, 0x00000302}, -- {0x00008334, 0x00000700}, -- {0x00008338, 0x00ff0000}, -- {0x0000833c, 0x02400000}, -- {0x00008340, 0x000107ff}, -- {0x00008344, 0xa248105b}, -- {0x00008348, 0x008f0000}, -- {0x0000835c, 0x00000000}, -- {0x00008360, 0xffffffff}, -- {0x00008364, 0xffffffff}, -- {0x00008368, 0x00000000}, -- {0x00008370, 0x00000000}, -- {0x00008374, 0x000000ff}, -- {0x00008378, 0x00000000}, -- {0x0000837c, 0x00000000}, -- {0x00008380, 0xffffffff}, -- {0x00008384, 0xffffffff}, -- {0x00008390, 0xffffffff}, -- {0x00008394, 0xffffffff}, -- {0x00008398, 0x00000000}, -- {0x0000839c, 0x00000000}, -- {0x000083a0, 0x00000000}, -- {0x000083a4, 0x0000fa14}, -- {0x000083a8, 0x000f0c00}, -- {0x000083ac, 0x33332210}, -- {0x000083b0, 0x33332210}, -- {0x000083b4, 0x33332210}, -- {0x000083b8, 0x33332210}, -- {0x000083bc, 0x00000000}, -- {0x000083c0, 0x00000000}, -- {0x000083c4, 0x00000000}, -- {0x000083c8, 0x00000000}, -- {0x000083cc, 0x00000200}, -- {0x000083d0, 0x000301ff}, --}; -- - static const u32 ar9485_1_1_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, -@@ -1321,7 +396,7 @@ - {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}, -@@ -1394,7 +469,7 @@ - {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}, -@@ -1560,7 +635,7 @@ - {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}, -@@ -1653,7 +728,7 @@ - {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}, -@@ -1752,7 +827,7 @@ - {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}, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ath9k.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ath9k.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/ath9k.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/ath9k.h 2011-05-05 23:29:49.077485265 +0200 -@@ -120,13 +120,11 @@ - /* RX / TX */ - /***********/ - --#define ATH_MAX_ANTENNA 3 - #define ATH_RXBUF 512 - #define ATH_TXBUF 512 - #define ATH_TXBUF_RESERVE 5 - #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) - #define ATH_TXMAXTRY 13 --#define ATH_MGT_TXMAXTRY 4 - - #define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ -@@ -202,6 +200,7 @@ - int sched; - struct list_head list; - struct list_head tid_q; -+ bool clear_ps_filter; - }; - - struct ath_frame_info { -@@ -257,8 +256,12 @@ - #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) -@@ -340,17 +343,18 @@ - 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 */ - /********/ - - struct ath_vif { - int av_bslot; -- bool is_bslot_active; -+ bool is_bslot_active, primary_sta_vif; - __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ -- enum nl80211_iftype av_opmode; - struct ath_buf *av_bcbuf; -- u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ - }; - - /*******************/ -@@ -362,7 +366,7 @@ - * number of BSSIDs) if a given beacon does not go out even after waiting this - * number of beacon intervals, the game's up. - */ --#define BSTUCK_THRESH (9 * ATH_BCBUF) -+#define BSTUCK_THRESH 9 - #define ATH_BCBUF 4 - #define ATH_DEFAULT_BINTVAL 100 /* TU */ - #define ATH_DEFAULT_BMISS_LIMIT 10 -@@ -386,7 +390,7 @@ - u32 beaconq; - u32 bmisscnt; - u32 ast_be_xmit; -- u64 bc_tstamp; -+ u32 bc_tstamp; - struct ieee80211_vif *bslot[ATH_BCBUF]; - int slottime; - int slotupdate; -@@ -401,6 +405,7 @@ - int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); - void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); - int ath_beaconq_config(struct ath_softc *sc); -+void ath_set_beacon(struct ath_softc *sc); - void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); - - /*******/ -@@ -418,6 +423,7 @@ - #define ATH_PAPRD_TIMEOUT 100 /* msecs */ - - void ath_hw_check(struct work_struct *work); -+void ath_hw_pll_work(struct work_struct *work); - void ath_paprd_calibrate(struct work_struct *work); - void ath_ani_calibrate(unsigned long data); - -@@ -448,6 +454,7 @@ - - #define ATH_LED_PIN_DEF 1 - #define ATH_LED_PIN_9287 8 -+#define ATH_LED_PIN_9300 10 - #define ATH_LED_PIN_9485 6 - - #ifdef CONFIG_MAC80211_LEDS -@@ -550,6 +557,7 @@ - #define SC_OP_BT_SCAN BIT(13) - #define SC_OP_ANI_RUN BIT(14) - #define SC_OP_ENABLE_APM BIT(15) -+#define SC_OP_PRIM_STA_VIF BIT(16) - - /* Powersave flags */ - #define PS_WAIT_FOR_BEACON BIT(0) -@@ -667,7 +675,7 @@ - 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 -@@ -675,7 +683,7 @@ - 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 -@@ -688,8 +696,6 @@ - - u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); - --void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -- - void ath_start_rfkill_poll(struct ath_softc *sc); - extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); - void ath9k_calculate_iter_data(struct ieee80211_hw *hw, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/beacon.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/beacon.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/beacon.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/beacon.c 2011-05-05 23:29:49.082485325 +0200 -@@ -57,8 +57,8 @@ - - /* - * Associates the beacon frame buffer with a transmit descriptor. Will set -- * up all required antenna switch parameters, rate codes, and channel flags. -- * Beacons are always sent out at the lowest rate, and are not retried. -+ * up rate codes, and channel flags. Beacons are always sent out at the -+ * lowest rate, and are not retried. - */ - static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, - struct ath_buf *bf, int rateidx) -@@ -68,7 +68,7 @@ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_desc *ds; - struct ath9k_11n_rate_series series[4]; -- int flags, antenna, ctsrate = 0, ctsduration = 0; -+ int flags, ctsrate = 0, ctsduration = 0; - struct ieee80211_supported_band *sband; - u8 rate = 0; - -@@ -76,12 +76,6 @@ - flags = ATH9K_TXDESC_NOACK; - - ds->ds_link = 0; -- /* -- * Switch antenna every beacon. -- * Should only switch every beacon period, not for every SWBA -- * XXX assumes two antennae -- */ -- antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); - - sband = &sc->sbands[common->hw->conf.channel->band]; - rate = sband->bitrates[rateidx].hw_value; -@@ -278,7 +272,7 @@ - return -ENOMEM; - - tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; -- sc->beacon.bc_tstamp = le64_to_cpu(tstamp); -+ sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); - /* Calculate a TSF adjustment factor required for staggered beacons. */ - if (avp->av_bslot > 0) { - u64 tsfadjust; -@@ -294,8 +288,8 @@ - * adjustment. Other slots are adjusted to get the timestamp - * close to the TBTT for the BSS. - */ -- tsfadjust = intval * avp->av_bslot / ATH_BCBUF; -- avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); -+ tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; -+ avp->tsf_adjust = cpu_to_le64(tsfadjust); - - ath_dbg(common, ATH_DBG_BEACON, - "stagger beacons, bslot %d intval %u tsfadjust %llu\n", -@@ -326,9 +320,11 @@ - 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--; -+ avp->av_bslot = -1; - } - - bf = avp->av_bcbuf; -@@ -369,12 +365,13 @@ - if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { - sc->beacon.bmisscnt++; - -- if (sc->beacon.bmisscnt < BSTUCK_THRESH) { -+ if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { - ath_dbg(common, ATH_DBG_BSTUCK, - "missed %u consecutive beacons\n", - sc->beacon.bmisscnt); - ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); -- ath9k_hw_bstuck_nfcal(ah); -+ if (sc->beacon.bmisscnt > 3) -+ ath9k_hw_bstuck_nfcal(ah); - } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - ath_dbg(common, ATH_DBG_BSTUCK, - "beacon is officially stuck\n"); -@@ -385,13 +382,6 @@ - return; - } - -- if (sc->beacon.bmisscnt != 0) { -- ath_dbg(common, ATH_DBG_BSTUCK, -- "resume beacon xmit after %u misses\n", -- sc->beacon.bmisscnt); -- sc->beacon.bmisscnt = 0; -- } -- - /* - * Generate beacon frames. we are sending frames - * staggered so calculate the slot for this frame based -@@ -401,21 +391,14 @@ - intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; - - tsf = ath9k_hw_gettsf64(ah); -- tsftu = TSF_TO_TU(tsf>>32, tsf); -- slot = ((tsftu % intval) * ATH_BCBUF) / intval; -- /* -- * Reverse the slot order to get slot 0 on the TBTT offset that does -- * not require TSF adjustment and other slots adding -- * slot/ATH_BCBUF * beacon_int to timestamp. For example, with -- * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. -- * and slot 0 is at correct offset to TBTT. -- */ -- slot = ATH_BCBUF - slot - 1; -+ tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); -+ tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); -+ slot = (tsftu % (intval * ATH_BCBUF)) / intval; - vif = sc->beacon.bslot[slot]; - - ath_dbg(common, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", -- slot, tsf, tsftu, intval, vif); -+ slot, tsf, tsftu / ATH_BCBUF, intval, vif); - - bfaddr = 0; - if (vif) { -@@ -424,6 +407,13 @@ - bfaddr = bf->bf_daddr; - bc = 1; - } -+ -+ if (sc->beacon.bmisscnt != 0) { -+ ath_dbg(common, ATH_DBG_BSTUCK, -+ "resume beacon xmit after %u misses\n", -+ sc->beacon.bmisscnt); -+ sc->beacon.bmisscnt = 0; -+ } - } - - /* -@@ -463,13 +453,17 @@ - u32 next_beacon, - u32 beacon_period) - { -- if (beacon_period & ATH9K_BEACON_RESET_TSF) -+ if (sc->sc_flags & SC_OP_TSF_RESET) { - ath9k_ps_wakeup(sc); -+ ath9k_hw_reset_tsf(sc->sc_ah); -+ } - - ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); - -- if (beacon_period & ATH9K_BEACON_RESET_TSF) -+ if (sc->sc_flags & SC_OP_TSF_RESET) { - ath9k_ps_restore(sc); -+ sc->sc_flags &= ~SC_OP_TSF_RESET; -+ } - } - - /* -@@ -484,18 +478,14 @@ - u32 nexttbtt, intval; - - /* NB: the beacon interval is kept internally in TU's */ -- intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; -+ intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); - intval /= ATH_BCBUF; /* for staggered beacons */ - nexttbtt = intval; - -- if (sc->sc_flags & SC_OP_TSF_RESET) -- intval |= ATH9K_BEACON_RESET_TSF; -- - /* - * In AP mode we enable the beacon timers and SWBA interrupts to - * prepare beacon frames. - */ -- intval |= ATH9K_BEACON_ENA; - ah->imask |= ATH9K_INT_SWBA; - ath_beaconq_config(sc); - -@@ -505,11 +495,6 @@ - ath9k_beacon_init(sc, nexttbtt, intval); - sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(ah, ah->imask); -- -- /* Clear the reset TSF flag, so that subsequent beacon updation -- will not reset the HW TSF. */ -- -- sc->sc_flags &= ~SC_OP_TSF_RESET; - } - - /* -@@ -643,25 +628,20 @@ - { - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); -- u64 tsf; -- u32 tsftu, intval, nexttbtt; -- -- intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; -+ u32 tsf, delta, intval, nexttbtt; - -+ tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); -+ intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); - -- /* Pull nexttbtt forward to reflect the current TSF */ -- -- nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); -- if (nexttbtt == 0) -- nexttbtt = intval; -- else if (intval) -- nexttbtt = roundup(nexttbtt, intval); -- -- tsf = ath9k_hw_gettsf64(ah); -- tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; -- do { -- nexttbtt += intval; -- } while (nexttbtt < tsftu); -+ if (!sc->beacon.bc_tstamp) -+ nexttbtt = tsf + intval; -+ else { -+ if (tsf > sc->beacon.bc_tstamp) -+ delta = (tsf - sc->beacon.bc_tstamp); -+ else -+ delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); -+ nexttbtt = tsf + roundup(delta, intval); -+ } - - ath_dbg(common, ATH_DBG_BEACON, - "IBSS nexttbtt %u intval %u (%u)\n", -@@ -672,7 +652,6 @@ - * if we need to manually prepare beacon frames. Otherwise we use a - * self-linked tx descriptor and let the hardware deal with things. - */ -- intval |= ATH9K_BEACON_ENA; - ah->imask |= ATH9K_INT_SWBA; - - ath_beaconq_config(sc); -@@ -685,22 +664,63 @@ - ath9k_hw_set_interrupts(ah, ah->imask); - } - --void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) -+static bool ath9k_allow_beacon_config(struct ath_softc *sc, -+ struct ieee80211_vif *vif) - { - struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); -- enum nl80211_iftype iftype; -+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -+ struct ath_vif *avp = (void *)vif->drv_priv; - -- /* Setup the beacon configuration parameters */ -- if (vif) { -- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -- iftype = vif->type; -- cur_conf->beacon_interval = bss_conf->beacon_int; -- cur_conf->dtim_period = bss_conf->dtim_period; -- } else { -- iftype = sc->sc_ah->opmode; -+ /* -+ * Can not have different beacon interval on multiple -+ * AP interface case -+ */ -+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && -+ (sc->nbcnvifs > 1) && -+ (vif->type == NL80211_IFTYPE_AP) && -+ (cur_conf->beacon_interval != bss_conf->beacon_int)) { -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Changing beacon interval of multiple \ -+ AP interfaces !\n"); -+ return false; -+ } -+ /* -+ * Can not configure station vif's beacon config -+ * while on AP opmode -+ */ -+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && -+ (vif->type != NL80211_IFTYPE_AP)) { -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "STA vif's beacon not allowed on AP mode\n"); -+ return false; -+ } -+ /* -+ * Do not allow beacon config if HW was already configured -+ * with another STA vif -+ */ -+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && -+ (vif->type == NL80211_IFTYPE_STATION) && -+ (sc->sc_flags & SC_OP_BEACONS) && -+ !avp->primary_sta_vif) { -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Beacon already configured for a station interface\n"); -+ return false; - } -+ return true; -+} -+ -+void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) -+{ -+ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; -+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - -+ if (!ath9k_allow_beacon_config(sc, vif)) -+ return; -+ -+ /* Setup the beacon configuration parameters */ -+ cur_conf->beacon_interval = bss_conf->beacon_int; -+ cur_conf->dtim_period = bss_conf->dtim_period; - cur_conf->listen_interval = 1; - cur_conf->dtim_count = 1; - cur_conf->bmiss_timeout = -@@ -723,9 +743,37 @@ - if (cur_conf->dtim_period == 0) - cur_conf->dtim_period = 1; - -- switch (iftype) { -+ ath_set_beacon(sc); -+} -+ -+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); -+ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; -+ -+ 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: -@@ -746,26 +794,15 @@ - 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; -+ -+ if (!ath_has_valid_bslot(sc)) -+ return; - - ath9k_ps_wakeup(sc); - if (status) { -- 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) { -- /* Re-enable beaconing */ -- ah->imask |= ATH9K_INT_SWBA; -- ath9k_hw_set_interrupts(ah, ah->imask); -- } -+ /* Re-enable beaconing */ -+ ah->imask |= ATH9K_INT_SWBA; -+ ath9k_hw_set_interrupts(ah, ah->imask); - } else { - /* Disable SWBA interrupt */ - ah->imask &= ~ATH9K_INT_SWBA; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/btcoex.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/btcoex.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/btcoex.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/btcoex.c 2011-05-05 23:29:49.071485191 +0200 -@@ -51,6 +51,10 @@ - .bt_hold_rx_clear = true, - }; - u32 i; -+ bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; -+ -+ if (AR_SREV_9300_20_OR_LATER(ah)) -+ rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; - - btcoex_hw->bt_coex_mode = - (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | -@@ -59,7 +63,7 @@ - SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | - SM(ath_bt_config.bt_mode, AR_BT_MODE) | - SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | -- SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | -+ SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | - SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | - SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | - SM(qnum, AR_BT_QCU_THRESH); -@@ -142,6 +146,7 @@ - } - EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); - -+ - static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) - { - struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; -@@ -152,9 +157,22 @@ - * enable coex 3-wire - */ - REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); -- REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); - REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); - -+ -+ if (AR_SREV_9300_20_OR_LATER(ah)) { -+ REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]); -+ REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]); -+ -+ } else -+ REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); -+ -+ -+ - if (AR_SREV_9271(ah)) { - val = REG_READ(ah, 0x50040); - val &= 0xFFFFFEFF; -@@ -202,10 +220,86 @@ - - if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { - REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); -- REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); - REG_WRITE(ah, AR_BT_COEX_MODE2, 0); -+ -+ if (AR_SREV_9300_20_OR_LATER(ah)) { -+ REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0); -+ REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0); -+ REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0); -+ } else -+ REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); -+ - } - - ah->btcoex_hw.enabled = false; - } - EXPORT_SYMBOL(ath9k_hw_btcoex_disable); -+ -+static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, -+ enum ath_stomp_type stomp_type) -+{ -+ ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT; -+ ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT; -+ ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT; -+ ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT; -+ -+ -+ switch (stomp_type) { -+ case ATH_BTCOEX_STOMP_ALL: -+ ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0; -+ ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1; -+ break; -+ case ATH_BTCOEX_STOMP_LOW: -+ ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0; -+ ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1; -+ break; -+ case ATH_BTCOEX_STOMP_NONE: -+ ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0; -+ ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1; -+ break; -+ -+ default: -+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, -+ "Invalid Stomptype\n"); -+ break; -+ } -+ -+ ath9k_hw_btcoex_enable(ah); -+} -+ -+/* -+ * Configures appropriate weight based on stomp type. -+ */ -+void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, -+ enum ath_stomp_type stomp_type) -+{ -+ if (AR_SREV_9300_20_OR_LATER(ah)) { -+ ar9003_btcoex_bt_stomp(ah, stomp_type); -+ return; -+ } -+ -+ switch (stomp_type) { -+ case ATH_BTCOEX_STOMP_ALL: -+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -+ AR_STOMP_ALL_WLAN_WGHT); -+ break; -+ case ATH_BTCOEX_STOMP_LOW: -+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -+ AR_STOMP_LOW_WLAN_WGHT); -+ break; -+ case ATH_BTCOEX_STOMP_NONE: -+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -+ AR_STOMP_NONE_WLAN_WGHT); -+ break; -+ default: -+ ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, -+ "Invalid Stomptype\n"); -+ break; -+ } -+ -+ ath9k_hw_btcoex_enable(ah); -+} -+EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/btcoex.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/btcoex.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/btcoex.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/btcoex.h 2011-05-05 23:29:49.078485277 +0200 -@@ -19,9 +19,13 @@ - - #include "hw.h" - --#define ATH_WLANACTIVE_GPIO 5 --#define ATH_BTACTIVE_GPIO 6 --#define ATH_BTPRIORITY_GPIO 7 -+#define ATH_WLANACTIVE_GPIO_9280 5 -+#define ATH_BTACTIVE_GPIO_9280 6 -+#define ATH_BTPRIORITY_GPIO_9285 7 -+ -+#define ATH_WLANACTIVE_GPIO_9300 5 -+#define ATH_BTACTIVE_GPIO_9300 4 -+#define ATH_BTPRIORITY_GPIO_9300 8 - - #define ATH_BTCOEX_DEF_BT_PERIOD 45 - #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 -@@ -32,6 +36,14 @@ - #define ATH_BT_CNT_THRESHOLD 3 - #define ATH_BT_CNT_SCAN_THRESHOLD 15 - -+/* Defines the BT AR_BT_COEX_WGHT used */ -+enum ath_stomp_type { -+ ATH_BTCOEX_NO_STOMP, -+ ATH_BTCOEX_STOMP_ALL, -+ ATH_BTCOEX_STOMP_LOW, -+ ATH_BTCOEX_STOMP_NONE -+}; -+ - enum ath_btcoex_scheme { - ATH_BTCOEX_CFG_NONE, - ATH_BTCOEX_CFG_2WIRE, -@@ -57,5 +69,7 @@ - u32 wlan_weight); - void ath9k_hw_btcoex_enable(struct ath_hw *ah); - void ath9k_hw_btcoex_disable(struct ath_hw *ah); -+void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, -+ enum ath_stomp_type stomp_type); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/common.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/common.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/common.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/common.c 2011-05-05 23:29:49.070485179 +0200 -@@ -116,7 +116,7 @@ - - if (chan->band == IEEE80211_BAND_2GHZ) { - ichan->chanmode = CHANNEL_G; -- ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; -+ ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; - } else { - ichan->chanmode = CHANNEL_A; - ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; -@@ -158,37 +158,6 @@ - } - EXPORT_SYMBOL(ath9k_cmn_count_streams); - --/* -- * Configures appropriate weight based on stomp type. -- */ --void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, -- enum ath_stomp_type stomp_type) --{ -- struct ath_hw *ah = common->ah; -- -- switch (stomp_type) { -- case ATH_BTCOEX_STOMP_ALL: -- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -- AR_STOMP_ALL_WLAN_WGHT); -- break; -- case ATH_BTCOEX_STOMP_LOW: -- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -- AR_STOMP_LOW_WLAN_WGHT); -- break; -- case ATH_BTCOEX_STOMP_NONE: -- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, -- AR_STOMP_NONE_WLAN_WGHT); -- break; -- default: -- ath_dbg(common, ATH_DBG_BTCOEX, -- "Invalid Stomptype\n"); -- break; -- } -- -- ath9k_hw_btcoex_enable(ah); --} --EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); -- - void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, - u16 new_txpow, u16 *txpower) - { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/common.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/common.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/common.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/common.h 2011-05-05 23:29:49.079485289 +0200 -@@ -50,14 +50,6 @@ - #define ATH_EP_RND(x, mul) \ - ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) - --/* Defines the BT AR_BT_COEX_WGHT used */ --enum ath_stomp_type { -- ATH_BTCOEX_NO_STOMP, -- ATH_BTCOEX_STOMP_ALL, -- ATH_BTCOEX_STOMP_LOW, -- ATH_BTCOEX_STOMP_NONE --}; -- - int ath9k_cmn_padpos(__le16 frame_control); - int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); - void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/debug.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/debug.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/debug.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/debug.c 2011-05-05 23:29:49.081485313 +0200 -@@ -326,6 +326,8 @@ - sc->debug.stats.istats.dtimsync++; - if (status & ATH9K_INT_DTIM) - sc->debug.stats.istats.dtim++; -+ if (status & ATH9K_INT_TSFOOR) -+ sc->debug.stats.istats.tsfoor++; - } - - static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, -@@ -380,8 +382,11 @@ - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); - len += snprintf(buf + len, sizeof(buf) - len, -+ "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); -+ len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); - -+ - if (len > sizeof(buf)) - len = sizeof(buf); - -@@ -845,7 +850,7 @@ - - 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 +879,34 @@ - "%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 +981,16 @@ - 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 - } -@@ -1088,67 +1131,43 @@ - return -ENOMEM; - - #ifdef CONFIG_ATH_DEBUG -- if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_debug)) -- goto err; -+ debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_debug); - #endif -+ debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_dma); -+ debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_interrupt); -+ debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_wiphy); -+ debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_xmit); -+ debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_stations); -+ debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_misc); -+ debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_recv); -+ debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, sc, &fops_rx_chainmask); -+ debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, sc, &fops_tx_chainmask); -+ debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_regidx); -+ debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -+ sc, &fops_regval); -+ debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, -+ &ah->config.cwm_ignore_extcca); -+ debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, -+ &fops_regdump); -+ -+ debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); - -- if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_dma)) -- goto err; -- -- if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_interrupt)) -- goto err; -- -- if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_wiphy)) -- goto err; -- -- if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_xmit)) -- goto err; -- -- if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_stations)) -- goto err; -- -- if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_misc)) -- goto err; -- -- if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_recv)) -- goto err; -- -- if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_rx_chainmask)) -- goto err; -- -- if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) -- goto err; -- -- if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_regidx)) -- goto err; -- -- if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, &fops_regval)) -- goto err; -- -- if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) -- goto err; -- -- if (!debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, -- sc, &fops_regdump)) -- goto err; -+ debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); - - sc->debug.regidx = 0; - return 0; --err: -- debugfs_remove_recursive(sc->debug.debugfs_phy); -- sc->debug.debugfs_phy = NULL; -- return -ENOMEM; - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/debug.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/debug.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/debug.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/debug.h 2011-05-05 23:29:49.086485373 +0200 -@@ -54,6 +54,9 @@ - * @dtimsync: DTIM sync lossage - * @dtim: RX Beacon with DTIM - * @bb_watchdog: Baseband watchdog -+ * @tsfoor: TSF out of range, indicates that the corrected TSF received -+ * from a beacon differs from the PCU's internal TSF by more than a -+ * (programmable) threshold - */ - struct ath_interrupt_stats { - u32 total; -@@ -78,6 +81,7 @@ - u32 dtimsync; - u32 dtim; - u32 bb_watchdog; -+ u32 tsfoor; - }; - - /** -@@ -157,6 +161,13 @@ - 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 { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_4k.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_4k.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_4k.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_4k.c 2011-05-05 23:29:49.064485107 +0200 -@@ -781,6 +781,7 @@ - { - 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 @@ - 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) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_9287.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_9287.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_9287.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_9287.c 2011-05-05 23:29:49.043484853 +0200 -@@ -319,10 +319,9 @@ - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; - u32 reg32, regOffset, regChainOffset, regval; -- int16_t modalIdx, diff = 0; -+ int16_t diff = 0; - struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; - -- modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; - xpdMask = pEepData->modalHeader.xpdGain; - - if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= -@@ -392,6 +391,8 @@ - numXpdGain); - } - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - if (i == 0) { - if (!ath9k_hw_ar9287_get_eeprom(ah, - EEP_OL_PWRCTRL)) { -@@ -442,6 +443,7 @@ - regOffset += 4; - } - } -+ REGWRITE_BUFFER_FLUSH(ah); - } - } - -@@ -757,6 +759,8 @@ - ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; - } - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - /* OFDM power per rate */ - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) -@@ -840,6 +844,7 @@ - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } -+ REGWRITE_BUFFER_FLUSH(ah); - } - - static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, -@@ -852,35 +857,12 @@ - { - 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++) { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_def.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_def.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom_def.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom_def.c 2011-05-05 23:29:49.074485227 +0200 -@@ -231,6 +231,10 @@ - integer = swab32(pModal->antCtrlChain[i]); - pModal->antCtrlChain[i] = integer; - } -+ for (i = 0; i < 3; i++) { -+ word = swab16(pModal->xpaBiasLvlFreq[i]); -+ pModal->xpaBiasLvlFreq[i] = word; -+ } - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - word = swab16(pModal->spurChans[i].spurChan); -@@ -799,6 +803,8 @@ - pwr_table_offset, - &diff); - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - if (OLC_FOR_AR9280_20_LATER) { - REG_WRITE(ah, -@@ -847,6 +853,7 @@ - - regOffset += 4; - } -+ REGWRITE_BUFFER_FLUSH(ah); - } - } - -@@ -1205,6 +1212,8 @@ - } - } - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) -@@ -1291,6 +1300,8 @@ - REG_WRITE(ah, AR_PHY_POWER_TX_SUB, - ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) - | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); -+ -+ REGWRITE_BUFFER_FLUSH(ah); - } - - static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/eeprom.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/eeprom.h 2011-05-05 23:29:49.075485239 +0200 -@@ -436,7 +436,11 @@ - 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; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/gpio.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/gpio.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/gpio.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/gpio.c 2011-05-05 23:29:49.080485301 +0200 -@@ -41,12 +41,16 @@ - { - int ret; - -- if (AR_SREV_9287(sc->sc_ah)) -- sc->sc_ah->led_pin = ATH_LED_PIN_9287; -- else if (AR_SREV_9485(sc->sc_ah)) -- sc->sc_ah->led_pin = ATH_LED_PIN_9485; -- else -- sc->sc_ah->led_pin = ATH_LED_PIN_DEF; -+ if (sc->sc_ah->led_pin < 0) { -+ if (AR_SREV_9287(sc->sc_ah)) -+ sc->sc_ah->led_pin = ATH_LED_PIN_9287; -+ else if (AR_SREV_9485(sc->sc_ah)) -+ sc->sc_ah->led_pin = ATH_LED_PIN_9485; -+ else if (AR_SREV_9300(sc->sc_ah)) -+ sc->sc_ah->led_pin = ATH_LED_PIN_9300; -+ else -+ sc->sc_ah->led_pin = ATH_LED_PIN_DEF; -+ } - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, -@@ -136,10 +140,10 @@ - - static void ath9k_gen_timer_start(struct ath_hw *ah, - struct ath_gen_timer *timer, -- u32 timer_next, -+ u32 trig_timeout, - u32 timer_period) - { -- ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); -+ ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period); - - if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_disable_interrupts(ah); -@@ -172,17 +176,17 @@ - struct ath_softc *sc = (struct ath_softc *) data; - struct ath_hw *ah = sc->sc_ah; - struct ath_btcoex *btcoex = &sc->btcoex; -- struct ath_common *common = ath9k_hw_common(ah); - u32 timer_period; - bool is_btscan; - -+ ath9k_ps_wakeup(sc); - ath_detect_bt_priority(sc); - - is_btscan = sc->sc_flags & SC_OP_BT_SCAN; - - spin_lock_bh(&btcoex->btcoex_lock); - -- ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : -+ ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : - btcoex->bt_stomp_type); - - spin_unlock_bh(&btcoex->btcoex_lock); -@@ -193,11 +197,12 @@ - - timer_period = is_btscan ? btcoex->btscan_no_stomp : - btcoex->btcoex_no_stomp; -- ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0, -+ ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, - timer_period * 10); - btcoex->hw_timer_enabled = true; - } - -+ ath9k_ps_restore(sc); - mod_timer(&btcoex->period_timer, jiffies + - msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); - } -@@ -217,14 +222,16 @@ - ath_dbg(common, ATH_DBG_BTCOEX, - "no stomp timer running\n"); - -+ ath9k_ps_wakeup(sc); - spin_lock_bh(&btcoex->btcoex_lock); - - if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) -- ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); -+ ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); - else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) -- ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); -+ ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); - - spin_unlock_bh(&btcoex->btcoex_lock); -+ ath9k_ps_restore(sc); - } - - int ath_init_btcoex_timer(struct ath_softc *sc) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hif_usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hif_usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hif_usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hif_usb.c 2011-05-05 23:29:49.091485433 +0200 -@@ -17,11 +17,9 @@ - #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 @@ - - if (cmd) { - ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, -- cmd->skb, 1); -+ cmd->skb, true); - kfree(cmd); - } - -@@ -126,6 +124,90 @@ - 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 @@ - - 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 @@ - { - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - &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 @@ - 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 @@ - - .start = hif_usb_start, - .stop = hif_usb_stop, -+ .sta_drain = hif_usb_sta_drain, - .send = hif_usb_send, - }; - -@@ -567,6 +686,9 @@ - case -ESHUTDOWN: - goto free; - default: -+ skb_reset_tail_pointer(skb); -+ skb_trim(skb, 0); -+ - goto resubmit; - } - -@@ -591,23 +713,15 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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 @@ - /* 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; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hif_usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hif_usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hif_usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hif_usb.h 2011-05-05 23:29:49.085485361 +0200 -@@ -17,6 +17,9 @@ - #ifndef HTC_USB_H - #define HTC_USB_H - -+#define MAJOR_VERSION_REQ 1 -+#define MINOR_VERSION_REQ 2 -+ - #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) - - #define AR9271_FIRMWARE 0x501000 -@@ -31,7 +34,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 +43,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 +93,10 @@ - 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c 2011-05-05 23:29:49.072485203 +0200 -@@ -18,6 +18,50 @@ - - #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) - { -@@ -30,7 +74,7 @@ - __be32 htc_imask = 0; - u64 tsf; - int num_beacons, offset, dtim_dec_count, cfp_dec_count; -- int ret; -+ int ret __attribute__ ((unused)); - u8 cmd_rsp; - - memset(&bs, 0, sizeof(bs)); -@@ -146,7 +190,7 @@ - enum ath9k_int imask = 0; - u32 nexttbtt, intval, tsftu; - __be32 htc_imask = 0; -- int ret; -+ int ret __attribute__ ((unused)); - u8 cmd_rsp; - u64 tsf; - -@@ -154,8 +198,17 @@ - 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) { -- intval |= ATH9K_BEACON_RESET_TSF; -+ ath9k_hw_reset_tsf(priv->ah); - priv->op_flags &= ~OP_TSF_RESET; - } else { - /* -@@ -168,18 +221,20 @@ - } while (nexttbtt < tsftu); - } - -- intval |= ATH9K_BEACON_ENA; -- - if (priv->op_flags & OP_ENABLE_BEACON) - 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, nexttbtt, intval); -- priv->bmiss_cnt = 0; -+ ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); -+ priv->cur_beacon_conf.bmiss_cnt = 0; - htc_imask = cpu_to_be32(imask); - WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); - } -@@ -191,7 +246,7 @@ - enum ath9k_int imask = 0; - u32 nexttbtt, intval, tsftu; - __be32 htc_imask = 0; -- int ret; -+ int ret __attribute__ ((unused)); - u8 cmd_rsp; - u64 tsf; - -@@ -207,17 +262,26 @@ - nexttbtt += intval; - } while (nexttbtt < tsftu); - -- intval |= ATH9K_BEACON_ENA; -+ /* -+ * 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, nexttbtt, intval); -- priv->bmiss_cnt = 0; -+ ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); -+ priv->cur_beacon_conf.bmiss_cnt = 0; - htc_imask = cpu_to_be32(imask); - WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); - } -@@ -228,38 +292,101 @@ - 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 = -@@ -269,45 +396,149 @@ - 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); - } - --/* Currently, only for IBSS */ --void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) -+static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, -+ struct wmi_event_swba *swba) - { -- 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); -+ 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); - -- memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); -- memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); -+ return slot; -+} - -- ath9k_hw_get_txq_props(ah, qnum, &qi_be); -+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; - -- 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 (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 (!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); -+ 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); -+} -+ -+void ath9k_htc_assign_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; -+ int i = 0; -+ -+ 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); -+} -+ -+/* -+ * 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; -+ -+ /* -+ * 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. -+ */ -+ tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; -+ avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); -+ -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "tsfadjust is: %llu for bslot: %d\n", -+ (unsigned long long)tsfadjust, avp->bslot); - } - - static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_debug.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_debug.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_debug.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_debug.c 2011-05-05 23:29:49.025484635 +0200 -@@ -0,0 +1,960 @@ -+/* -+ * 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)); -+ -+ ath9k_htc_ps_wakeup(priv); -+ -+ WMI_CMD(WMI_INT_STATS_CMDID); -+ if (ret) { -+ ath9k_htc_ps_restore(priv); -+ return -EINVAL; -+ } -+ -+ ath9k_htc_ps_restore(priv); -+ -+ 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)); -+ -+ ath9k_htc_ps_wakeup(priv); -+ -+ WMI_CMD(WMI_TX_STATS_CMDID); -+ if (ret) { -+ ath9k_htc_ps_restore(priv); -+ return -EINVAL; -+ } -+ -+ ath9k_htc_ps_restore(priv); -+ -+ 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)); -+ -+ ath9k_htc_ps_wakeup(priv); -+ -+ WMI_CMD(WMI_RX_STATS_CMDID); -+ if (ret) { -+ ath9k_htc_ps_restore(priv); -+ return -EINVAL; -+ } -+ -+ ath9k_htc_ps_restore(priv); -+ -+ 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, -+}; -+ -+static ssize_t read_file_base_eeprom(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); -+ struct base_eep_header *pBase = NULL; -+ unsigned int len = 0, size = 1500; -+ ssize_t retval = 0; -+ char *buf; -+ -+ /* -+ * This can be done since all the 3 EEPROM families have the -+ * same base header upto a certain point, and we are interested in -+ * the data only upto that point. -+ */ -+ -+ if (AR_SREV_9271(priv->ah)) -+ pBase = (struct base_eep_header *) -+ &priv->ah->eeprom.map4k.baseEepHeader; -+ else if (priv->ah->hw_version.usbdev == AR9280_USB) -+ pBase = (struct base_eep_header *) -+ &priv->ah->eeprom.def.baseEepHeader; -+ else if (priv->ah->hw_version.usbdev == AR9287_USB) -+ pBase = (struct base_eep_header *) -+ &priv->ah->eeprom.map9287.baseEepHeader; -+ -+ if (pBase == NULL) { -+ ath_err(common, "Unknown EEPROM type\n"); -+ return 0; -+ } -+ -+ buf = kzalloc(size, GFP_KERNEL); -+ if (buf == NULL) -+ return -ENOMEM; -+ -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "Major Version", -+ pBase->version >> 12); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "Minor Version", -+ pBase->version & 0xFFF); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "Checksum", -+ pBase->checksum); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "Length", -+ pBase->length); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "RegDomain1", -+ pBase->regDmn[0]); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", "RegDomain2", -+ pBase->regDmn[1]); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "TX Mask", pBase->txMask); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "RX Mask", pBase->rxMask); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Allow 5GHz", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Allow 2GHz", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Disable 2GHz HT20", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Disable 2GHz HT40", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Disable 5Ghz HT20", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Disable 5Ghz HT40", -+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Big Endian", -+ !!(pBase->eepMisc & 0x01)); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Cal Bin Major Ver", -+ (pBase->binBuildNumber >> 24) & 0xFF); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Cal Bin Minor Ver", -+ (pBase->binBuildNumber >> 16) & 0xFF); -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "Cal Bin Build", -+ (pBase->binBuildNumber >> 8) & 0xFF); -+ -+ /* -+ * UB91 specific data. -+ */ -+ if (AR_SREV_9271(priv->ah)) { -+ struct base_eep_header_4k *pBase4k = -+ &priv->ah->eeprom.map4k.baseEepHeader; -+ -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "TX Gain type", -+ pBase4k->txGainType); -+ } -+ -+ /* -+ * UB95 specific data. -+ */ -+ if (priv->ah->hw_version.usbdev == AR9287_USB) { -+ struct base_eep_ar9287_header *pBase9287 = -+ &priv->ah->eeprom.map9287.baseEepHeader; -+ -+ len += snprintf(buf + len, size - len, -+ "%20s : %10ddB\n", -+ "Power Table Offset", -+ pBase9287->pwrTableOffset); -+ -+ len += snprintf(buf + len, size - len, -+ "%20s : %10d\n", -+ "OpenLoop Power Ctrl", -+ pBase9287->openLoopPwrCntl); -+ } -+ -+ len += snprintf(buf + len, size - len, -+ "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n", -+ "MacAddress", -+ pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2], -+ pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]); -+ if (len > size) -+ len = size; -+ -+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); -+ kfree(buf); -+ -+ return retval; -+} -+ -+static const struct file_operations fops_base_eeprom = { -+ .read = read_file_base_eeprom, -+ .open = ath9k_debugfs_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+static ssize_t read_4k_modal_eeprom(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+#define PR_EEP(_s, _val) \ -+ do { \ -+ len += snprintf(buf + len, size - len, "%20s : %10d\n", \ -+ _s, (_val)); \ -+ } while (0) -+ -+ struct ath9k_htc_priv *priv = file->private_data; -+ struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader; -+ unsigned int len = 0, size = 2048; -+ ssize_t retval = 0; -+ char *buf; -+ -+ buf = kzalloc(size, GFP_KERNEL); -+ if (buf == NULL) -+ return -ENOMEM; -+ -+ PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); -+ PR_EEP("Ant. Common Control", pModal->antCtrlCommon); -+ PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); -+ PR_EEP("Switch Settle", pModal->switchSettling); -+ PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); -+ PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); -+ PR_EEP("ADC Desired size", pModal->adcDesiredSize); -+ PR_EEP("PGA Desired size", pModal->pgaDesiredSize); -+ PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); -+ PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); -+ PR_EEP("txEndToRxOn", pModal->txEndToRxOn); -+ PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); -+ PR_EEP("CCA Threshold)", pModal->thresh62); -+ PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); -+ PR_EEP("xpdGain", pModal->xpdGain); -+ PR_EEP("External PD", pModal->xpd); -+ PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); -+ PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); -+ PR_EEP("pdGainOverlap", pModal->pdGainOverlap); -+ PR_EEP("O/D Bias Version", pModal->version); -+ PR_EEP("CCK OutputBias", pModal->ob_0); -+ PR_EEP("BPSK OutputBias", pModal->ob_1); -+ PR_EEP("QPSK OutputBias", pModal->ob_2); -+ PR_EEP("16QAM OutputBias", pModal->ob_3); -+ PR_EEP("64QAM OutputBias", pModal->ob_4); -+ PR_EEP("CCK Driver1_Bias", pModal->db1_0); -+ PR_EEP("BPSK Driver1_Bias", pModal->db1_1); -+ PR_EEP("QPSK Driver1_Bias", pModal->db1_2); -+ PR_EEP("16QAM Driver1_Bias", pModal->db1_3); -+ PR_EEP("64QAM Driver1_Bias", pModal->db1_4); -+ PR_EEP("CCK Driver2_Bias", pModal->db2_0); -+ PR_EEP("BPSK Driver2_Bias", pModal->db2_1); -+ PR_EEP("QPSK Driver2_Bias", pModal->db2_2); -+ PR_EEP("16QAM Driver2_Bias", pModal->db2_3); -+ PR_EEP("64QAM Driver2_Bias", pModal->db2_4); -+ PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); -+ PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); -+ PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); -+ PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); -+ PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); -+ PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); -+ PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); -+ PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); -+ PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); -+ PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1); -+ PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2); -+ PR_EEP("TX Diversity", pModal->tx_diversity); -+ -+ if (len > size) -+ len = size; -+ -+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); -+ kfree(buf); -+ -+ return retval; -+ -+#undef PR_EEP -+} -+ -+static ssize_t read_def_modal_eeprom(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+#define PR_EEP(_s, _val) \ -+ do { \ -+ if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ -+ pModal = &priv->ah->eeprom.def.modalHeader[1]; \ -+ len += snprintf(buf + len, size - len, "%20s : %8d%7s", \ -+ _s, (_val), "|"); \ -+ } \ -+ if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ -+ pModal = &priv->ah->eeprom.def.modalHeader[0]; \ -+ len += snprintf(buf + len, size - len, "%9d\n", \ -+ (_val)); \ -+ } \ -+ } while (0) -+ -+ struct ath9k_htc_priv *priv = file->private_data; -+ struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader; -+ struct modal_eep_header *pModal = NULL; -+ unsigned int len = 0, size = 3500; -+ ssize_t retval = 0; -+ char *buf; -+ -+ buf = kzalloc(size, GFP_KERNEL); -+ if (buf == NULL) -+ return -ENOMEM; -+ -+ len += snprintf(buf + len, size - len, -+ "%31s %15s\n", "2G", "5G"); -+ len += snprintf(buf + len, size - len, -+ "%32s %16s\n", "====", "====\n"); -+ -+ PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); -+ PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); -+ PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]); -+ PR_EEP("Ant. Common Control", pModal->antCtrlCommon); -+ PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); -+ PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); -+ PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]); -+ PR_EEP("Switch Settle", pModal->switchSettling); -+ PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); -+ PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); -+ PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]); -+ PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); -+ PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); -+ PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]); -+ PR_EEP("ADC Desired size", pModal->adcDesiredSize); -+ PR_EEP("PGA Desired size", pModal->pgaDesiredSize); -+ PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); -+ PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]); -+ PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]); -+ PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); -+ PR_EEP("txEndToRxOn", pModal->txEndToRxOn); -+ PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); -+ PR_EEP("CCA Threshold)", pModal->thresh62); -+ PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); -+ PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); -+ PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]); -+ PR_EEP("xpdGain", pModal->xpdGain); -+ PR_EEP("External PD", pModal->xpd); -+ PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); -+ PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); -+ PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]); -+ PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); -+ PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); -+ PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]); -+ PR_EEP("pdGainOverlap", pModal->pdGainOverlap); -+ PR_EEP("Chain0 OutputBias", pModal->ob); -+ PR_EEP("Chain0 DriverBias", pModal->db); -+ PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); -+ PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain); -+ PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain); -+ PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); -+ PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); -+ PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); -+ PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); -+ PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); -+ PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]); -+ PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); -+ PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); -+ PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]); -+ PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); -+ PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); -+ PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]); -+ PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]); -+ PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); -+ PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]); -+ PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]); -+ PR_EEP("Chain1 OutputBias", pModal->ob_ch1); -+ PR_EEP("Chain1 DriverBias", pModal->db_ch1); -+ PR_EEP("LNA Control", pModal->lna_ctl); -+ PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]); -+ PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]); -+ PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]); -+ -+ if (len > size) -+ len = size; -+ -+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); -+ kfree(buf); -+ -+ return retval; -+ -+#undef PR_EEP -+} -+ -+static ssize_t read_9287_modal_eeprom(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+#define PR_EEP(_s, _val) \ -+ do { \ -+ len += snprintf(buf + len, size - len, "%20s : %10d\n", \ -+ _s, (_val)); \ -+ } while (0) -+ -+ struct ath9k_htc_priv *priv = file->private_data; -+ struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader; -+ unsigned int len = 0, size = 3000; -+ ssize_t retval = 0; -+ char *buf; -+ -+ buf = kzalloc(size, GFP_KERNEL); -+ if (buf == NULL) -+ return -ENOMEM; -+ -+ PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); -+ PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); -+ PR_EEP("Ant. Common Control", pModal->antCtrlCommon); -+ PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); -+ PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); -+ PR_EEP("Switch Settle", pModal->switchSettling); -+ PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); -+ PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); -+ PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); -+ PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); -+ PR_EEP("ADC Desired size", pModal->adcDesiredSize); -+ PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); -+ PR_EEP("txEndToRxOn", pModal->txEndToRxOn); -+ PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); -+ PR_EEP("CCA Threshold)", pModal->thresh62); -+ PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); -+ PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); -+ PR_EEP("xpdGain", pModal->xpdGain); -+ PR_EEP("External PD", pModal->xpd); -+ PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); -+ PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); -+ PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); -+ PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); -+ PR_EEP("pdGainOverlap", pModal->pdGainOverlap); -+ PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); -+ PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); -+ PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); -+ PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); -+ PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); -+ PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); -+ PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); -+ PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); -+ PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); -+ PR_EEP("AR92x7 Version", pModal->version); -+ PR_EEP("DriverBias1", pModal->db1); -+ PR_EEP("DriverBias2", pModal->db1); -+ PR_EEP("CCK OutputBias", pModal->ob_cck); -+ PR_EEP("PSK OutputBias", pModal->ob_psk); -+ PR_EEP("QAM OutputBias", pModal->ob_qam); -+ PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off); -+ -+ if (len > size) -+ len = size; -+ -+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); -+ kfree(buf); -+ -+ return retval; -+ -+#undef PR_EEP -+} -+ -+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath9k_htc_priv *priv = file->private_data; -+ -+ if (AR_SREV_9271(priv->ah)) -+ return read_4k_modal_eeprom(file, user_buf, count, ppos); -+ else if (priv->ah->hw_version.usbdev == AR9280_USB) -+ return read_def_modal_eeprom(file, user_buf, count, ppos); -+ else if (priv->ah->hw_version.usbdev == AR9287_USB) -+ return read_9287_modal_eeprom(file, user_buf, count, ppos); -+ -+ return 0; -+} -+ -+static const struct file_operations fops_modal_eeprom = { -+ .read = read_file_modal_eeprom, -+ .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); -+ debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy, -+ priv, &fops_base_eeprom); -+ debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy, -+ priv, &fops_modal_eeprom); -+ -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c 2011-05-05 23:29:49.089485409 +0200 -@@ -65,17 +65,19 @@ - u32 timer_period; - bool is_btscan; - int ret; -- u8 cmd_rsp, aggr; - - ath_detect_bt_priority(priv); - - is_btscan = !!(priv->op_flags & OP_BT_SCAN); - -- aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; -- -- WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); -+ ret = ath9k_htc_update_cap_target(priv, -+ !!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); -+ if (ret) { -+ ath_err(common, "Unable to set BTCOEX parameters\n"); -+ return; -+ } - -- ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : -+ ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : - btcoex->bt_stomp_type); - - timer_period = is_btscan ? btcoex->btscan_no_stomp : -@@ -103,9 +105,9 @@ - "time slice work for bt and wlan\n"); - - if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) -- ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); -+ ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); - else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) -- ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); -+ ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); - } - - void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) -@@ -152,140 +154,41 @@ - /* LED */ - /*******/ - --static void ath9k_led_blink_work(struct work_struct *work) -+#ifdef CONFIG_MAC80211_LEDS -+void ath9k_led_work(struct work_struct *work) - { -- struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, -- ath9k_led_blink_work.work); -- -- if (!(priv->op_flags & OP_LED_ASSOCIATED)) -- return; -- -- if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || -- (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) -- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); -- else -- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, -- (priv->op_flags & OP_LED_ON) ? 1 : 0); -+ struct ath9k_htc_priv *priv = container_of(work, -+ struct ath9k_htc_priv, -+ led_work); - -- ieee80211_queue_delayed_work(priv->hw, -- &priv->ath9k_led_blink_work, -- (priv->op_flags & OP_LED_ON) ? -- msecs_to_jiffies(priv->led_off_duration) : -- msecs_to_jiffies(priv->led_on_duration)); -- -- priv->led_on_duration = priv->led_on_cnt ? -- max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : -- ATH_LED_ON_DURATION_IDLE; -- priv->led_off_duration = priv->led_off_cnt ? -- max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : -- ATH_LED_OFF_DURATION_IDLE; -- priv->led_on_cnt = priv->led_off_cnt = 0; -- -- if (priv->op_flags & OP_LED_ON) -- priv->op_flags &= ~OP_LED_ON; -- else -- priv->op_flags |= OP_LED_ON; --} -- --static void ath9k_led_brightness_work(struct work_struct *work) --{ -- struct ath_led *led = container_of(work, struct ath_led, -- brightness_work.work); -- struct ath9k_htc_priv *priv = led->priv; -- -- switch (led->brightness) { -- case LED_OFF: -- if (led->led_type == ATH_LED_ASSOC || -- led->led_type == ATH_LED_RADIO) { -- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, -- (led->led_type == ATH_LED_RADIO)); -- priv->op_flags &= ~OP_LED_ASSOCIATED; -- if (led->led_type == ATH_LED_RADIO) -- priv->op_flags &= ~OP_LED_ON; -- } else { -- priv->led_off_cnt++; -- } -- break; -- case LED_FULL: -- if (led->led_type == ATH_LED_ASSOC) { -- priv->op_flags |= OP_LED_ASSOCIATED; -- ieee80211_queue_delayed_work(priv->hw, -- &priv->ath9k_led_blink_work, 0); -- } else if (led->led_type == ATH_LED_RADIO) { -- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); -- priv->op_flags |= OP_LED_ON; -- } else { -- priv->led_on_cnt++; -- } -- break; -- default: -- break; -- } -+ ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, -+ (priv->brightness == LED_OFF)); - } - - static void ath9k_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) - { -- struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); -- struct ath9k_htc_priv *priv = led->priv; -- -- led->brightness = brightness; -- if (!(priv->op_flags & OP_LED_DEINIT)) -- ieee80211_queue_delayed_work(priv->hw, -- &led->brightness_work, 0); --} -- --void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) --{ -- cancel_delayed_work_sync(&priv->radio_led.brightness_work); -- cancel_delayed_work_sync(&priv->assoc_led.brightness_work); -- cancel_delayed_work_sync(&priv->tx_led.brightness_work); -- cancel_delayed_work_sync(&priv->rx_led.brightness_work); --} -- --static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, -- char *trigger) --{ -- int ret; -- -- led->priv = priv; -- led->led_cdev.name = led->name; -- led->led_cdev.default_trigger = trigger; -- led->led_cdev.brightness_set = ath9k_led_brightness; -- -- ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); -- if (ret) -- ath_err(ath9k_hw_common(priv->ah), -- "Failed to register led:%s", led->name); -- else -- led->registered = 1; -- -- INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); -- -- return ret; --} -- --static void ath9k_unregister_led(struct ath_led *led) --{ -- if (led->registered) { -- led_classdev_unregister(&led->led_cdev); -- led->registered = 0; -- } -+ struct ath9k_htc_priv *priv = container_of(led_cdev, -+ struct ath9k_htc_priv, -+ led_cdev); -+ -+ /* Not locked, but it's just a tiny green light..*/ -+ priv->brightness = brightness; -+ ieee80211_queue_work(priv->hw, &priv->led_work); - } - - void ath9k_deinit_leds(struct ath9k_htc_priv *priv) - { -- priv->op_flags |= OP_LED_DEINIT; -- ath9k_unregister_led(&priv->assoc_led); -- priv->op_flags &= ~OP_LED_ASSOCIATED; -- ath9k_unregister_led(&priv->tx_led); -- ath9k_unregister_led(&priv->rx_led); -- ath9k_unregister_led(&priv->radio_led); -+ if (!priv->led_registered) -+ return; -+ -+ ath9k_led_brightness(&priv->led_cdev, LED_OFF); -+ led_classdev_unregister(&priv->led_cdev); -+ cancel_work_sync(&priv->led_work); - } - - void ath9k_init_leds(struct ath9k_htc_priv *priv) - { -- char *trigger; - int ret; - - if (AR_SREV_9287(priv->ah)) -@@ -303,48 +206,21 @@ - /* LED off, active low */ - ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); - -- INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); -+ snprintf(priv->led_name, sizeof(priv->led_name), -+ "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); -+ priv->led_cdev.name = priv->led_name; -+ priv->led_cdev.brightness_set = ath9k_led_brightness; - -- trigger = ieee80211_get_radio_led_name(priv->hw); -- snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), -- "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); -- ret = ath9k_register_led(priv, &priv->radio_led, trigger); -- priv->radio_led.led_type = ATH_LED_RADIO; -- if (ret) -- goto fail; -- -- trigger = ieee80211_get_assoc_led_name(priv->hw); -- snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), -- "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); -- ret = ath9k_register_led(priv, &priv->assoc_led, trigger); -- priv->assoc_led.led_type = ATH_LED_ASSOC; -- if (ret) -- goto fail; -- -- trigger = ieee80211_get_tx_led_name(priv->hw); -- snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), -- "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); -- ret = ath9k_register_led(priv, &priv->tx_led, trigger); -- priv->tx_led.led_type = ATH_LED_TX; -- if (ret) -- goto fail; -- -- trigger = ieee80211_get_rx_led_name(priv->hw); -- snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), -- "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); -- ret = ath9k_register_led(priv, &priv->rx_led, trigger); -- priv->rx_led.led_type = ATH_LED_RX; -- if (ret) -- goto fail; -+ ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev); -+ if (ret < 0) -+ return; - -- priv->op_flags &= ~OP_LED_DEINIT; -+ INIT_WORK(&priv->led_work, ath9k_led_work); -+ priv->led_registered = true; - - return; -- --fail: -- cancel_delayed_work_sync(&priv->ath9k_led_blink_work); -- ath9k_deinit_leds(priv); - } -+#endif - - /*******************/ - /* Rfkill */ -@@ -398,9 +274,9 @@ - - /* 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 +305,15 @@ - - /* 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. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_init.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_init.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_init.c 2011-05-05 23:29:49.094485469 +0200 -@@ -117,6 +117,21 @@ - RATE(540, 0x0c, 0), - }; - -+#ifdef CONFIG_MAC80211_LEDS -+static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { -+ { .throughput = 0 * 1024, .blink_time = 334 }, -+ { .throughput = 1 * 1024, .blink_time = 260 }, -+ { .throughput = 5 * 1024, .blink_time = 220 }, -+ { .throughput = 10 * 1024, .blink_time = 190 }, -+ { .throughput = 20 * 1024, .blink_time = 170 }, -+ { .throughput = 50 * 1024, .blink_time = 150 }, -+ { .throughput = 70 * 1024, .blink_time = 130 }, -+ { .throughput = 100 * 1024, .blink_time = 110 }, -+ { .throughput = 200 * 1024, .blink_time = 80 }, -+ { .throughput = 300 * 1024, .blink_time = 50 }, -+}; -+#endif -+ - static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) - { - int time_left; -@@ -140,7 +155,6 @@ - - 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; -@@ -244,7 +258,7 @@ - */ - - if (IS_AR7010_DEVICE(drv_info)) -- priv->htc->credits = 45; -+ priv->htc->credits = 48; - else - priv->htc->credits = 33; - -@@ -430,13 +444,16 @@ - mutex_unlock(&priv->wmi->multi_write_mutex); - } - --static const struct ath_ops ath9k_common_ops = { -- .read = ath9k_regread, -- .multi_read = ath9k_multi_regread, -- .write = ath9k_regwrite, -- .enable_write_buffer = ath9k_enable_regwrite_buffer, -- .write_flush = ath9k_regwrite_flush, --}; -+static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -+{ -+ u32 val; -+ -+ val = ath9k_regread(hw_priv, reg_offset); -+ val &= ~clr; -+ val |= set; -+ ath9k_regwrite(hw_priv, val, reg_offset); -+ return val; -+} - - static void ath_usb_read_cachesize(struct ath_common *common, int *csz) - { -@@ -561,13 +578,7 @@ - int i = 0; - - /* Get the hardware key cache size. */ -- common->keymax = priv->ah->caps.keycache_size; -- if (common->keymax > ATH_KEYMAX) { -- ath_dbg(common, ATH_DBG_ANY, -- "Warning, using only %u entries in %u key cache\n", -- ATH_KEYMAX, common->keymax); -- common->keymax = ATH_KEYMAX; -- } -+ common->keymax = AR_KEYTABLE_SIZE; - - if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) - common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; -@@ -646,7 +657,7 @@ - { - 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; - -@@ -658,30 +669,35 @@ - ah->hw_version.subsysid = 0; /* FIXME */ - ah->hw_version.usbdev = drv_info; - ah->ah_flags |= AH_USE_EEPROM; -+ ah->reg_ops.read = ath9k_regread; -+ ah->reg_ops.multi_read = ath9k_multi_regread; -+ ah->reg_ops.write = ath9k_regwrite; -+ ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; -+ ah->reg_ops.write_flush = ath9k_regwrite_flush; -+ ah->reg_ops.rmw = ath9k_reg_rmw; - priv->ah = ah; - - common = ath9k_hw_common(ah); -- common->ops = &ath9k_common_ops; -+ common->ops = &ah->reg_ops; - common->bus_ops = &ath9k_usb_bus_ops; - common->ah = ah; - common->hw = priv->hw; - 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 -@@ -698,16 +714,13 @@ - 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); -@@ -720,8 +733,6 @@ - return 0; - - err_queues: -- ath9k_htc_exit_debug(ah); --err_debug: - ath9k_hw_deinit(ah); - err_hw: - -@@ -742,17 +753,27 @@ - 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; - - hw->queues = 4; - hw->channel_change_time = 5000; - hw->max_listen_interval = 10; -+ -+ if (AR_SREV_9271(priv->ah)) -+ hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271; -+ else -+ hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010; -+ - hw->vif_data_size = sizeof(struct ath9k_htc_vif); - hw->sta_data_size = sizeof(struct ath9k_htc_sta); - -@@ -779,6 +800,43 @@ - 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); -+ -+ /* -+ * Check if the available FW matches the driver's -+ * required version. -+ */ -+ if (priv->fw_version_major != MAJOR_VERSION_REQ || -+ priv->fw_version_minor != MINOR_VERSION_REQ) { -+ dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", -+ MAJOR_VERSION_REQ, MINOR_VERSION_REQ); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - static int ath9k_init_device(struct ath9k_htc_priv *priv, - u16 devid, char *product, u32 drv_info) - { -@@ -798,6 +856,10 @@ - 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); -@@ -816,6 +878,13 @@ - if (error != 0) - goto err_rx; - -+#ifdef CONFIG_MAC80211_LEDS -+ /* must be initialized before ieee80211_register_hw */ -+ priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, -+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink, -+ ARRAY_SIZE(ath9k_htc_tpt_blink)); -+#endif -+ - /* Register with mac80211 */ - error = ieee80211_register_hw(hw); - if (error) -@@ -828,6 +897,12 @@ - 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", -@@ -858,6 +933,8 @@ - err_tx: - /* Nothing */ - err_regd: -+ /* Nothing */ -+err_fw: - ath9k_deinit_priv(priv); - err_init: - return error; -@@ -946,38 +1023,20 @@ - - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_main.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_main.c 2011-05-05 23:29:49.095485481 +0200 -@@ -16,10 +16,6 @@ - - #include "htc.h" - --#ifdef CONFIG_ATH9K_HTC_DEBUGFS --static struct dentry *ath9k_debugfs_root; --#endif -- - /*************/ - /* Utilities */ - /*************/ -@@ -197,11 +193,16 @@ - - 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 @@ - 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 @@ - 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 @@ - - if (!fastcc) - caldata = &priv->caldata; -+ - ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); - if (ret) { - ath_err(common, -@@ -296,6 +306,9 @@ - !(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; -@@ -319,6 +332,11 @@ - memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); - hvif.index = priv->mon_vif_idx; - WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); -+ if (ret) { -+ ath_err(common, "Unable to remove monitor interface at idx: %d\n", -+ priv->mon_vif_idx); -+ } -+ - priv->nvifs--; - priv->vif_slot &= ~(1 << priv->mon_vif_idx); - } -@@ -349,7 +367,7 @@ - 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 +400,7 @@ - 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) { -@@ -449,6 +467,7 @@ - struct ath9k_htc_sta *ista; - int ret, sta_idx; - u8 cmd_rsp; -+ u16 maxampdu; - - if (priv->nstations >= ATH9K_HTC_MAX_STA) - return -ENOBUFS; -@@ -463,9 +482,7 @@ - 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 +491,15 @@ - - tsta.sta_index = sta_idx; - tsta.vif_index = avp->index; -- tsta.maxampdu = 0xffff; -+ -+ if (!sta) { -+ tsta.maxampdu = cpu_to_be16(0xffff); -+ } else { -+ maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + -+ sta->ht_cap.ampdu_factor); -+ tsta.maxampdu = cpu_to_be16(maxampdu); -+ } -+ - if (sta && sta->ht_cap.ht_supported) - tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); - -@@ -547,7 +572,8 @@ - return 0; - } - --int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) -+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, -+ u8 enable_coex) - { - struct ath9k_htc_cap_target tcap; - int ret; -@@ -555,13 +581,9 @@ - - memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); - -- /* FIXME: Values are hardcoded */ -- tcap.flags = 0x240c40; -- tcap.flags_ext = 0x80601000; -- tcap.ampdu_limit = 0xffff0000; -- tcap.ampdu_subframes = 20; -- tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; -- tcap.protmode = 1; -+ tcap.ampdu_limit = cpu_to_be32(0xffff); -+ tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; -+ tcap.enable_coex = enable_coex; - tcap.tx_chainmask = priv->ah->caps.tx_chainmask; - - WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); -@@ -709,218 +731,13 @@ - (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 +857,8 @@ - { - 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 +866,32 @@ - 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); - } -@@ -1122,7 +942,7 @@ - - ath9k_host_rx_init(priv); - -- ret = ath9k_htc_update_cap_target(priv); -+ ret = ath9k_htc_update_cap_target(priv, 0); - if (ret) - ath_dbg(common, ATH_DBG_CONFIG, - "Failed to update capability in target\n"); -@@ -1130,12 +950,15 @@ - 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); -@@ -1152,7 +975,7 @@ - struct ath9k_htc_priv *priv = hw->priv; - struct ath_hw *ah = priv->ah; - struct ath_common *common = ath9k_hw_common(ah); -- int ret = 0; -+ int ret __attribute__ ((unused)); - u8 cmd_rsp; - - mutex_lock(&priv->mutex); -@@ -1164,25 +987,27 @@ - } - - 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); - - /* Cancel all the running timers/work .. */ - cancel_work_sync(&priv->fatal_work); - cancel_work_sync(&priv->ps_work); -- cancel_delayed_work_sync(&priv->ath9k_led_blink_work); -+ -+#ifdef CONFIG_MAC80211_LEDS -+ cancel_work_sync(&priv->led_work); -+#endif - ath9k_htc_stop_ani(priv); -- ath9k_led_stop_brightness(priv); - - mutex_lock(&priv->mutex); - -@@ -1245,13 +1070,13 @@ - - 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 +1106,20 @@ - - 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); -@@ -1317,13 +1148,21 @@ - memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); - hvif.index = avp->index; - WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); -+ if (ret) { -+ ath_err(common, "Unable to remove interface at idx: %d\n", -+ avp->index); -+ } - priv->nvifs--; - 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 +1332,13 @@ - 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 +1486,7 @@ - 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); - } -@@ -1741,6 +1584,7 @@ - int ret = 0; - - mutex_lock(&priv->mutex); -+ ath9k_htc_ps_wakeup(priv); - - switch (action) { - case IEEE80211_AMPDU_RX_START: -@@ -1758,14 +1602,15 @@ - 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"); - } - -+ ath9k_htc_ps_restore(priv); - mutex_unlock(&priv->mutex); - - return ret; -@@ -1816,6 +1661,55 @@ - mutex_unlock(&priv->mutex); - } - -+/* -+ * Currently, this is used only for selecting the minimum rate -+ * for management frames, rate selection for data frames remain -+ * unaffected. -+ */ -+static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ struct ath9k_htc_priv *priv = hw->priv; -+ struct ath_common *common = ath9k_hw_common(priv->ah); -+ struct ath9k_htc_target_rate_mask tmask; -+ struct ath9k_htc_vif *avp = (void *)vif->drv_priv; -+ int ret = 0; -+ u8 cmd_rsp; -+ -+ memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); -+ -+ tmask.vif_index = avp->index; -+ tmask.band = IEEE80211_BAND_2GHZ; -+ tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); -+ -+ WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); -+ if (ret) { -+ ath_err(common, -+ "Unable to set 2G rate mask for " -+ "interface at idx: %d\n", avp->index); -+ goto out; -+ } -+ -+ tmask.band = IEEE80211_BAND_5GHZ; -+ tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); -+ -+ WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); -+ if (ret) { -+ ath_err(common, -+ "Unable to set 5G rate mask for " -+ "interface at idx: %d\n", avp->index); -+ goto out; -+ } -+ -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Set bitrate masks: 0x%x, 0x%x\n", -+ mask->control[IEEE80211_BAND_2GHZ].legacy, -+ mask->control[IEEE80211_BAND_5GHZ].legacy); -+out: -+ return ret; -+} -+ - struct ieee80211_ops ath9k_htc_ops = { - .tx = ath9k_htc_tx, - .start = ath9k_htc_start, -@@ -1838,4 +1732,5 @@ - .set_rts_threshold = ath9k_htc_set_rts_threshold, - .rfkill_poll = ath9k_htc_rfkill_poll_state, - .set_coverage_class = ath9k_htc_set_coverage_class, -+ .set_bitrate_mask = ath9k_htc_set_bitrate_mask, - }; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c 2011-05-05 23:29:49.077485265 +0200 -@@ -53,6 +53,138 @@ - } - } - -+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 @@ - 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,430 @@ - 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; -- -- /* 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)); -- -- qnum = skb_get_queue_mapping(skb); -- -- 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; -+ rcu_read_unlock(); -+} -+ -+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; -+ bool txok; -+ int slot; -+ -+ slot = strip_drv_header(priv, skb); -+ if (slot < 0) { -+ dev_kfree_skb_any(skb); -+ return; -+ } -+ -+ 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]; - -- memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); -+ memset(&tx_info->status, 0, sizeof(tx_info->status)); - -- tx_ctl.type = ATH9K_HTC_NORMAL; -+ /* -+ * URB submission failed for this frame, it never reached -+ * the target. -+ */ -+ if (!txok || !vif || !txs) -+ goto send_mac80211; -+ -+ if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) -+ tx_info->flags |= IEEE80211_TX_STAT_ACK; - -- mgmt_hdr.node_idx = sta_idx; -- mgmt_hdr.vif_idx = vif_idx; -- mgmt_hdr.tidno = 0; -- mgmt_hdr.flags = 0; -+ if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) -+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - -- 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_RTC_CTS) -+ rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; - -- tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); -- memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); -- epid = priv->mgmt_ep; -+ rate->count = 1; -+ rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); -+ -+ if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { -+ rate->flags |= IEEE80211_TX_RC_MCS; -+ -+ 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 (!vif) -- goto send_mac80211; -+ 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; -+ } - -- rcu_read_lock(); -+ if (fcookie == cookie) -+ return true; - -- sta = ieee80211_find_sta(vif, hdr->addr1); -- if (!sta) { -- rcu_read_unlock(); -- ieee80211_tx_status(priv->hw, skb); -- continue; -- } -+ return false; -+} - -- /* Check if we need to start aggregation */ -+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); - -- 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); -- 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_lock); -- ista->tid_state[tid] = AGGR_PROGRESS; -- spin_unlock_bh(&priv->tx_lock); -- } -- } -+ 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); - -- rcu_read_unlock(); -+ ath_dbg(common, ATH_DBG_XMIT, -+ "No matching packet for cookie: %d, epid: %d\n", -+ txs->cookie, epid); - -- send_mac80211: -- /* Send status to mac80211 */ -- ieee80211_tx_status(priv->hw, skb); -+ return NULL; -+} -+ -+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; -+ -+ for (i = 0; i < txs->cnt; i++) { -+ WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); -+ -+ __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); -+ -+ 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 +968,9 @@ - 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 +984,8 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc.h 2011-05-05 23:29:49.001484345 +0200 -@@ -66,13 +66,13 @@ - HTC_M_WDS = 2 - }; - --#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 --#define ATH9K_HTC_TX_USE_MIN_RATE 0x100 - - struct tx_frame_hdr { - u8 data_type; -@@ -82,7 +82,8 @@ - __be32 flags; /* ATH9K_HTC_TX_* */ - u8 key_type; - u8 keyix; -- u8 reserved[26]; -+ u8 cookie; -+ u8 pad; - } __packed; - - struct tx_mgmt_hdr { -@@ -92,50 +93,34 @@ - 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; -+#define MAX_TX_AMPDU_SUBFRAMES_9271 17 -+#define MAX_TX_AMPDU_SUBFRAMES_7010 22 - - struct ath9k_htc_cap_target { -- u32 flags; -- u32 flags_ext; -- u32 ampdu_limit; -+ __be32 ampdu_limit; - u8 ampdu_subframes; -+ u8 enable_coex; - u8 tx_chainmask; -- 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 +128,16 @@ - #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 +171,38 @@ - 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_rate_mask { -+ u8 vif_index; -+ u8 band; -+ __be32 mask; -+ u16 pad; -+} __packed; -+ -+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 +244,8 @@ - u8 index; - u16 seq_no; - bool beacon_configured; -+ int bslot; -+ __le64 tsfadjust; - }; - - struct ath9k_vif_iter_data { -@@ -282,23 +284,65 @@ - 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,55 +350,57 @@ - 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 --#define ATH_LED_PIN_9287 8 -+#define ATH_LED_PIN_9287 10 - #define ATH_LED_PIN_9271 15 - #define ATH_LED_PIN_7010 12 --#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ --#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ - --enum ath_led_type { -- ATH_LED_RADIO, -- ATH_LED_ASSOC, -- ATH_LED_TX, -- ATH_LED_RX --}; -+#define BSTUCK_THRESHOLD 10 - --struct ath_led { -- struct ath9k_htc_priv *priv; -- struct led_classdev led_cdev; -- enum ath_led_type led_type; -- struct delayed_work brightness_work; -- char name[32]; -- bool registered; -- int brightness; --}; -+/* -+ * 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 { -@@ -372,14 +418,11 @@ - - #define OP_INVALID BIT(0) - #define OP_SCANNING BIT(1) --#define OP_LED_ASSOCIATED BIT(2) --#define OP_LED_ON BIT(3) --#define OP_ENABLE_BEACON BIT(4) --#define OP_LED_DEINIT BIT(5) --#define OP_BT_PRIORITY_DETECTED BIT(6) --#define OP_BT_SCAN BIT(7) --#define OP_ANI_RUNNING BIT(8) --#define OP_TSF_RESET BIT(9) -+#define OP_ENABLE_BEACON BIT(2) -+#define OP_BT_PRIORITY_DETECTED BIT(3) -+#define OP_BT_SCAN BIT(4) -+#define OP_ANI_RUNNING BIT(5) -+#define OP_TSF_RESET BIT(6) - - struct ath9k_htc_priv { - struct device *dev; -@@ -388,6 +431,9 @@ - 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 +457,23 @@ - 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; - -@@ -440,15 +482,13 @@ - bool ps_enabled; - bool ps_idle; - -- struct ath_led radio_led; -- struct ath_led assoc_led; -- struct ath_led tx_led; -- struct ath_led rx_led; -- struct delayed_work ath9k_led_blink_work; -- int led_on_duration; -- int led_off_duration; -- int led_on_cnt; -- int led_off_cnt; -+#ifdef CONFIG_MAC80211_LEDS -+ enum led_brightness brightness; -+ bool led_registered; -+ char led_name[32]; -+ struct led_classdev led_cdev; -+ struct work_struct led_work; -+#endif - - int beaconq; - int cabq; -@@ -470,11 +510,18 @@ - - 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); -@@ -483,7 +530,8 @@ - void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, - enum htc_endpoint_id ep_id, bool txok); - --int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); -+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, -+ u8 enable_coex); - void ath9k_htc_station_work(struct work_struct *work); - void ath9k_htc_aggr_work(struct work_struct *work); - void ath9k_htc_ani_work(struct work_struct *work); -@@ -491,14 +539,23 @@ - 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); -@@ -516,9 +573,24 @@ - void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); - void ath9k_htc_radio_enable(struct ieee80211_hw *hw); - void ath9k_htc_radio_disable(struct ieee80211_hw *hw); --void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv); -+ -+#ifdef CONFIG_MAC80211_LEDS - void ath9k_init_leds(struct ath9k_htc_priv *priv); - void ath9k_deinit_leds(struct ath9k_htc_priv *priv); -+void ath9k_led_work(struct work_struct *work); -+#else -+static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) -+{ -+} -+ -+static inline void ath9k_deinit_leds(struct ath9k_htc_priv *priv) -+{ -+} -+ -+static inline void ath9k_led_work(struct work_struct *work) -+{ -+} -+#endif - - int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product, u32 drv_info); -@@ -528,15 +600,9 @@ - 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 */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_hst.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_hst.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_hst.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_hst.c 2011-05-05 23:29:49.070485179 +0200 -@@ -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 @@ - 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 @@ - - 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 @@ - - 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 @@ - 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 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_hst.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_hst.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/htc_hst.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/htc_hst.h 2011-05-05 23:29:49.073485215 +0200 -@@ -33,10 +33,10 @@ - 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 { -@@ -83,21 +83,10 @@ - void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); - }; - --#define HTC_TX_QUEUE_SIZE 256 -- --struct htc_txq { -- struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; -- u32 txqdepth; -- u16 txbuf_cnt; -- u16 txq_head; -- u16 txq_tail; --}; -- - struct htc_endpoint { - u16 service_id; - - struct htc_ep_callbacks ep_callbacks; -- struct htc_txq htc_txq; - u32 max_txqdepth; - int max_msglen; - -@@ -205,10 +194,12 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw.c 2011-05-05 23:29:49.090485421 +0200 -@@ -130,6 +130,20 @@ - } - EXPORT_SYMBOL(ath9k_hw_wait); - -+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, -+ int column, unsigned int *writecnt) -+{ -+ int r; -+ -+ ENABLE_REGWRITE_BUFFER(ah); -+ for (r = 0; r < array->ia_rows; r++) { -+ REG_WRITE(ah, INI_RA(array, r, 0), -+ INI_RA(array, r, column)); -+ DO_DELAY(*writecnt); -+ } -+ REGWRITE_BUFFER_FLUSH(ah); -+} -+ - u32 ath9k_hw_reverse_bits(u32 val, u32 n) - { - u32 retval; -@@ -142,25 +156,6 @@ - return retval; - } - --bool ath9k_get_channel_edges(struct ath_hw *ah, -- u16 flags, u16 *low, -- u16 *high) --{ -- struct ath9k_hw_capabilities *pCap = &ah->caps; -- -- if (flags & CHANNEL_5GHZ) { -- *low = pCap->low_5ghz_chan; -- *high = pCap->high_5ghz_chan; -- return true; -- } -- if ((flags & CHANNEL_2GHZ)) { -- *low = pCap->low_2ghz_chan; -- *high = pCap->high_2ghz_chan; -- return true; -- } -- return false; --} -- - u16 ath9k_hw_computetxtime(struct ath_hw *ah, - u8 phy, int kbps, - u32 frameLen, u16 rateix, -@@ -252,6 +247,17 @@ - { - u32 val; - -+ switch (ah->hw_version.devid) { -+ case AR5416_AR9100_DEVID: -+ ah->hw_version.macVersion = AR_SREV_VERSION_9100; -+ break; -+ case AR9300_DEVID_AR9340: -+ ah->hw_version.macVersion = AR_SREV_VERSION_9340; -+ val = REG_READ(ah, AR_SREV); -+ ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); -+ return; -+ } -+ - val = REG_READ(ah, AR_SREV) & AR_SREV_ID; - - if (val == 0xFF) { -@@ -364,11 +370,6 @@ - ah->config.spurchans[i][1] = AR_NO_SPUR; - } - -- if (ah->hw_version.devid != AR2427_DEVID_PCIE) -- ah->config.ht_enable = 1; -- else -- ah->config.ht_enable = 0; -- - /* PAPRD needs some more work to be enabled */ - ah->config.paprd_disable = 1; - -@@ -410,6 +411,8 @@ - ah->sta_id1_defaults = - AR_STA_ID1_CRPT_MIC_ENABLE | - AR_STA_ID1_MCAST_KSRCH; -+ if (AR_SREV_9100(ah)) -+ ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; - ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = 20; - ah->globaltxtimeout = (u32) -1; -@@ -470,7 +473,7 @@ - return ecode; - } - -- if (!AR_SREV_9100(ah)) { -+ if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { - ath9k_hw_ani_setup(ah); - ath9k_hw_ani_init(ah); - } -@@ -492,9 +495,6 @@ - struct ath_common *common = ath9k_hw_common(ah); - int r = 0; - -- if (ah->hw_version.devid == AR5416_AR9100_DEVID) -- ah->hw_version.macVersion = AR_SREV_VERSION_9100; -- - ath9k_hw_read_revisions(ah); - - /* -@@ -552,6 +552,7 @@ - case AR_SREV_VERSION_9271: - case AR_SREV_VERSION_9300: - case AR_SREV_VERSION_9485: -+ case AR_SREV_VERSION_9340: - break; - default: - ath_err(common, -@@ -560,7 +561,7 @@ - return -EOPNOTSUPP; - } - -- if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) -+ if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah)) - ah->is_pciexpress = false; - - ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); -@@ -629,6 +630,7 @@ - case AR2427_DEVID_PCIE: - case AR9300_DEVID_PCIE: - case AR9300_DEVID_AR9485_PCIE: -+ case AR9300_DEVID_AR9340: - break; - default: - if (common->bus_ops->ath_bus_type == ATH_USB) -@@ -671,48 +673,89 @@ - REGWRITE_BUFFER_FLUSH(ah); - } - --unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) -+u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) - { -- REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); -- udelay(100); -- REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); -+ REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); -+ udelay(100); -+ REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - -- while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) -- udelay(100); -+ while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) -+ udelay(100); - -- return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; -+ return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; - } - EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); - --#define DPLL2_KD_VAL 0x3D --#define DPLL2_KI_VAL 0x06 --#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); -+ } else if (AR_SREV_9340(ah)) { -+ u32 regval, pll2_divint, pll2_divfrac, refdiv; -+ -+ REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); -+ udelay(1000); -+ -+ REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); -+ udelay(100); -+ -+ if (ah->is_clk_25mhz) { -+ pll2_divint = 0x54; -+ pll2_divfrac = 0x1eb85; -+ refdiv = 3; -+ } else { -+ pll2_divint = 88; -+ pll2_divfrac = 0; -+ refdiv = 5; -+ } -+ -+ regval = REG_READ(ah, AR_PHY_PLL_MODE); -+ regval |= (0x1 << 16); -+ REG_WRITE(ah, AR_PHY_PLL_MODE, regval); -+ udelay(100); -+ -+ REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | -+ (pll2_divint << 18) | pll2_divfrac); -+ udelay(100); -+ -+ regval = REG_READ(ah, AR_PHY_PLL_MODE); -+ regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | -+ (0x4 << 26) | (0x18 << 19); -+ REG_WRITE(ah, AR_PHY_PLL_MODE, regval); -+ REG_WRITE(ah, AR_PHY_PLL_MODE, -+ REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); - udelay(1000); - } - -@@ -720,6 +763,9 @@ - - REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - -+ if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) -+ udelay(1000); -+ - /* Switch the core clock for ar9271 to 117Mhz */ - if (AR_SREV_9271(ah)) { - udelay(500); -@@ -729,17 +775,34 @@ - udelay(RTC_PLL_SETTLE_DELAY); - - REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); -+ -+ if (AR_SREV_9340(ah)) { -+ if (ah->is_clk_25mhz) { -+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); -+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); -+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); -+ } else { -+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); -+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); -+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); -+ } -+ udelay(100); -+ } - } - - static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, - enum nl80211_iftype opmode) - { -+ u32 sync_default = AR_INTR_SYNC_DEFAULT; - u32 imr_reg = AR_IMR_TXERR | - AR_IMR_TXURN | - AR_IMR_RXERR | - AR_IMR_RXORN | - AR_IMR_BCNMISC; - -+ if (AR_SREV_9340(ah)) -+ sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; -+ - if (AR_SREV_9300_20_OR_LATER(ah)) { - imr_reg |= AR_IMR_RXOK_HP; - if (ah->config.rx_intr_mitigation) -@@ -770,7 +833,7 @@ - - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); -- REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); -+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); - REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); - } - -@@ -830,8 +893,7 @@ - ah->misc_mode); - - if (ah->misc_mode != 0) -- REG_WRITE(ah, AR_PCU_MISC, -- REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); -+ REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); - - if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) - sifstime = 16; -@@ -899,23 +961,19 @@ - static inline void ath9k_hw_set_dma(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -- u32 regval; - - ENABLE_REGWRITE_BUFFER(ah); - - /* - * set AHB_MODE not to do cacheline prefetches - */ -- if (!AR_SREV_9300_20_OR_LATER(ah)) { -- regval = REG_READ(ah, AR_AHB_MODE); -- REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); -- } -+ if (!AR_SREV_9300_20_OR_LATER(ah)) -+ REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); - - /* - * let mac dma reads be in 128 byte chunks - */ -- regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; -- REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); -+ REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); - - REGWRITE_BUFFER_FLUSH(ah); - -@@ -932,8 +990,7 @@ - /* - * let mac dma writes be in 128 byte chunks - */ -- regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; -- REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); -+ REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); - - /* - * Setup receive FIFO threshold to hold off TX activities -@@ -972,30 +1029,27 @@ - - static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) - { -- u32 val; -+ u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; -+ u32 set = AR_STA_ID1_KSRCH_MODE; - -- val = REG_READ(ah, AR_STA_ID1); -- val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); - switch (opmode) { -- case NL80211_IFTYPE_AP: -- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP -- | AR_STA_ID1_KSRCH_MODE); -- REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); -- break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: -- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC -- | AR_STA_ID1_KSRCH_MODE); -+ set |= AR_STA_ID1_ADHOC; - REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; -+ case NL80211_IFTYPE_AP: -+ set |= AR_STA_ID1_STA_AP; -+ /* fall through */ - case NL80211_IFTYPE_STATION: -- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); -+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; - default: -- if (ah->is_monitoring) -- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); -+ if (!ah->is_monitoring) -+ set = 0; - break; - } -+ REG_RMW(ah, AR_STA_ID1, set, mask); - } - - void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, -@@ -1021,10 +1075,8 @@ - u32 tmpReg; - - if (AR_SREV_9100(ah)) { -- u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); -- val &= ~AR_RTC_DERIVED_CLK_PERIOD; -- val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); -- REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); -+ REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK, -+ AR_RTC_DERIVED_CLK_PERIOD, 1); - (void)REG_READ(ah, AR_RTC_DERIVED_CLK); - } - -@@ -1212,6 +1264,20 @@ - return true; - } - -+static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) -+{ -+ u32 gpio_mask = ah->gpio_mask; -+ int i; -+ -+ for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { -+ if (!(gpio_mask & 1)) -+ continue; -+ -+ ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); -+ } -+} -+ - bool ath9k_hw_check_alive(struct ath_hw *ah) - { - int count = 50; -@@ -1409,7 +1475,7 @@ - REGWRITE_BUFFER_FLUSH(ah); - - ah->intr_txqs = 0; -- for (i = 0; i < ah->caps.total_queues; i++) -+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - ath9k_hw_resettxqueue(ah, i); - - ath9k_hw_init_interrupt_masks(ah, ah->opmode); -@@ -1426,8 +1492,7 @@ - ar9002_hw_enable_wep_aggregation(ah); - } - -- REG_WRITE(ah, AR_STA_ID1, -- REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); -+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); - - ath9k_hw_set_dma(ah); - -@@ -1480,7 +1545,9 @@ - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); - } - #ifdef __BIG_ENDIAN -- else -+ else if (AR_SREV_9340(ah)) -+ REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); -+ else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); - #endif - } -@@ -1491,6 +1558,8 @@ - if (AR_SREV_9300_20_OR_LATER(ah)) - ar9003_hw_bb_watchdog_config(ah); - -+ ath9k_hw_apply_gpio_override(ah); -+ - return 0; - } - EXPORT_SYMBOL(ath9k_hw_reset); -@@ -1670,21 +1739,15 @@ - case NL80211_IFTYPE_MESH_POINT: - REG_SET_BIT(ah, AR_TXCFG, - AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); -- REG_WRITE(ah, AR_NEXT_NDP_TIMER, -- TU_TO_USEC(next_beacon + -- (ah->atim_window ? ah-> -- atim_window : 1))); -+ REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + -+ TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); - flags |= AR_NDP_TIMER_EN; - case NL80211_IFTYPE_AP: -- REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); -- REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, -- TU_TO_USEC(next_beacon - -- ah->config. -- dma_beacon_response_time)); -- REG_WRITE(ah, AR_NEXT_SWBA, -- TU_TO_USEC(next_beacon - -- ah->config. -- sw_beacon_response_time)); -+ REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); -+ REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - -+ TU_TO_USEC(ah->config.dma_beacon_response_time)); -+ REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - -+ TU_TO_USEC(ah->config.sw_beacon_response_time)); - flags |= - AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; - break; -@@ -1696,18 +1759,13 @@ - break; - } - -- REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); -- REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); -- REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); -- REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); -+ REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); -+ REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); -+ REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); -+ REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); - - REGWRITE_BUFFER_FLUSH(ah); - -- beacon_period &= ~ATH9K_BEACON_ENA; -- if (beacon_period & ATH9K_BEACON_RESET_TSF) { -- ath9k_hw_reset_tsf(ah); -- } -- - REG_SET_BIT(ah, AR_TIMER_MODE, flags); - } - EXPORT_SYMBOL(ath9k_hw_beaconinit); -@@ -1795,7 +1853,7 @@ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - -- u16 capField = 0, eeval; -+ u16 eeval; - u8 ant_div_ctl1, tx_chainmask, rx_chainmask; - - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); -@@ -1806,8 +1864,6 @@ - eeval |= AR9285_RDEXT_DEFAULT; - regulatory->current_rd_ext = eeval; - -- capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); -- - if (ah->opmode != NL80211_IFTYPE_AP && - ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { - if (regulatory->current_rd == 0x64 || -@@ -1842,6 +1898,8 @@ - !(AR_SREV_9271(ah))) - /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ - pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; -+ else if (AR_SREV_9100(ah)) -+ pCap->rx_chainmask = 0x7; - else - /* Use rx_chainmask from EEPROM. */ - pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); -@@ -1852,36 +1910,13 @@ - if (AR_SREV_9300_20_OR_LATER(ah)) - ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; - -- pCap->low_2ghz_chan = 2312; -- pCap->high_2ghz_chan = 2732; -- -- pCap->low_5ghz_chan = 4920; -- pCap->high_5ghz_chan = 6100; -- - common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; - -- if (ah->config.ht_enable) -+ if (ah->hw_version.devid != AR2427_DEVID_PCIE) - pCap->hw_caps |= ATH9K_HW_CAP_HT; - else - pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - -- if (capField & AR_EEPROM_EEPCAP_MAXQCU) -- pCap->total_queues = -- MS(capField, AR_EEPROM_EEPCAP_MAXQCU); -- else -- pCap->total_queues = ATH9K_NUM_TX_QUEUES; -- -- if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) -- pCap->keycache_size = -- 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); -- else -- pCap->keycache_size = AR_KEYTABLE_SIZE; -- -- if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) -- pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; -- else -- pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; -- - if (AR_SREV_9271(ah)) - pCap->num_gpio_pins = AR9271_NUM_GPIO; - else if (AR_DEVID_7010(ah)) -@@ -1900,8 +1935,6 @@ - pCap->rts_aggr_limit = (8 * 1024); - } - -- pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; -- - #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); - if (ah->rfsilent & EEP_RFSILENT_ENABLED) { -@@ -1923,32 +1956,23 @@ - else - pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - -- if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { -- pCap->reg_cap = -- AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | -- AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | -- AR_EEPROM_EEREGCAP_EN_KK_U2 | -- AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; -- } else { -- pCap->reg_cap = -- AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | -- AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; -- } -- -- /* Advertise midband for AR5416 with FCC midband set in eeprom */ -- if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && -- AR_SREV_5416(ah)) -- pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; -- -- if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { -- btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; -- btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; -- -- if (AR_SREV_9285(ah)) { -+ if (common->btcoex_enabled) { -+ if (AR_SREV_9300_20_OR_LATER(ah)) { - btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; -- btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; -- } else { -- btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; -+ btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; -+ btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; -+ btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300; -+ } else if (AR_SREV_9280_20_OR_LATER(ah)) { -+ btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280; -+ btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280; -+ -+ if (AR_SREV_9285(ah)) { -+ btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; -+ btcoex_hw->btpriority_gpio = -+ ATH_BTPRIORITY_GPIO_9285; -+ } else { -+ btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; -+ } - } - } else { - btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; -@@ -2186,11 +2210,9 @@ - REG_WRITE(ah, AR_PHY_ERR, phybits); - - if (phybits) -- REG_WRITE(ah, AR_RXCFG, -- REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); -+ REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); - else -- REG_WRITE(ah, AR_RXCFG, -- REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); -+ REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); - - REGWRITE_BUFFER_FLUSH(ah); - } -@@ -2366,10 +2388,11 @@ - return timer_table->gen_timer_index[b]; - } - --static u32 ath9k_hw_gettsf32(struct ath_hw *ah) -+u32 ath9k_hw_gettsf32(struct ath_hw *ah) - { - return REG_READ(ah, AR_TSF_L32); - } -+EXPORT_SYMBOL(ath9k_hw_gettsf32); - - struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, - void (*trigger)(void *), -@@ -2402,11 +2425,11 @@ - - void ath9k_hw_gen_timer_start(struct ath_hw *ah, - struct ath_gen_timer *timer, -- u32 timer_next, -+ u32 trig_timeout, - u32 timer_period) - { - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; -- u32 tsf; -+ u32 tsf, timer_next; - - BUG_ON(!timer_period); - -@@ -2414,18 +2437,13 @@ - - tsf = ath9k_hw_gettsf32(ah); - -+ timer_next = tsf + trig_timeout; -+ - ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, - "current tsf %x period %x timer_next %x\n", - tsf, timer_period, timer_next); - - /* -- * Pull timer_next forward if the current TSF already passed it -- * because of software latency -- */ -- if (timer_next < tsf) -- timer_next = tsf + timer_period; -- -- /* - * Program generic timer registers - */ - REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw.h 2011-05-05 23:29:49.079485289 +0200 -@@ -43,6 +43,7 @@ - #define AR9287_DEVID_PCI 0x002d - #define AR9287_DEVID_PCIE 0x002e - #define AR9300_DEVID_PCIE 0x0030 -+#define AR9300_DEVID_AR9340 0x0031 - #define AR9300_DEVID_AR9485_PCIE 0x0032 - - #define AR5416_AR9100_DEVID 0x000b -@@ -55,6 +56,9 @@ - #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa - #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab - -+#define AR9300_NUM_BT_WEIGHTS 4 -+#define AR9300_NUM_WLAN_WEIGHTS 4 -+ - #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) - - #define ATH_DEFAULT_NOISE_FLOOR -95 -@@ -65,53 +69,49 @@ - - /* Register read/write primitives */ - #define REG_WRITE(_ah, _reg, _val) \ -- ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) -+ (_ah)->reg_ops.write((_ah), (_val), (_reg)) - - #define REG_READ(_ah, _reg) \ -- ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) -+ (_ah)->reg_ops.read((_ah), (_reg)) - - #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ -- ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt)) -+ (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt)) -+ -+#define REG_RMW(_ah, _reg, _set, _clr) \ -+ (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr)) - - #define ENABLE_REGWRITE_BUFFER(_ah) \ - do { \ -- if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ -- ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ -+ if ((_ah)->reg_ops.enable_write_buffer) \ -+ (_ah)->reg_ops.enable_write_buffer((_ah)); \ - } while (0) - - #define REGWRITE_BUFFER_FLUSH(_ah) \ - do { \ -- if (ath9k_hw_common(_ah)->ops->write_flush) \ -- ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ -+ if ((_ah)->reg_ops.write_flush) \ -+ (_ah)->reg_ops.write_flush((_ah)); \ - } while (0) - - #define SM(_v, _f) (((_v) << _f##_S) & _f) - #define MS(_v, _f) (((_v) & _f) >> _f##_S) --#define REG_RMW(_a, _r, _set, _clr) \ -- REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) - #define REG_RMW_FIELD(_a, _r, _f, _v) \ -- REG_WRITE(_a, _r, \ -- (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) -+ REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f)) - #define REG_READ_FIELD(_a, _r, _f) \ - (((REG_READ(_a, _r) & _f) >> _f##_S)) - #define REG_SET_BIT(_a, _r, _f) \ -- REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f)) -+ REG_RMW(_a, _r, (_f), 0) - #define REG_CLR_BIT(_a, _r, _f) \ -- REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f)) -+ REG_RMW(_a, _r, 0, (_f)) - --#define DO_DELAY(x) do { \ -- if ((++(x) % 64) == 0) \ -- udelay(1); \ -+#define DO_DELAY(x) do { \ -+ if (((++(x) % 64) == 0) && \ -+ (ath9k_hw_common(ah)->bus_ops->ath_bus_type \ -+ != ATH_USB)) \ -+ udelay(1); \ - } while (0) - --#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ -- int r; \ -- for (r = 0; r < ((iniarray)->ia_rows); r++) { \ -- REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ -- INI_RA((iniarray), r, (column))); \ -- DO_DELAY(regWr); \ -- } \ -- } while (0) -+#define REG_WRITE_ARRAY(iniarray, column, regWr) \ -+ ath9k_hw_write_array(ah, iniarray, column, &(regWr)) - - #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 - #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 -@@ -125,7 +125,7 @@ - #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) - - #define BASE_ACTIVATE_DELAY 100 --#define RTC_PLL_SETTLE_DELAY 100 -+#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) - #define COEF_SCALE_S 24 - #define HT40_CHANNEL_CENTER_SHIFT 10 - -@@ -178,7 +178,6 @@ - ATH9K_HW_CAP_HT = BIT(0), - ATH9K_HW_CAP_RFSILENT = BIT(1), - ATH9K_HW_CAP_CST = BIT(2), -- ATH9K_HW_CAP_ENHANCEDPM = BIT(3), - ATH9K_HW_CAP_AUTOSLEEP = BIT(4), - ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), - ATH9K_HW_CAP_EDMA = BIT(6), -@@ -195,17 +194,11 @@ - - struct ath9k_hw_capabilities { - u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ -- u16 total_queues; -- u16 keycache_size; -- u16 low_5ghz_chan, high_5ghz_chan; -- u16 low_2ghz_chan, high_2ghz_chan; - u16 rts_aggr_limit; - u8 tx_chainmask; - u8 rx_chainmask; - u8 max_txchains; - u8 max_rxchains; -- u16 tx_triglevel_max; -- u16 reg_cap; - u8 num_gpio_pins; - u8 rx_hp_qdepth; - u8 rx_lp_qdepth; -@@ -227,7 +220,6 @@ - u8 pcie_clock_req; - u32 pcie_waen; - u8 analog_shiftreg; -- u8 ht_enable; - u8 paprd_disable; - u32 ofdm_trig_low; - u32 ofdm_trig_high; -@@ -412,8 +404,6 @@ - u32 bs_nextdtim; - u32 bs_intval; - #define ATH9K_BEACON_PERIOD 0x0000ffff --#define ATH9K_BEACON_ENA 0x00800000 --#define ATH9K_BEACON_RESET_TSF 0x01000000 - #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ - u32 bs_dtimperiod; - u16 bs_cfpperiod; -@@ -640,8 +630,7 @@ - void (*clr11n_aggr)(struct ath_hw *ah, void *ds); - void (*set11n_burstduration)(struct ath_hw *ah, void *ds, - u32 burstDuration); -- void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, -- u32 vmf); -+ void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); - }; - - struct ath_nf_limits { -@@ -655,6 +644,8 @@ - #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ - - struct ath_hw { -+ struct ath_ops reg_ops; -+ - struct ieee80211_hw *hw; - struct ath_common common; - struct ath9k_hw_version hw_version; -@@ -784,6 +775,8 @@ - - /* Bluetooth coexistance */ - struct ath_btcoex_hw btcoex_hw; -+ u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; -+ u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; - - u32 intr_txqs; - u8 txchainmask; -@@ -794,7 +787,9 @@ - u32 originalGain[22]; - int initPDADC; - int PDADCdelta; -- u8 led_pin; -+ int led_pin; -+ u32 gpio_mask; -+ u32 gpio_val; - - struct ar5416IniArray iniModes; - struct ar5416IniArray iniCommon; -@@ -810,6 +805,7 @@ - struct ar5416IniArray iniPcieSerdes; - struct ar5416IniArray iniPcieSerdesLowPower; - struct ar5416IniArray iniModesAdditional; -+ struct ar5416IniArray iniModesAdditional_40M; - struct ar5416IniArray iniModesRxGain; - struct ar5416IniArray iniModesTxGain; - struct ar5416IniArray iniModes_9271_1_0_only; -@@ -856,6 +852,16 @@ - - /* Enterprise mode cap */ - u32 ent_mode; -+ -+ bool is_clk_25mhz; -+}; -+ -+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) -@@ -907,8 +913,9 @@ - - /* General Operation */ - bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); -+void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, -+ int column, unsigned int *writecnt); - u32 ath9k_hw_reverse_bits(u32 val, u32 n); --bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); - u16 ath9k_hw_computetxtime(struct ath_hw *ah, - u8 phy, int kbps, - u32 frameLen, u16 rateix, bool shortPreamble); -@@ -924,12 +931,13 @@ - void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); - void ath9k_hw_setbssidmask(struct ath_hw *ah); - void ath9k_hw_write_associd(struct ath_hw *ah); -+u32 ath9k_hw_gettsf32(struct ath_hw *ah); - u64 ath9k_hw_gettsf64(struct ath_hw *ah); - void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); - void ath9k_hw_reset_tsf(struct ath_hw *ah); - void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); - void ath9k_hw_init_global_settings(struct ath_hw *ah); --unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); -+u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); - void ath9k_hw_set11nmac2040(struct ath_hw *ah); - void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); - void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw-ops.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw-ops.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/hw-ops.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/hw-ops.h 2011-05-05 23:29:49.085485361 +0200 -@@ -122,10 +122,9 @@ - ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); - } - --static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, -- u32 vmf) -+static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) - { -- ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); -+ ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); - } - - /* Private hardware call ops */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/init.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/init.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/init.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/init.c 2011-05-05 23:29:49.083485337 +0200 -@@ -15,6 +15,7 @@ - */ - - #include -+#include - - #include "ath9k.h" - -@@ -195,10 +196,27 @@ - return val; - } - --static const struct ath_ops ath9k_common_ops = { -- .read = ath9k_ioread32, -- .write = ath9k_iowrite32, --}; -+static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) -+{ -+ struct ath_hw *ah = (struct ath_hw *) hw_priv; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath_softc *sc = (struct ath_softc *) common->priv; -+ unsigned long uninitialized_var(flags); -+ u32 val; -+ -+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) -+ spin_lock_irqsave(&sc->sc_serial_rw, flags); -+ -+ val = ioread32(sc->mem + reg_offset); -+ val &= ~clr; -+ val |= set; -+ iowrite32(val, sc->mem + reg_offset); -+ -+ if (ah->config.serialize_regmode == SER_REG_MODE_ON) -+ spin_unlock_irqrestore(&sc->sc_serial_rw, flags); -+ -+ return val; -+} - - /**************************/ - /* Initialization */ -@@ -389,13 +407,7 @@ - int i = 0; - - /* Get the hardware key cache size. */ -- common->keymax = sc->sc_ah->caps.keycache_size; -- if (common->keymax > ATH_KEYMAX) { -- ath_dbg(common, ATH_DBG_ANY, -- "Warning, using only %u entries in %u key cache\n", -- ATH_KEYMAX, common->keymax); -- common->keymax = ATH_KEYMAX; -- } -+ common->keymax = AR_KEYTABLE_SIZE; - - /* - * Reset the key cache since some parts do not -@@ -537,6 +549,7 @@ - static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, - const struct ath_bus_ops *bus_ops) - { -+ struct ath9k_platform_data *pdata = sc->dev->platform_data; - struct ath_hw *ah = NULL; - struct ath_common *common; - int ret = 0, i; -@@ -549,13 +562,23 @@ - ah->hw = sc->hw; - ah->hw_version.devid = devid; - ah->hw_version.subsysid = subsysid; -+ ah->reg_ops.read = ath9k_ioread32; -+ ah->reg_ops.write = ath9k_iowrite32; -+ ah->reg_ops.rmw = ath9k_reg_rmw; - sc->sc_ah = ah; - -- if (!sc->dev->platform_data) -+ if (!pdata) { - ah->ah_flags |= AH_USE_EEPROM; -+ sc->sc_ah->led_pin = -1; -+ } else { -+ sc->sc_ah->gpio_mask = pdata->gpio_mask; -+ sc->sc_ah->gpio_val = pdata->gpio_val; -+ sc->sc_ah->led_pin = pdata->led_pin; -+ ah->is_clk_25mhz = pdata->is_clk_25mhz; -+ } - - common = ath9k_hw_common(ah); -- common->ops = &ath9k_common_ops; -+ common->ops = &ah->reg_ops; - common->bus_ops = bus_ops; - common->ah = ah; - common->hw = sc->hw; -@@ -587,6 +610,9 @@ - if (ret) - goto err_hw; - -+ if (pdata && pdata->macaddr) -+ memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); -+ - ret = ath9k_init_queues(sc); - if (ret) - goto err_queues; -@@ -679,6 +705,8 @@ - if (AR_SREV_5416(sc->sc_ah)) - hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - -+ hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; -+ - hw->queues = 4; - hw->max_rates = 4; - hw->channel_change_time = 5000; -@@ -773,6 +801,7 @@ - - INIT_WORK(&sc->hw_check_work, ath_hw_check); - INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); -+ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); - sc->last_rssi = ATH_RSSI_DUMMY_MARKER; - - ath_init_leds(sc); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/Kconfig 2011-05-05 23:29:49.097485505 +0200 -@@ -5,7 +5,7 @@ - - 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 @@ - - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/mac.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/mac.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/mac.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/mac.c 2011-05-05 23:29:49.078485277 +0200 -@@ -209,15 +209,8 @@ - { - u32 cw; - struct ath_common *common = ath9k_hw_common(ah); -- struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - -- if (q >= pCap->total_queues) { -- ath_dbg(common, ATH_DBG_QUEUE, -- "Set TXQ properties, invalid queue: %u\n", q); -- return false; -- } -- - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_dbg(common, ATH_DBG_QUEUE, -@@ -280,15 +273,8 @@ - struct ath9k_tx_queue_info *qinfo) - { - struct ath_common *common = ath9k_hw_common(ah); -- struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - -- if (q >= pCap->total_queues) { -- ath_dbg(common, ATH_DBG_QUEUE, -- "Get TXQ properties, invalid queue: %u\n", q); -- return false; -- } -- - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_dbg(common, ATH_DBG_QUEUE, -@@ -320,28 +306,27 @@ - { - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_tx_queue_info *qi; -- struct ath9k_hw_capabilities *pCap = &ah->caps; - int q; - - switch (type) { - case ATH9K_TX_QUEUE_BEACON: -- q = pCap->total_queues - 1; -+ q = ATH9K_NUM_TX_QUEUES - 1; - break; - case ATH9K_TX_QUEUE_CAB: -- q = pCap->total_queues - 2; -+ q = ATH9K_NUM_TX_QUEUES - 2; - break; - case ATH9K_TX_QUEUE_PSPOLL: - q = 1; - break; - case ATH9K_TX_QUEUE_UAPSD: -- q = pCap->total_queues - 3; -+ q = ATH9K_NUM_TX_QUEUES - 3; - break; - case ATH9K_TX_QUEUE_DATA: -- for (q = 0; q < pCap->total_queues; q++) -+ for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) - if (ah->txq[q].tqi_type == - ATH9K_TX_QUEUE_INACTIVE) - break; -- if (q == pCap->total_queues) { -+ if (q == ATH9K_NUM_TX_QUEUES) { - ath_err(common, "No available TX queue\n"); - return -1; - } -@@ -382,15 +367,9 @@ - - bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) - { -- struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_tx_queue_info *qi; - -- if (q >= pCap->total_queues) { -- ath_dbg(common, ATH_DBG_QUEUE, -- "Release TXQ, invalid queue: %u\n", q); -- return false; -- } - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_dbg(common, ATH_DBG_QUEUE, -@@ -414,18 +393,11 @@ - - bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) - { -- struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_channel *chan = ah->curchan; - struct ath9k_tx_queue_info *qi; - u32 cwMin, chanCwMin, value; - -- if (q >= pCap->total_queues) { -- ath_dbg(common, ATH_DBG_QUEUE, -- "Reset TXQ, invalid queue: %u\n", q); -- return false; -- } -- - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_dbg(common, ATH_DBG_QUEUE, -@@ -465,10 +437,9 @@ - REG_WRITE(ah, AR_QCBRCFG(q), - SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | - SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); -- REG_WRITE(ah, AR_QMISC(q), -- REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | -- (qi->tqi_cbrOverflowLimit ? -- AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); -+ REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR | -+ (qi->tqi_cbrOverflowLimit ? -+ AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); - } - if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { - REG_WRITE(ah, AR_QRDYTIMECFG(q), -@@ -481,40 +452,31 @@ - (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); - - if (qi->tqi_burstTime -- && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { -- REG_WRITE(ah, AR_QMISC(q), -- REG_READ(ah, AR_QMISC(q)) | -- AR_Q_MISC_RDYTIME_EXP_POLICY); -+ && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) -+ REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY); - -- } -- -- if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { -- REG_WRITE(ah, AR_DMISC(q), -- REG_READ(ah, AR_DMISC(q)) | -- AR_D_MISC_POST_FR_BKOFF_DIS); -- } -+ if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) -+ REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); - - REGWRITE_BUFFER_FLUSH(ah); - -- if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { -- REG_WRITE(ah, AR_DMISC(q), -- REG_READ(ah, AR_DMISC(q)) | -- AR_D_MISC_FRAG_BKOFF_EN); -- } -+ if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) -+ REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN); -+ - switch (qi->tqi_type) { - case ATH9K_TX_QUEUE_BEACON: - ENABLE_REGWRITE_BUFFER(ah); - -- REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) -- | AR_Q_MISC_FSP_DBA_GATED -- | AR_Q_MISC_BEACON_USE -- | AR_Q_MISC_CBR_INCR_DIS1); -+ REG_SET_BIT(ah, AR_QMISC(q), -+ AR_Q_MISC_FSP_DBA_GATED -+ | AR_Q_MISC_BEACON_USE -+ | AR_Q_MISC_CBR_INCR_DIS1); - -- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) -- | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << -+ REG_SET_BIT(ah, AR_DMISC(q), -+ (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S) -- | AR_D_MISC_BEACON_USE -- | AR_D_MISC_POST_FR_BKOFF_DIS); -+ | AR_D_MISC_BEACON_USE -+ | AR_D_MISC_POST_FR_BKOFF_DIS); - - REGWRITE_BUFFER_FLUSH(ah); - -@@ -533,41 +495,38 @@ - case ATH9K_TX_QUEUE_CAB: - ENABLE_REGWRITE_BUFFER(ah); - -- REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) -- | AR_Q_MISC_FSP_DBA_GATED -- | AR_Q_MISC_CBR_INCR_DIS1 -- | AR_Q_MISC_CBR_INCR_DIS0); -+ REG_SET_BIT(ah, AR_QMISC(q), -+ AR_Q_MISC_FSP_DBA_GATED -+ | AR_Q_MISC_CBR_INCR_DIS1 -+ | AR_Q_MISC_CBR_INCR_DIS0); - value = (qi->tqi_readyTime - - (ah->config.sw_beacon_response_time - - ah->config.dma_beacon_response_time) - - ah->config.additional_swba_backoff) * 1024; - REG_WRITE(ah, AR_QRDYTIMECFG(q), - value | AR_Q_RDYTIMECFG_EN); -- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) -- | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << -+ REG_SET_BIT(ah, AR_DMISC(q), -+ (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); - - REGWRITE_BUFFER_FLUSH(ah); - - break; - case ATH9K_TX_QUEUE_PSPOLL: -- REG_WRITE(ah, AR_QMISC(q), -- REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); -+ REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1); - break; - case ATH9K_TX_QUEUE_UAPSD: -- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | -- AR_D_MISC_POST_FR_BKOFF_DIS); -+ REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); - break; - default: - break; - } - - if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { -- REG_WRITE(ah, AR_DMISC(q), -- REG_READ(ah, AR_DMISC(q)) | -- SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, -- AR_D_MISC_ARB_LOCKOUT_CNTRL) | -- AR_D_MISC_POST_FR_BKOFF_DIS); -+ REG_SET_BIT(ah, AR_DMISC(q), -+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, -+ AR_D_MISC_ARB_LOCKOUT_CNTRL) | -+ AR_D_MISC_POST_FR_BKOFF_DIS); - } - - if (AR_SREV_9300_20_OR_LATER(ah)) -@@ -754,7 +713,6 @@ - bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) - { - #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ --#define AH_RX_TIME_QUANTUM 100 /* usec */ - struct ath_common *common = ath9k_hw_common(ah); - u32 mac_status, last_mac_status = 0; - int i; -@@ -797,7 +755,6 @@ - return true; - } - --#undef AH_RX_TIME_QUANTUM - #undef AH_RX_STOP_DMA_TIMEOUT - } - EXPORT_SYMBOL(ath9k_hw_stopdmarecv); -@@ -855,10 +812,14 @@ - void ath9k_hw_enable_interrupts(struct ath_hw *ah) - { - struct ath_common *common = ath9k_hw_common(ah); -+ u32 sync_default = AR_INTR_SYNC_DEFAULT; - - if (!(ah->imask & ATH9K_INT_GLOBAL)) - return; - -+ if (AR_SREV_9340(ah)) -+ sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; -+ - ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { -@@ -867,10 +828,8 @@ - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - -- REG_WRITE(ah, AR_INTR_SYNC_ENABLE, -- AR_INTR_SYNC_DEFAULT); -- REG_WRITE(ah, AR_INTR_SYNC_MASK, -- AR_INTR_SYNC_DEFAULT); -+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); -+ REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); - } - ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); -@@ -926,6 +885,9 @@ - mask |= AR_IMR_GENTMR; - } - -+ if (ints & ATH9K_INT_GENTIMER) -+ mask |= AR_IMR_GENTMR; -+ - if (ints & (ATH9K_INT_BMISC)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_TIM) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/mac.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/mac.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/mac.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/mac.h 2011-05-05 23:29:49.078485277 +0200 -@@ -239,7 +239,6 @@ - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/main.c 2011-05-05 23:29:49.085485361 +0200 -@@ -299,7 +299,7 @@ - - if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { - if (sc->sc_flags & SC_OP_BEACONS) -- ath_beacon_config(sc, NULL); -+ ath_set_beacon(sc); - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); - ath_start_ani(common); -@@ -624,6 +624,43 @@ - ath9k_ps_restore(sc); - } - -+static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) -+{ -+ static int count; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ -+ if (pll_sqsum >= 0x40000) { -+ count++; -+ if (count == 3) { -+ /* Rx is hung for more than 500ms. Reset it */ -+ ath_dbg(common, ATH_DBG_RESET, -+ "Possible RX hang, resetting"); -+ ath_reset(sc, true); -+ count = 0; -+ } -+ } else -+ count = 0; -+} -+ -+void ath_hw_pll_work(struct work_struct *work) -+{ -+ struct ath_softc *sc = container_of(work, struct ath_softc, -+ hw_pll_work.work); -+ u32 pll_sqsum; -+ -+ if (AR_SREV_9485(sc->sc_ah)) { -+ -+ ath9k_ps_wakeup(sc); -+ pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); -+ ath9k_ps_restore(sc); -+ -+ ath_hw_pll_rx_hang_check(sc, pll_sqsum); -+ -+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); -+ } -+} -+ -+ - void ath9k_tasklet(unsigned long data) - { - struct ath_softc *sc = (struct ath_softc *)data; -@@ -828,48 +865,6 @@ - #undef SCHED_INTR - } - --static void ath9k_bss_assoc_info(struct ath_softc *sc, -- struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_bss_conf *bss_conf) --{ -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- -- if (bss_conf->assoc) { -- ath_dbg(common, ATH_DBG_CONFIG, -- "Bss Info ASSOC %d, bssid: %pM\n", -- bss_conf->aid, common->curbssid); -- -- /* New association, store aid */ -- common->curaid = bss_conf->aid; -- ath9k_hw_write_associd(ah); -- -- /* -- * 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; -- -- /* Configure the beacon */ -- ath_beacon_config(sc, vif); -- -- /* Reset rssi stats */ -- sc->last_rssi = ATH_RSSI_DUMMY_MARKER; -- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; -- -- sc->sc_flags |= SC_OP_ANI_RUN; -- ath_start_ani(common); -- } else { -- ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); -- common->curaid = 0; -- /* Stop ANI */ -- sc->sc_flags &= ~SC_OP_ANI_RUN; -- del_timer_sync(&common->ani.timer); -- } --} -- - void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) - { - struct ath_hw *ah = sc->sc_ah; -@@ -899,7 +894,7 @@ - goto out; - } - if (sc->sc_flags & SC_OP_BEACONS) -- ath_beacon_config(sc, NULL); /* restart beacons */ -+ ath_set_beacon(sc); /* restart beacons */ - - /* Re-Enable interrupts */ - ath9k_hw_set_interrupts(ah, ah->imask); -@@ -1006,7 +1001,7 @@ - sc->config.txpowlimit, &sc->curtxpow); - - if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) -- ath_beacon_config(sc, NULL); /* restart beacons */ -+ ath_set_beacon(sc); /* restart beacons */ - - ath9k_hw_set_interrupts(ah, ah->imask); - -@@ -1452,7 +1447,6 @@ - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); -- struct ath_vif *avp = (void *)vif->drv_priv; - int ret = 0; - - ath9k_ps_wakeup(sc); -@@ -1482,8 +1476,9 @@ - } - } - -- if ((vif->type == NL80211_IFTYPE_ADHOC) && -- sc->nvifs > 0) { -+ if ((ah->opmode == NL80211_IFTYPE_ADHOC) || -+ ((vif->type == NL80211_IFTYPE_ADHOC) && -+ sc->nvifs > 0)) { - ath_err(common, "Cannot create ADHOC interface when other" - " interfaces already exist.\n"); - ret = -EINVAL; -@@ -1493,10 +1488,6 @@ - ath_dbg(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", vif->type); - -- /* Set the VIF opmode */ -- avp->av_opmode = vif->type; -- avp->av_bslot = -1; -- - sc->nvifs++; - - ath9k_do_vif_add_setup(hw, vif); -@@ -1782,23 +1773,63 @@ - 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) - { -@@ -1855,12 +1886,29 @@ - if (ath9k_modparam_nohwcrypt) - return -ENOSPC; - -+ if (vif->type == NL80211_IFTYPE_ADHOC && -+ (key->cipher == WLAN_CIPHER_SUITE_TKIP || -+ key->cipher == WLAN_CIPHER_SUITE_CCMP) && -+ !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { -+ /* -+ * For now, disable hw crypto for the RSN IBSS group keys. This -+ * could be optimized in the future to use a modified key cache -+ * design to support per-STA RX GTK, but until that gets -+ * implemented, use of software crypto for group addressed -+ * frames is a acceptable to allow RSN IBSS to be used. -+ */ -+ return -EOPNOTSUPP; -+ } -+ - mutex_lock(&sc->mutex); - ath9k_ps_wakeup(sc); - ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); - - 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; -@@ -1886,6 +1934,92 @@ - - return ret; - } -+static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -+{ -+ struct ath_softc *sc = data; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -+ struct ath_vif *avp = (void *)vif->drv_priv; -+ -+ switch (sc->sc_ah->opmode) { -+ case NL80211_IFTYPE_ADHOC: -+ /* There can be only one vif available */ -+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -+ common->curaid = bss_conf->aid; -+ ath9k_hw_write_associd(sc->sc_ah); -+ /* configure beacon */ -+ if (bss_conf->enable_beacon) -+ ath_beacon_config(sc, vif); -+ break; -+ case NL80211_IFTYPE_STATION: -+ /* -+ * Skip iteration if primary station vif's bss info -+ * was not changed -+ */ -+ if (sc->sc_flags & SC_OP_PRIM_STA_VIF) -+ break; -+ -+ if (bss_conf->assoc) { -+ sc->sc_flags |= SC_OP_PRIM_STA_VIF; -+ avp->primary_sta_vif = true; -+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -+ common->curaid = bss_conf->aid; -+ ath9k_hw_write_associd(sc->sc_ah); -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Bss Info ASSOC %d, bssid: %pM\n", -+ bss_conf->aid, common->curbssid); -+ ath_beacon_config(sc, vif); -+ /* -+ * 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; -+ /* Reset rssi stats */ -+ sc->last_rssi = ATH_RSSI_DUMMY_MARKER; -+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; -+ -+ sc->sc_flags |= SC_OP_ANI_RUN; -+ ath_start_ani(common); -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) -+{ -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -+ struct ath_vif *avp = (void *)vif->drv_priv; -+ -+ /* Reconfigure bss info */ -+ if (avp->primary_sta_vif && !bss_conf->assoc) { -+ ath_dbg(common, ATH_DBG_CONFIG, -+ "Bss Info DISASSOC %d, bssid %pM\n", -+ common->curaid, common->curbssid); -+ sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); -+ avp->primary_sta_vif = false; -+ memset(common->curbssid, 0, ETH_ALEN); -+ common->curaid = 0; -+ } -+ -+ ieee80211_iterate_active_interfaces_atomic( -+ sc->hw, ath9k_bss_iter, sc); -+ -+ /* -+ * None of station vifs are associated. -+ * Clear bssid & aid -+ */ -+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && -+ !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { -+ ath9k_hw_write_associd(sc->sc_ah); -+ /* Stop ANI */ -+ sc->sc_flags &= ~SC_OP_ANI_RUN; -+ del_timer_sync(&common->ani.timer); -+ } -+} - - static void ath9k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, -@@ -1893,7 +2027,6 @@ - u32 changed) - { - struct ath_softc *sc = hw->priv; -- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_vif *avp = (void *)vif->drv_priv; -@@ -1904,20 +2037,13 @@ - mutex_lock(&sc->mutex); - - if (changed & BSS_CHANGED_BSSID) { -- /* Set BSSID */ -- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -- memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); -- common->curaid = 0; -- ath9k_hw_write_associd(ah); -+ ath9k_config_bss(sc, vif); - - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - - ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); -- -- /* need to reconfigure the beacon */ -- sc->sc_flags &= ~SC_OP_BEACONS ; - } - - /* Enable transmission of beacons (AP, IBSS, MESH) */ -@@ -1958,7 +2084,6 @@ - } - - if (changed & BSS_CHANGED_BEACON_INT) { -- cur_conf->beacon_interval = bss_conf->beacon_int; - /* - * In case of AP mode, the HW TSF has to be reset - * when the beacon interval changes. -@@ -1970,9 +2095,8 @@ - if (!error) - ath_beacon_config(sc, vif); - ath9k_set_beaconing_status(sc, true); -- } else { -+ } else - ath_beacon_config(sc, vif); -- } - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { -@@ -1994,12 +2118,6 @@ - sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; - } - -- if (changed & BSS_CHANGED_ASSOC) { -- ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", -- bss_conf->assoc); -- ath9k_bss_assoc_info(sc, hw, vif, bss_conf); -- } -- - mutex_unlock(&sc->mutex); - ath9k_ps_restore(sc); - } -@@ -2144,9 +2262,7 @@ - int timeout = 200; /* ms */ - int i, j; - -- ath9k_ps_wakeup(sc); - mutex_lock(&sc->mutex); -- - cancel_delayed_work_sync(&sc->tx_complete_work); - - if (drop) -@@ -2169,15 +2285,30 @@ - goto out; - } - -+ ath9k_ps_wakeup(sc); - if (!ath_drain_all_txq(sc, false)) - ath_reset(sc, false); -- -+ ath9k_ps_restore(sc); - ieee80211_wake_queues(hw); - - out: - ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); - mutex_unlock(&sc->mutex); -- 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 = { -@@ -2191,6 +2322,7 @@ - .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, -@@ -2202,4 +2334,5 @@ - .rfkill_poll = ath9k_rfkill_poll_state, - .set_coverage_class = ath9k_set_coverage_class, - .flush = ath9k_flush, -+ .tx_frames_pending = ath9k_tx_frames_pending, - }; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/Makefile 2011-05-05 23:29:49.076485252 +0200 -@@ -6,8 +6,8 @@ - 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 @@ - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/phy.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/phy.h 2011-05-05 23:29:49.075485239 +0200 -@@ -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 -@@ -38,26 +37,15 @@ - #define AR_PHY_CLC_Q0 0x0000ffd0 - #define AR_PHY_CLC_Q0_S 5 - --#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ -- int r; \ -- for (r = 0; r < ((iniarray)->ia_rows); r++) { \ -- REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ -- DO_DELAY(regWr); \ -- } \ -- } while (0) -- - #define ANTSWAP_AB 0x0001 - #define REDUCE_CHAIN_0 0x00000050 - #define REDUCE_CHAIN_1 0x00000051 - #define AR_PHY_CHIP_ID 0x9818 - --#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ -- int i; \ -- for (i = 0; i < (_iniarray)->ia_rows; i++) \ -- (_bank)[i] = INI_RA((_iniarray), i, _col);; \ -- } while (0) -- - #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 - #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 - -+#define AR_PHY_PLL_CONTROL 0x16180 -+#define AR_PHY_PLL_MODE 0x16184 -+ - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/rc.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/rc.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/rc.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/rc.c 2011-05-05 23:29:49.098485517 +0200 -@@ -854,14 +854,13 @@ - ath_rc_rate_set_rtscts(sc, rate_table, tx_info); - } - --static bool ath_rc_update_per(struct ath_softc *sc, -+static void ath_rc_update_per(struct ath_softc *sc, - const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int tx_rate, int xretries, int retries, - u32 now_msec) - { -- bool state_change = false; - int count, n_bad_frames; - u8 last_per; - static const u32 nretry_to_per_lookup[10] = { -@@ -992,8 +991,6 @@ - - } - } -- -- return state_change; - } - - static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, -@@ -1017,7 +1014,6 @@ - u32 now_msec = jiffies_to_msecs(jiffies); - int rate; - u8 last_per; -- bool state_change = false; - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - int size = ath_rc_priv->rate_table_size; - -@@ -1027,9 +1023,9 @@ - last_per = ath_rc_priv->per[tx_rate]; - - /* Update PER first */ -- state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, -- tx_info, tx_rate, xretries, -- retries, now_msec); -+ ath_rc_update_per(sc, rate_table, ath_rc_priv, -+ tx_info, tx_rate, xretries, -+ retries, now_msec); - - /* - * If this rate looks bad (high PER) then stop using it for -@@ -1092,8 +1088,7 @@ - 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++; - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/recv.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/recv.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/recv.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/recv.c 2011-05-05 23:29:49.084485349 +0200 -@@ -75,7 +75,6 @@ - *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 @@ - 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; - -@@ -574,7 +571,7 @@ - sc->ps_flags &= ~PS_BEACON_SYNC; - ath_dbg(common, ATH_DBG_PS, - "Reconfigure Beacon timers based on timestamp from the AP\n"); -- ath_beacon_config(sc, NULL); -+ ath_set_beacon(sc); - } - - if (ath_beacon_dtim_pending_cab(skb)) { -@@ -1342,7 +1339,7 @@ - struct ath_hw_antcomb_conf div_ant_conf; - struct ath_ant_comb *antcomb = &sc->ant_comb; - int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; -- int curr_main_set, curr_bias; -+ int curr_main_set; - int main_rssi = rs->rs_rssi_ctl0; - int alt_rssi = rs->rs_rssi_ctl1; - int rx_ant_conf, main_ant_conf; -@@ -1396,7 +1393,6 @@ - ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); - curr_alt_set = div_ant_conf.alt_lna_conf; - curr_main_set = div_ant_conf.main_lna_conf; -- curr_bias = div_ant_conf.fast_div_bias; - - antcomb->count++; - -@@ -1746,7 +1742,7 @@ - if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | - PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA)) || -- unlikely(ath9k_check_auto_sleep(sc))) -+ ath9k_check_auto_sleep(sc)) - ath_rx_ps(sc, skb); - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - -@@ -1767,6 +1763,7 @@ - } else { - list_move_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_buf_link(sc, bf); -+ ath9k_hw_rxena(ah); - } - } while (1); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/reg.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/reg.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/reg.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/reg.h 2011-05-05 23:29:49.093485457 +0200 -@@ -693,7 +693,7 @@ - #define AR_RC_APB 0x00000002 - #define AR_RC_HOSTIF 0x00000100 - --#define AR_WA 0x4004 -+#define AR_WA (AR_SREV_9340(ah) ? 0x40c4 : 0x4004) - #define AR_WA_BIT6 (1 << 6) - #define AR_WA_BIT7 (1 << 7) - #define AR_WA_BIT23 (1 << 23) -@@ -712,7 +712,7 @@ - #define AR_PM_STATE 0x4008 - #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 - --#define AR_HOST_TIMEOUT 0x4018 -+#define AR_HOST_TIMEOUT (AR_SREV_9340(ah) ? 0x4008 : 0x4018) - #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF - #define AR_HOST_TIMEOUT_APB_CNTR_S 0 - #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 -@@ -742,7 +742,8 @@ - #define EEPROM_PROTECT_WP_1024_2047 0x8000 - - #define AR_SREV \ -- ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) -+ ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \ -+ ? 0x400c : 0x4020)) - - #define AR_SREV_ID \ - ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) -@@ -790,6 +791,7 @@ - #define AR_SREV_VERSION_9485 0x240 - #define AR_SREV_REVISION_9485_10 0 - #define AR_SREV_REVISION_9485_11 1 -+#define AR_SREV_VERSION_9340 0x300 - - #define AR_SREV_5416(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ -@@ -858,9 +860,7 @@ - #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)) -@@ -870,6 +870,11 @@ - #define AR_SREV_9485_11(_ah) \ - (AR_SREV_9485(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) -+#define AR_SREV_9485_OR_LATER(_ah) \ -+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) -+ -+#define AR_SREV_9340(_ah) \ -+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) - - #define AR_SREV_9285E_20(_ah) \ - (AR_SREV_9285_12_OR_LATER(_ah) && \ -@@ -912,11 +917,11 @@ - #define AR_INTR_SPURIOUS 0xFFFFFFFF - - --#define AR_INTR_SYNC_CAUSE_CLR 0x4028 -+#define AR_INTR_SYNC_CAUSE (AR_SREV_9340(ah) ? 0x4010 : 0x4028) -+#define AR_INTR_SYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4010 : 0x4028) - --#define AR_INTR_SYNC_CAUSE 0x4028 - --#define AR_INTR_SYNC_ENABLE 0x402c -+#define AR_INTR_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4014 : 0x402c) - #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 - #define AR_INTR_SYNC_ENABLE_GPIO_S 18 - -@@ -956,24 +961,24 @@ - - }; - --#define AR_INTR_ASYNC_MASK 0x4030 -+#define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) - #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 - #define AR_INTR_ASYNC_MASK_GPIO_S 18 - --#define AR_INTR_SYNC_MASK 0x4034 -+#define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) - #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 - #define AR_INTR_SYNC_MASK_GPIO_S 18 - --#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 --#define AR_INTR_ASYNC_CAUSE 0x4038 -+#define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) -+#define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) - --#define AR_INTR_ASYNC_ENABLE 0x403c -+#define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) - #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 - #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 - - #define AR_PCIE_SERDES 0x4040 - #define AR_PCIE_SERDES2 0x4044 --#define AR_PCIE_PM_CTRL 0x4014 -+#define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014) - #define AR_PCIE_PM_CTRL_ENA 0x00080000 - - #define AR_NUM_GPIO 14 -@@ -984,7 +989,7 @@ - #define AR9300_NUM_GPIO 17 - #define AR7010_NUM_GPIO 16 - --#define AR_GPIO_IN_OUT 0x4048 -+#define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048) - #define AR_GPIO_IN_VAL 0x0FFFC000 - #define AR_GPIO_IN_VAL_S 14 - #define AR928X_GPIO_IN_VAL 0x000FFC00 -@@ -998,11 +1003,12 @@ - #define AR7010_GPIO_IN_VAL 0x0000FFFF - #define AR7010_GPIO_IN_VAL_S 0 - --#define AR_GPIO_IN 0x404c -+#define AR_GPIO_IN (AR_SREV_9340(ah) ? 0x402c : 0x404c) - #define AR9300_GPIO_IN_VAL 0x0001FFFF - #define AR9300_GPIO_IN_VAL_S 0 - --#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) -+#define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)) - #define AR_GPIO_OE_OUT_DRV 0x3 - #define AR_GPIO_OE_OUT_DRV_NO 0x0 - #define AR_GPIO_OE_OUT_DRV_LOW 0x1 -@@ -1024,11 +1030,13 @@ - #define AR7010_GPIO_INT_MASK 0x52024 - #define AR7010_GPIO_FUNCTION 0x52028 - --#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) -+#define AR_GPIO_INTR_POL (AR_SREV_9340(ah) ? 0x4038 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)) - #define AR_GPIO_INTR_POL_VAL 0x0001FFFF - #define AR_GPIO_INTR_POL_VAL_S 0 - --#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054) -+#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9340(ah) ? 0x403c : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)) - #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 - #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 - #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 -@@ -1046,13 +1054,15 @@ - #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 - #define AR_GPIO_JTAG_DISABLE 0x00020000 - --#define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058) -+#define AR_GPIO_INPUT_MUX1 (AR_SREV_9340(ah) ? 0x4040 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)) - #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 - #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 - #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 - #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 - --#define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c) -+#define AR_GPIO_INPUT_MUX2 (AR_SREV_9340(ah) ? 0x4044 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)) - #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f - #define AR_GPIO_INPUT_MUX2_CLK25_S 0 - #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 -@@ -1060,13 +1070,18 @@ - #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 - #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 - --#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) --#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) --#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) -+#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9340(ah) ? 0x4048 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060)) -+#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9340(ah) ? 0x404c : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064)) -+#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9340(ah) ? 0x4050 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068)) - --#define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) -+#define AR_INPUT_STATE (AR_SREV_9340(ah) ? 0x4054 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c)) - --#define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c) -+#define AR_EEPROM_STATUS_DATA (AR_SREV_9340(ah) ? 0x40c8 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)) - #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff - #define AR_EEPROM_STATUS_DATA_VAL_S 0 - #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 -@@ -1074,28 +1089,51 @@ - #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 - #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 - --#define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) -+#define AR_OBS (AR_SREV_9340(ah) ? 0x405c : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080)) - - #define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) - --#define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) -+#define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \ -+ (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)) - #define AR_PCIE_MSI_ENABLE 0x00000001 - --#define AR_INTR_PRIO_SYNC_ENABLE 0x40c4 --#define AR_INTR_PRIO_ASYNC_MASK 0x40c8 --#define AR_INTR_PRIO_SYNC_MASK 0x40cc --#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 -+#define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4) -+#define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8) -+#define AR_INTR_PRIO_SYNC_MASK (AR_SREV_9340(ah) ? 0x4090 : 0x40cc) -+#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) - #define AR_ENT_OTP 0x40d8 - #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 - #define AR_ENT_OTP_MPSD 0x00800000 --#define AR_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 -@@ -1144,6 +1182,7 @@ - #define AR_RTC_PLL_REFDIV_5 0x000000c0 - #define AR_RTC_PLL_CLKSEL 0x00000300 - #define AR_RTC_PLL_CLKSEL_S 8 -+#define AR_RTC_PLL_BYPASS 0x00010000 - - #define PLL3 0x16188 - #define PLL3_DO_MEAS_MASK 0x40000000 -@@ -1190,7 +1229,8 @@ - - /* RTC_DERIVED_* - only for AR9100 */ - --#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) -+#define AR_RTC_DERIVED_CLK \ -+ (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038) - #define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe - #define AR_RTC_DERIVED_CLK_PERIOD_S 1 - -@@ -1396,6 +1436,7 @@ - #define AR_STA_ID1_PCF 0x00100000 - #define AR_STA_ID1_USE_DEFANT 0x00200000 - #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 -+#define AR_STA_ID1_AR9100_BA_FIX 0x00400000 - #define AR_STA_ID1_RTS_USE_DEF 0x00800000 - #define AR_STA_ID1_ACKCTS_6MB 0x01000000 - #define AR_STA_ID1_BASE_RATE_11B 0x02000000 -@@ -1668,6 +1709,22 @@ - #define AR_BTCOEX_WL_WGHT 0xffff0000 - #define AR_BTCOEX_WL_WGHT_S 16 - -+#define AR_BT_COEX_WL_WEIGHTS0 0x8174 -+#define AR_BT_COEX_WL_WEIGHTS1 0x81c4 -+ -+#define AR_BT_COEX_BT_WEIGHTS0 0x83ac -+#define AR_BT_COEX_BT_WEIGHTS1 0x83b0 -+#define AR_BT_COEX_BT_WEIGHTS2 0x83b4 -+#define AR_BT_COEX_BT_WEIGHTS3 0x83b8 -+ -+#define AR9300_BT_WGHT 0xcccc4444 -+#define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 -+#define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 -+#define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 -+#define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 -+#define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 -+#define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 -+ - #define AR_BT_COEX_MODE2 0x817c - #define AR_BT_BCN_MISS_THRESH 0x000000ff - #define AR_BT_BCN_MISS_THRESH_S 0 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/wmi.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/wmi.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/wmi.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/wmi.c 2011-05-05 23:29:49.094485469 +0200 -@@ -23,20 +23,18 @@ - 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 @@ - 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 @@ - 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,22 +65,22 @@ - 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_AGGR_LIMIT_CMD: -- return "WMI_AGGR_LIMIT_CMD"; -+ 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_BITRATE_MASK_CMDID: -+ return "WMI_BITRATE_MASK_CMDID"; - } - - return "Bogus"; -@@ -102,9 +96,15 @@ - - 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 @@ - 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; -+ -+ 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_swba(priv, priv->wmi->beacon_pending); -+ 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 @@ - 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 @@ - 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 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/wmi.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/wmi.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/wmi.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/wmi.h 2011-05-05 23:29:49.071485191 +0200 -@@ -17,7 +17,6 @@ - #ifndef WMI_H - #define WMI_H - -- - struct wmi_event_txrate { - __be32 txrate; - struct { -@@ -31,18 +30,65 @@ - __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,24 +96,22 @@ - 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_AGGR_LIMIT_CMD = 0x0026, -+ WMI_NODE_UPDATE_CMDID, -+ WMI_INT_STATS_CMDID, -+ WMI_TX_STATS_CMDID, -+ WMI_RX_STATS_CMDID, -+ WMI_BITRATE_MASK_CMDID, - }; - - enum wmi_event_id { -@@ -76,9 +120,8 @@ - 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 @@ - __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 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 @@ - 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 { \ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/xmit.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/xmit.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath9k/xmit.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath9k/xmit.c 2011-05-05 23:29:49.072485203 +0200 -@@ -357,6 +357,7 @@ - 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 @@ - /* 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 @@ - !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 @@ - - /* 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 @@ - 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 @@ - 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 @@ - 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 @@ - - 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 @@ - 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 @@ - 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 @@ - 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); - } - -@@ -1980,7 +2061,7 @@ - if (ieee80211_is_data(hdr->frame_control) && - (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | - ATH9K_TX_DELIM_UNDERRUN)) && -- ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) -+ ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) - tx_info->status.rates[tx_rateindex].count = - hw->max_rate_tries; - } -@@ -2099,28 +2180,6 @@ - } - } - --static void ath_hw_pll_work(struct work_struct *work) --{ -- struct ath_softc *sc = container_of(work, struct ath_softc, -- hw_pll_work.work); -- static int count; -- -- if (AR_SREV_9485(sc->sc_ah)) { -- if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { -- count++; -- -- if (count == 3) { -- /* Rx is hung for more than 500ms. Reset it */ -- ath_reset(sc, true); -- count = 0; -- } -- } else -- count = 0; -- -- ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); -- } --} -- - static void ath_tx_complete_poll_work(struct work_struct *work) - { - struct ath_softc *sc = container_of(work, struct ath_softc, -@@ -2144,33 +2203,6 @@ - } else { - txq->axq_tx_inprogress = true; - } -- } else { -- /* If the queue has pending buffers, then it -- * should be doing tx work (and have axq_depth). -- * Shouldn't get to this state I think..but -- * we do. -- */ -- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && -- (txq->pending_frames > 0 || -- !list_empty(&txq->axq_acq) || -- txq->stopped)) { -- ath_err(ath9k_hw_common(sc->sc_ah), -- "txq: %p axq_qnum: %u," -- " mac80211_qnum: %i" -- " axq_link: %p" -- " pending frames: %i" -- " axq_acq empty: %i" -- " stopped: %i" -- " axq_depth: 0 Attempting to" -- " restart tx logic.\n", -- txq, txq->axq_qnum, -- txq->mac80211_qnum, -- txq->axq_link, -- txq->pending_frames, -- list_empty(&txq->axq_acq), -- txq->stopped); -- ath_txq_schedule(sc, txq); -- } - } - spin_unlock_bh(&txq->axq_lock); - } -@@ -2342,7 +2374,6 @@ - } - - INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); -- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { - error = ath_tx_edma_init(sc); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/ath.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/ath.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/ath.h 2011-05-05 23:29:49.113485699 +0200 -@@ -119,17 +119,11 @@ - void (*write)(void *, u32 val, u32 reg_offset); - void (*enable_write_buffer)(void *); - void (*write_flush) (void *); -+ u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); - }; - - 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/carl9170.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/carl9170.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/carl9170.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/carl9170.h 2011-05-05 23:29:48.973484007 +0200 -@@ -448,6 +448,8 @@ - - struct carl9170_sta_info { - bool ht_sta; -+ bool sleeping; -+ atomic_t pending_frames; - unsigned int ampdu_max_len; - struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; - struct carl9170_ba_stats stats[CARL9170_NUM_TID]; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/main.c 2011-05-05 23:29:48.978484068 +0200 -@@ -1193,6 +1193,8 @@ - struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; - unsigned int i; - -+ atomic_set(&sta_info->pending_frames, 0); -+ - if (sta->ht_cap.ht_supported) { - if (sta->ht_cap.ampdu_density > 6) { - /* -@@ -1467,99 +1469,17 @@ - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) - { -- struct ar9170 *ar = hw->priv; - struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; -- struct sk_buff *skb, *tmp; -- struct sk_buff_head free; -- int i; - - switch (cmd) { - case STA_NOTIFY_SLEEP: -- /* -- * Since the peer is no longer listening, we have to return -- * as many SKBs as possible back to the mac80211 stack. -- * It will deal with the retry procedure, once the peer -- * has become available again. -- * -- * NB: Ideally, the driver should return the all frames in -- * the correct, ascending order. However, I think that this -- * functionality should be implemented in the stack and not -- * here... -- */ -- -- __skb_queue_head_init(&free); -- -- if (sta->ht_cap.ht_supported) { -- rcu_read_lock(); -- for (i = 0; i < CARL9170_NUM_TID; i++) { -- struct carl9170_sta_tid *tid_info; -- -- tid_info = rcu_dereference(sta_info->agg[i]); -- -- if (!tid_info) -- continue; -- -- spin_lock_bh(&ar->tx_ampdu_list_lock); -- if (tid_info->state > -- CARL9170_TID_STATE_SUSPEND) -- tid_info->state = -- CARL9170_TID_STATE_SUSPEND; -- spin_unlock_bh(&ar->tx_ampdu_list_lock); -- -- spin_lock_bh(&tid_info->lock); -- while ((skb = __skb_dequeue(&tid_info->queue))) -- __skb_queue_tail(&free, skb); -- spin_unlock_bh(&tid_info->lock); -- } -- rcu_read_unlock(); -- } -- -- for (i = 0; i < ar->hw->queues; i++) { -- spin_lock_bh(&ar->tx_pending[i].lock); -- skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) { -- struct _carl9170_tx_superframe *super; -- struct ieee80211_hdr *hdr; -- struct ieee80211_tx_info *info; -- -- super = (void *) skb->data; -- hdr = (void *) super->frame_data; -- -- if (compare_ether_addr(hdr->addr1, sta->addr)) -- continue; -- -- __skb_unlink(skb, &ar->tx_pending[i]); -- -- info = IEEE80211_SKB_CB(skb); -- if (info->flags & IEEE80211_TX_CTL_AMPDU) -- atomic_dec(&ar->tx_ampdu_upload); -- -- carl9170_tx_status(ar, skb, false); -- } -- spin_unlock_bh(&ar->tx_pending[i].lock); -- } -- -- while ((skb = __skb_dequeue(&free))) -- carl9170_tx_status(ar, skb, false); -- -+ sta_info->sleeping = true; -+ if (atomic_read(&sta_info->pending_frames)) -+ ieee80211_sta_block_awake(hw, sta, true); - break; - - case STA_NOTIFY_AWAKE: -- if (!sta->ht_cap.ht_supported) -- return; -- -- rcu_read_lock(); -- for (i = 0; i < CARL9170_NUM_TID; i++) { -- struct carl9170_sta_tid *tid_info; -- -- tid_info = rcu_dereference(sta_info->agg[i]); -- -- if (!tid_info) -- continue; -- -- if ((tid_info->state == CARL9170_TID_STATE_SUSPEND)) -- tid_info->state = CARL9170_TID_STATE_IDLE; -- } -- rcu_read_unlock(); -+ sta_info->sleeping = false; - break; - } - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/carl9170/tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/carl9170/tx.c 2011-05-05 23:29:48.951483741 +0200 -@@ -104,6 +104,56 @@ - spin_unlock_bh(&ar->tx_stats_lock); - } - -+/* needs rcu_read_lock */ -+static struct ieee80211_sta *__carl9170_get_tx_sta(struct ar9170 *ar, -+ struct sk_buff *skb) -+{ -+ struct _carl9170_tx_superframe *super = (void *) skb->data; -+ struct ieee80211_hdr *hdr = (void *) super->frame_data; -+ struct ieee80211_vif *vif; -+ unsigned int vif_id; -+ -+ vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> -+ CARL9170_TX_SUPER_MISC_VIF_ID_S; -+ -+ if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) -+ return NULL; -+ -+ vif = rcu_dereference(ar->vif_priv[vif_id].vif); -+ if (unlikely(!vif)) -+ return NULL; -+ -+ /* -+ * Normally we should use wrappers like ieee80211_get_DA to get -+ * the correct peer ieee80211_sta. -+ * -+ * But there is a problem with indirect traffic (broadcasts, or -+ * data which is designated for other stations) in station mode. -+ * The frame will be directed to the AP for distribution and not -+ * to the actual destination. -+ */ -+ -+ return ieee80211_find_sta(vif, hdr->addr1); -+} -+ -+static void carl9170_tx_ps_unblock(struct ar9170 *ar, struct sk_buff *skb) -+{ -+ struct ieee80211_sta *sta; -+ struct carl9170_sta_info *sta_info; -+ -+ rcu_read_lock(); -+ sta = __carl9170_get_tx_sta(ar, skb); -+ if (unlikely(!sta)) -+ goto out_rcu; -+ -+ sta_info = (struct carl9170_sta_info *) sta->drv_priv; -+ if (atomic_dec_return(&sta_info->pending_frames) == 0) -+ ieee80211_sta_block_awake(ar->hw, sta, false); -+ -+out_rcu: -+ rcu_read_unlock(); -+} -+ - static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) - { - struct ieee80211_tx_info *txinfo; -@@ -135,6 +185,7 @@ - } - - spin_unlock_bh(&ar->tx_stats_lock); -+ - if (atomic_dec_and_test(&ar->tx_total_queued)) - complete(&ar->tx_flush); - } -@@ -329,13 +380,10 @@ - { - struct _carl9170_tx_superframe *super = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) super->frame_data; -- struct ieee80211_tx_info *tx_info; - struct carl9170_tx_info *ar_info; -- struct carl9170_sta_info *sta_info; - struct ieee80211_sta *sta; -+ struct carl9170_sta_info *sta_info; - struct carl9170_sta_tid *tid_info; -- struct ieee80211_vif *vif; -- unsigned int vif_id; - u8 tid; - - if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || -@@ -343,30 +391,10 @@ - (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) - return; - -- tx_info = IEEE80211_SKB_CB(skb); -- ar_info = (void *) tx_info->rate_driver_data; -- -- vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> -- CARL9170_TX_SUPER_MISC_VIF_ID_S; -- -- if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) -- return; -+ ar_info = (void *) txinfo->rate_driver_data; - - rcu_read_lock(); -- vif = rcu_dereference(ar->vif_priv[vif_id].vif); -- if (unlikely(!vif)) -- goto out_rcu; -- -- /* -- * Normally we should use wrappers like ieee80211_get_DA to get -- * the correct peer ieee80211_sta. -- * -- * But there is a problem with indirect traffic (broadcasts, or -- * data which is designated for other stations) in station mode. -- * The frame will be directed to the AP for distribution and not -- * to the actual destination. -- */ -- sta = ieee80211_find_sta(vif, hdr->addr1); -+ sta = __carl9170_get_tx_sta(ar, skb); - if (unlikely(!sta)) - goto out_rcu; - -@@ -427,6 +455,7 @@ - if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) - carl9170_tx_status_process_ampdu(ar, skb, txinfo); - -+ carl9170_tx_ps_unblock(ar, skb); - carl9170_tx_put_skb(skb); - } - -@@ -540,11 +569,7 @@ - struct sk_buff *skb; - struct ieee80211_tx_info *txinfo; - struct carl9170_tx_info *arinfo; -- struct _carl9170_tx_superframe *super; - struct ieee80211_sta *sta; -- struct ieee80211_vif *vif; -- struct ieee80211_hdr *hdr; -- unsigned int vif_id; - - rcu_read_lock(); - list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { -@@ -562,20 +587,7 @@ - msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) - goto unlock; - -- super = (void *) skb->data; -- hdr = (void *) super->frame_data; -- -- vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> -- CARL9170_TX_SUPER_MISC_VIF_ID_S; -- -- if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) -- goto unlock; -- -- vif = rcu_dereference(ar->vif_priv[vif_id].vif); -- if (WARN_ON(!vif)) -- goto unlock; -- -- sta = ieee80211_find_sta(vif, hdr->addr1); -+ sta = __carl9170_get_tx_sta(ar, skb); - if (WARN_ON(!sta)) - goto unlock; - -@@ -1199,15 +1211,6 @@ - arinfo = (void *) info->rate_driver_data; - - arinfo->timeout = jiffies; -- -- /* -- * increase ref count to "2". -- * Ref counting is the easiest way to solve the race between -- * the the urb's completion routine: carl9170_tx_callback and -- * wlan tx status functions: carl9170_tx_status/janitor. -- */ -- carl9170_tx_get_skb(skb); -- - return skb; - - err_unlock: -@@ -1228,6 +1231,36 @@ - __carl9170_tx_process_status(ar, super->s.cookie, q); - } - -+static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) -+{ -+ struct ieee80211_sta *sta; -+ struct carl9170_sta_info *sta_info; -+ -+ rcu_read_lock(); -+ sta = __carl9170_get_tx_sta(ar, skb); -+ if (!sta) -+ goto out_rcu; -+ -+ sta_info = (void *) sta->drv_priv; -+ if (unlikely(sta_info->sleeping)) { -+ struct ieee80211_tx_info *tx_info; -+ -+ rcu_read_unlock(); -+ -+ tx_info = IEEE80211_SKB_CB(skb); -+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) -+ atomic_dec(&ar->tx_ampdu_upload); -+ -+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; -+ carl9170_tx_status(ar, skb, false); -+ return true; -+ } -+ -+out_rcu: -+ rcu_read_unlock(); -+ return false; -+} -+ - static void carl9170_tx(struct ar9170 *ar) - { - struct sk_buff *skb; -@@ -1247,6 +1280,9 @@ - if (unlikely(!skb)) - break; - -+ if (unlikely(carl9170_tx_ps_drop(ar, skb))) -+ continue; -+ - atomic_inc(&ar->tx_total_pending); - - q = __carl9170_get_queue(ar, i); -@@ -1256,6 +1292,16 @@ - */ - skb_queue_tail(&ar->tx_status[q], skb); - -+ /* -+ * increase ref count to "2". -+ * Ref counting is the easiest way to solve the -+ * race between the urb's completion routine: -+ * carl9170_tx_callback -+ * and wlan tx status functions: -+ * carl9170_tx_status/janitor. -+ */ -+ carl9170_tx_get_skb(skb); -+ - carl9170_usb_tx(ar, skb); - schedule_garbagecollector = true; - } -@@ -1368,6 +1414,11 @@ - * all ressouces which are associated with the frame. - */ - -+ if (sta) { -+ struct carl9170_sta_info *stai = (void *) sta->drv_priv; -+ atomic_inc(&stai->pending_frames); -+ } -+ - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - run = carl9170_tx_ampdu_queue(ar, sta, skb); - if (run) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/ath/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/Kconfig 2011-05-05 23:29:49.145486085 +0200 -@@ -24,7 +24,6 @@ - - source "drivers/net/wireless/ath/ath5k/Kconfig" - source "drivers/net/wireless/ath/ath9k/Kconfig" --source "drivers/net/wireless/ath/ar9170/Kconfig" - source "drivers/net/wireless/ath/carl9170/Kconfig" - - endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/key.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/key.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/key.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/key.c 2011-05-05 23:29:49.136485977 +0200 -@@ -23,6 +23,14 @@ - - #define REG_READ (common->ops->read) - #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) -+#define ENABLE_REGWRITE_BUFFER(_ah) \ -+ if (common->ops->enable_write_buffer) \ -+ common->ops->enable_write_buffer((_ah)); -+ -+#define REGWRITE_BUFFER_FLUSH(_ah) \ -+ if (common->ops->write_flush) \ -+ common->ops->write_flush((_ah)); -+ - - #define IEEE80211_WEP_NKID 4 /* number of key ids */ - -@@ -42,6 +50,8 @@ - - keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); -@@ -66,6 +76,8 @@ - - } - -+ REGWRITE_BUFFER_FLUSH(ah); -+ - return true; - } - EXPORT_SYMBOL(ath_hw_keyreset); -@@ -104,9 +116,13 @@ - } else { - macLo = macHi = 0; - } -+ ENABLE_REGWRITE_BUFFER(ah); -+ - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); - -+ REGWRITE_BUFFER_FLUSH(ah); -+ - return true; - } - -@@ -223,6 +239,8 @@ - mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; - mic4 = get_unaligned_le32(k->kv_txmic + 4); - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - /* Write RX[31:0] and TX[31:16] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); -@@ -236,6 +254,8 @@ - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); - -+ REGWRITE_BUFFER_FLUSH(ah); -+ - } else { - /* - * TKIP uses four key cache entries (two for group -@@ -258,6 +278,8 @@ - mic0 = get_unaligned_le32(k->kv_mic + 0); - mic2 = get_unaligned_le32(k->kv_mic + 4); - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - /* Write MIC key[31:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); -@@ -270,8 +292,12 @@ - REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); -+ -+ REGWRITE_BUFFER_FLUSH(ah); - } - -+ ENABLE_REGWRITE_BUFFER(ah); -+ - /* MAC address registers are reserved for the MIC entry */ - REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); -@@ -283,7 +309,11 @@ - */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); -+ -+ REGWRITE_BUFFER_FLUSH(ah); - } else { -+ ENABLE_REGWRITE_BUFFER(ah); -+ - /* Write key[47:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); -@@ -296,6 +326,8 @@ - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - -+ REGWRITE_BUFFER_FLUSH(ah); -+ - /* Write MAC address for the entry */ - (void) ath_hw_keysetmac(common, entry, mac); - } -@@ -451,6 +483,9 @@ - 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; -@@ -466,7 +501,8 @@ - } - - 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) { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/ath/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/Makefile 2011-05-05 23:29:49.115485723 +0200 -@@ -1,6 +1,5 @@ - obj-$(CONFIG_ATH5K) += ath5k/ - obj-$(CONFIG_ATH9K_HW) += ath9k/ --obj-$(CONFIG_AR9170_USB) += ar9170/ - obj-$(CONFIG_CARL9170) += carl9170/ - - obj-$(CONFIG_ATH_COMMON) += ath.o -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/regd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/regd.c ---- linux-2.6.39-rc6/drivers/net/wireless/ath/regd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/regd.c 2011-05-05 23:29:48.947483693 +0200 -@@ -97,8 +97,8 @@ - } - }; - --/* 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 @@ - 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 @@ - case 0x63: - case 0x66: - case 0x67: -+ case 0x6C: - ath_reg_apply_beaconing_flags(wiphy, initiator); - break; - case 0x68: -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/ath/regd_common.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/regd_common.h ---- linux-2.6.39-rc6/drivers/net/wireless/ath/regd_common.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/ath/regd_common.h 2011-05-05 23:29:49.114485711 +0200 -@@ -86,6 +86,7 @@ - WOR9_WORLD = 0x69, - WORA_WORLD = 0x6A, - WORB_WORLD = 0x6B, -+ WORC_WORLD = 0x6C, - - MKK3_MKKB = 0x80, - MKK3_MKKA2 = 0x81, -@@ -282,6 +283,7 @@ - {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[] = { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/b43/phy_n.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/b43/phy_n.c ---- linux-2.6.39-rc6/drivers/net/wireless/b43/phy_n.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/b43/phy_n.c 2011-05-05 23:29:49.401489179 +0200 -@@ -2281,6 +2281,7 @@ - save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); - save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); - save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); -+ save_regs_phy[8] = 0; - } else { - save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); - save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); -@@ -2289,6 +2290,8 @@ - save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); - save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); - save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); -+ save_regs_phy[7] = 0; -+ save_regs_phy[8] = 0; - } - - b43_nphy_rssi_select(dev, 5, type); -@@ -3845,8 +3848,8 @@ - { - struct b43_phy *phy = &dev->phy; - -- const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; -- const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; -+ const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; -+ const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; - - u8 tmp; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl3945-base.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl3945-base.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl3945-base.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl3945-base.c 2011-05-05 23:29:47.275463493 +0200 -@@ -2748,11 +2748,12 @@ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, init_alive_start.work); - -+ mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - -- mutex_lock(&priv->mutex); - iwl3945_init_alive_start(priv); -+out: - mutex_unlock(&priv->mutex); - } - -@@ -2761,11 +2762,12 @@ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, alive_start.work); - -+ mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - -- mutex_lock(&priv->mutex); - iwl3945_alive_start(priv); -+out: - mutex_unlock(&priv->mutex); - } - -@@ -2995,10 +2997,12 @@ - } else { - iwl3945_down(priv); - -- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -+ mutex_lock(&priv->mutex); -+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { -+ mutex_unlock(&priv->mutex); - return; -+ } - -- mutex_lock(&priv->mutex); - __iwl3945_up(priv); - mutex_unlock(&priv->mutex); - } -@@ -3009,11 +3013,12 @@ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rx_replenish); - -+ mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - -- mutex_lock(&priv->mutex); - iwl3945_rx_replenish(priv); -+out: - mutex_unlock(&priv->mutex); - } - -@@ -3810,7 +3815,6 @@ - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); -- mutex_init(&priv->sync_cmd_mutex); - - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl4965-base.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl4965-base.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl4965-base.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl4965-base.c 2011-05-05 23:29:46.838458213 +0200 -@@ -1069,9 +1069,12 @@ - } - - /* Re-enable all interrupts */ -- /* only Re-enable if diabled by irq */ -+ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_legacy_enable_interrupts(priv); -+ /* Re-enable RF_KILL if it occurred */ -+ else if (handled & CSR_INT_BIT_RF_KILL) -+ iwl_legacy_enable_rfkill_int(priv); - - #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG - if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) { -@@ -2139,7 +2142,7 @@ - static void __iwl4965_down(struct iwl_priv *priv) - { - unsigned long flags; -- int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); -+ int exit_pending; - - IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); - -@@ -2401,11 +2404,12 @@ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, init_alive_start.work); - -+ mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - -- mutex_lock(&priv->mutex); - priv->cfg->ops->lib->init_alive_start(priv); -+out: - mutex_unlock(&priv->mutex); - } - -@@ -2414,11 +2418,12 @@ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, alive_start.work); - -+ mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - -- mutex_lock(&priv->mutex); - iwl4965_alive_start(priv); -+out: - mutex_unlock(&priv->mutex); - } - -@@ -2468,10 +2473,12 @@ - } else { - iwl4965_down(priv); - -- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -+ mutex_lock(&priv->mutex); -+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { -+ mutex_unlock(&priv->mutex); - return; -+ } - -- mutex_lock(&priv->mutex); - __iwl4965_up(priv); - mutex_unlock(&priv->mutex); - } -@@ -2624,9 +2631,10 @@ - - flush_workqueue(priv->workqueue); - -- /* enable interrupts again in order to receive rfkill changes */ -+ /* User space software may expect getting rfkill changes -+ * even if interface is down */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); -- iwl_legacy_enable_interrupts(priv); -+ iwl_legacy_enable_rfkill_int(priv); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - } -@@ -2847,21 +2855,22 @@ - - IWL_DEBUG_MAC80211(priv, "enter\n"); - -+ mutex_lock(&priv->mutex); -+ - if (iwl_legacy_is_rfkill(priv)) -- goto out_exit; -+ goto out; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) -- goto out_exit; -+ goto out; - - if (!iwl_legacy_is_associated_ctx(ctx)) -- goto out_exit; -+ goto out; - - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) -- goto out_exit; -+ goto out; - -- mutex_lock(&priv->mutex); - if (priv->cfg->ops->lib->set_channel_switch) { - - ch = channel->hw_value; -@@ -2917,7 +2926,6 @@ - } - out: - mutex_unlock(&priv->mutex); --out_exit: - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); - IWL_DEBUG_MAC80211(priv, "leave\n"); -@@ -3116,7 +3124,6 @@ - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); -- mutex_init(&priv->sync_cmd_mutex); - - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; -@@ -3173,7 +3180,7 @@ - { - 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); - } - -@@ -3406,14 +3413,14 @@ - * 8. Enable interrupts and read RFKILL state - *********************************************/ - -- /* enable interrupts if needed: hw bug w/a */ -+ /* enable rfkill interrupt: hw bug w/a */ - pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); - } - -- iwl_legacy_enable_interrupts(priv); -+ iwl_legacy_enable_rfkill_int(priv); - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-4965-lib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-4965-lib.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-4965-lib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-4965-lib.c 2011-05-05 23:29:47.072461039 +0200 -@@ -955,9 +955,6 @@ - if (priv->cfg->scan_rx_antennas[band]) - rx_ant = priv->cfg->scan_rx_antennas[band]; - -- if (priv->cfg->scan_tx_antennas[band]) -- scan_tx_antennas = priv->cfg->scan_tx_antennas[band]; -- - priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv, - priv->scan_tx_ant[band], - scan_tx_antennas); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-4965-rs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-4965-rs.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-4965-rs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-4965-rs.c 2011-05-05 23:29:47.107461463 +0200 -@@ -2860,7 +2860,6 @@ - - int iwl4965_rate_control_register(void) - { -- pr_err("Registering 4965 rate control operations\n"); - return ieee80211_rate_control_register(&rs_4965_ops); - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-core.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-core.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-core.c 2011-05-05 23:29:47.210462707 +0200 -@@ -211,10 +211,7 @@ - if (!iwl_legacy_is_channel_valid(ch)) - continue; - -- if (iwl_legacy_is_channel_a_band(ch)) -- sband = &priv->bands[IEEE80211_BAND_5GHZ]; -- else -- sband = &priv->bands[IEEE80211_BAND_2GHZ]; -+ sband = &priv->bands[ch->band]; - - geo_ch = &sband->channels[sband->n_channels++]; - -@@ -2117,10 +2114,9 @@ - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - channel->hw_value, changed); - -- if (unlikely(!priv->cfg->mod_params->disable_hw_scan && -- test_bit(STATUS_SCANNING, &priv->status))) { -+ if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; -- IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); -+ IWL_DEBUG_MAC80211(priv, "scan active\n"); - } - - if (changed & (IEEE80211_CONF_CHANGE_SMPS | -@@ -2433,11 +2429,13 @@ - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - -- if (!iwl_legacy_is_alive(priv)) -- return; -- - mutex_lock(&priv->mutex); - -+ if (!iwl_legacy_is_alive(priv)) { -+ mutex_unlock(&priv->mutex); -+ return; -+ } -+ - if (changes & BSS_CHANGED_QOS) { - unsigned long flags; - -@@ -2646,7 +2644,7 @@ - - none: - /* re-enable interrupts here since we don't have anything to service. */ -- /* only Re-enable if diabled by irq */ -+ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_legacy_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-core.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-core.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-core.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-core.h 2011-05-05 23:29:47.311463927 +0200 -@@ -287,7 +287,6 @@ - struct iwl_base_params *base_params; - /* params likely to change within a device family */ - u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; -- u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; - enum iwl_led_mode led_mode; - }; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-dev.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-dev.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-dev.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-dev.h 2011-05-05 23:29:47.218462803 +0200 -@@ -134,7 +134,7 @@ - * space more than this */ - int high_mark; /* high watermark, stop queue if free - * space less than this */ --} __packed; -+}; - - /* One for each TFD */ - struct iwl_tx_info { -@@ -290,6 +290,7 @@ - CMD_SIZE_HUGE = (1 << 0), - CMD_ASYNC = (1 << 1), - CMD_WANT_SKB = (1 << 2), -+ CMD_MAPPED = (1 << 3), - }; - - #define DEF_CMD_PAYLOAD_SIZE 320 -@@ -1076,7 +1077,6 @@ - spinlock_t hcmd_lock; /* protect hcmd */ - spinlock_t reg_lock; /* protect hw register access */ - struct mutex mutex; -- struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ - - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-hcmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-hcmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-hcmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-hcmd.c 2011-05-05 23:29:47.123461655 +0200 -@@ -145,6 +145,8 @@ - int cmd_idx; - int ret; - -+ lockdep_assert_held(&priv->mutex); -+ - BUG_ON(cmd->flags & CMD_ASYNC); - - /* A synchronous command can not have a callback set. */ -@@ -152,7 +154,6 @@ - - IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", - iwl_legacy_get_cmd_string(cmd->id)); -- mutex_lock(&priv->sync_cmd_mutex); - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", -@@ -224,7 +225,6 @@ - cmd->reply_page = 0; - } - out: -- mutex_unlock(&priv->sync_cmd_mutex); - return ret; - } - EXPORT_SYMBOL(iwl_legacy_send_cmd_sync); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-helpers.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-helpers.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-helpers.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-helpers.h 2011-05-05 23:29:47.183462381 +0200 -@@ -149,6 +149,12 @@ - IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); - } - -+static inline void iwl_legacy_enable_rfkill_int(struct iwl_priv *priv) -+{ -+ IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); -+ iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); -+} -+ - static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv) - { - IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlegacy/iwl-tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlegacy/iwl-tx.c 2011-05-05 23:29:46.814457923 +0200 -@@ -146,33 +146,32 @@ - { - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; - struct iwl_queue *q = &txq->q; -- bool huge = false; - int i; - - if (q->n_bd == 0) - return; - - while (q->read_ptr != q->write_ptr) { -- /* we have no way to tell if it is a huge cmd ATM */ - i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0); - -- if (txq->meta[i].flags & CMD_SIZE_HUGE) -- huge = true; -- else -+ if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); -+ txq->meta[i].flags = 0; -+ } - - q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd); - } - -- if (huge) { -- i = q->n_window; -+ i = q->n_window; -+ if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); -+ txq->meta[i].flags = 0; - } - } - EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap); -@@ -467,29 +466,27 @@ - return -EIO; - } - -+ spin_lock_irqsave(&priv->hcmd_lock, flags); -+ - if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { -- IWL_ERR(priv, "No space in command queue\n"); -- IWL_ERR(priv, "Restarting adapter due to queue full\n"); -+ spin_unlock_irqrestore(&priv->hcmd_lock, flags); -+ -+ IWL_ERR(priv, "Restarting adapter due to command queue full\n"); - queue_work(priv->workqueue, &priv->restart); - return -ENOSPC; - } - -- spin_lock_irqsave(&priv->hcmd_lock, flags); -- -- /* If this is a huge cmd, mark the huge flag also on the meta.flags -- * of the _original_ cmd. This is used for DMA mapping clean up. -- */ -- if (cmd->flags & CMD_SIZE_HUGE) { -- idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0); -- txq->meta[idx].flags = CMD_SIZE_HUGE; -- } -- - idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); - out_cmd = txq->cmd[idx]; - out_meta = &txq->meta[idx]; - -+ if (WARN_ON(out_meta->flags & CMD_MAPPED)) { -+ spin_unlock_irqrestore(&priv->hcmd_lock, flags); -+ return -ENOSPC; -+ } -+ - memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ -- out_meta->flags = cmd->flags; -+ out_meta->flags = cmd->flags | CMD_MAPPED; - if (cmd->flags & CMD_WANT_SKB) - out_meta->source = cmd; - if (cmd->flags & CMD_ASYNC) -@@ -610,6 +607,7 @@ - struct iwl_device_cmd *cmd; - struct iwl_cmd_meta *meta; - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; -+ unsigned long flags; - - /* If a Tx command is being handled and it isn't in the actual - * command queue then there a command routing bug has been introduced -@@ -623,14 +621,6 @@ - return; - } - -- /* If this is a huge cmd, clear the huge flag on the meta.flags -- * of the _original_ cmd. So that iwl_legacy_cmd_queue_free won't unmap -- * the DMA buffer for the scan (huge) command. -- */ -- if (huge) { -- cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, 0); -- txq->meta[cmd_index].flags = 0; -- } - cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge); - cmd = txq->cmd[cmd_index]; - meta = &txq->meta[cmd_index]; -@@ -647,6 +637,8 @@ - } else if (meta->callback) - meta->callback(priv, cmd, pkt); - -+ spin_lock_irqsave(&priv->hcmd_lock, flags); -+ - iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); - - if (!(meta->flags & CMD_ASYNC)) { -@@ -655,6 +647,10 @@ - iwl_legacy_get_cmd_string(cmd->hdr.cmd)); - wake_up_interruptible(&priv->wait_command_queue); - } -+ -+ /* Mark as unmapped */ - meta->flags = 0; -+ -+ spin_unlock_irqrestore(&priv->hcmd_lock, flags); - } - EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-1000.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-1000.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-1000.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-1000.c 2011-05-05 23:29:45.326439943 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as -@@ -45,8 +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 IWL1000_UCODE_API_MAX 5 -@@ -57,12 +55,10 @@ - #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" - - - /* -@@ -124,10 +120,10 @@ - - static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) - { -- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && -- priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) -+ if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && -+ iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - priv->cfg->base_params->num_of_queues = -- priv->cfg->mod_params->num_of_queues; -+ iwlagn_mod_params.num_of_queues; - - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; -@@ -141,7 +137,6 @@ - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - -- priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; -@@ -179,21 +174,12 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .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, -- .load_ucode = iwlagn_load_ucode, -- .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, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .apm_ops = { -@@ -208,45 +194,21 @@ - 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, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwlagn_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -@@ -254,8 +216,6 @@ - .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, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_1000, - .shadow_ram_support = false, - .led_compensation = 51, -@@ -265,9 +225,6 @@ - .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, -@@ -281,7 +238,6 @@ - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ - .ops = &iwl1000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl1000_base_params, \ - .led_mode = IWL_LED_BLINK - -@@ -303,7 +259,6 @@ - .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ - .ops = &iwl1000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl1000_base_params, \ - .led_mode = IWL_LED_RF_STATE, \ - .rx_with_siso_diversity = true -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-2000.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-2000.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-2000.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-2000.c 2011-05-05 23:29:45.339440101 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as -@@ -46,30 +46,25 @@ - #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 IWL2030_UCODE_API_MAX 5 - #define IWL2000_UCODE_API_MAX 5 --#define IWL200_UCODE_API_MAX 5 -+#define IWL105_UCODE_API_MAX 5 - - /* Lowest firmware API version supported */ - #define IWL2030_UCODE_API_MIN 5 - #define IWL2000_UCODE_API_MIN 5 --#define IWL200_UCODE_API_MIN 5 -+#define IWL105_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 IWL105_FW_PRE "iwlwifi-105-" -+#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE #api ".ucode" - - static void iwl2000_set_ct_threshold(struct iwl_priv *priv) - { -@@ -101,6 +96,8 @@ - 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 = { -@@ -130,10 +127,10 @@ - - static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) - { -- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && -- priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) -+ if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && -+ iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - priv->cfg->base_params->num_of_queues = -- priv->cfg->mod_params->num_of_queues; -+ iwlagn_mod_params.num_of_queues; - - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; -@@ -147,7 +144,6 @@ - priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - -- priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; -@@ -259,8 +255,6 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, -@@ -268,13 +262,6 @@ - .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, -- .load_ucode = iwlagn_load_ucode, -- .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, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl2030_hw_channel_switch, -@@ -290,70 +277,40 @@ - 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, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwlagn_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -+static const struct iwl_ops iwl105_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 = { -+static const struct iwl_ops iwl135_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 = { -@@ -361,8 +318,6 @@ - .num_of_queues = IWLAGN_NUM_QUEUES, - .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, -- .set_l0s = true, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_2x00, - .shadow_ram_support = true, - .led_compensation = 51, -@@ -373,9 +328,6 @@ - .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, - }; - -@@ -385,8 +337,6 @@ - .num_of_queues = IWLAGN_NUM_QUEUES, - .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, -- .set_l0s = true, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_2x00, - .shadow_ram_support = true, - .led_compensation = 57, -@@ -397,9 +347,6 @@ - .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, - }; - -@@ -409,7 +356,6 @@ - }; - - 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, -@@ -426,12 +372,12 @@ - .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl2000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl2000_base_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", -@@ -451,7 +397,6 @@ - .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ - .ops = &iwl2030_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl2030_base_params, \ - .bt_params = &iwl2030_bt_params, \ - .need_dc_calib = true, \ -@@ -471,45 +416,13 @@ - IWL_DEVICE_2030, - }; - --#define IWL_DEVICE_6035 \ -- .fw_name_pre = IWL2030_FW_PRE, \ -- .ucode_api_max = IWL2030_UCODE_API_MAX, \ -- .ucode_api_min = IWL2030_UCODE_API_MIN, \ -- .eeprom_ver = EEPROM_6035_EEPROM_VERSION, \ -- .eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION, \ -- .ops = &iwl2030_ops, \ -- .mod_params = &iwlagn_mod_params, \ -- .base_params = &iwl2030_base_params, \ -- .bt_params = &iwl2030_bt_params, \ -- .need_dc_calib = true, \ -- .need_temp_offset_calib = true, \ -- .led_mode = IWL_LED_RF_STATE, \ -- .adv_pm = true \ -- --struct iwl_cfg iwl6035_2agn_cfg = { -- .name = "2000 Series 2x2 AGN/BT", -- IWL_DEVICE_6035, -- .ht_params = &iwl2000_ht_params, --}; -- --struct iwl_cfg iwl6035_2abg_cfg = { -- .name = "2000 Series 2x2 ABG/BT", -- IWL_DEVICE_6035, --}; -- --struct iwl_cfg iwl6035_2bg_cfg = { -- .name = "2000 Series 2x2 BG/BT", -- IWL_DEVICE_6035, --}; -- --#define IWL_DEVICE_200 \ -- .fw_name_pre = IWL200_FW_PRE, \ -- .ucode_api_max = IWL200_UCODE_API_MAX, \ -- .ucode_api_min = IWL200_UCODE_API_MIN, \ -+#define IWL_DEVICE_105 \ -+ .fw_name_pre = IWL105_FW_PRE, \ -+ .ucode_api_max = IWL105_UCODE_API_MAX, \ -+ .ucode_api_min = IWL105_UCODE_API_MIN, \ - .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ -- .ops = &iwl200_ops, \ -- .mod_params = &iwlagn_mod_params, \ -+ .ops = &iwl105_ops, \ - .base_params = &iwl2000_base_params, \ - .need_dc_calib = true, \ - .need_temp_offset_calib = true, \ -@@ -517,25 +430,24 @@ - .adv_pm = true, \ - .rx_with_siso_diversity = true \ - --struct iwl_cfg iwl200_bg_cfg = { -- .name = "200 Series 1x1 BG", -- IWL_DEVICE_200, -+struct iwl_cfg iwl105_bg_cfg = { -+ .name = "105 Series 1x1 BG", -+ IWL_DEVICE_105, - }; - --struct iwl_cfg iwl200_bgn_cfg = { -- .name = "200 Series 1x1 BGN", -- IWL_DEVICE_200, -+struct iwl_cfg iwl105_bgn_cfg = { -+ .name = "105 Series 1x1 BGN", -+ IWL_DEVICE_105, - .ht_params = &iwl2000_ht_params, - }; - --#define IWL_DEVICE_230 \ -- .fw_name_pre = IWL200_FW_PRE, \ -- .ucode_api_max = IWL200_UCODE_API_MAX, \ -- .ucode_api_min = IWL200_UCODE_API_MIN, \ -+#define IWL_DEVICE_135 \ -+ .fw_name_pre = IWL105_FW_PRE, \ -+ .ucode_api_max = IWL105_UCODE_API_MAX, \ -+ .ucode_api_min = IWL105_UCODE_API_MIN, \ - .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ -- .ops = &iwl230_ops, \ -- .mod_params = &iwlagn_mod_params, \ -+ .ops = &iwl135_ops, \ - .base_params = &iwl2030_base_params, \ - .bt_params = &iwl2030_bt_params, \ - .need_dc_calib = true, \ -@@ -544,17 +456,17 @@ - .adv_pm = true, \ - .rx_with_siso_diversity = true \ - --struct iwl_cfg iwl230_bg_cfg = { -- .name = "200 Series 1x1 BG/BT", -- IWL_DEVICE_230, -+struct iwl_cfg iwl135_bg_cfg = { -+ .name = "105 Series 1x1 BG/BT", -+ IWL_DEVICE_135, - }; - --struct iwl_cfg iwl230_bgn_cfg = { -- .name = "200 Series 1x1 BGN/BT", -- IWL_DEVICE_230, -+struct iwl_cfg iwl135_bgn_cfg = { -+ .name = "105 Series 1x1 BGN/BT", -+ IWL_DEVICE_135, - .ht_params = &iwl2000_ht_params, - }; - - MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); - MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); --MODULE_FIRMWARE(IWL200_MODULE_FIRMWARE(IWL200_UCODE_API_MAX)); -+MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-5000.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-5000.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-5000.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-5000.c 2011-05-05 23:29:45.408440933 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as -@@ -45,10 +45,8 @@ - #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" - - /* Highest firmware API version supported */ - #define IWL5000_UCODE_API_MAX 5 -@@ -59,12 +57,10 @@ - #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) -@@ -168,10 +164,10 @@ - - static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) - { -- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && -- priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) -+ if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && -+ iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - priv->cfg->base_params->num_of_queues = -- priv->cfg->mod_params->num_of_queues; -+ iwlagn_mod_params.num_of_queues; - - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; -@@ -185,7 +181,6 @@ - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - -- priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; -@@ -214,10 +209,10 @@ - - static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) - { -- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && -- priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) -+ if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && -+ iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - priv->cfg->base_params->num_of_queues = -- priv->cfg->mod_params->num_of_queues; -+ iwlagn_mod_params.num_of_queues; - - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; -@@ -231,7 +226,6 @@ - priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - -- priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; -@@ -263,7 +257,7 @@ - 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); -@@ -348,21 +342,12 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .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, -- .load_ucode = iwlagn_load_ucode, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl5000_hw_channel_switch, -@@ -380,35 +365,13 @@ - EEPROM_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS - }, -- .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, -- .release_semaphore = iwlcore_eeprom_release_semaphore, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwlagn_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -@@ -416,20 +379,12 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .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, -- .load_ucode = iwlagn_load_ucode, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl5000_hw_channel_switch, -@@ -447,51 +402,25 @@ - EEPROM_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS - }, -- .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, -- .release_semaphore = iwlcore_eeprom_release_semaphore, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwl5150_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -@@ -499,17 +428,12 @@ - .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, -- .use_bsm = false, - .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, -@@ -523,7 +447,6 @@ - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \ - .ops = &iwl5000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl5000_base_params, \ - .led_mode = IWL_LED_BLINK - -@@ -567,7 +490,6 @@ - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .ops = &iwl5000_ops, -- .mod_params = &iwlagn_mod_params, - .base_params = &iwl5000_base_params, - .ht_params = &iwl5000_ht_params, - .led_mode = IWL_LED_BLINK, -@@ -581,7 +503,6 @@ - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ - .ops = &iwl5150_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl5000_base_params, \ - .need_dc_calib = true, \ - .led_mode = IWL_LED_BLINK, \ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-5000-hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-5000-hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-5000-hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-5000-hw.h 2011-05-05 23:29:45.290439508 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-6000.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-6000.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-6000.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-6000.c 2011-05-05 23:29:45.377440559 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as -@@ -46,8 +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 IWL6000_UCODE_API_MAX 4 -@@ -60,20 +58,16 @@ - #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) - { -@@ -85,7 +79,7 @@ - static void iwl6050_additional_nic_config(struct iwl_priv *priv) - { - /* Indicate calibration version to uCode. */ -- if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) -+ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(priv, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - } -@@ -93,7 +87,7 @@ - static void iwl6150_additional_nic_config(struct iwl_priv *priv) - { - /* Indicate calibration version to uCode. */ -- if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) -+ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(priv, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(priv, CSR_GP_DRIVER_REG, -@@ -159,10 +153,10 @@ - - static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) - { -- if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && -- priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) -+ if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && -+ iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - priv->cfg->base_params->num_of_queues = -- priv->cfg->mod_params->num_of_queues; -+ iwlagn_mod_params.num_of_queues; - - priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; -@@ -176,7 +170,6 @@ - priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - -- priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; -@@ -288,21 +281,12 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .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, -- .load_ucode = iwlagn_load_ucode, -- .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, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl6000_hw_channel_switch, -@@ -320,36 +304,14 @@ - EEPROM_6000_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS - }, -- .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, -- .release_semaphore = iwlcore_eeprom_release_semaphore, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwlagn_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -@@ -357,8 +319,6 @@ - .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwlagn_txq_set_sched, -- .txq_agg_enable = iwlagn_txq_agg_enable, -- .txq_agg_disable = iwlagn_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, -@@ -366,13 +326,6 @@ - .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, -- .load_ucode = iwlagn_load_ucode, -- .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, -- .init_alive_start = iwlagn_init_alive_start, -- .alive_notify = iwlagn_alive_notify, - .send_tx_power = iwlagn_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .set_channel_switch = iwl6000_hw_channel_switch, -@@ -390,36 +343,14 @@ - EEPROM_6000_REG_BAND_24_HT40_CHANNELS, - EEPROM_REG_BAND_52_HT40_CHANNELS - }, -- .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, -- .release_semaphore = iwlcore_eeprom_release_semaphore, -- .calib_version = iwlagn_eeprom_calib_version, - .query_addr = iwlagn_eeprom_query_addr, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, - }, -- .isr_ops = { -- .isr = iwl_isr_ict, -- .free = iwl_free_isr_ict, -- .alloc = iwl_alloc_isr_ict, -- .reset = iwl_reset_ict, -- .disable = iwl_disable_ict, -- }, - .temp_ops = { - .temperature = iwlagn_temperature, - }, -- .debugfs_ops = { -- .rx_stats_read = iwl_ucode_rx_stats_read, -- .tx_stats_read = iwl_ucode_tx_stats_read, -- .general_stats_read = iwl_ucode_general_stats_read, -- .bt_stats_read = iwl_ucode_bt_stats_read, -- .reply_tx_error = iwl_reply_tx_error_read, -- }, - .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 = { -@@ -434,34 +365,26 @@ - .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 = { -@@ -469,8 +392,6 @@ - .num_of_queues = IWLAGN_NUM_QUEUES, - .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, -- .set_l0s = true, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .led_compensation = 51, -@@ -481,9 +402,6 @@ - .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, - }; - -@@ -492,8 +410,6 @@ - .num_of_queues = IWLAGN_NUM_QUEUES, - .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, -- .set_l0s = true, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_6x50, - .shadow_ram_support = true, - .led_compensation = 51, -@@ -504,9 +420,6 @@ - .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 = { -@@ -514,8 +427,6 @@ - .num_of_queues = IWLAGN_NUM_QUEUES, - .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, -- .set_l0s = true, -- .use_bsm = false, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .led_compensation = 57, -@@ -526,9 +437,6 @@ - .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, - }; - -@@ -538,7 +446,6 @@ - }; - - 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, -@@ -554,7 +461,6 @@ - .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ - .ops = &iwl6000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl6000_g2_base_params, \ - .need_dc_calib = true, \ - .need_temp_offset_calib = true, \ -@@ -583,7 +489,6 @@ - .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ - .ops = &iwl6030_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl6000_g2_base_params, \ - .bt_params = &iwl6000_bt_params, \ - .need_dc_calib = true, \ -@@ -613,6 +518,22 @@ - IWL_DEVICE_6030, - }; - -+struct iwl_cfg iwl6035_2agn_cfg = { -+ .name = "6035 Series 2x2 AGN/BT", -+ IWL_DEVICE_6030, -+ .ht_params = &iwl6000_ht_params, -+}; -+ -+struct iwl_cfg iwl6035_2abg_cfg = { -+ .name = "6035 Series 2x2 ABG/BT", -+ IWL_DEVICE_6030, -+}; -+ -+struct iwl_cfg iwl6035_2bg_cfg = { -+ .name = "6035 Series 2x2 BG/BT", -+ IWL_DEVICE_6030, -+}; -+ - struct iwl_cfg iwl1030_bgn_cfg = { - .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", - IWL_DEVICE_6030, -@@ -649,7 +570,6 @@ - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ - .ops = &iwl6000_ops, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl6000_base_params, \ - .pa_type = IWL_PA_INTERNAL, \ - .led_mode = IWL_LED_BLINK -@@ -679,7 +599,6 @@ - .ops = &iwl6050_ops, \ - .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ -- .mod_params = &iwlagn_mod_params, \ - .base_params = &iwl6050_base_params, \ - .need_dc_calib = true, \ - .led_mode = IWL_LED_BLINK, \ -@@ -704,7 +623,6 @@ - .eeprom_ver = EEPROM_6150_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, - .ops = &iwl6150_ops, -- .mod_params = &iwlagn_mod_params, - .base_params = &iwl6050_base_params, - .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, -@@ -720,7 +638,6 @@ - .eeprom_ver = EEPROM_6000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, - .ops = &iwl6000_ops, -- .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, - .ht_params = &iwl6000_ht_params, - .need_dc_calib = true, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-6000-hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-6000-hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-6000-hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-6000-hw.h 2011-05-05 23:29:45.358440329 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn.c 2011-05-05 23:29:45.404440885 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -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 @@ - 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 @@ - 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 @@ - 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); -@@ -409,7 +416,7 @@ - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * -- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA -+ * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ - int iwl_hw_tx_queue_init(struct iwl_priv *priv, -@@ -483,12 +490,14 @@ - container_of(work, struct iwl_priv, bt_full_concurrency); - struct iwl_rxon_context *ctx; - -+ mutex_lock(&priv->mutex); -+ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -+ goto out; - - /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) -- return; -+ goto out; - - IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", - priv->bt_full_concurrent ? -@@ -498,15 +507,15 @@ - * LQ & RXON updated cmds must be sent before BT Config cmd - * to avoid 3-wire collisions - */ -- mutex_lock(&priv->mutex); - for_each_context(priv, ctx) { - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); - iwlcore_commit_rxon(priv, ctx); - } -- mutex_unlock(&priv->mutex); - - priv->cfg->ops->hcmd->send_bt_config(priv); -+out: -+ mutex_unlock(&priv->mutex); - } - - /** -@@ -556,7 +565,7 @@ - } - - /* Set starting address; reads will auto-increment */ -- _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); -+ iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); - rmb(); - - /* -@@ -564,13 +573,13 @@ - * place event id # at far right for easier visual parsing. - */ - for (i = 0; i < num_events; i++) { -- ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -- time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -+ ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); -+ time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (mode == 0) { - trace_iwlwifi_dev_ucode_cont_event(priv, - 0, time, ev); - } else { -- data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -+ data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - trace_iwlwifi_dev_ucode_cont_event(priv, - time, data, ev); - } -@@ -588,10 +597,7 @@ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - -- if (priv->ucode_type == UCODE_INIT) -- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); -- else -- base = le32_to_cpu(priv->card_alive.log_event_table_ptr); -+ base = priv->device_pointers.error_event_table; - if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - capacity = iwl_read_targ_mem(priv, base); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); -@@ -720,7 +726,10 @@ - /* 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; - -@@ -760,7 +769,7 @@ - if (w->cmd == pkt->hdr.cmd) { - w->triggered = true; - if (w->fn) -- w->fn(priv, pkt); -+ w->fn(priv, pkt, w->fn_data); - } - } - spin_unlock(&priv->_agn.notif_wait_lock); -@@ -837,199 +846,6 @@ - iwlagn_rx_queue_restock(priv); - } - --/* call this function to flush any scheduled tasklet */ --static inline void iwl_synchronize_irq(struct iwl_priv *priv) --{ -- /* wait to make sure we flush pending tasklet*/ -- synchronize_irq(priv->pci_dev->irq); -- tasklet_kill(&priv->irq_tasklet); --} -- --static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) --{ -- u32 inta, handled = 0; -- u32 inta_fh; -- unsigned long flags; -- u32 i; --#ifdef CONFIG_IWLWIFI_DEBUG -- u32 inta_mask; --#endif -- -- spin_lock_irqsave(&priv->lock, flags); -- -- /* Ack/clear/reset pending uCode interrupts. -- * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, -- * and will clear only when CSR_FH_INT_STATUS gets cleared. */ -- inta = iwl_read32(priv, CSR_INT); -- iwl_write32(priv, CSR_INT, inta); -- -- /* Ack/clear/reset pending flow-handler (DMA) interrupts. -- * Any new interrupts that happen after this, either while we're -- * in this tasklet, or later, will show up in next ISR/tasklet. */ -- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); -- iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); -- --#ifdef CONFIG_IWLWIFI_DEBUG -- if (iwl_get_debug_level(priv) & IWL_DL_ISR) { -- /* just for debug */ -- inta_mask = iwl_read32(priv, CSR_INT_MASK); -- IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", -- inta, inta_mask, inta_fh); -- } --#endif -- -- spin_unlock_irqrestore(&priv->lock, flags); -- -- /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not -- * atomic, make sure that inta covers all the interrupts that -- * we've discovered, even if FH interrupt came in just after -- * reading CSR_INT. */ -- if (inta_fh & CSR49_FH_INT_RX_MASK) -- inta |= CSR_INT_BIT_FH_RX; -- if (inta_fh & CSR49_FH_INT_TX_MASK) -- inta |= CSR_INT_BIT_FH_TX; -- -- /* Now service all interrupt bits discovered above. */ -- if (inta & CSR_INT_BIT_HW_ERR) { -- IWL_ERR(priv, "Hardware error detected. Restarting.\n"); -- -- /* Tell the device to stop sending interrupts */ -- iwl_disable_interrupts(priv); -- -- priv->isr_stats.hw++; -- iwl_irq_handle_error(priv); -- -- handled |= CSR_INT_BIT_HW_ERR; -- -- return; -- } -- --#ifdef CONFIG_IWLWIFI_DEBUG -- if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { -- /* NIC fires this, but we don't use it, redundant with WAKEUP */ -- if (inta & CSR_INT_BIT_SCD) { -- IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " -- "the frame/frames.\n"); -- priv->isr_stats.sch++; -- } -- -- /* Alive notification via Rx interrupt will do the real work */ -- if (inta & CSR_INT_BIT_ALIVE) { -- IWL_DEBUG_ISR(priv, "Alive interrupt\n"); -- priv->isr_stats.alive++; -- } -- } --#endif -- /* Safely ignore these bits for debug checks below */ -- inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); -- -- /* HW RF KILL switch toggled */ -- if (inta & CSR_INT_BIT_RF_KILL) { -- int hw_rf_kill = 0; -- if (!(iwl_read32(priv, CSR_GP_CNTRL) & -- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) -- hw_rf_kill = 1; -- -- IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", -- hw_rf_kill ? "disable radio" : "enable radio"); -- -- priv->isr_stats.rfkill++; -- -- /* driver only loads ucode once setting the interface up. -- * the driver allows loading the ucode even if the radio -- * is killed. Hence update the killswitch state here. The -- * rfkill handler will care about restarting if needed. -- */ -- if (!test_bit(STATUS_ALIVE, &priv->status)) { -- if (hw_rf_kill) -- set_bit(STATUS_RF_KILL_HW, &priv->status); -- else -- clear_bit(STATUS_RF_KILL_HW, &priv->status); -- wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); -- } -- -- handled |= CSR_INT_BIT_RF_KILL; -- } -- -- /* Chip got too hot and stopped itself */ -- if (inta & CSR_INT_BIT_CT_KILL) { -- IWL_ERR(priv, "Microcode CT kill error detected.\n"); -- priv->isr_stats.ctkill++; -- handled |= CSR_INT_BIT_CT_KILL; -- } -- -- /* Error detected by uCode */ -- if (inta & CSR_INT_BIT_SW_ERR) { -- IWL_ERR(priv, "Microcode SW error detected. " -- " Restarting 0x%X.\n", inta); -- priv->isr_stats.sw++; -- iwl_irq_handle_error(priv); -- handled |= CSR_INT_BIT_SW_ERR; -- } -- -- /* -- * uCode wakes up after power-down sleep. -- * Tell device about any new tx or host commands enqueued, -- * and about any Rx buffers made available while asleep. -- */ -- if (inta & CSR_INT_BIT_WAKEUP) { -- IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); -- iwl_rx_queue_update_write_ptr(priv, &priv->rxq); -- for (i = 0; i < priv->hw_params.max_txq_num; i++) -- iwl_txq_update_write_ptr(priv, &priv->txq[i]); -- priv->isr_stats.wakeup++; -- handled |= CSR_INT_BIT_WAKEUP; -- } -- -- /* All uCode command responses, including Tx command responses, -- * Rx "responses" (frame-received notification), and other -- * notifications from uCode come through here*/ -- if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { -- iwl_rx_handle(priv); -- priv->isr_stats.rx++; -- handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); -- } -- -- /* This "Tx" DMA channel is used only for loading uCode */ -- if (inta & CSR_INT_BIT_FH_TX) { -- IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); -- priv->isr_stats.tx++; -- handled |= CSR_INT_BIT_FH_TX; -- /* Wake up uCode load routine, now that load is complete */ -- priv->ucode_write_complete = 1; -- wake_up_interruptible(&priv->wait_command_queue); -- } -- -- if (inta & ~handled) { -- IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); -- priv->isr_stats.unhandled++; -- } -- -- if (inta & ~(priv->inta_mask)) { -- IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", -- inta & ~priv->inta_mask); -- IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); -- } -- -- /* Re-enable all interrupts */ -- /* only Re-enable if disabled by irq */ -- if (test_bit(STATUS_INT_ENABLED, &priv->status)) -- iwl_enable_interrupts(priv); -- /* Re-enable RF_KILL if it occurred */ -- else if (handled & CSR_INT_BIT_RF_KILL) -- iwl_enable_rfkill_int(priv); -- --#ifdef CONFIG_IWLWIFI_DEBUG -- if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { -- inta = iwl_read32(priv, CSR_INT); -- inta_mask = iwl_read32(priv, CSR_INT_MASK); -- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); -- IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " -- "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); -- } --#endif --} -- - /* tasklet for iwlagn interrupt */ - static void iwl_irq_tasklet(struct iwl_priv *priv) - { -@@ -1171,7 +987,7 @@ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(priv, CSR_FH_INT_STATUS, -- CSR49_FH_INT_RX_MASK); -+ CSR_FH_INT_RX_MASK); - } - if (inta & CSR_INT_BIT_RX_PERIODIC) { - handled |= CSR_INT_BIT_RX_PERIODIC; -@@ -1209,7 +1025,7 @@ - - /* This "Tx" DMA channel is used only for loading uCode */ - if (inta & CSR_INT_BIT_FH_TX) { -- iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); -+ iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); - IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); - priv->isr_stats.tx++; - handled |= CSR_INT_BIT_FH_TX; -@@ -1357,26 +1173,48 @@ - * - ******************************************************************************/ - --static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) -+static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) - { -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); -- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); -+ if (desc->v_addr) -+ dma_free_coherent(&pci_dev->dev, desc->len, -+ desc->v_addr, desc->p_addr); -+ desc->v_addr = NULL; -+ desc->len = 0; -+} -+ -+static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img) -+{ -+ iwl_free_fw_desc(pci_dev, &img->code); -+ iwl_free_fw_desc(pci_dev, &img->data); -+} -+ -+static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc, -+ const void *data, size_t len) -+{ -+ if (!len) { -+ desc->v_addr = NULL; -+ return -EINVAL; -+ } -+ -+ desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len, -+ &desc->p_addr, GFP_KERNEL); -+ if (!desc->v_addr) -+ return -ENOMEM; -+ desc->len = len; -+ memcpy(desc->v_addr, data, len); -+ return 0; - } - --static void iwl_nic_start(struct iwl_priv *priv) -+static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) - { -- /* Remove all resets to allow NIC to operate */ -- iwl_write32(priv, CSR_RESET, 0); -+ iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt); -+ iwl_free_fw_img(priv->pci_dev, &priv->ucode_init); - } - - struct iwlagn_ucode_capabilities { - u32 max_probe_length; - u32 standard_phy_calibration_size; -- bool pan; -+ u32 flags; - }; - - static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); -@@ -1422,8 +1260,8 @@ - } - - struct iwlagn_firmware_pieces { -- const void *inst, *data, *init, *init_data, *boot; -- size_t inst_size, data_size, init_size, init_data_size, boot_size; -+ const void *inst, *data, *init, *init_data; -+ size_t inst_size, data_size, init_size, init_data_size; - - u32 build; - -@@ -1444,28 +1282,18 @@ - - switch (api_ver) { - default: -- /* -- * 4965 doesn't revision the firmware file format -- * along with the API version, it always uses v1 -- * file format. -- */ -- if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != -- CSR_HW_REV_TYPE_4965) { -- hdr_size = 28; -- if (ucode_raw->size < hdr_size) { -- IWL_ERR(priv, "File size too small!\n"); -- return -EINVAL; -- } -- pieces->build = le32_to_cpu(ucode->u.v2.build); -- pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); -- pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); -- pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); -- pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); -- pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); -- src = ucode->u.v2.data; -- break; -+ hdr_size = 28; -+ if (ucode_raw->size < hdr_size) { -+ IWL_ERR(priv, "File size too small!\n"); -+ return -EINVAL; - } -- /* fall through for 4965 */ -+ pieces->build = le32_to_cpu(ucode->u.v2.build); -+ pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); -+ pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); -+ pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); -+ pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); -+ src = ucode->u.v2.data; -+ break; - case 0: - case 1: - case 2: -@@ -1479,7 +1307,6 @@ - pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); -- pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); - src = ucode->u.v1.data; - break; - } -@@ -1487,7 +1314,7 @@ - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != hdr_size + pieces->inst_size + - pieces->data_size + pieces->init_size + -- pieces->init_data_size + pieces->boot_size) { -+ pieces->init_data_size) { - - IWL_ERR(priv, - "uCode file size %d does not match expected size\n", -@@ -1503,8 +1330,6 @@ - src += pieces->init_size; - pieces->init_data = src; - src += pieces->init_data_size; -- pieces->boot = src; -- src += pieces->boot_size; - - return 0; - } -@@ -1605,8 +1430,7 @@ - pieces->init_data_size = tlv_len; - break; - case IWL_UCODE_TLV_BOOT: -- pieces->boot = tlv_data; -- pieces->boot_size = tlv_len; -+ IWL_ERR(priv, "Found unexpected BOOT ucode\n"); - break; - case IWL_UCODE_TLV_PROBE_MAX_LEN: - if (tlv_len != sizeof(u32)) -@@ -1617,7 +1441,23 @@ - case IWL_UCODE_TLV_PAN: - if (tlv_len) - goto invalid_tlv_len; -- capa->pan = true; -+ capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; -+ break; -+ case IWL_UCODE_TLV_FLAGS: -+ /* must be at least one u32 */ -+ if (tlv_len < sizeof(u32)) -+ goto invalid_tlv_len; -+ /* and a proper number of u32s */ -+ if (tlv_len % sizeof(u32)) -+ goto invalid_tlv_len; -+ /* -+ * This driver only reads the first u32 as -+ * right now no more features are defined, -+ * if that changes then either the driver -+ * will not work with the new firmware, or -+ * it'll not take advantage of new features. -+ */ -+ capa->flags = le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_EVTLOG_PTR: - if (tlv_len != sizeof(u32)) -@@ -1667,7 +1507,7 @@ - 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; - } - } -@@ -1806,8 +1646,6 @@ - pieces.init_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", - pieces.init_data_size); -- IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", -- pieces.boot_size); - - /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > priv->hw_params.max_inst_size) { -@@ -1834,48 +1672,25 @@ - goto try_again; - } - -- if (pieces.boot_size > priv->hw_params.max_bsm_size) { -- IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", -- pieces.boot_size); -- goto try_again; -- } -- - /* Allocate ucode buffers for card's bus-master loading ... */ - - /* Runtime instructions and 2 copies of data: - * 1) unmodified from disk - * 2) backup cache for save/restore during power-downs */ -- priv->ucode_code.len = pieces.inst_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); -- -- priv->ucode_data.len = pieces.data_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); -- -- priv->ucode_data_backup.len = pieces.data_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); -- -- if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || -- !priv->ucode_data_backup.v_addr) -+ if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code, -+ pieces.inst, pieces.inst_size)) -+ goto err_pci_alloc; -+ if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data, -+ pieces.data, pieces.data_size)) - goto err_pci_alloc; - - /* Initialization instructions and data */ - if (pieces.init_size && pieces.init_data_size) { -- priv->ucode_init.len = pieces.init_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); -- -- priv->ucode_init_data.len = pieces.init_data_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); -- -- if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) -+ if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code, -+ pieces.init, pieces.init_size)) - goto err_pci_alloc; -- } -- -- /* Bootstrap (instructions only, no data) */ -- if (pieces.boot_size) { -- priv->ucode_boot.len = pieces.boot_size; -- iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); -- -- if (!priv->ucode_boot.v_addr) -+ if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data, -+ pieces.init_data, pieces.init_data_size)) - goto err_pci_alloc; - } - -@@ -1901,50 +1716,19 @@ - priv->cfg->base_params->max_event_log_size; - priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; - -- if (ucode_capa.pan) { -+ priv->new_scan_threshold_behaviour = -+ !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); -+ -+ if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { - priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); - priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - } else - priv->sta_key_max_num = STA_KEY_MAX_NUM; - -- /* Copy images into buffers for card's bus-master reads ... */ -- -- /* Runtime instructions (first block of data in file) */ -- IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", -- pieces.inst_size); -- memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); -- -- IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", -- priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); -- -- /* -- * Runtime data -- * NOTE: Copy into backup buffer will be done in iwl_up() -- */ -- IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", -- pieces.data_size); -- memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); -- memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); -- -- /* Initialization instructions */ -- if (pieces.init_size) { -- IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", -- pieces.init_size); -- memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); -- } -- -- /* Initialization data */ -- if (pieces.init_data_size) { -- IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", -- pieces.init_data_size); -- memcpy(priv->ucode_init_data.v_addr, pieces.init_data, -- pieces.init_data_size); -- } -- -- /* Bootstrap instructions */ -- IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", -- pieces.boot_size); -- memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); -+ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) -+ priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; -+ else -+ priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - - /* - * figure out the offset of chain noise reset and gain commands -@@ -2076,13 +1860,13 @@ - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - u32 pc, hcmd; -+ struct iwl_error_event_table table; - -- if (priv->ucode_type == UCODE_INIT) { -- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); -+ base = priv->device_pointers.error_event_table; -+ if (priv->ucode_type == UCODE_SUBTYPE_INIT) { - if (!base) - base = priv->_agn.init_errlog_ptr; - } else { -- base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - if (!base) - base = priv->_agn.inst_errlog_ptr; - } -@@ -2090,11 +1874,15 @@ - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, - "Not valid error log pointer 0x%08X for %s uCode\n", -- base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); -+ base, -+ (priv->ucode_type == UCODE_SUBTYPE_INIT) -+ ? "Init" : "RT"); - return; - } - -- count = iwl_read_targ_mem(priv, base); -+ iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); -+ -+ count = table.valid; - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); -@@ -2102,18 +1890,18 @@ - priv->status, count); - } - -- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); -+ desc = table.error_id; - priv->isr_stats.err_code = desc; -- pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); -- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); -- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); -- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); -- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); -- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); -- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); -- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); -- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); -- hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); -+ pc = table.pc; -+ blink1 = table.blink1; -+ blink2 = table.blink2; -+ ilink1 = table.ilink1; -+ ilink2 = table.ilink2; -+ data1 = table.data1; -+ data2 = table.data2; -+ line = table.line; -+ time = table.tsf_low; -+ hcmd = table.hcmd; - - trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, - blink1, blink2, ilink1, ilink2); -@@ -2147,12 +1935,11 @@ - if (num_events == 0) - return pos; - -- if (priv->ucode_type == UCODE_INIT) { -- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); -+ base = priv->device_pointers.log_event_table; -+ if (priv->ucode_type == UCODE_SUBTYPE_INIT) { - if (!base) - base = priv->_agn.init_evtlog_ptr; - } else { -- base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - if (!base) - base = priv->_agn.inst_evtlog_ptr; - } -@@ -2169,14 +1956,14 @@ - iwl_grab_nic_access(priv); - - /* Set starting address; reads will auto-increment */ -- _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); -+ iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); - rmb(); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { -- ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -- time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -+ ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); -+ time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (mode == 0) { - /* data, ev */ - if (bufsz) { -@@ -2190,7 +1977,7 @@ - time, ev); - } - } else { -- data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -+ data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOGT:%010u:0x%08x:%04u\n", -@@ -2261,13 +2048,12 @@ - int pos = 0; - size_t bufsz = 0; - -- if (priv->ucode_type == UCODE_INIT) { -- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); -+ base = priv->device_pointers.log_event_table; -+ if (priv->ucode_type == UCODE_SUBTYPE_INIT) { - logsize = priv->_agn.init_evtlog_size; - if (!base) - base = priv->_agn.init_evtlog_ptr; - } else { -- base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - logsize = priv->_agn.inst_evtlog_size; - if (!base) - base = priv->_agn.inst_evtlog_ptr; -@@ -2276,7 +2062,9 @@ - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, - "Invalid event log pointer 0x%08X for %s uCode\n", -- base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); -+ base, -+ (priv->ucode_type == UCODE_SUBTYPE_INIT) -+ ? "Init" : "RT"); - return -EINVAL; - } - -@@ -2423,30 +2211,14 @@ - * from protocol/runtime uCode (initialization uCode's - * Alive gets handled by iwl_init_alive_start()). - */ --static void iwl_alive_start(struct iwl_priv *priv) -+static int iwl_alive_start(struct iwl_priv *priv) - { - int ret = 0; - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - -- IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); -- -- /* Initialize uCode has loaded Runtime uCode ... verify inst image. -- * This is a paranoid check, because we would not have gotten the -- * "runtime" alive if code weren't properly loaded. */ -- if (iwl_verify_ucode(priv)) { -- /* Runtime instruction load was bad; -- * take it all the way back down so we can try again */ -- IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); -- goto restart; -- } -- -- ret = priv->cfg->ops->lib->alive_notify(priv); -- if (ret) { -- IWL_WARN(priv, -- "Could not complete ALIVE transition [ntf]: %d\n", ret); -- goto restart; -- } -+ iwl_reset_ict(priv); - -+ IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - - /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->status); -@@ -2455,7 +2227,7 @@ - iwl_setup_watchdog(priv); - - if (iwl_is_rfkill(priv)) -- return; -+ return -ERFKILL; - - /* download priority table before any calibration request */ - if (priv->cfg->bt_params && -@@ -2469,10 +2241,14 @@ - iwlagn_send_prio_tbl(priv); - - /* FIXME: w/a to force change uCode BT state machine */ -- iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, -- BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); -- iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, -- BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); -+ ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, -+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); -+ if (ret) -+ return ret; -+ ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, -+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); -+ if (ret) -+ return ret; - } - if (priv->hw_params.calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); -@@ -2514,30 +2290,23 @@ - set_bit(STATUS_READY, &priv->status); - - /* Configure the adapter for unassociated operation */ -- iwlcore_commit_rxon(priv, ctx); -+ ret = iwlcore_commit_rxon(priv, ctx); -+ if (ret) -+ return ret; - - /* At this point, the NIC is initialized and operational */ - iwl_rf_kill_ct_config(priv); - - IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); -- wake_up_interruptible(&priv->wait_command_queue); -- -- iwl_power_update_mode(priv, true); -- IWL_DEBUG_INFO(priv, "Updated power mode\n"); - -- -- return; -- -- restart: -- queue_work(priv->workqueue, &priv->restart); -+ return iwl_power_update_mode(priv, true); - } - - static void iwl_cancel_deferred_work(struct iwl_priv *priv); - - static void __iwl_down(struct iwl_priv *priv) - { -- unsigned long flags; -- int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); -+ int exit_pending; - - IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); - -@@ -2563,40 +2332,15 @@ - priv->bt_full_concurrent = false; - priv->bt_ci_compliance = 0; - -- /* Unblock any waiting calls */ -- wake_up_interruptible_all(&priv->wait_command_queue); -- - /* Wipe out the EXIT_PENDING status bit if we are not actually - * exiting the module */ - if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->status); - -- /* stop and reset the on-board processor */ -- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); -- -- /* tell the device to stop sending interrupts */ -- spin_lock_irqsave(&priv->lock, flags); -- iwl_disable_interrupts(priv); -- spin_unlock_irqrestore(&priv->lock, flags); -- iwl_synchronize_irq(priv); -- - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - -- /* If we have not previously called iwl_init() then -- * clear all bits but the RF Kill bit and return */ -- if (!iwl_is_init(priv)) { -- priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << -- STATUS_RF_KILL_HW | -- test_bit(STATUS_GEO_CONFIGURED, &priv->status) << -- STATUS_GEO_CONFIGURED | -- test_bit(STATUS_EXIT_PENDING, &priv->status) << -- STATUS_EXIT_PENDING; -- goto exit; -- } -- -- /* ...otherwise clear out all the status bits but the RF Kill -- * bit and continue taking the NIC down. */ -+ /* Clear out all status bits but a few that are stable across reset */ - priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << -@@ -2606,25 +2350,7 @@ - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - -- /* device going down, Stop using ICT table */ -- if (priv->cfg->ops->lib->isr_ops.disable) -- priv->cfg->ops->lib->isr_ops.disable(priv); -- -- iwlagn_txq_ctx_stop(priv); -- iwlagn_rxq_stop(priv); -- -- /* Power-down device's busmaster DMA clocks */ -- iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); -- udelay(5); -- -- /* Make sure (redundant) we've released our request to stay awake */ -- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -- -- /* Stop the device, and put it in low power state */ -- iwl_apm_stop(priv); -- -- exit: -- memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); -+ iwlagn_stop_device(priv); - - dev_kfree_skb(priv->beacon_skb); - priv->beacon_skb = NULL; -@@ -2644,9 +2370,10 @@ - - #define HW_READY_TIMEOUT (50) - -+/* Note: returns poll_bit return value, which is >= 0 if success */ - static int iwl_set_hw_ready(struct iwl_priv *priv) - { -- int ret = 0; -+ int ret; - - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); -@@ -2656,25 +2383,21 @@ - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - HW_READY_TIMEOUT); -- if (ret != -ETIMEDOUT) -- priv->hw_ready = true; -- else -- priv->hw_ready = false; - -- IWL_DEBUG_INFO(priv, "hardware %s\n", -- (priv->hw_ready == 1) ? "ready" : "not ready"); -+ IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); - return ret; - } - --static int iwl_prepare_card_hw(struct iwl_priv *priv) -+/* Note: returns standard 0/-ERROR code */ -+int iwl_prepare_card_hw(struct iwl_priv *priv) - { -- int ret = 0; -+ int ret; - - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); - - ret = iwl_set_hw_ready(priv); -- if (priv->hw_ready) -- return ret; -+ if (ret >= 0) -+ return 0; - - /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -@@ -2684,10 +2407,13 @@ - ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, - CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - -- /* HW should be ready by now, check again. */ -- if (ret != -ETIMEDOUT) -- iwl_set_hw_ready(priv); -+ if (ret < 0) -+ return ret; - -+ /* HW should be ready by now, check again. */ -+ ret = iwl_set_hw_ready(priv); -+ if (ret >= 0) -+ return 0; - return ret; - } - -@@ -2696,19 +2422,15 @@ - static int __iwl_up(struct iwl_priv *priv) - { - struct iwl_rxon_context *ctx; -- int i; - int ret; - -+ lockdep_assert_held(&priv->mutex); -+ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); - return -EIO; - } - -- if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { -- IWL_ERR(priv, "ucode not available for device bringup\n"); -- return -EIO; -- } -- - for_each_context(priv, ctx) { - ret = iwlagn_alloc_bcast_station(priv, ctx); - if (ret) { -@@ -2717,89 +2439,33 @@ - } - } - -- iwl_prepare_card_hw(priv); -- -- if (!priv->hw_ready) { -- IWL_WARN(priv, "Exit HW not ready\n"); -- return -EIO; -- } -- -- /* If platform's RF_KILL switch is NOT set to KILL */ -- if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) -- clear_bit(STATUS_RF_KILL_HW, &priv->status); -- else -- set_bit(STATUS_RF_KILL_HW, &priv->status); -- -- if (iwl_is_rfkill(priv)) { -- wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); -- -- iwl_enable_interrupts(priv); -- IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); -- return 0; -+ ret = iwlagn_run_init_ucode(priv); -+ if (ret) { -+ IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); -+ goto error; - } - -- iwl_write32(priv, CSR_INT, 0xFFFFFFFF); -- -- /* must be initialised before iwl_hw_nic_init */ -- if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) -- priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; -- else -- priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; -- -- ret = iwlagn_hw_nic_init(priv); -+ ret = iwlagn_load_ucode_wait_alive(priv, -+ &priv->ucode_rt, -+ UCODE_SUBTYPE_REGULAR, -+ UCODE_SUBTYPE_REGULAR_NEW); - if (ret) { -- IWL_ERR(priv, "Unable to init nic\n"); -- return ret; -+ IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); -+ goto error; - } - -- /* make sure rfkill handshake bits are cleared */ -- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, -- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); -- -- /* clear (again), then enable host interrupts */ -- iwl_write32(priv, CSR_INT, 0xFFFFFFFF); -- iwl_enable_interrupts(priv); -- -- /* really make sure rfkill handshake bits are cleared */ -- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -- -- /* Copy original ucode data image from disk into backup cache. -- * This will be used to initialize the on-board processor's -- * data SRAM for a clean start when the runtime program first loads. */ -- memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, -- priv->ucode_data.len); -- -- for (i = 0; i < MAX_HW_RESTARTS; i++) { -- -- /* load bootstrap state machine, -- * load bootstrap program into processor's memory, -- * prepare to load the "initialize" uCode */ -- ret = priv->cfg->ops->lib->load_ucode(priv); -- -- if (ret) { -- IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", -- ret); -- continue; -- } -- -- /* start card; "initialize" will load runtime ucode */ -- iwl_nic_start(priv); -- -- IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); -- -- return 0; -- } -+ ret = iwl_alive_start(priv); -+ if (ret) -+ goto error; -+ return 0; - -+ error: - set_bit(STATUS_EXIT_PENDING, &priv->status); - __iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->status); - -- /* tried to restart and config the device for as long as our -- * patience could withstand */ -- IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); -- return -EIO; -+ IWL_ERR(priv, "Unable to initialize device.\n"); -+ return ret; - } - - -@@ -2809,36 +2475,6 @@ - * - *****************************************************************************/ - --static void iwl_bg_init_alive_start(struct work_struct *data) --{ -- struct iwl_priv *priv = -- container_of(data, struct iwl_priv, init_alive_start.work); -- -- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -- -- mutex_lock(&priv->mutex); -- priv->cfg->ops->lib->init_alive_start(priv); -- mutex_unlock(&priv->mutex); --} -- --static void iwl_bg_alive_start(struct work_struct *data) --{ -- struct iwl_priv *priv = -- container_of(data, struct iwl_priv, alive_start.work); -- -- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -- -- /* enable dram interrupt */ -- if (priv->cfg->ops->lib->isr_ops.reset) -- priv->cfg->ops->lib->isr_ops.reset(priv); -- -- mutex_lock(&priv->mutex); -- iwl_alive_start(priv); -- mutex_unlock(&priv->mutex); --} -- - static void iwl_bg_run_time_calib_work(struct work_struct *work) - { - struct iwl_priv *priv = container_of(work, struct iwl_priv, -@@ -2853,22 +2489,49 @@ - } - - 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); - } - -+static void iwlagn_prepare_restart(struct iwl_priv *priv) -+{ -+ struct iwl_rxon_context *ctx; -+ bool bt_full_concurrent; -+ u8 bt_ci_compliance; -+ u8 bt_load; -+ u8 bt_status; -+ -+ lockdep_assert_held(&priv->mutex); -+ -+ for_each_context(priv, ctx) -+ ctx->vif = NULL; -+ priv->is_open = 0; -+ -+ /* -+ * __iwl_down() will clear the BT status variables, -+ * which is correct, but when we restart we really -+ * want to keep them so restore them afterwards. -+ * -+ * The restart process will later pick them up and -+ * re-configure the hw when we reconfigure the BT -+ * command. -+ */ -+ bt_full_concurrent = priv->bt_full_concurrent; -+ bt_ci_compliance = priv->bt_ci_compliance; -+ bt_load = priv->bt_traffic_load; -+ bt_status = priv->bt_status; -+ -+ __iwl_down(priv); -+ -+ priv->bt_full_concurrent = bt_full_concurrent; -+ priv->bt_ci_compliance = bt_ci_compliance; -+ priv->bt_traffic_load = bt_load; -+ priv->bt_status = bt_status; -+} -+ - static void iwl_bg_restart(struct work_struct *data) - { - struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); -@@ -2877,50 +2540,13 @@ - return; - - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { -- struct iwl_rxon_context *ctx; -- bool bt_full_concurrent; -- u8 bt_ci_compliance; -- u8 bt_load; -- u8 bt_status; -- - mutex_lock(&priv->mutex); -- for_each_context(priv, ctx) -- ctx->vif = NULL; -- priv->is_open = 0; -- -- /* -- * __iwl_down() will clear the BT status variables, -- * which is correct, but when we restart we really -- * want to keep them so restore them afterwards. -- * -- * The restart process will later pick them up and -- * re-configure the hw when we reconfigure the BT -- * command. -- */ -- bt_full_concurrent = priv->bt_full_concurrent; -- bt_ci_compliance = priv->bt_ci_compliance; -- bt_load = priv->bt_traffic_load; -- bt_status = priv->bt_status; -- -- __iwl_down(priv); -- -- priv->bt_full_concurrent = bt_full_concurrent; -- priv->bt_ci_compliance = bt_ci_compliance; -- priv->bt_traffic_load = bt_load; -- priv->bt_status = bt_status; -- -+ iwlagn_prepare_restart(priv); - mutex_unlock(&priv->mutex); - iwl_cancel_deferred_work(priv); - ieee80211_restart_hw(priv->hw); - } else { -- iwl_down(priv); -- -- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -- return; -- -- mutex_lock(&priv->mutex); -- __iwl_up(priv); -- mutex_unlock(&priv->mutex); -+ WARN_ON(1); - } - } - -@@ -3031,8 +2657,6 @@ - * - *****************************************************************************/ - --#define UCODE_READY_TIMEOUT (4 * HZ) -- - /* - * Not a mac80211 entry point function, but it fits in with all the - * other mac80211 functions grouped here. -@@ -3055,14 +2679,16 @@ - - 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 | - IEEE80211_HW_SUPPORTS_STATIC_SMPS; - -+ if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) -+ hw->flags |= IEEE80211_HW_MFP_CAPABLE; -+ - hw->sta_data_size = sizeof(struct iwl_station_priv); - hw->vif_data_size = sizeof(struct iwl_vif_priv); - -@@ -3112,7 +2738,7 @@ - } - - --int iwlagn_mac_start(struct ieee80211_hw *hw) -+static int iwlagn_mac_start(struct ieee80211_hw *hw) - { - struct iwl_priv *priv = hw->priv; - int ret; -@@ -3123,37 +2749,23 @@ - mutex_lock(&priv->mutex); - ret = __iwl_up(priv); - mutex_unlock(&priv->mutex); -- - if (ret) - return ret; - -- if (iwl_is_rfkill(priv)) -- goto out; -- - IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - -- /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from -- * mac80211 will not be run successfully. */ -- ret = wait_event_interruptible_timeout(priv->wait_command_queue, -- test_bit(STATUS_READY, &priv->status), -- UCODE_READY_TIMEOUT); -- if (!ret) { -- if (!test_bit(STATUS_READY, &priv->status)) { -- IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", -- jiffies_to_msecs(UCODE_READY_TIMEOUT)); -- return -ETIMEDOUT; -- } -- } -+ /* Now we should be done, and the READY bit should be set. */ -+ if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) -+ ret = -EIO; - - iwlagn_led_enable(priv); - --out: - priv->is_open = 1; - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; - } - --void iwlagn_mac_stop(struct ieee80211_hw *hw) -+static void iwlagn_mac_stop(struct ieee80211_hw *hw) - { - struct iwl_priv *priv = hw->priv; - -@@ -3176,7 +2788,7 @@ - IWL_DEBUG_MAC80211(priv, "leave\n"); - } - --void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -+static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) - { - struct iwl_priv *priv = hw->priv; - -@@ -3191,11 +2803,11 @@ - IWL_DEBUG_MACDUMP(priv, "leave\n"); - } - --void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_key_conf *keyconf, -- struct ieee80211_sta *sta, -- u32 iv32, u16 *phase1key) -+static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_key_conf *keyconf, -+ struct ieee80211_sta *sta, -+ u32 iv32, u16 *phase1key) - { - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; -@@ -3208,9 +2820,10 @@ - IWL_DEBUG_MAC80211(priv, "leave\n"); - } - --int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, -- struct ieee80211_vif *vif, struct ieee80211_sta *sta, -- struct ieee80211_key_conf *key) -+static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta, -+ struct ieee80211_key_conf *key) - { - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; -@@ -3221,7 +2834,7 @@ - - IWL_DEBUG_MAC80211(priv, "enter\n"); - -- if (priv->cfg->mod_params->sw_crypto) { -+ if (iwlagn_mod_params.sw_crypto) { - IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); - return -EOPNOTSUPP; - } -@@ -3285,11 +2898,11 @@ - return ret; - } - --int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- enum ieee80211_ampdu_mlme_action action, -- struct ieee80211_sta *sta, u16 tid, u16 *ssn, -- u8 buf_size) -+static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ enum ieee80211_ampdu_mlme_action action, -+ struct ieee80211_sta *sta, u16 tid, u16 *ssn, -+ u8 buf_size) - { - struct iwl_priv *priv = hw->priv; - int ret = -EINVAL; -@@ -3348,6 +2961,10 @@ - } - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: -+ buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); -+ -+ iwlagn_txq_agg_queue_setup(priv, sta, tid, buf_size); -+ - /* - * If the limit is 0, then it wasn't initialised yet, - * use the default. We can do that since we take the -@@ -3392,9 +3009,9 @@ - return ret; - } - --int iwlagn_mac_sta_add(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_sta *sta) -+static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta) - { - struct iwl_priv *priv = hw->priv; - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; -@@ -3435,8 +3052,8 @@ - return 0; - } - --void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, -- struct ieee80211_channel_switch *ch_switch) -+static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, -+ struct ieee80211_channel_switch *ch_switch) - { - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; -@@ -3457,21 +3074,22 @@ - - IWL_DEBUG_MAC80211(priv, "enter\n"); - -+ mutex_lock(&priv->mutex); -+ - if (iwl_is_rfkill(priv)) -- goto out_exit; -+ goto out; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) -- goto out_exit; -+ goto out; - - if (!iwl_is_associated_ctx(ctx)) -- goto out_exit; -+ goto out; - - /* channel switch in progress */ - if (priv->switch_rxon.switch_in_progress == true) -- goto out_exit; -+ goto out; - -- mutex_lock(&priv->mutex); - if (priv->cfg->ops->lib->set_channel_switch) { - - ch = channel->hw_value; -@@ -3527,16 +3145,15 @@ - } - out: - mutex_unlock(&priv->mutex); --out_exit: - if (!priv->switch_rxon.switch_in_progress) - ieee80211_chswitch_done(ctx->vif, false); - IWL_DEBUG_MAC80211(priv, "leave\n"); - } - --void iwlagn_configure_filter(struct ieee80211_hw *hw, -- unsigned int changed_flags, -- unsigned int *total_flags, -- u64 multicast) -+static void iwlagn_configure_filter(struct ieee80211_hw *hw, -+ unsigned int changed_flags, -+ unsigned int *total_flags, -+ u64 multicast) - { - struct iwl_priv *priv = hw->priv; - __le32 filter_or = 0, filter_nand = 0; -@@ -3583,7 +3200,7 @@ - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; - } - --void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) -+static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) - { - struct iwl_priv *priv = hw->priv; - -@@ -3729,8 +3346,6 @@ - INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); - INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); - INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); -- INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); -- INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); - INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); - - iwl_setup_scan_deferred_work(priv); -@@ -3750,12 +3365,8 @@ - priv->watchdog.data = (unsigned long)priv; - priv->watchdog.function = iwl_bg_watchdog; - -- if (!priv->cfg->base_params->use_isr_legacy) -- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) -- iwl_irq_tasklet, (unsigned long)priv); -- else -- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) -- iwl_irq_tasklet_legacy, (unsigned long)priv); -+ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) -+ iwl_irq_tasklet, (unsigned long)priv); - } - - static void iwl_cancel_deferred_work(struct iwl_priv *priv) -@@ -3763,8 +3374,6 @@ - if (priv->cfg->ops->lib->cancel_deferred_work) - priv->cfg->ops->lib->cancel_deferred_work(priv); - -- cancel_delayed_work_sync(&priv->init_alive_start); -- cancel_delayed_work(&priv->alive_start); - cancel_work_sync(&priv->run_time_calib_work); - cancel_work_sync(&priv->beacon_update); - -@@ -3808,7 +3417,6 @@ - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); -- mutex_init(&priv->sync_cmd_mutex); - - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; -@@ -3845,12 +3453,6 @@ - priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; - } - -- /* Set the tx_power_user_lmt to the lowest power level -- * this value will get overwritten by channel max power avg -- * from eeprom */ -- priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; -- priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; -- - ret = iwl_init_channel_map(priv); - if (ret) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); -@@ -3907,26 +3509,27 @@ - .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, - }; - --static void iwl_hw_detect(struct iwl_priv *priv) -+static u32 iwl_hw_detect(struct iwl_priv *priv) - { -- priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); -- priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); -- priv->rev_id = priv->pci_dev->revision; -- IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); -+ u8 rev_id; -+ -+ pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); -+ IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); -+ return iwl_read32(priv, CSR_HW_REV); - } - - static int iwl_set_hw_params(struct iwl_priv *priv) - { - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; -- if (priv->cfg->mod_params->amsdu_size_8K) -+ if (iwlagn_mod_params.amsdu_size_8K) - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); - else - priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); - - priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; - -- if (priv->cfg->mod_params->disable_11n) -+ if (iwlagn_mod_params.disable_11n) - priv->cfg->sku &= ~IWL_SKU_N; - - /* Device-specific setup */ -@@ -3955,6 +3558,28 @@ - 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; -@@ -3963,19 +3588,12 @@ - struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - unsigned long flags; - u16 pci_cmd, num_mac; -+ u32 hw_rev; - - /************************ - * 1. Allocating HW data - ************************/ - -- /* Disabling hardware scan means that mac80211 will perform scans -- * "the hard way", rather than using device's scan. */ -- if (cfg->mod_params->disable_hw_scan) { -- dev_printk(KERN_DEBUG, &(pdev->dev), -- "sw scan support is deprecated\n"); -- iwlagn_hw_ops.hw_scan = NULL; -- } -- - hw = iwl_alloc_all(cfg); - if (!hw) { - err = -ENOMEM; -@@ -3984,6 +3602,8 @@ - priv = hw->priv; - /* At this point both hw and priv are allocated. */ - -+ priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED; -+ - /* - * The default context is always valid, - * more may be discovered when firmware -@@ -4116,16 +3736,15 @@ - */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - -- iwl_hw_detect(priv); -+ hw_rev = iwl_hw_detect(priv); - IWL_INFO(priv, "Detected %s, REV=0x%X\n", -- priv->cfg->name, priv->hw_rev); -+ priv->cfg->name, hw_rev); - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - -- iwl_prepare_card_hw(priv); -- if (!priv->hw_ready) { -+ if (iwl_prepare_card_hw(priv)) { - IWL_WARN(priv, "Failed, HW not ready\n"); - goto out_iounmap; - } -@@ -4134,7 +3753,7 @@ - * 4. Read EEPROM - *****************/ - /* Read the EEPROM */ -- err = iwl_eeprom_init(priv); -+ err = iwl_eeprom_init(priv, hw_rev); - if (err) { - IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_iounmap; -@@ -4186,10 +3805,9 @@ - - pci_enable_msi(priv->pci_dev); - -- if (priv->cfg->ops->lib->isr_ops.alloc) -- priv->cfg->ops->lib->isr_ops.alloc(priv); -+ iwl_alloc_isr_ict(priv); - -- err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr, -+ err = request_irq(priv->pci_dev->irq, iwl_isr_ict, - IRQF_SHARED, DRV_NAME, priv); - if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); -@@ -4236,8 +3854,7 @@ - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - free_irq(priv->pci_dev->irq, priv); -- if (priv->cfg->ops->lib->isr_ops.free) -- priv->cfg->ops->lib->isr_ops.free(priv); -+ iwl_free_isr_ict(priv); - out_disable_msi: - pci_disable_msi(priv->pci_dev); - iwl_uninit_drv(priv); -@@ -4283,17 +3900,9 @@ - if (priv->mac80211_registered) { - ieee80211_unregister_hw(priv->hw); - priv->mac80211_registered = 0; -- } else { -- iwl_down(priv); - } - -- /* -- * Make sure device is reset to low power before unloading driver. -- * This may be redundant with iwl_down(), but there are paths to -- * run iwl_down() without calling apm_ops.stop(), and there are -- * paths to avoid running iwl_down() at all before leaving driver. -- * This (inexpensive) call *makes sure* device is reset. -- */ -+ /* Reset to low power before unloading driver. */ - iwl_apm_stop(priv); - - iwl_tt_exit(priv); -@@ -4335,8 +3944,7 @@ - - iwl_uninit_drv(priv); - -- if (priv->cfg->ops->lib->isr_ops.free) -- priv->cfg->ops->lib->isr_ops.free(priv); -+ iwl_free_isr_ict(priv); - - dev_kfree_skb(priv->beacon_skb); - -@@ -4521,21 +4129,21 @@ - {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)}, - {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)}, - --/* 200 Series */ -- {IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)}, -- {IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)}, -- {IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)}, -- --/* 230 Series */ -- {IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)}, -- {IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)}, -- {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)}, -- {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)}, -+/* 105 Series */ -+ {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)}, -+ {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)}, -+ {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)}, -+ -+/* 135 Series */ -+ {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)}, -+ {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)}, -+ {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)}, -+ {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)}, - - {0} - }; -@@ -4585,43 +4193,21 @@ - module_init(iwl_init); - - #ifdef CONFIG_IWLWIFI_DEBUG --module_param_named(debug50, iwl_debug_level, uint, S_IRUGO); --MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); - module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(debug, "debug output mask"); - #endif - --module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); --MODULE_PARM_DESC(swcrypto50, -- "using crypto in software (default 0 [hardware]) (deprecated)"); - module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); - MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); --module_param_named(queues_num50, -- iwlagn_mod_params.num_of_queues, int, S_IRUGO); --MODULE_PARM_DESC(queues_num50, -- "number of hw queues in 50xx series (deprecated)"); - module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); - MODULE_PARM_DESC(queues_num, "number of hw queues."); --module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); --MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); - module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); - MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); --module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, -- int, S_IRUGO); --MODULE_PARM_DESC(amsdu_size_8K50, -- "enable 8K amsdu size in 50XX series (deprecated)"); - module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, - int, S_IRUGO); - MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); --module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); --MODULE_PARM_DESC(fw_restart50, -- "restart firmware in case of error (deprecated)"); - module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); - MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); --module_param_named( -- disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); --MODULE_PARM_DESC(disable_hw_scan, -- "disable hardware scanning (default 0) (deprecated)"); - - module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, - S_IRUGO); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-calib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-calib.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-calib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-calib.c 2011-05-05 23:29:45.361440365 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -605,7 +605,7 @@ - IWL_DEBUG_CALIB(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 @@ - * 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 @@ - } - - 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 @@ - - 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). */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-calib.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-calib.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-calib.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-calib.h 2011-05-05 23:29:45.373440511 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,1073 +0,0 @@ --/****************************************************************************** --* --* GPL LICENSE SUMMARY --* --* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. --* --* This program is free software; you can redistribute it and/or modify --* it under the terms of version 2 of the GNU General Public License as --* published by the Free Software Foundation. --* --* This program is distributed in the hope that it will be useful, but --* WITHOUT ANY WARRANTY; without even the implied warranty of --* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --* General Public License for more details. --* --* You should have received a copy of the GNU General Public License --* along with this program; if not, write to the Free Software --* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, --* USA --* --* The full GNU General Public License is included in this distribution --* in the file called LICENSE.GPL. --* --* Contact Information: --* Intel Linux Wireless --* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 --*****************************************************************************/ --#include "iwl-agn.h" --#include "iwl-agn-debugfs.h" -- --static const char *fmt_value = " %-30s %10u\n"; --static const char *fmt_hex = " %-30s 0x%02X\n"; --static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; --static const char *fmt_header = -- "%-32s current cumulative delta max\n"; -- --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); -- -- p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); -- if (flag & UCODE_STATISTICS_CLEAR_MSK) -- p += scnprintf(buf + p, bufsz - p, -- "\tStatistics have been cleared\n"); -- p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", -- (flag & UCODE_STATISTICS_FREQUENCY_MSK) -- ? "2.4 GHz" : "5.2 GHz"); -- p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", -- (flag & UCODE_STATISTICS_NARROW_BAND_MSK) -- ? "enabled" : "disabled"); -- -- return p; --} -- --ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) -- { -- struct iwl_priv *priv = file->private_data; -- int pos = 0; -- char *buf; -- int bufsz = sizeof(struct statistics_rx_phy) * 40 + -- sizeof(struct statistics_rx_non_phy) * 40 + -- sizeof(struct statistics_rx_ht_phy) * 40 + 400; -- ssize_t ret; -- struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; -- struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; -- struct statistics_rx_non_phy *general, *accum_general; -- struct statistics_rx_non_phy *delta_general, *max_general; -- struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; -- -- if (!iwl_is_alive(priv)) -- return -EAGAIN; -- -- buf = kzalloc(bufsz, GFP_KERNEL); -- if (!buf) { -- IWL_ERR(priv, "Can not allocate Buffer\n"); -- return -ENOMEM; -- } -- -- /* -- * 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)) { -- 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; -- } -- -- pos += iwl_statistics_flag(priv, buf, bufsz); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_Rx - OFDM:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "ina_cnt:", -- le32_to_cpu(ofdm->ina_cnt), -- accum_ofdm->ina_cnt, -- delta_ofdm->ina_cnt, max_ofdm->ina_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_cnt:", -- le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, -- delta_ofdm->fina_cnt, max_ofdm->fina_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "plcp_err:", -- le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, -- delta_ofdm->plcp_err, max_ofdm->plcp_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_err:", -- le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, -- delta_ofdm->crc32_err, max_ofdm->crc32_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "overrun_err:", -- le32_to_cpu(ofdm->overrun_err), -- accum_ofdm->overrun_err, delta_ofdm->overrun_err, -- max_ofdm->overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "early_overrun_err:", -- le32_to_cpu(ofdm->early_overrun_err), -- accum_ofdm->early_overrun_err, -- delta_ofdm->early_overrun_err, -- max_ofdm->early_overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_good:", -- le32_to_cpu(ofdm->crc32_good), -- accum_ofdm->crc32_good, delta_ofdm->crc32_good, -- max_ofdm->crc32_good); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "false_alarm_cnt:", -- le32_to_cpu(ofdm->false_alarm_cnt), -- accum_ofdm->false_alarm_cnt, -- delta_ofdm->false_alarm_cnt, -- max_ofdm->false_alarm_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_sync_err_cnt:", -- le32_to_cpu(ofdm->fina_sync_err_cnt), -- accum_ofdm->fina_sync_err_cnt, -- delta_ofdm->fina_sync_err_cnt, -- max_ofdm->fina_sync_err_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sfd_timeout:", -- le32_to_cpu(ofdm->sfd_timeout), -- accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, -- max_ofdm->sfd_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_timeout:", -- le32_to_cpu(ofdm->fina_timeout), -- accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, -- max_ofdm->fina_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "unresponded_rts:", -- le32_to_cpu(ofdm->unresponded_rts), -- accum_ofdm->unresponded_rts, -- delta_ofdm->unresponded_rts, -- max_ofdm->unresponded_rts); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "rxe_frame_lmt_ovrun:", -- le32_to_cpu(ofdm->rxe_frame_limit_overrun), -- accum_ofdm->rxe_frame_limit_overrun, -- delta_ofdm->rxe_frame_limit_overrun, -- max_ofdm->rxe_frame_limit_overrun); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_ack_cnt:", -- le32_to_cpu(ofdm->sent_ack_cnt), -- accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, -- max_ofdm->sent_ack_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_cts_cnt:", -- le32_to_cpu(ofdm->sent_cts_cnt), -- accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, -- max_ofdm->sent_cts_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_ba_rsp_cnt:", -- le32_to_cpu(ofdm->sent_ba_rsp_cnt), -- accum_ofdm->sent_ba_rsp_cnt, -- delta_ofdm->sent_ba_rsp_cnt, -- max_ofdm->sent_ba_rsp_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "dsp_self_kill:", -- le32_to_cpu(ofdm->dsp_self_kill), -- accum_ofdm->dsp_self_kill, -- delta_ofdm->dsp_self_kill, -- max_ofdm->dsp_self_kill); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "mh_format_err:", -- le32_to_cpu(ofdm->mh_format_err), -- accum_ofdm->mh_format_err, -- delta_ofdm->mh_format_err, -- max_ofdm->mh_format_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "re_acq_main_rssi_sum:", -- le32_to_cpu(ofdm->re_acq_main_rssi_sum), -- accum_ofdm->re_acq_main_rssi_sum, -- delta_ofdm->re_acq_main_rssi_sum, -- max_ofdm->re_acq_main_rssi_sum); -- -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_Rx - CCK:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "ina_cnt:", -- le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, -- delta_cck->ina_cnt, max_cck->ina_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_cnt:", -- le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, -- delta_cck->fina_cnt, max_cck->fina_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "plcp_err:", -- le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, -- delta_cck->plcp_err, max_cck->plcp_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_err:", -- le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, -- delta_cck->crc32_err, max_cck->crc32_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "overrun_err:", -- le32_to_cpu(cck->overrun_err), -- accum_cck->overrun_err, delta_cck->overrun_err, -- max_cck->overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "early_overrun_err:", -- le32_to_cpu(cck->early_overrun_err), -- accum_cck->early_overrun_err, -- delta_cck->early_overrun_err, -- max_cck->early_overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_good:", -- le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, -- delta_cck->crc32_good, max_cck->crc32_good); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "false_alarm_cnt:", -- le32_to_cpu(cck->false_alarm_cnt), -- accum_cck->false_alarm_cnt, -- delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_sync_err_cnt:", -- le32_to_cpu(cck->fina_sync_err_cnt), -- accum_cck->fina_sync_err_cnt, -- delta_cck->fina_sync_err_cnt, -- max_cck->fina_sync_err_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sfd_timeout:", -- le32_to_cpu(cck->sfd_timeout), -- accum_cck->sfd_timeout, delta_cck->sfd_timeout, -- max_cck->sfd_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "fina_timeout:", -- le32_to_cpu(cck->fina_timeout), -- accum_cck->fina_timeout, delta_cck->fina_timeout, -- max_cck->fina_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "unresponded_rts:", -- le32_to_cpu(cck->unresponded_rts), -- accum_cck->unresponded_rts, delta_cck->unresponded_rts, -- max_cck->unresponded_rts); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "rxe_frame_lmt_ovrun:", -- le32_to_cpu(cck->rxe_frame_limit_overrun), -- accum_cck->rxe_frame_limit_overrun, -- delta_cck->rxe_frame_limit_overrun, -- max_cck->rxe_frame_limit_overrun); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_ack_cnt:", -- le32_to_cpu(cck->sent_ack_cnt), -- accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, -- max_cck->sent_ack_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_cts_cnt:", -- le32_to_cpu(cck->sent_cts_cnt), -- accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, -- max_cck->sent_cts_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sent_ba_rsp_cnt:", -- le32_to_cpu(cck->sent_ba_rsp_cnt), -- accum_cck->sent_ba_rsp_cnt, -- delta_cck->sent_ba_rsp_cnt, -- max_cck->sent_ba_rsp_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "dsp_self_kill:", -- le32_to_cpu(cck->dsp_self_kill), -- accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, -- max_cck->dsp_self_kill); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "mh_format_err:", -- le32_to_cpu(cck->mh_format_err), -- accum_cck->mh_format_err, delta_cck->mh_format_err, -- max_cck->mh_format_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "re_acq_main_rssi_sum:", -- le32_to_cpu(cck->re_acq_main_rssi_sum), -- accum_cck->re_acq_main_rssi_sum, -- delta_cck->re_acq_main_rssi_sum, -- max_cck->re_acq_main_rssi_sum); -- -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_Rx - GENERAL:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "bogus_cts:", -- le32_to_cpu(general->bogus_cts), -- accum_general->bogus_cts, delta_general->bogus_cts, -- max_general->bogus_cts); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "bogus_ack:", -- le32_to_cpu(general->bogus_ack), -- accum_general->bogus_ack, delta_general->bogus_ack, -- max_general->bogus_ack); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "non_bssid_frames:", -- le32_to_cpu(general->non_bssid_frames), -- accum_general->non_bssid_frames, -- delta_general->non_bssid_frames, -- max_general->non_bssid_frames); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "filtered_frames:", -- le32_to_cpu(general->filtered_frames), -- accum_general->filtered_frames, -- delta_general->filtered_frames, -- max_general->filtered_frames); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "non_channel_beacons:", -- le32_to_cpu(general->non_channel_beacons), -- accum_general->non_channel_beacons, -- delta_general->non_channel_beacons, -- max_general->non_channel_beacons); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "channel_beacons:", -- le32_to_cpu(general->channel_beacons), -- accum_general->channel_beacons, -- delta_general->channel_beacons, -- max_general->channel_beacons); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "num_missed_bcon:", -- le32_to_cpu(general->num_missed_bcon), -- accum_general->num_missed_bcon, -- delta_general->num_missed_bcon, -- max_general->num_missed_bcon); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "adc_rx_saturation_time:", -- le32_to_cpu(general->adc_rx_saturation_time), -- accum_general->adc_rx_saturation_time, -- delta_general->adc_rx_saturation_time, -- max_general->adc_rx_saturation_time); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "ina_detect_search_tm:", -- le32_to_cpu(general->ina_detection_search_time), -- accum_general->ina_detection_search_time, -- delta_general->ina_detection_search_time, -- max_general->ina_detection_search_time); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_silence_rssi_a:", -- le32_to_cpu(general->beacon_silence_rssi_a), -- accum_general->beacon_silence_rssi_a, -- delta_general->beacon_silence_rssi_a, -- max_general->beacon_silence_rssi_a); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_silence_rssi_b:", -- le32_to_cpu(general->beacon_silence_rssi_b), -- accum_general->beacon_silence_rssi_b, -- delta_general->beacon_silence_rssi_b, -- max_general->beacon_silence_rssi_b); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_silence_rssi_c:", -- le32_to_cpu(general->beacon_silence_rssi_c), -- accum_general->beacon_silence_rssi_c, -- delta_general->beacon_silence_rssi_c, -- max_general->beacon_silence_rssi_c); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "interference_data_flag:", -- le32_to_cpu(general->interference_data_flag), -- accum_general->interference_data_flag, -- delta_general->interference_data_flag, -- max_general->interference_data_flag); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "channel_load:", -- le32_to_cpu(general->channel_load), -- accum_general->channel_load, -- delta_general->channel_load, -- max_general->channel_load); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "dsp_false_alarms:", -- le32_to_cpu(general->dsp_false_alarms), -- accum_general->dsp_false_alarms, -- delta_general->dsp_false_alarms, -- max_general->dsp_false_alarms); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_rssi_a:", -- le32_to_cpu(general->beacon_rssi_a), -- accum_general->beacon_rssi_a, -- delta_general->beacon_rssi_a, -- max_general->beacon_rssi_a); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_rssi_b:", -- le32_to_cpu(general->beacon_rssi_b), -- accum_general->beacon_rssi_b, -- delta_general->beacon_rssi_b, -- max_general->beacon_rssi_b); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_rssi_c:", -- le32_to_cpu(general->beacon_rssi_c), -- accum_general->beacon_rssi_c, -- delta_general->beacon_rssi_c, -- max_general->beacon_rssi_c); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_energy_a:", -- le32_to_cpu(general->beacon_energy_a), -- accum_general->beacon_energy_a, -- delta_general->beacon_energy_a, -- max_general->beacon_energy_a); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_energy_b:", -- le32_to_cpu(general->beacon_energy_b), -- accum_general->beacon_energy_b, -- delta_general->beacon_energy_b, -- max_general->beacon_energy_b); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "beacon_energy_c:", -- le32_to_cpu(general->beacon_energy_c), -- accum_general->beacon_energy_c, -- delta_general->beacon_energy_c, -- max_general->beacon_energy_c); -- -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_Rx - OFDM_HT:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "plcp_err:", -- le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, -- delta_ht->plcp_err, max_ht->plcp_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "overrun_err:", -- le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, -- delta_ht->overrun_err, max_ht->overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "early_overrun_err:", -- le32_to_cpu(ht->early_overrun_err), -- accum_ht->early_overrun_err, -- delta_ht->early_overrun_err, -- max_ht->early_overrun_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_good:", -- le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, -- delta_ht->crc32_good, max_ht->crc32_good); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "crc32_err:", -- le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, -- delta_ht->crc32_err, max_ht->crc32_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "mh_format_err:", -- le32_to_cpu(ht->mh_format_err), -- accum_ht->mh_format_err, -- delta_ht->mh_format_err, max_ht->mh_format_err); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg_crc32_good:", -- le32_to_cpu(ht->agg_crc32_good), -- accum_ht->agg_crc32_good, -- delta_ht->agg_crc32_good, max_ht->agg_crc32_good); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg_mpdu_cnt:", -- le32_to_cpu(ht->agg_mpdu_cnt), -- accum_ht->agg_mpdu_cnt, -- delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg_cnt:", -- le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, -- delta_ht->agg_cnt, max_ht->agg_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "unsupport_mcs:", -- le32_to_cpu(ht->unsupport_mcs), -- accum_ht->unsupport_mcs, -- delta_ht->unsupport_mcs, max_ht->unsupport_mcs); -- -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- return ret; --} -- --ssize_t iwl_ucode_tx_stats_read(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = file->private_data; -- int pos = 0; -- char *buf; -- int bufsz = (sizeof(struct statistics_tx) * 48) + 250; -- ssize_t ret; -- struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; -- -- if (!iwl_is_alive(priv)) -- return -EAGAIN; -- -- buf = kzalloc(bufsz, GFP_KERNEL); -- if (!buf) { -- IWL_ERR(priv, "Can not allocate Buffer\n"); -- return -ENOMEM; -- } -- -- /* 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; -- } -- -- pos += iwl_statistics_flag(priv, buf, bufsz); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_Tx:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "preamble:", -- le32_to_cpu(tx->preamble_cnt), -- accum_tx->preamble_cnt, -- delta_tx->preamble_cnt, max_tx->preamble_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "rx_detected_cnt:", -- le32_to_cpu(tx->rx_detected_cnt), -- accum_tx->rx_detected_cnt, -- delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "bt_prio_defer_cnt:", -- le32_to_cpu(tx->bt_prio_defer_cnt), -- accum_tx->bt_prio_defer_cnt, -- delta_tx->bt_prio_defer_cnt, -- max_tx->bt_prio_defer_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "bt_prio_kill_cnt:", -- le32_to_cpu(tx->bt_prio_kill_cnt), -- accum_tx->bt_prio_kill_cnt, -- delta_tx->bt_prio_kill_cnt, -- max_tx->bt_prio_kill_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "few_bytes_cnt:", -- le32_to_cpu(tx->few_bytes_cnt), -- accum_tx->few_bytes_cnt, -- delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "cts_timeout:", -- le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, -- delta_tx->cts_timeout, max_tx->cts_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "ack_timeout:", -- le32_to_cpu(tx->ack_timeout), -- accum_tx->ack_timeout, -- delta_tx->ack_timeout, max_tx->ack_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "expected_ack_cnt:", -- le32_to_cpu(tx->expected_ack_cnt), -- accum_tx->expected_ack_cnt, -- delta_tx->expected_ack_cnt, -- max_tx->expected_ack_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "actual_ack_cnt:", -- le32_to_cpu(tx->actual_ack_cnt), -- accum_tx->actual_ack_cnt, -- delta_tx->actual_ack_cnt, -- max_tx->actual_ack_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "dump_msdu_cnt:", -- le32_to_cpu(tx->dump_msdu_cnt), -- accum_tx->dump_msdu_cnt, -- delta_tx->dump_msdu_cnt, -- max_tx->dump_msdu_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "abort_nxt_frame_mismatch:", -- le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), -- accum_tx->burst_abort_next_frame_mismatch_cnt, -- delta_tx->burst_abort_next_frame_mismatch_cnt, -- max_tx->burst_abort_next_frame_mismatch_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "abort_missing_nxt_frame:", -- le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), -- accum_tx->burst_abort_missing_next_frame_cnt, -- delta_tx->burst_abort_missing_next_frame_cnt, -- max_tx->burst_abort_missing_next_frame_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "cts_timeout_collision:", -- le32_to_cpu(tx->cts_timeout_collision), -- accum_tx->cts_timeout_collision, -- delta_tx->cts_timeout_collision, -- max_tx->cts_timeout_collision); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "ack_ba_timeout_collision:", -- le32_to_cpu(tx->ack_or_ba_timeout_collision), -- accum_tx->ack_or_ba_timeout_collision, -- delta_tx->ack_or_ba_timeout_collision, -- max_tx->ack_or_ba_timeout_collision); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg ba_timeout:", -- le32_to_cpu(tx->agg.ba_timeout), -- accum_tx->agg.ba_timeout, -- delta_tx->agg.ba_timeout, -- max_tx->agg.ba_timeout); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg ba_resched_frames:", -- le32_to_cpu(tx->agg.ba_reschedule_frames), -- accum_tx->agg.ba_reschedule_frames, -- delta_tx->agg.ba_reschedule_frames, -- max_tx->agg.ba_reschedule_frames); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg scd_query_agg_frame:", -- le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), -- accum_tx->agg.scd_query_agg_frame_cnt, -- delta_tx->agg.scd_query_agg_frame_cnt, -- max_tx->agg.scd_query_agg_frame_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg scd_query_no_agg:", -- le32_to_cpu(tx->agg.scd_query_no_agg), -- accum_tx->agg.scd_query_no_agg, -- delta_tx->agg.scd_query_no_agg, -- max_tx->agg.scd_query_no_agg); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg scd_query_agg:", -- le32_to_cpu(tx->agg.scd_query_agg), -- accum_tx->agg.scd_query_agg, -- delta_tx->agg.scd_query_agg, -- max_tx->agg.scd_query_agg); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg scd_query_mismatch:", -- le32_to_cpu(tx->agg.scd_query_mismatch), -- accum_tx->agg.scd_query_mismatch, -- delta_tx->agg.scd_query_mismatch, -- max_tx->agg.scd_query_mismatch); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg frame_not_ready:", -- le32_to_cpu(tx->agg.frame_not_ready), -- accum_tx->agg.frame_not_ready, -- delta_tx->agg.frame_not_ready, -- max_tx->agg.frame_not_ready); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg underrun:", -- le32_to_cpu(tx->agg.underrun), -- accum_tx->agg.underrun, -- delta_tx->agg.underrun, max_tx->agg.underrun); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg bt_prio_kill:", -- le32_to_cpu(tx->agg.bt_prio_kill), -- accum_tx->agg.bt_prio_kill, -- delta_tx->agg.bt_prio_kill, -- max_tx->agg.bt_prio_kill); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "agg rx_ba_rsp_cnt:", -- le32_to_cpu(tx->agg.rx_ba_rsp_cnt), -- accum_tx->agg.rx_ba_rsp_cnt, -- delta_tx->agg.rx_ba_rsp_cnt, -- max_tx->agg.rx_ba_rsp_cnt); -- -- if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { -- pos += scnprintf(buf + pos, bufsz - pos, -- "tx power: (1/2 dB step)\n"); -- if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_hex, "antenna A:", -- tx->tx_power.ant_a); -- if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_hex, "antenna B:", -- tx->tx_power.ant_b); -- if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_hex, "antenna C:", -- tx->tx_power.ant_c); -- } -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- return ret; --} -- --ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = file->private_data; -- int pos = 0; -- char *buf; -- int bufsz = sizeof(struct statistics_general) * 10 + 300; -- ssize_t ret; -- struct statistics_general_common *general, *accum_general; -- struct statistics_general_common *delta_general, *max_general; -- struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; -- struct statistics_div *div, *accum_div, *delta_div, *max_div; -- -- if (!iwl_is_alive(priv)) -- return -EAGAIN; -- -- buf = kzalloc(bufsz, GFP_KERNEL); -- if (!buf) { -- IWL_ERR(priv, "Can not allocate Buffer\n"); -- return -ENOMEM; -- } -- -- /* 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; -- } -- -- pos += iwl_statistics_flag(priv, buf, bufsz); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_header, "Statistics_General:"); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_value, "temperature:", -- le32_to_cpu(general->temperature)); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_value, "temperature_m:", -- le32_to_cpu(general->temperature_m)); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_value, "ttl_timestamp:", -- le32_to_cpu(general->ttl_timestamp)); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "burst_check:", -- le32_to_cpu(dbg->burst_check), -- accum_dbg->burst_check, -- delta_dbg->burst_check, max_dbg->burst_check); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "burst_count:", -- le32_to_cpu(dbg->burst_count), -- accum_dbg->burst_count, -- delta_dbg->burst_count, max_dbg->burst_count); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "wait_for_silence_timeout_count:", -- le32_to_cpu(dbg->wait_for_silence_timeout_cnt), -- accum_dbg->wait_for_silence_timeout_cnt, -- delta_dbg->wait_for_silence_timeout_cnt, -- max_dbg->wait_for_silence_timeout_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "sleep_time:", -- le32_to_cpu(general->sleep_time), -- accum_general->sleep_time, -- delta_general->sleep_time, max_general->sleep_time); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "slots_out:", -- le32_to_cpu(general->slots_out), -- accum_general->slots_out, -- delta_general->slots_out, max_general->slots_out); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "slots_idle:", -- le32_to_cpu(general->slots_idle), -- accum_general->slots_idle, -- delta_general->slots_idle, max_general->slots_idle); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "tx_on_a:", -- le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, -- delta_div->tx_on_a, max_div->tx_on_a); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "tx_on_b:", -- le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, -- delta_div->tx_on_b, max_div->tx_on_b); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "exec_time:", -- le32_to_cpu(div->exec_time), accum_div->exec_time, -- delta_div->exec_time, max_div->exec_time); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "probe_time:", -- le32_to_cpu(div->probe_time), accum_div->probe_time, -- delta_div->probe_time, max_div->probe_time); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "rx_enable_counter:", -- le32_to_cpu(general->rx_enable_counter), -- accum_general->rx_enable_counter, -- delta_general->rx_enable_counter, -- max_general->rx_enable_counter); -- pos += scnprintf(buf + pos, bufsz - pos, -- fmt_table, "num_of_sos_states:", -- le32_to_cpu(general->num_of_sos_states), -- accum_general->num_of_sos_states, -- delta_general->num_of_sos_states, -- max_general->num_of_sos_states); -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- return ret; --} -- --ssize_t iwl_ucode_bt_stats_read(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = (struct iwl_priv *)file->private_data; -- int pos = 0; -- char *buf; -- int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; -- ssize_t ret; -- struct statistics_bt_activity *bt, *accum_bt; -- -- if (!iwl_is_alive(priv)) -- return -EAGAIN; -- -- if (!priv->bt_enable_flag) -- return -EINVAL; -- -- /* make request to uCode to retrieve statistics information */ -- mutex_lock(&priv->mutex); -- ret = iwl_send_statistics_request(priv, CMD_SYNC, false); -- mutex_unlock(&priv->mutex); -- -- if (ret) { -- IWL_ERR(priv, -- "Error sending statistics request: %zd\n", ret); -- return -EAGAIN; -- } -- buf = kzalloc(bufsz, GFP_KERNEL); -- if (!buf) { -- IWL_ERR(priv, "Can not allocate Buffer\n"); -- return -ENOMEM; -- } -- -- /* -- * the statistic information display here is based on -- * 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; -- -- pos += iwl_statistics_flag(priv, buf, bufsz); -- pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); -- pos += scnprintf(buf + pos, bufsz - pos, -- "\t\t\tcurrent\t\t\taccumulative\n"); -- pos += scnprintf(buf + pos, bufsz - pos, -- "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", -- le32_to_cpu(bt->hi_priority_tx_req_cnt), -- accum_bt->hi_priority_tx_req_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", -- le32_to_cpu(bt->hi_priority_tx_denied_cnt), -- accum_bt->hi_priority_tx_denied_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", -- le32_to_cpu(bt->lo_priority_tx_req_cnt), -- accum_bt->lo_priority_tx_req_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", -- le32_to_cpu(bt->lo_priority_tx_denied_cnt), -- accum_bt->lo_priority_tx_denied_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", -- le32_to_cpu(bt->hi_priority_rx_req_cnt), -- accum_bt->hi_priority_rx_req_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", -- le32_to_cpu(bt->hi_priority_rx_denied_cnt), -- accum_bt->hi_priority_rx_denied_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", -- le32_to_cpu(bt->lo_priority_rx_req_cnt), -- accum_bt->lo_priority_rx_req_cnt); -- pos += scnprintf(buf + pos, bufsz - pos, -- "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", -- le32_to_cpu(bt->lo_priority_rx_denied_cnt), -- accum_bt->lo_priority_rx_denied_cnt); -- -- 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); -- -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- return ret; --} -- --ssize_t iwl_reply_tx_error_read(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = (struct iwl_priv *)file->private_data; -- int pos = 0; -- char *buf; -- int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + -- (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; -- ssize_t ret; -- -- if (!iwl_is_alive(priv)) -- return -EAGAIN; -- -- buf = kzalloc(bufsz, GFP_KERNEL); -- if (!buf) { -- IWL_ERR(priv, "Can not allocate Buffer\n"); -- return -ENOMEM; -- } -- -- pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), -- priv->_agn.reply_tx_stats.pp_delay); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), -- priv->_agn.reply_tx_stats.pp_few_bytes); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), -- priv->_agn.reply_tx_stats.pp_bt_prio); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), -- priv->_agn.reply_tx_stats.pp_quiet_period); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), -- priv->_agn.reply_tx_stats.pp_calc_ttak); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_tx_fail_reason( -- TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), -- priv->_agn.reply_tx_stats.int_crossed_retry); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), -- priv->_agn.reply_tx_stats.short_limit); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), -- priv->_agn.reply_tx_stats.long_limit); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), -- priv->_agn.reply_tx_stats.fifo_underrun); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), -- priv->_agn.reply_tx_stats.drain_flow); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), -- priv->_agn.reply_tx_stats.rfkill_flush); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), -- priv->_agn.reply_tx_stats.life_expire); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), -- priv->_agn.reply_tx_stats.dest_ps); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), -- priv->_agn.reply_tx_stats.host_abort); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), -- priv->_agn.reply_tx_stats.pp_delay); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), -- priv->_agn.reply_tx_stats.sta_invalid); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), -- priv->_agn.reply_tx_stats.frag_drop); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), -- priv->_agn.reply_tx_stats.tid_disable); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), -- priv->_agn.reply_tx_stats.fifo_flush); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_tx_fail_reason( -- TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), -- priv->_agn.reply_tx_stats.insuff_cf_poll); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), -- priv->_agn.reply_tx_stats.fail_hw_drop); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_tx_fail_reason( -- TX_STATUS_FAIL_NO_BEACON_ON_RADAR), -- priv->_agn.reply_tx_stats.sta_color_mismatch); -- pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", -- priv->_agn.reply_tx_stats.unknown); -- -- pos += scnprintf(buf + pos, bufsz - pos, -- "\nStatistics_Agg_TX_Error:\n"); -- -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), -- priv->_agn.reply_agg_tx_stats.underrun); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), -- priv->_agn.reply_agg_tx_stats.bt_prio); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), -- priv->_agn.reply_agg_tx_stats.few_bytes); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), -- priv->_agn.reply_agg_tx_stats.abort); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_agg_tx_fail_reason( -- AGG_TX_STATE_LAST_SENT_TTL_MSK), -- priv->_agn.reply_agg_tx_stats.last_sent_ttl); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_agg_tx_fail_reason( -- AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), -- priv->_agn.reply_agg_tx_stats.last_sent_try); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_agg_tx_fail_reason( -- AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), -- priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), -- priv->_agn.reply_agg_tx_stats.scd_query); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -- iwl_get_agg_tx_fail_reason( -- AGG_TX_STATE_TEST_BAD_CRC32_MSK), -- priv->_agn.reply_agg_tx_stats.bad_crc32); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), -- priv->_agn.reply_agg_tx_stats.response); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), -- priv->_agn.reply_agg_tx_stats.dump_tx); -- pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -- iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), -- priv->_agn.reply_agg_tx_stats.delay_tx); -- pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", -- priv->_agn.reply_agg_tx_stats.unknown); -- -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- kfree(buf); -- return ret; --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,70 +0,0 @@ --/****************************************************************************** -- * -- * GPL LICENSE SUMMARY -- * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of version 2 of the GNU General Public License as -- * published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, -- * USA -- * -- * The full GNU General Public License is included in this distribution -- * in the file called LICENSE.GPL. -- * -- * Contact Information: -- * Intel Linux Wireless -- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -- *****************************************************************************/ -- --#include "iwl-dev.h" --#include "iwl-core.h" --#include "iwl-debug.h" -- --#ifdef CONFIG_IWLWIFI_DEBUGFS --ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --#else --static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- return 0; --} --static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- return 0; --} --static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- return 0; --} --static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- return 0; --} --static ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- return 0; --} --#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c 2011-05-05 23:29:45.374440523 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -81,52 +81,13 @@ - * - ******************************************************************************/ - --/* -- * The device's EEPROM semaphore prevents conflicts between driver and uCode -- * when accessing the EEPROM; each access is a series of pulses to/from the -- * EEPROM chip, not a single event, so even reads could conflict if they -- * weren't arbitrated by the semaphore. -- */ --int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) --{ -- u16 count; -- int ret; -- -- for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { -- /* Request semaphore */ -- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -- -- /* See if we got it */ -- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, -- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, -- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, -- EEPROM_SEM_TIMEOUT); -- if (ret >= 0) { -- IWL_DEBUG_IO(priv, -- "Acquired semaphore after %d tries.\n", -- count+1); -- return ret; -- } -- } -- -- return ret; --} -- --void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) --{ -- iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, -- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -- --} -- - int iwl_eeprom_check_version(struct iwl_priv *priv) - { - u16 eeprom_ver; - u16 calib_ver; - - eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); -- calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); -+ calib_ver = iwlagn_eeprom_calib_version(priv); - - if (eeprom_ver < priv->cfg->eeprom_ver || - calib_ver < priv->cfg->eeprom_calib_ver) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn.h 2011-05-05 23:29:45.320439871 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -66,7 +66,6 @@ - #include "iwl-dev.h" - - /* configuration for the _agn devices */ --extern struct iwl_cfg iwl4965_agn_cfg; - extern struct iwl_cfg iwl5300_agn_cfg; - extern struct iwl_cfg iwl5100_agn_cfg; - extern struct iwl_cfg iwl5350_agn_cfg; -@@ -103,10 +102,10 @@ - extern struct iwl_cfg iwl6035_2agn_cfg; - extern struct iwl_cfg iwl6035_2abg_cfg; - extern struct iwl_cfg iwl6035_2bg_cfg; --extern struct iwl_cfg iwl200_bg_cfg; --extern struct iwl_cfg iwl200_bgn_cfg; --extern struct iwl_cfg iwl230_bg_cfg; --extern struct iwl_cfg iwl230_bgn_cfg; -+extern struct iwl_cfg iwl105_bg_cfg; -+extern struct iwl_cfg iwl105_bgn_cfg; -+extern struct iwl_cfg iwl135_bg_cfg; -+extern struct iwl_cfg iwl135_bgn_cfg; - - extern struct iwl_mod_params iwlagn_mod_params; - extern struct iwl_hcmd_ops iwlagn_hcmd; -@@ -114,7 +113,6 @@ - extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; - - extern struct ieee80211_ops iwlagn_hw_ops; --extern struct ieee80211_ops iwl4965_hw_ops; - - int iwl_reset_ict(struct iwl_priv *priv); - void iwl_disable_ict(struct iwl_priv *priv); -@@ -122,6 +120,19 @@ - void iwl_free_isr_ict(struct iwl_priv *priv); - irqreturn_t iwl_isr_ict(int irq, void *data); - -+/* call this function to flush any scheduled tasklet */ -+static inline void iwl_synchronize_irq(struct iwl_priv *priv) -+{ -+ /* wait to make sure we flush pending tasklet*/ -+ synchronize_irq(priv->pci_dev->irq); -+ tasklet_kill(&priv->irq_tasklet); -+} -+ -+int iwl_prepare_card_hw(struct iwl_priv *priv); -+ -+int iwlagn_start_device(struct iwl_priv *priv); -+void iwlagn_stop_device(struct iwl_priv *priv); -+ - /* tx queue */ - void iwlagn_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index); -@@ -133,10 +144,6 @@ - u16 byte_cnt); - void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); --int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, -- int tx_fifo, int sta_id, int tid, u16 ssn_idx); --int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, -- u16 ssn_idx, u8 tx_fifo); - void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); - void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed); -@@ -151,16 +158,14 @@ - u32 changes); - - /* uCode */ --int iwlagn_load_ucode(struct iwl_priv *priv); - void iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); --void iwlagn_rx_calib_complete(struct iwl_priv *priv, -- struct iwl_rx_mem_buffer *rxb); --void iwlagn_init_alive_start(struct iwl_priv *priv); --int iwlagn_alive_notify(struct iwl_priv *priv); --int iwl_verify_ucode(struct iwl_priv *priv); --void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); -+int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); - void iwlagn_send_prio_tbl(struct iwl_priv *priv); -+int iwlagn_run_init_ucode(struct iwl_priv *priv); -+int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, -+ struct fw_img *image, -+ int subtype, int alternate_subtype); - - /* lib */ - void iwl_check_abort_status(struct iwl_priv *priv, -@@ -179,8 +184,6 @@ - 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); -@@ -206,6 +209,9 @@ - struct ieee80211_sta *sta, u16 tid, u16 *ssn); - int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid); -+void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, -+ struct ieee80211_sta *sta, -+ int tid, int frame_limit); - int iwlagn_txq_check_empty(struct iwl_priv *priv, - int sta_id, u8 tid, int txq_id); - void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, -@@ -225,6 +231,7 @@ - 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; -@@ -249,8 +256,6 @@ - struct ieee80211_vif *vif, bool add); - - /* hcmd */ --int iwlagn_send_rxon_assoc(struct iwl_priv *priv, -- struct iwl_rxon_context *ctx); - int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); - int iwlagn_send_beacon_cmd(struct iwl_priv *priv); - -@@ -311,7 +316,7 @@ - - static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) - { -- return le32_to_cpu(rate_n_flags) & 0xFF; -+ return le32_to_cpu(rate_n_flags) & RATE_MCS_RATE_MSK; - } - - static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) -@@ -322,17 +327,17 @@ - /* eeprom */ - void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); - void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); --int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); --void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); - - /* notification wait support */ - void __acquires(wait_entry) - iwlagn_init_notification_wait(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, -+ u8 cmd, - void (*fn)(struct iwl_priv *priv, -- struct iwl_rx_packet *pkt), -- u8 cmd); --signed long __releases(wait_entry) -+ struct iwl_rx_packet *pkt, -+ void *data), -+ void *fn_data); -+int __must_check __releases(wait_entry) - iwlagn_wait_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - unsigned long timeout); -@@ -340,32 +345,4 @@ - iwlagn_remove_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry); - --/* mac80211 handlers (for 4965) */ --void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); --int iwlagn_mac_start(struct ieee80211_hw *hw); --void iwlagn_mac_stop(struct ieee80211_hw *hw); --void iwlagn_configure_filter(struct ieee80211_hw *hw, -- unsigned int changed_flags, -- unsigned int *total_flags, -- u64 multicast); --int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, -- struct ieee80211_vif *vif, struct ieee80211_sta *sta, -- struct ieee80211_key_conf *key); --void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_key_conf *keyconf, -- struct ieee80211_sta *sta, -- u32 iv32, u16 *phase1key); --int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- enum ieee80211_ampdu_mlme_action action, -- struct ieee80211_sta *sta, u16 tid, u16 *ssn, -- u8 buf_size); --int iwlagn_mac_sta_add(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- struct ieee80211_sta *sta); --void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, -- struct ieee80211_channel_switch *ch_switch); --void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); -- - #endif /* __iwl_agn_h__ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c 2011-05-05 23:29:45.251439037 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -37,54 +37,6 @@ - #include "iwl-io.h" - #include "iwl-agn.h" - --int iwlagn_send_rxon_assoc(struct iwl_priv *priv, -- struct iwl_rxon_context *ctx) --{ -- int ret = 0; -- struct iwl5000_rxon_assoc_cmd rxon_assoc; -- const struct iwl_rxon_cmd *rxon1 = &ctx->staging; -- const struct iwl_rxon_cmd *rxon2 = &ctx->active; -- -- if ((rxon1->flags == rxon2->flags) && -- (rxon1->filter_flags == rxon2->filter_flags) && -- (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && -- (rxon1->ofdm_ht_single_stream_basic_rates == -- rxon2->ofdm_ht_single_stream_basic_rates) && -- (rxon1->ofdm_ht_dual_stream_basic_rates == -- rxon2->ofdm_ht_dual_stream_basic_rates) && -- (rxon1->ofdm_ht_triple_stream_basic_rates == -- rxon2->ofdm_ht_triple_stream_basic_rates) && -- (rxon1->acquisition_data == rxon2->acquisition_data) && -- (rxon1->rx_chain == rxon2->rx_chain) && -- (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { -- IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); -- return 0; -- } -- -- rxon_assoc.flags = ctx->staging.flags; -- rxon_assoc.filter_flags = ctx->staging.filter_flags; -- rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; -- rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; -- rxon_assoc.reserved1 = 0; -- rxon_assoc.reserved2 = 0; -- rxon_assoc.reserved3 = 0; -- rxon_assoc.ofdm_ht_single_stream_basic_rates = -- ctx->staging.ofdm_ht_single_stream_basic_rates; -- rxon_assoc.ofdm_ht_dual_stream_basic_rates = -- ctx->staging.ofdm_ht_dual_stream_basic_rates; -- rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; -- rxon_assoc.ofdm_ht_triple_stream_basic_rates = -- ctx->staging.ofdm_ht_triple_stream_basic_rates; -- rxon_assoc.acquisition_data = ctx->staging.acquisition_data; -- -- ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, -- sizeof(rxon_assoc), &rxon_assoc, NULL); -- if (ret) -- return ret; -- -- return ret; --} -- - int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) - { - struct iwl_tx_ant_config_cmd tx_ant_cmd = { -@@ -364,7 +316,6 @@ - } - - struct iwl_hcmd_ops iwlagn_hcmd = { -- .rxon_assoc = iwlagn_send_rxon_assoc, - .commit_rxon = iwlagn_commit_rxon, - .set_rxon_chain = iwlagn_set_rxon_chain, - .set_tx_ant = iwlagn_send_tx_ant_config, -@@ -373,7 +324,6 @@ - }; - - struct iwl_hcmd_ops iwlagn_bt_hcmd = { -- .rxon_assoc = iwlagn_send_rxon_assoc, - .commit_rxon = iwlagn_commit_rxon, - .set_rxon_chain = iwlagn_set_rxon_chain, - .set_tx_ant = iwlagn_send_tx_ant_config, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-hw.h 2011-05-05 23:29:45.406440909 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-ict.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-ict.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-ict.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-ict.c 2011-05-05 23:29:45.389440705 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -59,8 +59,6 @@ - int iwl_alloc_isr_ict(struct iwl_priv *priv) - { - -- if (priv->cfg->base_params->use_isr_legacy) -- return 0; - /* allocate shrared data table */ - priv->_agn.ict_tbl_vir = - dma_alloc_coherent(&priv->pci_dev->dev, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-led.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-led.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-led.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-led.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,73 +0,0 @@ --/****************************************************************************** -- * -- * Copyright(c) 2003 - 2010 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 -- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -- * -- *****************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#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 -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-led.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-led.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-led.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-led.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,33 +0,0 @@ --/****************************************************************************** -- * -- * Copyright(c) 2003 - 2010 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 -- * 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__ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-lib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-lib.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-lib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-lib.c 2011-05-05 23:29:45.406440909 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -172,6 +172,7 @@ - - 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 @@ - 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 @@ - - /* # 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 @@ - 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 @@ - } - - 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 @@ - 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); - } - -@@ -470,8 +483,6 @@ - /* init calibration handlers */ - priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = - iwlagn_rx_calib_result; -- priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = -- iwlagn_rx_calib_complete; - priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; - - /* set up notification wait support */ -@@ -482,8 +493,10 @@ - - 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 +547,7 @@ - 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); - } - -@@ -652,10 +663,9 @@ - const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - -- if (!priv->cfg->base_params->use_isr_legacy) -- rb_timeout = RX_RB_TIMEOUT; -+ rb_timeout = RX_RB_TIMEOUT; - -- if (priv->cfg->mod_params->amsdu_size_8K) -+ if (iwlagn_mod_params.amsdu_size_8K) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; -@@ -913,7 +923,6 @@ - - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; -- priv->alloc_rxb_page++; - - spin_unlock_irqrestore(&rxq->lock, flags); - } -@@ -1285,9 +1294,17 @@ - * mean we never reach it, but at the same time work around - * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER - * here instead of IWL_GOOD_CRC_TH_DISABLED. -+ * -+ * This was fixed in later versions along with some other -+ * scan changes, and the threshold behaves as a flag in those -+ * versions. - */ -- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : -- IWL_GOOD_CRC_TH_NEVER; -+ if (priv->new_scan_threshold_behaviour) -+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : -+ IWL_GOOD_CRC_TH_DISABLED; -+ else -+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : -+ IWL_GOOD_CRC_TH_NEVER; - - band = priv->scan_band; - -@@ -2245,34 +2262,44 @@ - /* notification wait support */ - void iwlagn_init_notification_wait(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, -+ u8 cmd, - void (*fn)(struct iwl_priv *priv, -- struct iwl_rx_packet *pkt), -- u8 cmd) -+ struct iwl_rx_packet *pkt, -+ void *data), -+ void *fn_data) - { - wait_entry->fn = fn; -+ wait_entry->fn_data = fn_data; - wait_entry->cmd = cmd; - wait_entry->triggered = false; -+ wait_entry->aborted = false; - - spin_lock_bh(&priv->_agn.notif_wait_lock); - list_add(&wait_entry->list, &priv->_agn.notif_waits); - spin_unlock_bh(&priv->_agn.notif_wait_lock); - } - --signed long iwlagn_wait_notification(struct iwl_priv *priv, -- struct iwl_notification_wait *wait_entry, -- unsigned long timeout) -+int iwlagn_wait_notification(struct iwl_priv *priv, -+ struct iwl_notification_wait *wait_entry, -+ unsigned long timeout) - { - int ret; - - ret = wait_event_timeout(priv->_agn.notif_waitq, -- wait_entry->triggered, -+ wait_entry->triggered || wait_entry->aborted, - timeout); - - spin_lock_bh(&priv->_agn.notif_wait_lock); - list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); - -- return ret; -+ if (wait_entry->aborted) -+ return -EIO; -+ -+ /* return value is always >= 0 */ -+ if (ret <= 0) -+ return -ETIMEDOUT; -+ return 0; - } - - void iwlagn_remove_notification(struct iwl_priv *priv, -@@ -2282,3 +2309,87 @@ - list_del(&wait_entry->list); - spin_unlock_bh(&priv->_agn.notif_wait_lock); - } -+ -+int iwlagn_start_device(struct iwl_priv *priv) -+{ -+ int ret; -+ -+ if (iwl_prepare_card_hw(priv)) { -+ IWL_WARN(priv, "Exit HW not ready\n"); -+ return -EIO; -+ } -+ -+ /* If platform's RF_KILL switch is NOT set to KILL */ -+ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) -+ clear_bit(STATUS_RF_KILL_HW, &priv->status); -+ else -+ set_bit(STATUS_RF_KILL_HW, &priv->status); -+ -+ if (iwl_is_rfkill(priv)) { -+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); -+ iwl_enable_interrupts(priv); -+ return -ERFKILL; -+ } -+ -+ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); -+ -+ ret = iwlagn_hw_nic_init(priv); -+ if (ret) { -+ IWL_ERR(priv, "Unable to init nic\n"); -+ return ret; -+ } -+ -+ /* make sure rfkill handshake bits are cleared */ -+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, -+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); -+ -+ /* clear (again), then enable host interrupts */ -+ iwl_write32(priv, CSR_INT, 0xFFFFFFFF); -+ iwl_enable_interrupts(priv); -+ -+ /* really make sure rfkill handshake bits are cleared */ -+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); -+ -+ return 0; -+} -+ -+void iwlagn_stop_device(struct iwl_priv *priv) -+{ -+ unsigned long flags; -+ -+ /* stop and reset the on-board processor */ -+ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); -+ -+ /* tell the device to stop sending interrupts */ -+ spin_lock_irqsave(&priv->lock, flags); -+ iwl_disable_interrupts(priv); -+ spin_unlock_irqrestore(&priv->lock, flags); -+ iwl_synchronize_irq(priv); -+ -+ /* device going down, Stop using ICT table */ -+ iwl_disable_ict(priv); -+ -+ /* -+ * If a HW restart happens during firmware loading, -+ * then the firmware loading might call this function -+ * and later it might be called again due to the -+ * restart. So don't process again if the device is -+ * already dead. -+ */ -+ if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { -+ iwlagn_txq_ctx_stop(priv); -+ iwlagn_rxq_stop(priv); -+ -+ /* Power-down device's busmaster DMA clocks */ -+ iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); -+ udelay(5); -+ } -+ -+ /* Make sure (redundant) we've released our request to stay awake */ -+ iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -+ -+ /* Stop the device, and put it in low power state */ -+ iwl_apm_stop(priv); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rs.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2011-05-05 23:29:45.402440861 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 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 -@@ -115,13 +115,18 @@ - /* FIXME:RS: ^^ should be INV (legacy) */ - }; - -+static inline u8 rs_extract_rate(u32 rate_n_flags) -+{ -+ return (u8)(rate_n_flags & RATE_MCS_RATE_MSK); -+} -+ - static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) - { - int idx = 0; - - /* HT rate format */ - if (rate_n_flags & RATE_MCS_HT_MSK) { -- idx = (rate_n_flags & 0xff); -+ idx = rs_extract_rate(rate_n_flags); - - if (idx >= IWL_RATE_MIMO3_6M_PLCP) - idx = idx - IWL_RATE_MIMO3_6M_PLCP; -@@ -138,7 +143,8 @@ - /* legacy rate format, search for match in table */ - } else { - for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) -- if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) -+ if (iwl_rates[idx].plcp == -+ rs_extract_rate(rate_n_flags)) - return idx; - } - -@@ -239,11 +245,6 @@ - - #define MCS_INDEX_PER_STREAM (8) - --static inline u8 rs_extract_rate(u32 rate_n_flags) --{ -- return (u8)(rate_n_flags & 0xFF); --} -- - static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) - { - window->data = 0; -@@ -2770,16 +2771,13 @@ - static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, - gfp_t gfp) - { -- struct iwl_lq_sta *lq_sta; - struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; - struct iwl_priv *priv; - - priv = (struct iwl_priv *)priv_rate; - IWL_DEBUG_RATE(priv, "create station rate scale window\n"); - -- lq_sta = &sta_priv->lq_sta; -- -- return lq_sta; -+ return &sta_priv->lq_sta; - } - - /* -@@ -2912,7 +2910,8 @@ - ant_toggle_cnt = 1; - repeat_rate = IWL_NUMBER_TRY; - } else { -- repeat_rate = IWL_HT_NUMBER_TRY; -+ repeat_rate = min(IWL_HT_NUMBER_TRY, -+ LINK_QUAL_AGG_DISABLE_START_DEF - 1); - } - - lq_cmd->general_params.mimo_delimiter = -@@ -3257,7 +3256,6 @@ - { - char buff[120]; - int desc = 0; -- ssize_t ret; - - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; -@@ -3274,8 +3272,7 @@ - "Bit Rate= %d Mb/s\n", - iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - -- ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); -- return ret; -+ return simple_read_from_buffer(user_buf, count, ppos, buff, desc); - } - - static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rs.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rs.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rs.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rs.h 2011-05-05 23:29:45.217438626 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * 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 -@@ -41,20 +41,6 @@ - u8 next_rs_tgg; /* next rate used in TGG rs algo */ - }; - --struct iwl3945_rate_info { -- u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ -- u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ -- u8 prev_ieee; /* previous rate in IEEE speeds */ -- u8 next_ieee; /* next rate in IEEE speeds */ -- u8 prev_rs; /* previous rate used in rs algo */ -- u8 next_rs; /* next rate used in rs algo */ -- u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ -- u8 next_rs_tgg; /* next rate used in TGG rs algo */ -- u8 table_rs_index; /* index in rate scale table cmd */ -- u8 prev_table_rs; /* prev in rate table cmd */ --}; -- -- - /* - * These serve as indexes into - * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; -@@ -75,7 +61,6 @@ - IWL_RATE_60M_INDEX, - IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/ - IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1, /* Excluding 60M */ -- IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1, - IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, - IWL_RATE_INVALID = IWL_RATE_COUNT, - }; -@@ -98,7 +83,6 @@ - - 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, -@@ -213,7 +197,6 @@ - IWL_CCK_BASIC_RATES_MASK) - - #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) --#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1) - - #define IWL_INVALID_VALUE -1 - -@@ -453,19 +436,9 @@ - } - - --/** -- * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info -- * -- * The specific throughput table used is based on the type of network -- * the associated with, including A, B, G, and G w/ TGG protection -- */ --extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); -- - /* Initialize station's rate scaling information after adding station */ - extern void iwl_rs_rate_init(struct iwl_priv *priv, - struct ieee80211_sta *sta, u8 sta_id); --extern void iwl3945_rs_rate_init(struct iwl_priv *priv, -- struct ieee80211_sta *sta, u8 sta_id); - - /** - * iwl_rate_control_register - Register the rate control algorithm callbacks -@@ -478,7 +451,6 @@ - * - */ - extern int iwlagn_rate_control_register(void); --extern int iwl3945_rate_control_register(void); - - /** - * iwl_rate_control_unregister - Unregister the rate control callbacks -@@ -487,6 +459,5 @@ - * the driver is unloaded. - */ - extern void iwlagn_rate_control_unregister(void); --extern void iwl3945_rate_control_unregister(void); - - #endif /* __iwl_agn__rs__ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c 2011-05-05 23:29:45.375440535 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * 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 -@@ -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, -@@ -57,8 +58,9 @@ - u8 old_dev_type = send->dev_type; - int ret; - -- iwlagn_init_notification_wait(priv, &disable_wait, NULL, -- REPLY_WIPAN_DEACTIVATION_COMPLETE); -+ iwlagn_init_notification_wait(priv, &disable_wait, -+ REPLY_WIPAN_DEACTIVATION_COMPLETE, -+ NULL, NULL); - - send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - send->dev_type = RXON_DEV_TYPE_P2P; -@@ -71,13 +73,9 @@ - IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); - iwlagn_remove_notification(priv, &disable_wait); - } else { -- signed long wait_res; -- -- wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ); -- if (wait_res == 0) { -+ ret = iwlagn_wait_notification(priv, &disable_wait, HZ); -+ if (ret) - IWL_ERR(priv, "Timed out waiting for PAN disable\n"); -- ret = -EIO; -- } - } - - return ret; -@@ -123,6 +121,151 @@ - return iwlagn_send_beacon_cmd(priv); - } - -+static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, -+ struct iwl_rxon_context *ctx) -+{ -+ int ret = 0; -+ struct iwl_rxon_assoc_cmd rxon_assoc; -+ const struct iwl_rxon_cmd *rxon1 = &ctx->staging; -+ const struct iwl_rxon_cmd *rxon2 = &ctx->active; -+ -+ if ((rxon1->flags == rxon2->flags) && -+ (rxon1->filter_flags == rxon2->filter_flags) && -+ (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && -+ (rxon1->ofdm_ht_single_stream_basic_rates == -+ rxon2->ofdm_ht_single_stream_basic_rates) && -+ (rxon1->ofdm_ht_dual_stream_basic_rates == -+ rxon2->ofdm_ht_dual_stream_basic_rates) && -+ (rxon1->ofdm_ht_triple_stream_basic_rates == -+ rxon2->ofdm_ht_triple_stream_basic_rates) && -+ (rxon1->acquisition_data == rxon2->acquisition_data) && -+ (rxon1->rx_chain == rxon2->rx_chain) && -+ (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { -+ IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); -+ return 0; -+ } -+ -+ rxon_assoc.flags = ctx->staging.flags; -+ rxon_assoc.filter_flags = ctx->staging.filter_flags; -+ rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; -+ rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; -+ rxon_assoc.reserved1 = 0; -+ rxon_assoc.reserved2 = 0; -+ rxon_assoc.reserved3 = 0; -+ rxon_assoc.ofdm_ht_single_stream_basic_rates = -+ ctx->staging.ofdm_ht_single_stream_basic_rates; -+ rxon_assoc.ofdm_ht_dual_stream_basic_rates = -+ ctx->staging.ofdm_ht_dual_stream_basic_rates; -+ rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; -+ rxon_assoc.ofdm_ht_triple_stream_basic_rates = -+ ctx->staging.ofdm_ht_triple_stream_basic_rates; -+ rxon_assoc.acquisition_data = ctx->staging.acquisition_data; -+ -+ ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, -+ sizeof(rxon_assoc), &rxon_assoc, NULL); -+ if (ret) -+ return ret; -+ -+ return ret; -+} -+ -+static int iwlagn_rxon_disconn(struct iwl_priv *priv, -+ struct iwl_rxon_context *ctx) -+{ -+ int ret; -+ struct iwl_rxon_cmd *active = (void *)&ctx->active; -+ -+ if (ctx->ctxid == IWL_RXON_CTX_BSS) -+ ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); -+ else -+ ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); -+ if (ret) -+ return ret; -+ -+ /* -+ * Un-assoc RXON clears the station table and WEP -+ * keys, so we have to restore those afterwards. -+ */ -+ iwl_clear_ucode_stations(priv, ctx); -+ iwl_restore_stations(priv, ctx); -+ ret = iwl_restore_default_wep_keys(priv, ctx); -+ if (ret) { -+ IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); -+ return ret; -+ } -+ -+ memcpy(active, &ctx->staging, sizeof(*active)); -+ return 0; -+} -+ -+static int iwlagn_rxon_connect(struct iwl_priv *priv, -+ struct iwl_rxon_context *ctx) -+{ -+ int ret; -+ struct iwl_rxon_cmd *active = (void *)&ctx->active; -+ -+ /* RXON timing must be before associated RXON */ -+ ret = iwl_send_rxon_timing(priv, ctx); -+ if (ret) { -+ IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); -+ return ret; -+ } -+ /* QoS info may be cleared by previous un-assoc RXON */ -+ iwlagn_update_qos(priv, ctx); -+ -+ /* -+ * We'll run into this code path when beaconing is -+ * enabled, but then we also need to send the beacon -+ * to the device. -+ */ -+ if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { -+ ret = iwlagn_update_beacon(priv, ctx->vif); -+ if (ret) { -+ IWL_ERR(priv, -+ "Error sending required beacon (%d)!\n", -+ ret); -+ return ret; -+ } -+ } -+ -+ priv->start_calib = 0; -+ /* -+ * Apply the new configuration. -+ * -+ * Associated RXON doesn't clear the station table in uCode, -+ * so we don't need to restore stations etc. after this. -+ */ -+ ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, -+ sizeof(struct iwl_rxon_cmd), &ctx->staging); -+ if (ret) { -+ IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); -+ return ret; -+ } -+ memcpy(active, &ctx->staging, sizeof(*active)); -+ -+ iwl_reprogram_ap_sta(priv, ctx); -+ -+ /* IBSS beacon needs to be sent after setting assoc */ -+ if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) -+ if (iwlagn_update_beacon(priv, ctx->vif)) -+ IWL_ERR(priv, "Error sending IBSS beacon\n"); -+ iwl_init_sensitivity(priv); -+ -+ /* -+ * If we issue a new RXON command which required a tune then -+ * we must send a new TXPOWER command or we won't be able to -+ * Tx any frames. -+ * -+ * It's expected we set power here if channel is changing. -+ */ -+ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); -+ if (ret) { -+ IWL_ERR(priv, "Error sending TX power (%d)\n", ret); -+ return ret; -+ } -+ return 0; -+} -+ - /** - * iwlagn_commit_rxon - commit staging_rxon to hardware - * -@@ -130,6 +273,16 @@ - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. -+ * -+ * The connect/disconnect flow should be as the following: -+ * -+ * 1. make sure send RXON command with association bit unset if not connect -+ * this should include the channel and the band for the candidate -+ * to be connected to -+ * 2. Add Station before RXON association with the AP -+ * 3. RXON_timing has to send before RXON for connection -+ * 4. full RXON command - associated bit set -+ * 5. use RXON_ASSOC command to update any flags changes - */ - int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - { -@@ -179,6 +332,7 @@ - else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - -+ iwl_print_rx_config_cmd(priv, ctx); - ret = iwl_check_rxon_cmd(priv, ctx); - if (ret) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); -@@ -202,14 +356,13 @@ - * and other flags for the current radio configuration. - */ - if (!iwl_full_rxon_required(priv, ctx)) { -- ret = iwl_send_rxon_assoc(priv, ctx); -+ ret = iwlagn_send_rxon_assoc(priv, ctx); - if (ret) { - IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); - return ret; - } - - memcpy(active, &ctx->staging, sizeof(*active)); -- iwl_print_rx_config_cmd(priv, ctx); - return 0; - } - -@@ -219,7 +372,7 @@ - return ret; - } - -- iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto); -+ iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto); - - IWL_DEBUG_INFO(priv, - "Going to commit RXON\n" -@@ -237,92 +390,13 @@ - * set up filters in the device. - */ - if ((old_assoc && new_assoc) || !new_assoc) { -- if (ctx->ctxid == IWL_RXON_CTX_BSS) -- ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); -- else -- ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); -+ ret = iwlagn_rxon_disconn(priv, ctx); - if (ret) - return ret; -- -- memcpy(active, &ctx->staging, sizeof(*active)); -- -- /* -- * Un-assoc RXON clears the station table and WEP -- * keys, so we have to restore those afterwards. -- */ -- iwl_clear_ucode_stations(priv, ctx); -- iwl_restore_stations(priv, ctx); -- ret = iwl_restore_default_wep_keys(priv, ctx); -- if (ret) { -- IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); -- return ret; -- } -- } -- -- /* RXON timing must be before associated RXON */ -- ret = iwl_send_rxon_timing(priv, ctx); -- if (ret) { -- IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); -- return ret; -- } -- -- if (new_assoc) { -- /* QoS info may be cleared by previous un-assoc RXON */ -- iwlagn_update_qos(priv, ctx); -- -- /* -- * We'll run into this code path when beaconing is -- * enabled, but then we also need to send the beacon -- * to the device. -- */ -- if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { -- ret = iwlagn_update_beacon(priv, ctx->vif); -- if (ret) { -- IWL_ERR(priv, -- "Error sending required beacon (%d)!\n", -- ret); -- return ret; -- } -- } -- -- priv->start_calib = 0; -- /* -- * Apply the new configuration. -- * -- * Associated RXON doesn't clear the station table in uCode, -- * so we don't need to restore stations etc. after this. -- */ -- ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, -- sizeof(struct iwl_rxon_cmd), &ctx->staging); -- if (ret) { -- IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); -- return ret; -- } -- memcpy(active, &ctx->staging, sizeof(*active)); -- -- iwl_reprogram_ap_sta(priv, ctx); -- -- /* IBSS beacon needs to be sent after setting assoc */ -- if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) -- if (iwlagn_update_beacon(priv, ctx->vif)) -- IWL_ERR(priv, "Error sending IBSS beacon\n"); - } - -- iwl_print_rx_config_cmd(priv, ctx); -- -- iwl_init_sensitivity(priv); -- -- /* -- * If we issue a new RXON command which required a tune then we must -- * send a new TXPOWER command or we won't be able to Tx any frames. -- * -- * It's expected we set power here if channel is changing. -- */ -- ret = iwl_set_tx_power(priv, priv->tx_power_next, true); -- if (ret) { -- IWL_ERR(priv, "Error sending TX power (%d)\n", ret); -- return ret; -- } -+ if (new_assoc) -+ return iwlagn_rxon_connect(priv, ctx); - - return 0; - } -@@ -595,6 +669,18 @@ - 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; - } - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-sta.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-sta.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-sta.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-sta.c 2011-05-05 23:29:45.267439231 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -474,7 +474,7 @@ - memset(&priv->stations[sta_id].keyinfo, 0, - sizeof(struct iwl_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, -- sizeof(struct iwl4965_keyinfo)); -+ sizeof(struct iwl_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = - STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tt.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tt.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tt.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tt.c 2011-05-05 23:29:45.376440547 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tt.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tt.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tt.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tt.h 2011-05-05 23:29:45.227438747 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-tx.c 2011-05-05 23:29:45.407440921 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -222,13 +222,8 @@ - scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); - } - --int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, -- int tx_fifo, int sta_id, int tid, u16 ssn_idx) -+static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid) - { -- unsigned long flags; -- u16 ra_tid; -- int ret; -- - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + - priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { -@@ -240,12 +235,33 @@ - return -EINVAL; - } - -- ra_tid = BUILD_RAxTID(sta_id, tid); -- - /* Modify device's station table to Tx this TID */ -- ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); -- if (ret) -- return ret; -+ return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); -+} -+ -+void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv, -+ struct ieee80211_sta *sta, -+ int tid, int frame_limit) -+{ -+ int sta_id, tx_fifo, txq_id, ssn_idx; -+ u16 ra_tid; -+ unsigned long flags; -+ struct iwl_tid_data *tid_data; -+ -+ sta_id = iwl_sta_id(sta); -+ if (WARN_ON(sta_id == IWL_INVALID_STATION)) -+ return; -+ if (WARN_ON(tid >= MAX_TID_COUNT)) -+ return; -+ -+ spin_lock_irqsave(&priv->sta_lock, flags); -+ tid_data = &priv->stations[sta_id].tid[tid]; -+ ssn_idx = SEQ_TO_SN(tid_data->seq_number); -+ txq_id = tid_data->agg.txq_id; -+ tx_fifo = tid_data->agg.tx_fifo; -+ spin_unlock_irqrestore(&priv->sta_lock, flags); -+ -+ ra_tid = BUILD_RAxTID(sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - -@@ -271,10 +287,10 @@ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + - sizeof(u32), -- ((SCD_WIN_SIZE << -+ ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | -- ((SCD_FRAME_LIMIT << -+ ((frame_limit << - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - -@@ -284,12 +300,10 @@ - iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); -- -- return 0; - } - --int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, -- u16 ssn_idx, u8 tx_fifo) -+static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, -+ u16 ssn_idx, u8 tx_fifo) - { - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || - (IWLAGN_FIRST_AMPDU_QUEUE + -@@ -1039,11 +1053,11 @@ - tid_data = &priv->stations[sta_id].tid[tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; -+ tid_data->agg.tx_fifo = tx_fifo; - iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); - spin_unlock_irqrestore(&priv->sta_lock, flags); - -- ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, -- sta_id, tid, *ssn); -+ ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); - if (ret) - return ret; - -@@ -1130,8 +1144,7 @@ - * to deactivate the uCode queue, just return "success" to allow - * mac80211 to clean up it own data. - */ -- priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, -- tx_fifo_id); -+ iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); - spin_unlock_irqrestore(&priv->lock, flags); - - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); -@@ -1160,8 +1173,7 @@ - u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = get_fifo_from_tid(ctx, tid); - IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); -- priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, -- ssn, tx_fifo); -+ iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo); - tid_data->agg.state = IWL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); - } -@@ -1260,11 +1272,11 @@ - struct iwl_compressed_ba_resp *ba_resp) - - { -- int i, sh, ack; -+ int sh; - u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); -- int successes = 0; - struct ieee80211_tx_info *info; -+ u64 bitmap, sent_bitmap; - - if (unlikely(!agg->wait_for_ba)) { - if (unlikely(ba_resp->bitmap)) -@@ -1278,70 +1290,42 @@ - - /* Calculate shift to align block-ack bits with our Tx window bits */ - sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); -- if (sh < 0) /* tbw something is wrong with indices */ -+ if (sh < 0) - sh += 0x100; - -- if (agg->frame_count > (64 - sh)) { -- IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); -- return -1; -- } -- if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { -+ /* -+ * Check for success or failure according to the -+ * transmitted bitmap and block-ack bitmap -+ */ -+ bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; -+ sent_bitmap = bitmap & agg->bitmap; -+ -+ /* Sanity check values reported by uCode */ -+ if (ba_resp->txed_2_done > ba_resp->txed) { -+ IWL_DEBUG_TX_REPLY(priv, -+ "bogus sent(%d) and ack(%d) count\n", -+ ba_resp->txed, ba_resp->txed_2_done); - /* -- * sent and ack information provided by uCode -- * use it instead of figure out ourself -+ * set txed_2_done = txed, -+ * so it won't impact rate scale - */ -- if (ba_resp->txed_2_done > ba_resp->txed) { -- IWL_DEBUG_TX_REPLY(priv, -- "bogus sent(%d) and ack(%d) count\n", -- ba_resp->txed, ba_resp->txed_2_done); -- /* -- * set txed_2_done = txed, -- * so it won't impact rate scale -- */ -- ba_resp->txed = ba_resp->txed_2_done; -- } -- IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", -- ba_resp->txed, ba_resp->txed_2_done); -- } else { -- u64 bitmap, sent_bitmap; -- -- /* don't use 64-bit values for now */ -- bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; -- -- /* check for success or failure according to the -- * transmitted bitmap and block-ack bitmap */ -- sent_bitmap = bitmap & agg->bitmap; -- -- /* For each frame attempted in aggregation, -- * update driver's record of tx frame's status. */ -- i = 0; -- while (sent_bitmap) { -- ack = sent_bitmap & 1ULL; -- successes += ack; -- IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", -- ack ? "ACK" : "NACK", i, -- (agg->start_idx + i) & 0xff, -- agg->start_idx + i); -- sent_bitmap >>= 1; -- ++i; -- } -+ ba_resp->txed = ba_resp->txed_2_done; -+ } -+ IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", -+ ba_resp->txed, ba_resp->txed_2_done); - -- IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", -- (unsigned long long)bitmap); -+ /* Find the first ACKed frame to store the TX status */ -+ while (sent_bitmap && !(sent_bitmap & 1)) { -+ agg->start_idx = (agg->start_idx + 1) & 0xff; -+ sent_bitmap >>= 1; - } - - info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); - memset(&info->status, 0, sizeof(info->status)); - info->flags |= IEEE80211_TX_STAT_ACK; - info->flags |= IEEE80211_TX_STAT_AMPDU; -- if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { -- info->status.ampdu_ack_len = ba_resp->txed_2_done; -- info->status.ampdu_len = ba_resp->txed; -- -- } else { -- info->status.ampdu_ack_len = successes; -- info->status.ampdu_len = agg->frame_count; -- } -+ info->status.ampdu_ack_len = ba_resp->txed_2_done; -+ info->status.ampdu_len = ba_resp->txed; - iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); - - return 0; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c 2011-05-05 23:29:45.326439943 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -161,47 +161,19 @@ - } - - static int iwlagn_load_given_ucode(struct iwl_priv *priv, -- struct fw_desc *inst_image, -- struct fw_desc *data_image) -+ struct fw_img *image) - { - int ret = 0; - -- ret = iwlagn_load_section(priv, "INST", inst_image, -+ ret = iwlagn_load_section(priv, "INST", &image->code, - IWLAGN_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - -- return iwlagn_load_section(priv, "DATA", data_image, -+ return iwlagn_load_section(priv, "DATA", &image->data, - IWLAGN_RTC_DATA_LOWER_BOUND); - } - --int iwlagn_load_ucode(struct iwl_priv *priv) --{ -- int ret = 0; -- -- /* check whether init ucode should be loaded, or rather runtime ucode */ -- if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { -- IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); -- ret = iwlagn_load_given_ucode(priv, -- &priv->ucode_init, &priv->ucode_init_data); -- if (!ret) { -- IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); -- priv->ucode_type = UCODE_INIT; -- } -- } else { -- IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " -- "Loading runtime ucode...\n"); -- ret = iwlagn_load_given_ucode(priv, -- &priv->ucode_code, &priv->ucode_data); -- if (!ret) { -- IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); -- priv->ucode_type = UCODE_RT; -- } -- } -- -- return ret; --} -- - /* - * Calibration - */ -@@ -297,33 +269,9 @@ - iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); - } - --void iwlagn_rx_calib_complete(struct iwl_priv *priv, -- struct iwl_rx_mem_buffer *rxb) --{ -- IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); -- queue_work(priv->workqueue, &priv->restart); --} -- --void iwlagn_init_alive_start(struct iwl_priv *priv) -+static int iwlagn_init_alive_start(struct iwl_priv *priv) - { -- int ret = 0; -- -- /* initialize uCode was loaded... verify inst image. -- * This is a paranoid check, because we would not have gotten the -- * "initialize" alive if code weren't properly loaded. */ -- if (iwl_verify_ucode(priv)) { -- /* Runtime instruction load was bad; -- * take it all the way back down so we can try again */ -- IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); -- goto restart; -- } -- -- ret = priv->cfg->ops->lib->alive_notify(priv); -- if (ret) { -- IWL_WARN(priv, -- "Could not complete ALIVE transition: %d\n", ret); -- goto restart; -- } -+ int ret; - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { -@@ -333,24 +281,25 @@ - * no need to close the envlope since we are going - * to load the runtime uCode later. - */ -- iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, -+ ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); -+ if (ret) -+ return ret; - - } -- iwlagn_send_calib_cfg(priv); -+ -+ ret = iwlagn_send_calib_cfg(priv); -+ if (ret) -+ return ret; - - /** - * temperature offset calibration is only needed for runtime ucode, - * so prepare the value now. - */ - if (priv->cfg->need_temp_offset_calib) -- iwlagn_set_temperature_offset_calib(priv); -- -- return; -+ return iwlagn_set_temperature_offset_calib(priv); - --restart: -- /* real restart (first load init_ucode) */ -- queue_work(priv->workqueue, &priv->restart); -+ return 0; - } - - static int iwlagn_send_wimax_coex(struct iwl_priv *priv) -@@ -413,25 +362,30 @@ - IWL_ERR(priv, "failed to send BT prio tbl command\n"); - } - --void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) -+int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) - { - struct iwl_bt_coex_prot_env_cmd env_cmd; -+ int ret; - - env_cmd.action = action; - env_cmd.type = type; -- if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, -- sizeof(env_cmd), &env_cmd)) -+ ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, -+ sizeof(env_cmd), &env_cmd); -+ if (ret) - IWL_ERR(priv, "failed to send BT env command\n"); -+ return ret; - } - - --int iwlagn_alive_notify(struct iwl_priv *priv) -+static 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; - u32 reg_val; -+ int ret; - - spin_lock_irqsave(&priv->lock, flags); - -@@ -500,6 +454,8 @@ - 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; -@@ -527,12 +483,15 @@ - iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - -- iwlagn_send_wimax_coex(priv); -+ ret = iwlagn_send_wimax_coex(priv); -+ if (ret) -+ return ret; - -- iwlagn_set_Xtal_calib(priv); -- iwl_send_calib_results(priv); -+ ret = iwlagn_set_Xtal_calib(priv); -+ if (ret) -+ return ret; - -- return 0; -+ return iwl_send_calib_results(priv); - } - - -@@ -541,11 +500,12 @@ - * using sample data 100 bytes apart. If these sample points are good, - * it's a pretty good bet that everything between them is good, too. - */ --static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) -+static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, -+ struct fw_desc *fw_desc) - { -+ __le32 *image = (__le32 *)fw_desc->v_addr; -+ u32 len = fw_desc->len; - u32 val; -- int ret = 0; -- u32 errcnt = 0; - u32 i; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); -@@ -556,104 +516,204 @@ - * if IWL_DL_IO is set */ - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + IWLAGN_RTC_INST_LOWER_BOUND); -- val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -- if (val != le32_to_cpu(*image)) { -- ret = -EIO; -- errcnt++; -- if (errcnt >= 3) -- break; -- } -+ val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); -+ if (val != le32_to_cpu(*image)) -+ return -EIO; - } - -- return ret; -+ return 0; - } - --/** -- * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, -- * looking at all data. -- */ --static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, -- u32 len) -+static void iwl_print_mismatch_inst(struct iwl_priv *priv, -+ struct fw_desc *fw_desc) - { -+ __le32 *image = (__le32 *)fw_desc->v_addr; -+ u32 len = fw_desc->len; - u32 val; -- u32 save_len = len; -- int ret = 0; -- u32 errcnt; -+ u32 offs; -+ int errors = 0; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - IWLAGN_RTC_INST_LOWER_BOUND); - -- errcnt = 0; -- for (; len > 0; len -= sizeof(u32), image++) { -+ for (offs = 0; -+ offs < len && errors < 20; -+ offs += sizeof(u32), image++) { - /* read data comes through single port, auto-incr addr */ -- /* NOTE: Use the debugless read so we don't flood kernel log -- * if IWL_DL_IO is set */ -- val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -+ val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { -- IWL_ERR(priv, "uCode INST section is invalid at " -- "offset 0x%x, is 0x%x, s/b 0x%x\n", -- save_len - len, val, le32_to_cpu(*image)); -- ret = -EIO; -- errcnt++; -- if (errcnt >= 20) -- break; -+ IWL_ERR(priv, "uCode INST section at " -+ "offset 0x%x, is 0x%x, s/b 0x%x\n", -+ offs, val, le32_to_cpu(*image)); -+ errors++; - } - } -- -- if (!errcnt) -- IWL_DEBUG_INFO(priv, -- "ucode image in INSTRUCTION memory is good\n"); -- -- return ret; - } - - /** - * iwl_verify_ucode - determine which instruction image is in SRAM, - * and verify its contents - */ --int iwl_verify_ucode(struct iwl_priv *priv) -+static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) - { -- __le32 *image; -- u32 len; -+ if (!iwlcore_verify_inst_sparse(priv, &img->code)) { -+ IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); -+ return 0; -+ } -+ -+ IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); -+ -+ iwl_print_mismatch_inst(priv, &img->code); -+ return -EIO; -+} -+ -+struct iwlagn_alive_data { -+ bool valid; -+ u8 subtype; -+}; -+ -+static void iwlagn_alive_fn(struct iwl_priv *priv, -+ struct iwl_rx_packet *pkt, -+ void *data) -+{ -+ struct iwlagn_alive_data *alive_data = data; -+ struct iwl_alive_resp *palive; -+ -+ palive = &pkt->u.alive_frame; -+ -+ IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " -+ "0x%01X 0x%01X\n", -+ palive->is_valid, palive->ver_type, -+ palive->ver_subtype); -+ -+ priv->device_pointers.error_event_table = -+ le32_to_cpu(palive->error_event_table_ptr); -+ priv->device_pointers.log_event_table = -+ le32_to_cpu(palive->log_event_table_ptr); -+ -+ alive_data->subtype = palive->ver_subtype; -+ alive_data->valid = palive->is_valid == UCODE_VALID_OK; -+} -+ -+#define UCODE_ALIVE_TIMEOUT HZ -+#define UCODE_CALIB_TIMEOUT (2*HZ) -+ -+int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, -+ struct fw_img *image, -+ int subtype, int alternate_subtype) -+{ -+ struct iwl_notification_wait alive_wait; -+ struct iwlagn_alive_data alive_data; - int ret; -+ enum iwlagn_ucode_subtype old_type; - -- /* Try bootstrap */ -- image = (__le32 *)priv->ucode_boot.v_addr; -- len = priv->ucode_boot.len; -- ret = iwlcore_verify_inst_sparse(priv, image, len); -- if (!ret) { -- IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); -- return 0; -+ ret = iwlagn_start_device(priv); -+ if (ret) -+ return ret; -+ -+ iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, -+ iwlagn_alive_fn, &alive_data); -+ -+ old_type = priv->ucode_type; -+ priv->ucode_type = subtype; -+ -+ ret = iwlagn_load_given_ucode(priv, image); -+ if (ret) { -+ priv->ucode_type = old_type; -+ iwlagn_remove_notification(priv, &alive_wait); -+ return ret; - } - -- /* Try initialize */ -- image = (__le32 *)priv->ucode_init.v_addr; -- len = priv->ucode_init.len; -- ret = iwlcore_verify_inst_sparse(priv, image, len); -- if (!ret) { -- IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); -- return 0; -+ /* Remove all resets to allow NIC to operate */ -+ iwl_write32(priv, CSR_RESET, 0); -+ -+ /* -+ * Some things may run in the background now, but we -+ * just wait for the ALIVE notification here. -+ */ -+ ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); -+ if (ret) { -+ priv->ucode_type = old_type; -+ return ret; - } - -- /* Try runtime/protocol */ -- image = (__le32 *)priv->ucode_code.v_addr; -- len = priv->ucode_code.len; -- ret = iwlcore_verify_inst_sparse(priv, image, len); -- if (!ret) { -- IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); -- return 0; -+ if (!alive_data.valid) { -+ IWL_ERR(priv, "Loaded ucode is not valid!\n"); -+ priv->ucode_type = old_type; -+ return -EIO; -+ } -+ -+ if (alive_data.subtype != subtype && -+ alive_data.subtype != alternate_subtype) { -+ IWL_ERR(priv, -+ "Loaded ucode is not expected type (got %d, expected %d)!\n", -+ alive_data.subtype, subtype); -+ priv->ucode_type = old_type; -+ return -EIO; - } - -- IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); -+ ret = iwl_verify_ucode(priv, image); -+ if (ret) { -+ priv->ucode_type = old_type; -+ return ret; -+ } -+ -+ /* delay a bit to give rfkill time to run */ -+ msleep(5); -+ -+ ret = iwlagn_alive_notify(priv); -+ if (ret) { -+ IWL_WARN(priv, -+ "Could not complete ALIVE transition: %d\n", ret); -+ priv->ucode_type = old_type; -+ return ret; -+ } -+ -+ return 0; -+} -+ -+int iwlagn_run_init_ucode(struct iwl_priv *priv) -+{ -+ struct iwl_notification_wait calib_wait; -+ int ret; -+ -+ lockdep_assert_held(&priv->mutex); -+ -+ /* No init ucode required? Curious, but maybe ok */ -+ if (!priv->ucode_init.code.len) -+ return 0; -+ -+ if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) -+ return 0; -+ -+ iwlagn_init_notification_wait(priv, &calib_wait, -+ CALIBRATION_COMPLETE_NOTIFICATION, -+ NULL, NULL); -+ -+ /* Will also start the device */ -+ ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, -+ UCODE_SUBTYPE_INIT, -1); -+ if (ret) -+ goto error; -+ -+ ret = iwlagn_init_alive_start(priv); -+ if (ret) -+ goto error; -+ -+ /* -+ * Some things may run in the background now, but we -+ * just wait for the calibration complete notification. -+ */ -+ ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); - -- /* Since nothing seems to match, show first several data entries in -- * instruction SRAM, so maybe visual inspection will give a clue. -- * Selection of bootstrap image (vs. other images) is arbitrary. */ -- image = (__le32 *)priv->ucode_boot.v_addr; -- len = priv->ucode_boot.len; -- ret = iwl_verify_inst_full(priv, image, len); -+ goto out; - -+ error: -+ iwlagn_remove_notification(priv, &calib_wait); -+ out: -+ /* Whatever happened, stop the device */ -+ iwlagn_stop_device(priv); - return ret; - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-commands.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-commands.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-commands.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-commands.h 2011-05-05 23:29:45.280439387 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 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 -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -103,9 +103,7 @@ - REPLY_WEPKEY = 0x20, - - /* RX, TX, LEDs */ -- REPLY_3945_RX = 0x1b, /* 3945 only */ - REPLY_TX = 0x1c, -- REPLY_RATE_SCALE = 0x47, /* 3945 only */ - REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ - -@@ -229,7 +227,7 @@ - * There is one exception: uCode sets bit 15 when it originates - * the response/notification, i.e. when the response/notification - * is not a direct response to a command sent by the driver. For -- * example, uCode issues REPLY_3945_RX when it sends a received frame -+ * example, uCode issues REPLY_RX when it sends a received frame - * to the driver; it is not a direct response to any driver command. - * - * The Linux driver uses the following format: -@@ -249,36 +247,6 @@ - - - /** -- * struct iwl3945_tx_power -- * -- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH -- * -- * Each entry contains two values: -- * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained -- * linear value that multiplies the output of the digital signal processor, -- * before being sent to the analog radio. -- * 2) Radio gain. This sets the analog gain of the radio Tx path. -- * It is a coarser setting, and behaves in a logarithmic (dB) fashion. -- * -- * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. -- */ --struct iwl3945_tx_power { -- u8 tx_gain; /* gain for analog radio */ -- u8 dsp_atten; /* gain for DSP */ --} __packed; -- --/** -- * struct iwl3945_power_per_rate -- * -- * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH -- */ --struct iwl3945_power_per_rate { -- u8 rate; /* plcp */ -- struct iwl3945_tx_power tpc; -- u8 reserved; --} __packed; -- --/** - * iwlagn rate_n_flags bit fields - * - * rate_n_flags format is used in following iwlagn commands: -@@ -324,6 +292,8 @@ - #define RATE_MCS_SPATIAL_MSK 0x18 - #define RATE_MCS_HT_DUP_POS 5 - #define RATE_MCS_HT_DUP_MSK 0x20 -+/* Both legacy and HT use bits 7:0 as the CCK/OFDM rate or HT MCS */ -+#define RATE_MCS_RATE_MSK 0xff - - /* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */ - #define RATE_MCS_FLAGS_POS 8 -@@ -375,30 +345,6 @@ - #define IWL_PWR_CCK_ENTRIES 2 - - /** -- * union iwl4965_tx_power_dual_stream -- * -- * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH -- * Use __le32 version (struct tx_power_dual_stream) when building command. -- * -- * Driver provides radio gain and DSP attenuation settings to device in pairs, -- * one value for each transmitter chain. The first value is for transmitter A, -- * second for transmitter B. -- * -- * For SISO bit rates, both values in a pair should be identical. -- * For MIMO rates, one value may be different from the other, -- * in order to balance the Tx output between the two transmitters. -- * -- * See more details in doc for TXPOWER in iwl-4965-hw.h. -- */ --union iwl4965_tx_power_dual_stream { -- struct { -- u8 radio_tx_gain[2]; -- u8 dsp_predis_atten[2]; -- } s; -- u32 dw; --}; -- --/** - * struct tx_power_dual_stream - * - * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH -@@ -410,15 +356,6 @@ - } __packed; - - /** -- * struct iwl4965_tx_power_db -- * -- * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH -- */ --struct iwl4965_tx_power_db { -- struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; --} __packed; -- --/** - * Command REPLY_TX_POWER_DBM_CMD = 0x98 - * struct iwlagn_tx_power_dbm_cmd - */ -@@ -449,55 +386,18 @@ - *****************************************************************************/ - - #define UCODE_VALID_OK cpu_to_le32(0x1) --#define INITIALIZE_SUBTYPE (9) - --/* -- * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) -- * -- * uCode issues this "initialize alive" notification once the initialization -- * uCode image has completed its work, and is ready to load the runtime image. -- * This is the *first* "alive" notification that the driver will receive after -- * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. -- * -- * See comments documenting "BSM" (bootstrap state machine). -- * -- * For 4965, this notification contains important calibration data for -- * calculating txpower settings: -- * -- * 1) Power supply voltage indication. The voltage sensor outputs higher -- * values for lower voltage, and vice verse. -- * -- * 2) Temperature measurement parameters, for each of two channel widths -- * (20 MHz and 40 MHz) supported by the radios. Temperature sensing -- * is done via one of the receiver chains, and channel width influences -- * the results. -- * -- * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation, -- * for each of 5 frequency ranges. -- */ --struct iwl_init_alive_resp { -- u8 ucode_minor; -- u8 ucode_major; -- __le16 reserved1; -- u8 sw_rev[8]; -- u8 ver_type; -- u8 ver_subtype; /* "9" for initialize alive */ -- __le16 reserved2; -- __le32 log_event_table_ptr; -- __le32 error_event_table_ptr; -- __le32 timestamp; -- __le32 is_valid; -- -- /* calibration values from "initialize" uCode */ -- __le32 voltage; /* signed, higher value is lower voltage */ -- __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */ -- __le32 therm_r2[2]; /* signed */ -- __le32 therm_r3[2]; /* signed */ -- __le32 therm_r4[2]; /* signed */ -- __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, -- * 2 Tx chains */ --} __packed; -+enum iwlagn_ucode_subtype { -+ UCODE_SUBTYPE_REGULAR = 0, -+ UCODE_SUBTYPE_REGULAR_NEW = 1, -+ UCODE_SUBTYPE_INIT = 9, - -+ /* -+ * Not a valid subtype, the ucode has just a u8, so -+ * we can use something > 0xff for this value. -+ */ -+ UCODE_SUBTYPE_NONE_LOADED = 0x100, -+}; - - /** - * REPLY_ALIVE = 0x1 (response only, not a command) -@@ -533,49 +433,61 @@ - * - * 2) error_event_table_ptr indicates base of the error log. This contains - * information about any uCode error that occurs. For agn, the format -- * of the error log is: -- * -- * __le32 valid; (nonzero) valid, (0) log is empty -- * __le32 error_id; type of error -- * __le32 pc; program counter -- * __le32 blink1; branch link -- * __le32 blink2; branch link -- * __le32 ilink1; interrupt link -- * __le32 ilink2; interrupt link -- * __le32 data1; error-specific data -- * __le32 data2; error-specific data -- * __le32 line; source code line of error -- * __le32 bcon_time; beacon timer -- * __le32 tsf_low; network timestamp function timer -- * __le32 tsf_hi; network timestamp function timer -- * __le32 gp1; GP1 timer register -- * __le32 gp2; GP2 timer register -- * __le32 gp3; GP3 timer register -- * __le32 ucode_ver; uCode version -- * __le32 hw_ver; HW Silicon version -- * __le32 brd_ver; HW board version -- * __le32 log_pc; log program counter -- * __le32 frame_ptr; frame pointer -- * __le32 stack_ptr; stack pointer -- * __le32 hcmd; last host command -- * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag -- * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag -- * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag -- * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag -- * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt -- * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT -- * __le32 wait_event; wait event() caller address -- * __le32 l2p_control; L2pControlField -- * __le32 l2p_duration; L2pDurationField -- * __le32 l2p_mhvalid; L2pMhValidBits -- * __le32 l2p_addr_match; L2pAddrMatchStat -- * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) -- * __le32 u_timestamp; indicate when the date and time of the compilation -- * __le32 reserved; -+ * of the error log is defined by struct iwl_error_event_table. - * - * The Linux driver can print both logs to the system log when a uCode error - * occurs. - */ -+ -+/* -+ * Note: This structure is read from the device with IO accesses, -+ * and the reading already does the endian conversion. As it is -+ * read with u32-sized accesses, any members with a different size -+ * need to be ordered correctly though! -+ */ -+struct iwl_error_event_table { -+ u32 valid; /* (nonzero) valid, (0) log is empty */ -+ u32 error_id; /* type of error */ -+ u32 pc; /* program counter */ -+ u32 blink1; /* branch link */ -+ u32 blink2; /* branch link */ -+ u32 ilink1; /* interrupt link */ -+ u32 ilink2; /* interrupt link */ -+ u32 data1; /* error-specific data */ -+ u32 data2; /* error-specific data */ -+ u32 line; /* source code line of error */ -+ u32 bcon_time; /* beacon timer */ -+ u32 tsf_low; /* network timestamp function timer */ -+ u32 tsf_hi; /* network timestamp function timer */ -+ u32 gp1; /* GP1 timer register */ -+ u32 gp2; /* GP2 timer register */ -+ u32 gp3; /* GP3 timer register */ -+ u32 ucode_ver; /* uCode version */ -+ u32 hw_ver; /* HW Silicon version */ -+ u32 brd_ver; /* HW board version */ -+ u32 log_pc; /* log program counter */ -+ u32 frame_ptr; /* frame pointer */ -+ u32 stack_ptr; /* stack pointer */ -+ u32 hcmd; /* last host command header */ -+#if 0 -+ /* no need to read the remainder, we don't use the values */ -+ u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */ -+ u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */ -+ u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */ -+ u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */ -+ u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */ -+ u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */ -+ u32 wait_event; /* wait event() caller address */ -+ u32 l2p_control; /* L2pControlField */ -+ u32 l2p_duration; /* L2pDurationField */ -+ u32 l2p_mhvalid; /* L2pMhValidBits */ -+ u32 l2p_addr_match; /* L2pAddrMatchStat */ -+ u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */ -+ u32 u_timestamp; /* indicate when the date and time of the compilation */ -+ u32 flow_handler; /* FH read/write pointers, RX credit */ -+#endif -+} __packed; -+ - struct iwl_alive_resp { - u8 ucode_minor; - u8 ucode_major; -@@ -722,46 +634,6 @@ - * regardless of whether RXON_FILTER_ASSOC_MSK is set. - */ - --struct iwl3945_rxon_cmd { -- u8 node_addr[6]; -- __le16 reserved1; -- u8 bssid_addr[6]; -- __le16 reserved2; -- u8 wlap_bssid_addr[6]; -- __le16 reserved3; -- u8 dev_type; -- u8 air_propagation; -- __le16 reserved4; -- u8 ofdm_basic_rates; -- u8 cck_basic_rates; -- __le16 assoc_id; -- __le32 flags; -- __le32 filter_flags; -- __le16 channel; -- __le16 reserved5; --} __packed; -- --struct iwl4965_rxon_cmd { -- u8 node_addr[6]; -- __le16 reserved1; -- u8 bssid_addr[6]; -- __le16 reserved2; -- u8 wlap_bssid_addr[6]; -- __le16 reserved3; -- u8 dev_type; -- u8 air_propagation; -- __le16 rx_chain; -- u8 ofdm_basic_rates; -- u8 cck_basic_rates; -- __le16 assoc_id; -- __le32 flags; -- __le32 filter_flags; -- __le16 channel; -- u8 ofdm_ht_single_stream_basic_rates; -- u8 ofdm_ht_dual_stream_basic_rates; --} __packed; -- --/* 5000 HW just extend this command */ - struct iwl_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; -@@ -789,26 +661,7 @@ - /* - * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) - */ --struct iwl3945_rxon_assoc_cmd { -- __le32 flags; -- __le32 filter_flags; -- u8 ofdm_basic_rates; -- u8 cck_basic_rates; -- __le16 reserved; --} __packed; -- --struct iwl4965_rxon_assoc_cmd { -- __le32 flags; -- __le32 filter_flags; -- u8 ofdm_basic_rates; -- u8 cck_basic_rates; -- u8 ofdm_ht_single_stream_basic_rates; -- u8 ofdm_ht_dual_stream_basic_rates; -- __le16 rx_chain_select_flags; -- __le16 reserved; --} __packed; -- --struct iwl5000_rxon_assoc_cmd { -+struct iwl_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; -@@ -843,26 +696,6 @@ - /* - * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) - */ --struct iwl3945_channel_switch_cmd { -- u8 band; -- u8 expect_beacon; -- __le16 channel; -- __le32 rxon_flags; -- __le32 rxon_filter_flags; -- __le32 switch_time; -- struct iwl3945_power_per_rate power[IWL_MAX_RATES]; --} __packed; -- --struct iwl4965_channel_switch_cmd { -- u8 band; -- u8 expect_beacon; -- __le16 channel; -- __le32 rxon_flags; -- __le32 rxon_filter_flags; -- __le32 switch_time; -- struct iwl4965_tx_power_db tx_power; --} __packed; -- - /** - * struct iwl5000_channel_switch_cmd - * @band: 0- 5.2GHz, 1- 2.4GHz -@@ -976,15 +809,10 @@ - #define IWL_AP_ID 0 - #define IWL_AP_ID_PAN 1 - #define IWL_STA_ID 2 --#define IWL3945_BROADCAST_ID 24 --#define IWL3945_STATION_COUNT 25 --#define IWL4965_BROADCAST_ID 31 --#define IWL4965_STATION_COUNT 32 - #define IWLAGN_PAN_BCAST_ID 14 - #define IWLAGN_BROADCAST_ID 15 - #define IWLAGN_STATION_COUNT 16 - --#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ - #define IWL_INVALID_STATION 255 - - #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) -@@ -1032,16 +860,6 @@ - * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ - #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) - --struct iwl4965_keyinfo { -- __le16 key_flags; -- u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ -- u8 reserved1; -- __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ -- u8 key_offset; -- u8 reserved2; -- u8 key[16]; /* 16-byte unicast decryption key */ --} __packed; -- - /* agn */ - struct iwl_keyinfo { - __le16 key_flags; -@@ -1083,7 +901,6 @@ - * with info on security keys, aggregation parameters, and Tx rates for - * initial Tx attempt and any retries (agn devices uses - * REPLY_TX_LINK_QUALITY_CMD, -- * 3945 uses REPLY_RATE_SCALE to set up rate tables). - * - * REPLY_ADD_STA sets up the table entry for one station, either creating - * a new entry, or modifying a pre-existing one. -@@ -1103,72 +920,6 @@ - * entries for all STAs in network, starting with index IWL_STA_ID. - */ - --struct iwl3945_addsta_cmd { -- u8 mode; /* 1: modify existing, 0: add new station */ -- u8 reserved[3]; -- struct sta_id_modify sta; -- struct iwl4965_keyinfo key; -- __le32 station_flags; /* STA_FLG_* */ -- __le32 station_flags_msk; /* STA_FLG_* */ -- -- /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) -- * corresponding to bit (e.g. bit 5 controls TID 5). -- * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ -- __le16 tid_disable_tx; -- -- __le16 rate_n_flags; -- -- /* TID for which to add block-ack support. -- * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ -- u8 add_immediate_ba_tid; -- -- /* TID for which to remove block-ack support. -- * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ -- u8 remove_immediate_ba_tid; -- -- /* Starting Sequence Number for added block-ack support. -- * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ -- __le16 add_immediate_ba_ssn; --} __packed; -- --struct iwl4965_addsta_cmd { -- u8 mode; /* 1: modify existing, 0: add new station */ -- u8 reserved[3]; -- struct sta_id_modify sta; -- struct iwl4965_keyinfo key; -- __le32 station_flags; /* STA_FLG_* */ -- __le32 station_flags_msk; /* STA_FLG_* */ -- -- /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) -- * corresponding to bit (e.g. bit 5 controls TID 5). -- * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ -- __le16 tid_disable_tx; -- -- __le16 reserved1; -- -- /* TID for which to add block-ack support. -- * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ -- u8 add_immediate_ba_tid; -- -- /* TID for which to remove block-ack support. -- * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ -- u8 remove_immediate_ba_tid; -- -- /* Starting Sequence Number for added block-ack support. -- * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ -- __le16 add_immediate_ba_ssn; -- -- /* -- * Number of packets OK to transmit to station even though -- * it is asleep -- used to synchronise PS-poll and u-APSD -- * responses while ucode keeps track of STA sleep state. -- */ -- __le16 sleep_tx_count; -- -- __le16 reserved2; --} __packed; -- --/* agn */ - struct iwl_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; -@@ -1337,62 +1088,6 @@ - #define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) - - --struct iwl3945_rx_frame_stats { -- u8 phy_count; -- u8 id; -- u8 rssi; -- u8 agc; -- __le16 sig_avg; -- __le16 noise_diff; -- u8 payload[0]; --} __packed; -- --struct iwl3945_rx_frame_hdr { -- __le16 channel; -- __le16 phy_flags; -- u8 reserved1; -- u8 rate; -- __le16 len; -- u8 payload[0]; --} __packed; -- --struct iwl3945_rx_frame_end { -- __le32 status; -- __le64 timestamp; -- __le32 beacon_timestamp; --} __packed; -- --/* -- * REPLY_3945_RX = 0x1b (response only, not a command) -- * -- * NOTE: DO NOT dereference from casts to this structure -- * It is provided only for calculating minimum data set size. -- * The actual offsets of the hdr and end are dynamic based on -- * stats.phy_count -- */ --struct iwl3945_rx_frame { -- struct iwl3945_rx_frame_stats stats; -- struct iwl3945_rx_frame_hdr hdr; -- struct iwl3945_rx_frame_end end; --} __packed; -- --#define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) -- --/* Fixed (non-configurable) rx data from phy */ -- --#define IWL49_RX_RES_PHY_CNT 14 --#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) --#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) --#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ --#define IWL49_AGC_DB_POS (7) --struct iwl4965_rx_non_cfg_phy { -- __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ -- __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ -- u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ -- u8 pad[0]; --} __packed; -- -- - #define IWLAGN_RX_RES_PHY_CNT 8 - #define IWLAGN_RX_RES_AGC_IDX 1 - #define IWLAGN_RX_RES_RSSI_AB_IDX 2 -@@ -1576,80 +1271,6 @@ - * REPLY_TX = 0x1c (command) - */ - --struct iwl3945_tx_cmd { -- /* -- * MPDU byte count: -- * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, -- * + 8 byte IV for CCM or TKIP (not used for WEP) -- * + Data payload -- * + 8-byte MIC (not used for CCM/WEP) -- * NOTE: Does not include Tx command bytes, post-MAC pad bytes, -- * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i -- * Range: 14-2342 bytes. -- */ -- __le16 len; -- -- /* -- * MPDU or MSDU byte count for next frame. -- * Used for fragmentation and bursting, but not 11n aggregation. -- * Same as "len", but for next frame. Set to 0 if not applicable. -- */ -- __le16 next_frame_len; -- -- __le32 tx_flags; /* TX_CMD_FLG_* */ -- -- u8 rate; -- -- /* Index of recipient station in uCode's station table */ -- u8 sta_id; -- u8 tid_tspec; -- u8 sec_ctl; -- u8 key[16]; -- union { -- u8 byte[8]; -- __le16 word[4]; -- __le32 dw[2]; -- } tkip_mic; -- __le32 next_frame_info; -- union { -- __le32 life_time; -- __le32 attempt; -- } stop_time; -- u8 supp_rates[2]; -- u8 rts_retry_limit; /*byte 50 */ -- u8 data_retry_limit; /*byte 51 */ -- union { -- __le16 pm_frame_timeout; -- __le16 attempt_duration; -- } timeout; -- -- /* -- * Duration of EDCA burst Tx Opportunity, in 32-usec units. -- * Set this if txop time is not specified by HCCA protocol (e.g. by AP). -- */ -- __le16 driver_txop; -- -- /* -- * MAC header goes here, followed by 2 bytes padding if MAC header -- * length is 26 or 30 bytes, followed by payload data -- */ -- u8 payload[0]; -- struct ieee80211_hdr hdr[0]; --} __packed; -- --/* -- * REPLY_TX = 0x1c (response) -- */ --struct iwl3945_tx_resp { -- u8 failure_rts; -- u8 failure_frame; -- u8 bt_kill_count; -- u8 rate; -- __le32 wireless_media_time; -- __le32 status; /* TX status */ --} __packed; -- -- - /* - * 4965 uCode updates these Tx attempt count values in host DRAM. - * Used for managing Tx retries when expecting block-acks. -@@ -1740,54 +1361,6 @@ - struct ieee80211_hdr hdr[0]; - } __packed; - --/* TX command response is sent after *3945* transmission attempts. -- * -- * NOTES: -- * -- * TX_STATUS_FAIL_NEXT_FRAG -- * -- * If the fragment flag in the MAC header for the frame being transmitted -- * is set and there is insufficient time to transmit the next frame, the -- * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. -- * -- * TX_STATUS_FIFO_UNDERRUN -- * -- * Indicates the host did not provide bytes to the FIFO fast enough while -- * a TX was in progress. -- * -- * TX_STATUS_FAIL_MGMNT_ABORT -- * -- * This status is only possible if the ABORT ON MGMT RX parameter was -- * set to true with the TX command. -- * -- * If the MSB of the status parameter is set then an abort sequence is -- * required. This sequence consists of the host activating the TX Abort -- * control line, and then waiting for the TX Abort command response. This -- * indicates that a the device is no longer in a transmit state, and that the -- * command FIFO has been cleared. The host must then deactivate the TX Abort -- * control line. Receiving is still allowed in this case. -- */ --enum { -- TX_3945_STATUS_SUCCESS = 0x01, -- TX_3945_STATUS_DIRECT_DONE = 0x02, -- TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, -- TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, -- TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, -- TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, -- TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, -- TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, -- TX_3945_STATUS_FAIL_DEST_PS = 0x88, -- TX_3945_STATUS_FAIL_ABORTED = 0x89, -- TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, -- TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, -- TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, -- TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, -- TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, -- TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, -- TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, -- TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, --}; -- - /* - * TX command response is sent after *agn* transmission attempts. - * -@@ -1905,43 +1478,6 @@ - __le16 sequence; - } __packed; - --struct iwl4965_tx_resp { -- u8 frame_count; /* 1 no aggregation, >1 aggregation */ -- u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ -- u8 failure_rts; /* # failures due to unsuccessful RTS */ -- u8 failure_frame; /* # failures due to no ACK (unused for agg) */ -- -- /* For non-agg: Rate at which frame was successful. -- * For agg: Rate at which all frames were transmitted. */ -- __le32 rate_n_flags; /* RATE_MCS_* */ -- -- /* For non-agg: RTS + CTS + frame tx attempts time + ACK. -- * For agg: RTS + CTS + aggregation tx time + block-ack time. */ -- __le16 wireless_media_time; /* uSecs */ -- -- __le16 reserved; -- __le32 pa_power1; /* RF power amplifier measurement (not used) */ -- __le32 pa_power2; -- -- /* -- * For non-agg: frame status TX_STATUS_* -- * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status -- * fields follow this one, up to frame_count. -- * Bit fields: -- * 11- 0: AGG_TX_STATE_* status code -- * 15-12: Retry count for 1st frame in aggregation (retries -- * occur if tx failed for this frame when it was a -- * member of a previous aggregation block). If rate -- * scaling is used, retry count indicates the rate -- * table entry used for all frames in the new agg. -- * 31-16: Sequence # for this frame's Tx cmd (not SSN!) -- */ -- union { -- __le32 status; -- struct agg_tx_status agg_status[0]; /* for each agg frame */ -- } u; --} __packed; -- - /* - * definitions for initial rate index field - * bits [3:0] initial rate index -@@ -2030,51 +1566,7 @@ - /* - * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) - * -- * See details under "TXPOWER" in iwl-4965-hw.h. -- */ -- --struct iwl3945_txpowertable_cmd { -- u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ -- u8 reserved; -- __le16 channel; -- struct iwl3945_power_per_rate power[IWL_MAX_RATES]; --} __packed; -- --struct iwl4965_txpowertable_cmd { -- u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ -- u8 reserved; -- __le16 channel; -- struct iwl4965_tx_power_db tx_power; --} __packed; -- -- --/** -- * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response -- * -- * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) -- * -- * NOTE: The table of rates passed to the uCode via the -- * RATE_SCALE command sets up the corresponding order of -- * rates used for all related commands, including rate -- * masks, etc. -- * -- * For example, if you set 9MB (PLCP 0x0f) as the first -- * rate in the rate table, the bit mask for that rate -- * when passed through ofdm_basic_rates on the REPLY_RXON -- * command would be bit 0 (1 << 0) - */ --struct iwl3945_rate_scaling_info { -- __le16 rate_n_flags; -- u8 try_cnt; -- u8 next_rate_index; --} __packed; -- --struct iwl3945_rate_scaling_cmd { -- u8 table_id; -- u8 reserved[3]; -- struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; --} __packed; -- - - /*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ - #define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0) -@@ -2130,7 +1622,7 @@ - #define LINK_QUAL_AGG_DISABLE_START_MAX (255) - #define LINK_QUAL_AGG_DISABLE_START_MIN (0) - --#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31) -+#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63) - #define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) - #define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) - -@@ -2696,14 +2188,6 @@ - #define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) - #define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9)) - --struct iwl3945_powertable_cmd { -- __le16 flags; -- u8 reserved[2]; -- __le32 rx_data_timeout; -- __le32 tx_data_timeout; -- __le32 sleep_interval[IWL_POWER_VEC_SIZE]; --} __packed; -- - struct iwl_powertable_cmd { - __le16 flags; - u8 keep_alive_seconds; /* 3945 reserved */ -@@ -2806,25 +2290,6 @@ - * active_dwell < max_out_time - */ - --/* FIXME: rename to AP1, remove tpc */ --struct iwl3945_scan_channel { -- /* -- * type is defined as: -- * 0:0 1 = active, 0 = passive -- * 1:4 SSID direct bit map; if a bit is set, then corresponding -- * SSID IE is transmitted in probe request. -- * 5:7 reserved -- */ -- u8 type; -- u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ -- struct iwl3945_tx_power tpc; -- __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ -- __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ --} __packed; -- --/* set number of direct probes u8 type */ --#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) -- - struct iwl_scan_channel { - /* - * type is defined as: -@@ -2920,50 +2385,6 @@ - * struct iwl_scan_channel. - */ - --struct iwl3945_scan_cmd { -- __le16 len; -- u8 reserved0; -- u8 channel_count; /* # channels in channel list */ -- __le16 quiet_time; /* dwell only this # millisecs on quiet channel -- * (only for active scan) */ -- __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ -- __le16 good_CRC_th; /* passive -> active promotion threshold */ -- __le16 reserved1; -- __le32 max_out_time; /* max usec to be away from associated (service) -- * channel */ -- __le32 suspend_time; /* pause scan this long (in "extended beacon -- * format") when returning to service channel: -- * 3945; 31:24 # beacons, 19:0 additional usec, -- * 4965; 31:22 # beacons, 21:0 additional usec. -- */ -- __le32 flags; /* RXON_FLG_* */ -- __le32 filter_flags; /* RXON_FILTER_* */ -- -- /* For active scans (set to all-0s for passive scans). -- * Does not include payload. Must specify Tx rate; no rate scaling. */ -- struct iwl3945_tx_cmd tx_cmd; -- -- /* For directed active scans (set to all-0s otherwise) */ -- struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; -- -- /* -- * Probe request frame, followed by channel list. -- * -- * Size of probe request frame is specified by byte count in tx_cmd. -- * Channel list follows immediately after probe request frame. -- * Number of channels in list is specified by channel_count. -- * Each channel in list is of type: -- * -- * struct iwl3945_scan_channel channels[0]; -- * -- * NOTE: Only one band of channels can be scanned per pass. You -- * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait -- * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) -- * before requesting another scan. -- */ -- u8 data[0]; --} __packed; -- - enum iwl_scan_flags { - /* BIT(0) currently unused */ - IWL_SCAN_FLAGS_ACTION_FRAME_TX = BIT(1), -@@ -3090,20 +2511,6 @@ - * BEACON_NOTIFICATION = 0x90 (notification only, not a command) - */ - --struct iwl3945_beacon_notif { -- struct iwl3945_tx_resp beacon_notify_hdr; -- __le32 low_tsf; -- __le32 high_tsf; -- __le32 ibss_mgr_status; --} __packed; -- --struct iwl4965_beacon_notif { -- struct iwl4965_tx_resp beacon_notify_hdr; -- __le32 low_tsf; -- __le32 high_tsf; -- __le32 ibss_mgr_status; --} __packed; -- - struct iwlagn_beacon_notif { - struct iwlagn_tx_resp beacon_notify_hdr; - __le32 low_tsf; -@@ -3115,14 +2522,6 @@ - * REPLY_TX_BEACON = 0x91 (command, has simple generic response) - */ - --struct iwl3945_tx_beacon_cmd { -- struct iwl3945_tx_cmd tx; -- __le16 tim_idx; -- u8 tim_size; -- u8 reserved1; -- struct ieee80211_hdr frame[0]; /* beacon frame */ --} __packed; -- - struct iwl_tx_beacon_cmd { - struct iwl_tx_cmd tx; - __le16 tim_idx; -@@ -3159,53 +2558,6 @@ - - /* 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; -@@ -3213,23 +2565,6 @@ - __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; -@@ -3471,13 +2806,6 @@ - #define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) - #define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8) - --struct iwl3945_notif_statistics { -- __le32 flag; -- struct iwl39_statistics_rx rx; -- struct iwl39_statistics_tx tx; -- struct iwl39_statistics_general general; --} __packed; -- - struct iwl_notif_statistics { - __le32 flag; - struct statistics_rx rx; -@@ -4451,10 +3779,6 @@ - __le32 len_n_flags; - struct iwl_cmd_header hdr; - union { -- struct iwl3945_rx_frame rx_frame; -- struct iwl3945_tx_resp tx_resp; -- struct iwl3945_beacon_notif beacon_status; -- - struct iwl_alive_resp alive_frame; - struct iwl_spectrum_notification spectrum_notif; - struct iwl_csa_notification csa_notif; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-core.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-core.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-core.c 2011-05-05 23:29:45.359440341 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -41,6 +41,7 @@ - #include "iwl-power.h" - #include "iwl-sta.h" - #include "iwl-helpers.h" -+#include "iwl-agn.h" - - - /* -@@ -67,30 +68,6 @@ - - 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, -@@ -118,7 +95,7 @@ - max_bit_rate = MAX_BIT_RATE_40_MHZ; - } - -- if (priv->cfg->mod_params->amsdu_size_8K) -+ if (iwlagn_mod_params.amsdu_size_8K) - ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; - - ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; -@@ -159,6 +136,7 @@ - struct ieee80211_channel *geo_ch; - struct ieee80211_rate *rates; - int i = 0; -+ s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || - priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { -@@ -232,8 +210,8 @@ - - geo_ch->flags |= ch->ht40_extension_channel; - -- if (ch->max_power_avg > priv->tx_power_device_lmt) -- priv->tx_power_device_lmt = ch->max_power_avg; -+ if (ch->max_power_avg > max_tx_power) -+ max_tx_power = ch->max_power_avg; - } else { - geo_ch->flags |= IEEE80211_CHAN_DISABLED; - } -@@ -246,6 +224,10 @@ - geo_ch->flags); - } - -+ priv->tx_power_device_lmt = max_tx_power; -+ priv->tx_power_user_lmt = max_tx_power; -+ priv->tx_power_next = max_tx_power; -+ - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && - priv->cfg->sku & IWL_SKU_A) { - IWL_INFO(priv, "Incorrectly detected BG card as ABG. " -@@ -434,72 +416,72 @@ - int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - { - struct iwl_rxon_cmd *rxon = &ctx->staging; -- bool error = false; -+ u32 errors = 0; - - if (rxon->flags & RXON_FLG_BAND_24G_MSK) { - if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { - IWL_WARN(priv, "check 2.4G: wrong narrow\n"); -- error = true; -+ errors |= BIT(0); - } - if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { - IWL_WARN(priv, "check 2.4G: wrong radar\n"); -- error = true; -+ errors |= BIT(1); - } - } else { - if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { - IWL_WARN(priv, "check 5.2G: not short slot!\n"); -- error = true; -+ errors |= BIT(2); - } - if (rxon->flags & RXON_FLG_CCK_MSK) { - IWL_WARN(priv, "check 5.2G: CCK!\n"); -- error = true; -+ errors |= BIT(3); - } - } - if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { - IWL_WARN(priv, "mac/bssid mcast!\n"); -- error = true; -+ errors |= BIT(4); - } - - /* make sure basic rates 6Mbps and 1Mbps are supported */ - if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && - (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { - IWL_WARN(priv, "neither 1 nor 6 are basic\n"); -- error = true; -+ errors |= BIT(5); - } - - if (le16_to_cpu(rxon->assoc_id) > 2007) { - IWL_WARN(priv, "aid > 2007\n"); -- error = true; -+ errors |= BIT(6); - } - - if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { - IWL_WARN(priv, "CCK and short slot\n"); -- error = true; -+ errors |= BIT(7); - } - - if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { - IWL_WARN(priv, "CCK and auto detect"); -- error = true; -+ errors |= BIT(8); - } - - if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | - RXON_FLG_TGG_PROTECT_MSK)) == - RXON_FLG_TGG_PROTECT_MSK) { - IWL_WARN(priv, "TGg but no auto-detect\n"); -- error = true; -+ errors |= BIT(9); - } - -- if (error) -- IWL_WARN(priv, "Tuning to channel %d\n", -- le16_to_cpu(rxon->channel)); -- -- if (error) { -- IWL_ERR(priv, "Invalid RXON\n"); -- return -EINVAL; -+ if (rxon->channel == 0) { -+ IWL_WARN(priv, "zero channel is invalid\n"); -+ errors |= BIT(10); - } -- return 0; -+ -+ WARN(errors, "Invalid RXON (%#x), channel %d", -+ errors, le16_to_cpu(rxon->channel)); -+ -+ return errors ? -EINVAL : 0; - } - - /** -@@ -890,10 +872,21 @@ - IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); - } - #endif --/** -- * iwl_irq_handle_error - called for HW or SW error interrupt from card -- */ --void iwl_irq_handle_error(struct iwl_priv *priv) -+ -+static void iwlagn_abort_notification_waits(struct iwl_priv *priv) -+{ -+ unsigned long flags; -+ struct iwl_notification_wait *wait_entry; -+ -+ spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags); -+ list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list) -+ wait_entry->aborted = true; -+ spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags); -+ -+ wake_up_all(&priv->_agn.notif_waitq); -+} -+ -+void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) - { - unsigned int reload_msec; - unsigned long reload_jiffies; -@@ -904,18 +897,64 @@ - /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - -+ iwlagn_abort_notification_waits(priv); -+ -+ /* Keep the restart process from trying to send host -+ * commands by clearing the ready bit */ -+ clear_bit(STATUS_READY, &priv->status); -+ -+ wake_up_interruptible(&priv->wait_command_queue); -+ -+ if (!ondemand) { -+ /* -+ * If firmware keep reloading, then it indicate something -+ * serious wrong and firmware having problem to recover -+ * from it. Instead of keep trying which will fill the syslog -+ * and hang the system, let's just stop it -+ */ -+ reload_jiffies = jiffies; -+ reload_msec = jiffies_to_msecs((long) reload_jiffies - -+ (long) priv->reload_jiffies); -+ priv->reload_jiffies = reload_jiffies; -+ if (reload_msec <= IWL_MIN_RELOAD_DURATION) { -+ priv->reload_count++; -+ if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { -+ IWL_ERR(priv, "BUG_ON, Stop restarting\n"); -+ return; -+ } -+ } else -+ priv->reload_count = 0; -+ } -+ -+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { -+ if (iwlagn_mod_params.restart_fw) { -+ IWL_DEBUG(priv, IWL_DL_FW_ERRORS, -+ "Restarting adapter due to uCode error.\n"); -+ queue_work(priv->workqueue, &priv->restart); -+ } else -+ IWL_DEBUG(priv, IWL_DL_FW_ERRORS, -+ "Detected FW error, but not restarting\n"); -+ } -+} -+ -+/** -+ * iwl_irq_handle_error - called for HW or SW error interrupt from card -+ */ -+void iwl_irq_handle_error(struct iwl_priv *priv) -+{ - /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ - if (priv->cfg->internal_wimax_coex && - (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & - APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(priv, APMG_PS_CTRL_REG) & - APMG_PS_CTRL_VAL_RESET_REQ))) { -- wake_up_interruptible(&priv->wait_command_queue); - /* -- *Keep the restart process from trying to send host -- * commands by clearing the INIT status bit -+ * Keep the restart process from trying to send host -+ * commands by clearing the ready bit. - */ - clear_bit(STATUS_READY, &priv->status); -+ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); -+ wake_up_interruptible(&priv->wait_command_queue); - IWL_ERR(priv, "RF is used by WiMAX\n"); - return; - } -@@ -923,50 +962,17 @@ - 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, - &priv->contexts[IWL_RXON_CTX_BSS]); - #endif - -- wake_up_interruptible(&priv->wait_command_queue); -- -- /* Keep the restart process from trying to send host -- * commands by clearing the INIT status bit */ -- clear_bit(STATUS_READY, &priv->status); -- -- /* -- * If firmware keep reloading, then it indicate something -- * serious wrong and firmware having problem to recover -- * from it. Instead of keep trying which will fill the syslog -- * and hang the system, let's just stop it -- */ -- reload_jiffies = jiffies; -- reload_msec = jiffies_to_msecs((long) reload_jiffies - -- (long) priv->reload_jiffies); -- priv->reload_jiffies = reload_jiffies; -- if (reload_msec <= IWL_MIN_RELOAD_DURATION) { -- priv->reload_count++; -- if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { -- IWL_ERR(priv, "BUG_ON, Stop restarting\n"); -- return; -- } -- } else -- priv->reload_count = 0; -- -- if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { -- IWL_DEBUG(priv, IWL_DL_FW_ERRORS, -- "Restarting adapter due to uCode error.\n"); -- -- if (priv->cfg->mod_params->restart_fw) -- queue_work(priv->workqueue, &priv->restart); -- } -+ iwlagn_fw_error(priv, false); - } - - static int iwl_apm_stop_master(struct iwl_priv *priv) -@@ -990,6 +996,8 @@ - { - IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - -+ clear_bit(STATUS_DEVICE_ENABLED, &priv->status); -+ - /* Stop device's DMA activity */ - iwl_apm_stop_master(priv); - -@@ -1040,7 +1048,6 @@ - /* - * 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); -@@ -1053,20 +1060,18 @@ - * 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 */ -@@ -1094,27 +1099,21 @@ - } - - /* -- * Enable DMA and BSM (if used) clocks, wait for them to stabilize. -- * BSM (Boostrap State Machine) is only in 3945 and 4965; -- * later devices (i.e. 5000 and later) have non-volatile SRAM, -- * and don't need BSM to restore data after power-saving sleep. -+ * Enable DMA clock and wait for it to stabilize. - * - * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits - * do not disable clocks. This preserves any hardware bits already - * set by default in "CLK_CTRL_REG" after reset. - */ -- if (priv->cfg->base_params->use_bsm) -- iwl_write_prph(priv, APMG_CLK_EN_REG, -- APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); -- else -- iwl_write_prph(priv, APMG_CLK_EN_REG, -- APMG_CLK_VAL_DMA_CLK_RQT); -+ iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); - udelay(20); - - /* Disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - -+ set_bit(STATUS_DEVICE_ENABLED, &priv->status); -+ - out: - return ret; - } -@@ -1430,7 +1429,6 @@ - - iwl_teardown_interface(priv, vif, false); - -- memset(priv->bssid, 0, ETH_ALEN); - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -@@ -1750,21 +1748,13 @@ - * detect failure), then fw_restart module parameter - * need to be check before performing firmware reload - */ -- if (!external && !priv->cfg->mod_params->restart_fw) { -+ if (!external && !iwlagn_mod_params.restart_fw) { - IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " - "module parameter setting\n"); - break; - } - IWL_ERR(priv, "On demand firmware reload\n"); -- /* Set the FW error flag -- cleared on iwl_down */ -- set_bit(STATUS_FW_ERROR, &priv->status); -- wake_up_interruptible(&priv->wait_command_queue); -- /* -- * Keep the restart process from trying to send host -- * commands by clearing the INIT status bit -- */ -- clear_bit(STATUS_READY, &priv->status); -- queue_work(priv->workqueue, &priv->restart); -+ iwlagn_fw_error(priv, true); - break; - } - return 0; -@@ -1775,6 +1765,7 @@ - { - struct iwl_priv *priv = hw->priv; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); -+ struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl_rxon_context *tmp; - u32 interface_modes; - int err; -@@ -1783,6 +1774,15 @@ - - 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))) { -@@ -1790,6 +1790,19 @@ - goto out; - } - -+ /* -+ * Refuse a change that should be done by moving from the PAN -+ * context to the BSS context instead, if the BSS context is -+ * available and can support the new interface type. -+ */ -+ if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif && -+ (bss_ctx->interface_modes & BIT(newtype) || -+ bss_ctx->exclusive_interface_modes & BIT(newtype))) { -+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); -+ err = -EBUSY; -+ goto out; -+ } -+ - if (ctx->exclusive_interface_modes & BIT(newtype)) { - for_each_context(priv, tmp) { - if (ctx == tmp) -@@ -1810,6 +1823,7 @@ - /* success */ - iwl_teardown_interface(priv, vif, true); - vif->type = newtype; -+ vif->p2p = newp2p; - err = iwl_setup_interface(priv, ctx); - WARN_ON(err); - /* -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-core.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-core.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-core.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-core.h 2011-05-05 23:29:45.416441031 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -73,7 +73,7 @@ - - - #define IWLWIFI_VERSION "in-tree:" --#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" -+#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" - #define DRV_AUTHOR "" - - #define IWL_PCI_DEVICE(dev, subdev, cfg) \ -@@ -90,7 +90,6 @@ - #define IWL_CMD(x) case x: return #x - - struct iwl_hcmd_ops { -- int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); - int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); - void (*set_rxon_chain)(struct iwl_priv *priv, - struct iwl_rxon_context *ctx); -@@ -122,37 +121,10 @@ - void (*config)(struct iwl_priv *priv); - }; - --struct iwl_isr_ops { -- irqreturn_t (*isr) (int irq, void *data); -- void (*free)(struct iwl_priv *priv); -- int (*alloc)(struct iwl_priv *priv); -- int (*reset)(struct iwl_priv *priv); -- void (*disable)(struct iwl_priv *priv); --}; -- --struct iwl_debugfs_ops { -- ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); -- ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); -- ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); -- ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); -- ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos); --}; -- - 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,30 +143,14 @@ - struct iwl_tx_queue *txq); - int (*txq_init)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -- /* aggregations */ -- int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, -- int sta_id, int tid, u16 ssn_idx); -- int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, -- u8 tx_fifo); - /* setup Rx handler */ - void (*rx_handler_setup)(struct iwl_priv *priv); - /* setup deferred work */ - void (*setup_deferred_work)(struct iwl_priv *priv); - /* cancel deferred work */ - void (*cancel_deferred_work)(struct iwl_priv *priv); -- /* alive notification after init uCode load */ -- void (*init_alive_start)(struct iwl_priv *priv); -- /* alive notification */ -- int (*alive_notify)(struct iwl_priv *priv); - /* check validity of rtc data address */ - int (*is_valid_rtc_data_addr)(u32 addr); -- /* 1st ucode load */ -- int (*load_ucode)(struct iwl_priv *priv); -- 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 */ -@@ -204,9 +160,6 @@ - int (*send_tx_power) (struct iwl_priv *priv); - void (*update_chain_flags)(struct iwl_priv *priv); - -- /* isr */ -- struct iwl_isr_ops isr_ops; -- - /* eeprom operations (as defined in iwl-eeprom.h) */ - struct iwl_eeprom_ops eeprom_ops; - -@@ -216,14 +169,6 @@ - int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control); - 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 */ -@@ -231,28 +176,15 @@ - 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 { - int sw_crypto; /* def: 0 = using hardware encryption */ -- int disable_hw_scan; /* def: 0 = use h/w scan */ - int num_of_queues; /* def: HW dependent */ - int disable_11n; /* def: 0 = 11n capabilities enabled */ - int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ -@@ -278,16 +210,7 @@ - * @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 -- * @no_agg_framecnt_info: uCode do not provide aggregation frame count -- * information - */ - struct iwl_base_params { - int eeprom_size; -@@ -295,14 +218,10 @@ - int num_of_ampdu_queues;/* def: HW dependent */ - /* for iwl_apm_init() */ - u32 pll_cfg_val; -- bool set_l0s; -- bool use_bsm; - -- bool use_isr_legacy; - 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; -@@ -312,18 +231,12 @@ - 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; -- const bool no_agg_framecnt_info; - }; - /* - * @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 -@@ -333,7 +246,6 @@ - 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; -@@ -364,6 +276,7 @@ - * @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 -@@ -398,8 +311,6 @@ - u16 eeprom_ver; - u16 eeprom_calib_ver; - const struct iwl_ops *ops; -- /* module based parameters which can be set from modprobe cmd */ -- const struct iwl_mod_params *mod_params; - /* params not likely to change within a device family */ - struct iwl_base_params *base_params; - /* params likely to change within a device family */ -@@ -414,13 +325,13 @@ - 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); -@@ -625,6 +536,8 @@ - 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); -@@ -662,6 +575,7 @@ - #define STATUS_SCAN_HW 15 - #define STATUS_POWER_PMI 16 - #define STATUS_FW_ERROR 17 -+#define STATUS_DEVICE_ENABLED 18 - - - static inline int iwl_is_ready(struct iwl_priv *priv) -@@ -714,11 +628,6 @@ - int iwl_apm_init(struct iwl_priv *priv); - - int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); --static inline int iwl_send_rxon_assoc(struct iwl_priv *priv, -- struct iwl_rxon_context *ctx) --{ -- return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx); --} - static inline int iwlcore_commit_rxon(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) - { -@@ -736,12 +645,10 @@ - priv->cfg->bt_params->advanced_bt_coexist; - } - --static inline bool iwl_bt_statistics(struct iwl_priv *priv) --{ -- return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics; --} -- - extern bool bt_coex_active; - extern bool bt_siso_mode; - -+ -+void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); -+ - #endif /* __iwl_core_h__ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-csr.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-csr.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-csr.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-csr.h 2011-05-05 23:29:45.282439411 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 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 -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -155,18 +155,10 @@ - #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) - - /* Bits for CSR_HW_IF_CONFIG_REG */ --#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) - #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) - #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) - #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) - --#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) --#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) --#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) --#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) --#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) --#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) -- - #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) - #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) - #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ -@@ -186,7 +178,7 @@ - #define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ - #define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ - #define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ --#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ -+#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */ - #define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ - #define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ - -@@ -202,29 +194,17 @@ - /* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ - #define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ - #define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ --#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ - #define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ - #define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ --#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ - #define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ - #define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ - --#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ -- CSR39_FH_INT_BIT_RX_CHNL2 | \ -- CSR_FH_INT_BIT_RX_CHNL1 | \ -- CSR_FH_INT_BIT_RX_CHNL0) -- -- --#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ -- CSR_FH_INT_BIT_TX_CHNL1 | \ -- CSR_FH_INT_BIT_TX_CHNL0) -- --#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ -- CSR_FH_INT_BIT_RX_CHNL1 | \ -- CSR_FH_INT_BIT_RX_CHNL0) -+#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ -+ CSR_FH_INT_BIT_RX_CHNL1 | \ -+ CSR_FH_INT_BIT_RX_CHNL0) - --#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ -- CSR_FH_INT_BIT_TX_CHNL0) -+#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ -+ CSR_FH_INT_BIT_TX_CHNL0) - - /* GPIO */ - #define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) -@@ -268,7 +248,7 @@ - * Indicates MAC (ucode processor, etc.) is powered up and can run. - * Internal resources are accessible. - * NOTE: This does not indicate that the processor is actually running. -- * NOTE: This does not indicate that 4965 or 3945 has completed -+ * NOTE: This does not indicate that device has completed - * init or post-power-down restore of internal SRAM memory. - * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that - * SRAM is restored and uCode is in normal operation mode. -@@ -291,8 +271,6 @@ - - /* HW REV */ - #define CSR_HW_REV_TYPE_MSK (0x00001F0) --#define CSR_HW_REV_TYPE_3945 (0x00000D0) --#define CSR_HW_REV_TYPE_4965 (0x0000000) - #define CSR_HW_REV_TYPE_5300 (0x0000020) - #define CSR_HW_REV_TYPE_5350 (0x0000030) - #define CSR_HW_REV_TYPE_5100 (0x0000050) -@@ -363,7 +341,7 @@ - * 0: MAC_SLEEP - * uCode sets this when preparing a power-saving power-down. - * uCode resets this when power-up is complete and SRAM is sane. -- * NOTE: 3945/4965 saves internal SRAM data to host when powering down, -+ * NOTE: device saves internal SRAM data to host when powering down, - * and must restore this data after powering back up. - * MAC_SLEEP is the best indication that restore is complete. - * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and -@@ -394,7 +372,6 @@ - #define CSR_LED_REG_TRUN_OFF (0x38) - - /* ANA_PLL */ --#define CSR39_ANA_PLL_CFG_VAL (0x01000000) - #define CSR50_ANA_PLL_CFG_VAL (0x00880300) - - /* HPET MEM debug */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-debugfs.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2011-05-05 23:29:45.388440693 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -39,6 +39,7 @@ - #include "iwl-debug.h" - #include "iwl-core.h" - #include "iwl-io.h" -+#include "iwl-agn.h" - - /* create and remove of files */ - #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ -@@ -226,10 +227,10 @@ - /* default is to dump the entire data segment */ - if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { - priv->dbgfs_sram_offset = 0x800000; -- if (priv->ucode_type == UCODE_INIT) -- priv->dbgfs_sram_len = priv->ucode_init_data.len; -+ if (priv->ucode_type == UCODE_SUBTYPE_INIT) -+ priv->dbgfs_sram_len = priv->ucode_init.data.len; - else -- priv->dbgfs_sram_len = priv->ucode_data.len; -+ priv->dbgfs_sram_len = priv->ucode_rt.data.len; - } - len = priv->dbgfs_sram_len; - -@@ -437,8 +438,7 @@ - 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 +462,7 @@ - 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; - } -@@ -1039,13 +1038,463 @@ - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); - } - -+static const char *fmt_value = " %-30s %10u\n"; -+static const char *fmt_hex = " %-30s 0x%02X\n"; -+static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; -+static const char *fmt_header = -+ "%-32s current cumulative delta max\n"; -+ -+static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) -+{ -+ int p = 0; -+ u32 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) -+ p += scnprintf(buf + p, bufsz - p, -+ "\tStatistics have been cleared\n"); -+ p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", -+ (flag & UCODE_STATISTICS_FREQUENCY_MSK) -+ ? "2.4 GHz" : "5.2 GHz"); -+ p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", -+ (flag & UCODE_STATISTICS_NARROW_BAND_MSK) -+ ? "enabled" : "disabled"); -+ -+ return p; -+} -+ - static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) - { - struct iwl_priv *priv = file->private_data; -- return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, -- user_buf, count, ppos); -+ int pos = 0; -+ char *buf; -+ int bufsz = sizeof(struct statistics_rx_phy) * 40 + -+ sizeof(struct statistics_rx_non_phy) * 40 + -+ sizeof(struct statistics_rx_ht_phy) * 40 + 400; -+ ssize_t ret; -+ struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; -+ struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; -+ struct statistics_rx_non_phy *general, *accum_general; -+ struct statistics_rx_non_phy *delta_general, *max_general; -+ struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; -+ -+ if (!iwl_is_alive(priv)) -+ return -EAGAIN; -+ -+ buf = kzalloc(bufsz, GFP_KERNEL); -+ if (!buf) { -+ IWL_ERR(priv, "Can not allocate Buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* -+ * the statistic information display here is based on -+ * the last statistics notification from uCode -+ * might not reflect the current uCode activity -+ */ -+ 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, -+ fmt_header, "Statistics_Rx - OFDM:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "ina_cnt:", -+ le32_to_cpu(ofdm->ina_cnt), -+ accum_ofdm->ina_cnt, -+ delta_ofdm->ina_cnt, max_ofdm->ina_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_cnt:", -+ le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, -+ delta_ofdm->fina_cnt, max_ofdm->fina_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "plcp_err:", -+ le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, -+ delta_ofdm->plcp_err, max_ofdm->plcp_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_err:", -+ le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, -+ delta_ofdm->crc32_err, max_ofdm->crc32_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "overrun_err:", -+ le32_to_cpu(ofdm->overrun_err), -+ accum_ofdm->overrun_err, delta_ofdm->overrun_err, -+ max_ofdm->overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "early_overrun_err:", -+ le32_to_cpu(ofdm->early_overrun_err), -+ accum_ofdm->early_overrun_err, -+ delta_ofdm->early_overrun_err, -+ max_ofdm->early_overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_good:", -+ le32_to_cpu(ofdm->crc32_good), -+ accum_ofdm->crc32_good, delta_ofdm->crc32_good, -+ max_ofdm->crc32_good); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "false_alarm_cnt:", -+ le32_to_cpu(ofdm->false_alarm_cnt), -+ accum_ofdm->false_alarm_cnt, -+ delta_ofdm->false_alarm_cnt, -+ max_ofdm->false_alarm_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_sync_err_cnt:", -+ le32_to_cpu(ofdm->fina_sync_err_cnt), -+ accum_ofdm->fina_sync_err_cnt, -+ delta_ofdm->fina_sync_err_cnt, -+ max_ofdm->fina_sync_err_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sfd_timeout:", -+ le32_to_cpu(ofdm->sfd_timeout), -+ accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, -+ max_ofdm->sfd_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_timeout:", -+ le32_to_cpu(ofdm->fina_timeout), -+ accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, -+ max_ofdm->fina_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "unresponded_rts:", -+ le32_to_cpu(ofdm->unresponded_rts), -+ accum_ofdm->unresponded_rts, -+ delta_ofdm->unresponded_rts, -+ max_ofdm->unresponded_rts); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "rxe_frame_lmt_ovrun:", -+ le32_to_cpu(ofdm->rxe_frame_limit_overrun), -+ accum_ofdm->rxe_frame_limit_overrun, -+ delta_ofdm->rxe_frame_limit_overrun, -+ max_ofdm->rxe_frame_limit_overrun); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_ack_cnt:", -+ le32_to_cpu(ofdm->sent_ack_cnt), -+ accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, -+ max_ofdm->sent_ack_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_cts_cnt:", -+ le32_to_cpu(ofdm->sent_cts_cnt), -+ accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, -+ max_ofdm->sent_cts_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_ba_rsp_cnt:", -+ le32_to_cpu(ofdm->sent_ba_rsp_cnt), -+ accum_ofdm->sent_ba_rsp_cnt, -+ delta_ofdm->sent_ba_rsp_cnt, -+ max_ofdm->sent_ba_rsp_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "dsp_self_kill:", -+ le32_to_cpu(ofdm->dsp_self_kill), -+ accum_ofdm->dsp_self_kill, -+ delta_ofdm->dsp_self_kill, -+ max_ofdm->dsp_self_kill); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "mh_format_err:", -+ le32_to_cpu(ofdm->mh_format_err), -+ accum_ofdm->mh_format_err, -+ delta_ofdm->mh_format_err, -+ max_ofdm->mh_format_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "re_acq_main_rssi_sum:", -+ le32_to_cpu(ofdm->re_acq_main_rssi_sum), -+ accum_ofdm->re_acq_main_rssi_sum, -+ delta_ofdm->re_acq_main_rssi_sum, -+ max_ofdm->re_acq_main_rssi_sum); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_header, "Statistics_Rx - CCK:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "ina_cnt:", -+ le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, -+ delta_cck->ina_cnt, max_cck->ina_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_cnt:", -+ le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, -+ delta_cck->fina_cnt, max_cck->fina_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "plcp_err:", -+ le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, -+ delta_cck->plcp_err, max_cck->plcp_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_err:", -+ le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, -+ delta_cck->crc32_err, max_cck->crc32_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "overrun_err:", -+ le32_to_cpu(cck->overrun_err), -+ accum_cck->overrun_err, delta_cck->overrun_err, -+ max_cck->overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "early_overrun_err:", -+ le32_to_cpu(cck->early_overrun_err), -+ accum_cck->early_overrun_err, -+ delta_cck->early_overrun_err, -+ max_cck->early_overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_good:", -+ le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, -+ delta_cck->crc32_good, max_cck->crc32_good); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "false_alarm_cnt:", -+ le32_to_cpu(cck->false_alarm_cnt), -+ accum_cck->false_alarm_cnt, -+ delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_sync_err_cnt:", -+ le32_to_cpu(cck->fina_sync_err_cnt), -+ accum_cck->fina_sync_err_cnt, -+ delta_cck->fina_sync_err_cnt, -+ max_cck->fina_sync_err_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sfd_timeout:", -+ le32_to_cpu(cck->sfd_timeout), -+ accum_cck->sfd_timeout, delta_cck->sfd_timeout, -+ max_cck->sfd_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "fina_timeout:", -+ le32_to_cpu(cck->fina_timeout), -+ accum_cck->fina_timeout, delta_cck->fina_timeout, -+ max_cck->fina_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "unresponded_rts:", -+ le32_to_cpu(cck->unresponded_rts), -+ accum_cck->unresponded_rts, delta_cck->unresponded_rts, -+ max_cck->unresponded_rts); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "rxe_frame_lmt_ovrun:", -+ le32_to_cpu(cck->rxe_frame_limit_overrun), -+ accum_cck->rxe_frame_limit_overrun, -+ delta_cck->rxe_frame_limit_overrun, -+ max_cck->rxe_frame_limit_overrun); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_ack_cnt:", -+ le32_to_cpu(cck->sent_ack_cnt), -+ accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, -+ max_cck->sent_ack_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_cts_cnt:", -+ le32_to_cpu(cck->sent_cts_cnt), -+ accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, -+ max_cck->sent_cts_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sent_ba_rsp_cnt:", -+ le32_to_cpu(cck->sent_ba_rsp_cnt), -+ accum_cck->sent_ba_rsp_cnt, -+ delta_cck->sent_ba_rsp_cnt, -+ max_cck->sent_ba_rsp_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "dsp_self_kill:", -+ le32_to_cpu(cck->dsp_self_kill), -+ accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, -+ max_cck->dsp_self_kill); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "mh_format_err:", -+ le32_to_cpu(cck->mh_format_err), -+ accum_cck->mh_format_err, delta_cck->mh_format_err, -+ max_cck->mh_format_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "re_acq_main_rssi_sum:", -+ le32_to_cpu(cck->re_acq_main_rssi_sum), -+ accum_cck->re_acq_main_rssi_sum, -+ delta_cck->re_acq_main_rssi_sum, -+ max_cck->re_acq_main_rssi_sum); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_header, "Statistics_Rx - GENERAL:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "bogus_cts:", -+ le32_to_cpu(general->bogus_cts), -+ accum_general->bogus_cts, delta_general->bogus_cts, -+ max_general->bogus_cts); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "bogus_ack:", -+ le32_to_cpu(general->bogus_ack), -+ accum_general->bogus_ack, delta_general->bogus_ack, -+ max_general->bogus_ack); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "non_bssid_frames:", -+ le32_to_cpu(general->non_bssid_frames), -+ accum_general->non_bssid_frames, -+ delta_general->non_bssid_frames, -+ max_general->non_bssid_frames); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "filtered_frames:", -+ le32_to_cpu(general->filtered_frames), -+ accum_general->filtered_frames, -+ delta_general->filtered_frames, -+ max_general->filtered_frames); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "non_channel_beacons:", -+ le32_to_cpu(general->non_channel_beacons), -+ accum_general->non_channel_beacons, -+ delta_general->non_channel_beacons, -+ max_general->non_channel_beacons); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "channel_beacons:", -+ le32_to_cpu(general->channel_beacons), -+ accum_general->channel_beacons, -+ delta_general->channel_beacons, -+ max_general->channel_beacons); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "num_missed_bcon:", -+ le32_to_cpu(general->num_missed_bcon), -+ accum_general->num_missed_bcon, -+ delta_general->num_missed_bcon, -+ max_general->num_missed_bcon); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "adc_rx_saturation_time:", -+ le32_to_cpu(general->adc_rx_saturation_time), -+ accum_general->adc_rx_saturation_time, -+ delta_general->adc_rx_saturation_time, -+ max_general->adc_rx_saturation_time); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "ina_detect_search_tm:", -+ le32_to_cpu(general->ina_detection_search_time), -+ accum_general->ina_detection_search_time, -+ delta_general->ina_detection_search_time, -+ max_general->ina_detection_search_time); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_silence_rssi_a:", -+ le32_to_cpu(general->beacon_silence_rssi_a), -+ accum_general->beacon_silence_rssi_a, -+ delta_general->beacon_silence_rssi_a, -+ max_general->beacon_silence_rssi_a); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_silence_rssi_b:", -+ le32_to_cpu(general->beacon_silence_rssi_b), -+ accum_general->beacon_silence_rssi_b, -+ delta_general->beacon_silence_rssi_b, -+ max_general->beacon_silence_rssi_b); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_silence_rssi_c:", -+ le32_to_cpu(general->beacon_silence_rssi_c), -+ accum_general->beacon_silence_rssi_c, -+ delta_general->beacon_silence_rssi_c, -+ max_general->beacon_silence_rssi_c); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "interference_data_flag:", -+ le32_to_cpu(general->interference_data_flag), -+ accum_general->interference_data_flag, -+ delta_general->interference_data_flag, -+ max_general->interference_data_flag); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "channel_load:", -+ le32_to_cpu(general->channel_load), -+ accum_general->channel_load, -+ delta_general->channel_load, -+ max_general->channel_load); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "dsp_false_alarms:", -+ le32_to_cpu(general->dsp_false_alarms), -+ accum_general->dsp_false_alarms, -+ delta_general->dsp_false_alarms, -+ max_general->dsp_false_alarms); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_rssi_a:", -+ le32_to_cpu(general->beacon_rssi_a), -+ accum_general->beacon_rssi_a, -+ delta_general->beacon_rssi_a, -+ max_general->beacon_rssi_a); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_rssi_b:", -+ le32_to_cpu(general->beacon_rssi_b), -+ accum_general->beacon_rssi_b, -+ delta_general->beacon_rssi_b, -+ max_general->beacon_rssi_b); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_rssi_c:", -+ le32_to_cpu(general->beacon_rssi_c), -+ accum_general->beacon_rssi_c, -+ delta_general->beacon_rssi_c, -+ max_general->beacon_rssi_c); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_energy_a:", -+ le32_to_cpu(general->beacon_energy_a), -+ accum_general->beacon_energy_a, -+ delta_general->beacon_energy_a, -+ max_general->beacon_energy_a); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_energy_b:", -+ le32_to_cpu(general->beacon_energy_b), -+ accum_general->beacon_energy_b, -+ delta_general->beacon_energy_b, -+ max_general->beacon_energy_b); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "beacon_energy_c:", -+ le32_to_cpu(general->beacon_energy_c), -+ accum_general->beacon_energy_c, -+ delta_general->beacon_energy_c, -+ max_general->beacon_energy_c); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_header, "Statistics_Rx - OFDM_HT:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "plcp_err:", -+ le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, -+ delta_ht->plcp_err, max_ht->plcp_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "overrun_err:", -+ le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, -+ delta_ht->overrun_err, max_ht->overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "early_overrun_err:", -+ le32_to_cpu(ht->early_overrun_err), -+ accum_ht->early_overrun_err, -+ delta_ht->early_overrun_err, -+ max_ht->early_overrun_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_good:", -+ le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, -+ delta_ht->crc32_good, max_ht->crc32_good); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "crc32_err:", -+ le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, -+ delta_ht->crc32_err, max_ht->crc32_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "mh_format_err:", -+ le32_to_cpu(ht->mh_format_err), -+ accum_ht->mh_format_err, -+ delta_ht->mh_format_err, max_ht->mh_format_err); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg_crc32_good:", -+ le32_to_cpu(ht->agg_crc32_good), -+ accum_ht->agg_crc32_good, -+ delta_ht->agg_crc32_good, max_ht->agg_crc32_good); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg_mpdu_cnt:", -+ le32_to_cpu(ht->agg_mpdu_cnt), -+ accum_ht->agg_mpdu_cnt, -+ delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg_cnt:", -+ le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, -+ delta_ht->agg_cnt, max_ht->agg_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "unsupport_mcs:", -+ le32_to_cpu(ht->unsupport_mcs), -+ accum_ht->unsupport_mcs, -+ delta_ht->unsupport_mcs, max_ht->unsupport_mcs); -+ -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -+ kfree(buf); -+ return ret; - } - - static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, -@@ -1053,8 +1502,190 @@ - size_t count, loff_t *ppos) - { - struct iwl_priv *priv = file->private_data; -- return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, -- user_buf, count, ppos); -+ int pos = 0; -+ char *buf; -+ int bufsz = (sizeof(struct statistics_tx) * 48) + 250; -+ ssize_t ret; -+ struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; -+ -+ if (!iwl_is_alive(priv)) -+ return -EAGAIN; -+ -+ buf = kzalloc(bufsz, GFP_KERNEL); -+ if (!buf) { -+ IWL_ERR(priv, "Can not allocate Buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* the statistic information display here is based on -+ * 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, -+ fmt_header, "Statistics_Tx:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "preamble:", -+ le32_to_cpu(tx->preamble_cnt), -+ accum_tx->preamble_cnt, -+ delta_tx->preamble_cnt, max_tx->preamble_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "rx_detected_cnt:", -+ le32_to_cpu(tx->rx_detected_cnt), -+ accum_tx->rx_detected_cnt, -+ delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "bt_prio_defer_cnt:", -+ le32_to_cpu(tx->bt_prio_defer_cnt), -+ accum_tx->bt_prio_defer_cnt, -+ delta_tx->bt_prio_defer_cnt, -+ max_tx->bt_prio_defer_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "bt_prio_kill_cnt:", -+ le32_to_cpu(tx->bt_prio_kill_cnt), -+ accum_tx->bt_prio_kill_cnt, -+ delta_tx->bt_prio_kill_cnt, -+ max_tx->bt_prio_kill_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "few_bytes_cnt:", -+ le32_to_cpu(tx->few_bytes_cnt), -+ accum_tx->few_bytes_cnt, -+ delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "cts_timeout:", -+ le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, -+ delta_tx->cts_timeout, max_tx->cts_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "ack_timeout:", -+ le32_to_cpu(tx->ack_timeout), -+ accum_tx->ack_timeout, -+ delta_tx->ack_timeout, max_tx->ack_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "expected_ack_cnt:", -+ le32_to_cpu(tx->expected_ack_cnt), -+ accum_tx->expected_ack_cnt, -+ delta_tx->expected_ack_cnt, -+ max_tx->expected_ack_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "actual_ack_cnt:", -+ le32_to_cpu(tx->actual_ack_cnt), -+ accum_tx->actual_ack_cnt, -+ delta_tx->actual_ack_cnt, -+ max_tx->actual_ack_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "dump_msdu_cnt:", -+ le32_to_cpu(tx->dump_msdu_cnt), -+ accum_tx->dump_msdu_cnt, -+ delta_tx->dump_msdu_cnt, -+ max_tx->dump_msdu_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "abort_nxt_frame_mismatch:", -+ le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), -+ accum_tx->burst_abort_next_frame_mismatch_cnt, -+ delta_tx->burst_abort_next_frame_mismatch_cnt, -+ max_tx->burst_abort_next_frame_mismatch_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "abort_missing_nxt_frame:", -+ le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), -+ accum_tx->burst_abort_missing_next_frame_cnt, -+ delta_tx->burst_abort_missing_next_frame_cnt, -+ max_tx->burst_abort_missing_next_frame_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "cts_timeout_collision:", -+ le32_to_cpu(tx->cts_timeout_collision), -+ accum_tx->cts_timeout_collision, -+ delta_tx->cts_timeout_collision, -+ max_tx->cts_timeout_collision); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "ack_ba_timeout_collision:", -+ le32_to_cpu(tx->ack_or_ba_timeout_collision), -+ accum_tx->ack_or_ba_timeout_collision, -+ delta_tx->ack_or_ba_timeout_collision, -+ max_tx->ack_or_ba_timeout_collision); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg ba_timeout:", -+ le32_to_cpu(tx->agg.ba_timeout), -+ accum_tx->agg.ba_timeout, -+ delta_tx->agg.ba_timeout, -+ max_tx->agg.ba_timeout); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg ba_resched_frames:", -+ le32_to_cpu(tx->agg.ba_reschedule_frames), -+ accum_tx->agg.ba_reschedule_frames, -+ delta_tx->agg.ba_reschedule_frames, -+ max_tx->agg.ba_reschedule_frames); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg scd_query_agg_frame:", -+ le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), -+ accum_tx->agg.scd_query_agg_frame_cnt, -+ delta_tx->agg.scd_query_agg_frame_cnt, -+ max_tx->agg.scd_query_agg_frame_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg scd_query_no_agg:", -+ le32_to_cpu(tx->agg.scd_query_no_agg), -+ accum_tx->agg.scd_query_no_agg, -+ delta_tx->agg.scd_query_no_agg, -+ max_tx->agg.scd_query_no_agg); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg scd_query_agg:", -+ le32_to_cpu(tx->agg.scd_query_agg), -+ accum_tx->agg.scd_query_agg, -+ delta_tx->agg.scd_query_agg, -+ max_tx->agg.scd_query_agg); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg scd_query_mismatch:", -+ le32_to_cpu(tx->agg.scd_query_mismatch), -+ accum_tx->agg.scd_query_mismatch, -+ delta_tx->agg.scd_query_mismatch, -+ max_tx->agg.scd_query_mismatch); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg frame_not_ready:", -+ le32_to_cpu(tx->agg.frame_not_ready), -+ accum_tx->agg.frame_not_ready, -+ delta_tx->agg.frame_not_ready, -+ max_tx->agg.frame_not_ready); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg underrun:", -+ le32_to_cpu(tx->agg.underrun), -+ accum_tx->agg.underrun, -+ delta_tx->agg.underrun, max_tx->agg.underrun); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg bt_prio_kill:", -+ le32_to_cpu(tx->agg.bt_prio_kill), -+ accum_tx->agg.bt_prio_kill, -+ delta_tx->agg.bt_prio_kill, -+ max_tx->agg.bt_prio_kill); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "agg rx_ba_rsp_cnt:", -+ le32_to_cpu(tx->agg.rx_ba_rsp_cnt), -+ accum_tx->agg.rx_ba_rsp_cnt, -+ delta_tx->agg.rx_ba_rsp_cnt, -+ max_tx->agg.rx_ba_rsp_cnt); -+ -+ if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "tx power: (1/2 dB step)\n"); -+ if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_hex, "antenna A:", -+ tx->tx_power.ant_a); -+ if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_hex, "antenna B:", -+ tx->tx_power.ant_b); -+ if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_hex, "antenna C:", -+ tx->tx_power.ant_c); -+ } -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -+ kfree(buf); -+ return ret; - } - - static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, -@@ -1062,8 +1693,347 @@ - size_t count, loff_t *ppos) - { - struct iwl_priv *priv = file->private_data; -- return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, -- user_buf, count, ppos); -+ int pos = 0; -+ char *buf; -+ int bufsz = sizeof(struct statistics_general) * 10 + 300; -+ ssize_t ret; -+ struct statistics_general_common *general, *accum_general; -+ struct statistics_general_common *delta_general, *max_general; -+ struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; -+ struct statistics_div *div, *accum_div, *delta_div, *max_div; -+ -+ if (!iwl_is_alive(priv)) -+ return -EAGAIN; -+ -+ buf = kzalloc(bufsz, GFP_KERNEL); -+ if (!buf) { -+ IWL_ERR(priv, "Can not allocate Buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* the statistic information display here is based on -+ * 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, -+ fmt_header, "Statistics_General:"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_value, "temperature:", -+ le32_to_cpu(general->temperature)); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_value, "temperature_m:", -+ le32_to_cpu(general->temperature_m)); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_value, "ttl_timestamp:", -+ le32_to_cpu(general->ttl_timestamp)); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "burst_check:", -+ le32_to_cpu(dbg->burst_check), -+ accum_dbg->burst_check, -+ delta_dbg->burst_check, max_dbg->burst_check); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "burst_count:", -+ le32_to_cpu(dbg->burst_count), -+ accum_dbg->burst_count, -+ delta_dbg->burst_count, max_dbg->burst_count); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "wait_for_silence_timeout_count:", -+ le32_to_cpu(dbg->wait_for_silence_timeout_cnt), -+ accum_dbg->wait_for_silence_timeout_cnt, -+ delta_dbg->wait_for_silence_timeout_cnt, -+ max_dbg->wait_for_silence_timeout_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "sleep_time:", -+ le32_to_cpu(general->sleep_time), -+ accum_general->sleep_time, -+ delta_general->sleep_time, max_general->sleep_time); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "slots_out:", -+ le32_to_cpu(general->slots_out), -+ accum_general->slots_out, -+ delta_general->slots_out, max_general->slots_out); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "slots_idle:", -+ le32_to_cpu(general->slots_idle), -+ accum_general->slots_idle, -+ delta_general->slots_idle, max_general->slots_idle); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "tx_on_a:", -+ le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, -+ delta_div->tx_on_a, max_div->tx_on_a); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "tx_on_b:", -+ le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, -+ delta_div->tx_on_b, max_div->tx_on_b); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "exec_time:", -+ le32_to_cpu(div->exec_time), accum_div->exec_time, -+ delta_div->exec_time, max_div->exec_time); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "probe_time:", -+ le32_to_cpu(div->probe_time), accum_div->probe_time, -+ delta_div->probe_time, max_div->probe_time); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "rx_enable_counter:", -+ le32_to_cpu(general->rx_enable_counter), -+ accum_general->rx_enable_counter, -+ delta_general->rx_enable_counter, -+ max_general->rx_enable_counter); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ fmt_table, "num_of_sos_states:", -+ le32_to_cpu(general->num_of_sos_states), -+ accum_general->num_of_sos_states, -+ delta_general->num_of_sos_states, -+ max_general->num_of_sos_states); -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -+ kfree(buf); -+ return ret; -+} -+ -+static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data; -+ int pos = 0; -+ char *buf; -+ int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; -+ ssize_t ret; -+ struct statistics_bt_activity *bt, *accum_bt; -+ -+ if (!iwl_is_alive(priv)) -+ return -EAGAIN; -+ -+ if (!priv->bt_enable_flag) -+ return -EINVAL; -+ -+ /* make request to uCode to retrieve statistics information */ -+ mutex_lock(&priv->mutex); -+ ret = iwl_send_statistics_request(priv, CMD_SYNC, false); -+ mutex_unlock(&priv->mutex); -+ -+ if (ret) { -+ IWL_ERR(priv, -+ "Error sending statistics request: %zd\n", ret); -+ return -EAGAIN; -+ } -+ buf = kzalloc(bufsz, GFP_KERNEL); -+ if (!buf) { -+ IWL_ERR(priv, "Can not allocate Buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* -+ * the statistic information display here is based on -+ * the last statistics notification from uCode -+ * might not reflect the current uCode 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"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "\t\t\tcurrent\t\t\taccumulative\n"); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->hi_priority_tx_req_cnt), -+ accum_bt->hi_priority_tx_req_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->hi_priority_tx_denied_cnt), -+ accum_bt->hi_priority_tx_denied_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->lo_priority_tx_req_cnt), -+ accum_bt->lo_priority_tx_req_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->lo_priority_tx_denied_cnt), -+ accum_bt->lo_priority_tx_denied_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->hi_priority_rx_req_cnt), -+ accum_bt->hi_priority_rx_req_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->hi_priority_rx_denied_cnt), -+ accum_bt->hi_priority_rx_denied_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->lo_priority_rx_req_cnt), -+ accum_bt->lo_priority_rx_req_cnt); -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", -+ le32_to_cpu(bt->lo_priority_rx_denied_cnt), -+ accum_bt->lo_priority_rx_denied_cnt); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", -+ 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); -+ return ret; -+} -+ -+static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data; -+ int pos = 0; -+ char *buf; -+ int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + -+ (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; -+ ssize_t ret; -+ -+ if (!iwl_is_alive(priv)) -+ return -EAGAIN; -+ -+ buf = kzalloc(bufsz, GFP_KERNEL); -+ if (!buf) { -+ IWL_ERR(priv, "Can not allocate Buffer\n"); -+ return -ENOMEM; -+ } -+ -+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n"); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY), -+ priv->_agn.reply_tx_stats.pp_delay); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES), -+ priv->_agn.reply_tx_stats.pp_few_bytes); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO), -+ priv->_agn.reply_tx_stats.pp_bt_prio); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD), -+ priv->_agn.reply_tx_stats.pp_quiet_period); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK), -+ priv->_agn.reply_tx_stats.pp_calc_ttak); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_tx_fail_reason( -+ TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY), -+ priv->_agn.reply_tx_stats.int_crossed_retry); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT), -+ priv->_agn.reply_tx_stats.short_limit); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT), -+ priv->_agn.reply_tx_stats.long_limit); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN), -+ priv->_agn.reply_tx_stats.fifo_underrun); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW), -+ priv->_agn.reply_tx_stats.drain_flow); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH), -+ priv->_agn.reply_tx_stats.rfkill_flush); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE), -+ priv->_agn.reply_tx_stats.life_expire); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS), -+ priv->_agn.reply_tx_stats.dest_ps); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED), -+ priv->_agn.reply_tx_stats.host_abort); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY), -+ priv->_agn.reply_tx_stats.pp_delay); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID), -+ priv->_agn.reply_tx_stats.sta_invalid); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED), -+ priv->_agn.reply_tx_stats.frag_drop); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE), -+ priv->_agn.reply_tx_stats.tid_disable); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED), -+ priv->_agn.reply_tx_stats.fifo_flush); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_tx_fail_reason( -+ TX_STATUS_FAIL_INSUFFICIENT_CF_POLL), -+ priv->_agn.reply_tx_stats.insuff_cf_poll); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX), -+ priv->_agn.reply_tx_stats.fail_hw_drop); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_tx_fail_reason( -+ TX_STATUS_FAIL_NO_BEACON_ON_RADAR), -+ priv->_agn.reply_tx_stats.sta_color_mismatch); -+ pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", -+ priv->_agn.reply_tx_stats.unknown); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, -+ "\nStatistics_Agg_TX_Error:\n"); -+ -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK), -+ priv->_agn.reply_agg_tx_stats.underrun); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK), -+ priv->_agn.reply_agg_tx_stats.bt_prio); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK), -+ priv->_agn.reply_agg_tx_stats.few_bytes); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK), -+ priv->_agn.reply_agg_tx_stats.abort); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_agg_tx_fail_reason( -+ AGG_TX_STATE_LAST_SENT_TTL_MSK), -+ priv->_agn.reply_agg_tx_stats.last_sent_ttl); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_agg_tx_fail_reason( -+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK), -+ priv->_agn.reply_agg_tx_stats.last_sent_try); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_agg_tx_fail_reason( -+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK), -+ priv->_agn.reply_agg_tx_stats.last_sent_bt_kill); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK), -+ priv->_agn.reply_agg_tx_stats.scd_query); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n", -+ iwl_get_agg_tx_fail_reason( -+ AGG_TX_STATE_TEST_BAD_CRC32_MSK), -+ priv->_agn.reply_agg_tx_stats.bad_crc32); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK), -+ priv->_agn.reply_agg_tx_stats.response); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK), -+ priv->_agn.reply_agg_tx_stats.dump_tx); -+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n", -+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK), -+ priv->_agn.reply_agg_tx_stats.delay_tx); -+ pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n", -+ priv->_agn.reply_agg_tx_stats.unknown); -+ -+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -+ kfree(buf); -+ return ret; - } - - static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, -@@ -1268,8 +2238,7 @@ - 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 +2328,11 @@ - 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; -@@ -1531,16 +2498,6 @@ - return count; - } - --static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = (struct iwl_priv *)file->private_data; -- -- return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, -- user_buf, count, ppos); --} -- - static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) { -@@ -1572,12 +2529,10 @@ - int pos = 0; - char buf[200]; - const size_t bufsz = sizeof(buf); -- ssize_t ret; - - if (!priv->bt_enable_flag) { - pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n"); -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- return ret; -+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos); - } - pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n", - priv->bt_enable_flag); -@@ -1608,8 +2563,7 @@ - break; - } - -- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- return ret; -+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos); - } - - static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, -@@ -1658,18 +2612,6 @@ - return count; - } - --static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct iwl_priv *priv = file->private_data; -- -- if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error) -- return priv->cfg->ops->lib->debugfs_ops.reply_tx_error( -- file, user_buf, count, ppos); -- else -- return -ENODATA; --} - DEBUGFS_READ_FILE_OPS(rx_statistics); - DEBUGFS_READ_FILE_OPS(tx_statistics); - DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); -@@ -1731,11 +2673,8 @@ - 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); -@@ -1758,29 +2697,20 @@ - 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: -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-debug.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-debug.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-debug.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-debug.h 2011-05-05 23:29:45.348440209 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * -@@ -146,7 +146,6 @@ - #define IWL_DL_RX (1 << 24) - #define IWL_DL_ISR (1 << 25) - #define IWL_DL_HT (1 << 26) --#define IWL_DL_IO (1 << 27) - /* 0xF0000000 - 0x10000000 */ - #define IWL_DL_11H (1 << 28) - #define IWL_DL_STATS (1 << 29) -@@ -174,7 +173,6 @@ - IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) - #define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a) - #define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) --#define IWL_DEBUG_IO(p, f, a...) IWL_DEBUG(p, IWL_DL_IO, f, ## a) - #define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a) - #define IWL_DEBUG_RATE_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-dev.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-dev.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-dev.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-dev.h 2011-05-05 23:29:45.360440353 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * 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 -@@ -26,7 +26,6 @@ - /* - * Please use this file (iwl-dev.h) for driver implementation definitions. - * Please use iwl-commands.h for uCode API definitions. -- * Please use iwl-4965-hw.h for hardware-related definitions. - */ - - #ifndef __iwl_dev_h__ -@@ -179,53 +178,12 @@ - - #define IWL_NUM_SCAN_RATES (2) - --struct iwl4965_channel_tgd_info { -- u8 type; -- s8 max_power; --}; -- --struct iwl4965_channel_tgh_info { -- s64 last_radar_time; --}; -- --#define IWL4965_MAX_RATE (33) -- --struct iwl3945_clip_group { -- /* maximum power level to prevent clipping for each rate, derived by -- * us from this band's saturation power in EEPROM */ -- const s8 clip_powers[IWL_MAX_RATES]; --}; -- --/* current Tx power values to use, one for each rate for each channel. -- * requested power is limited by: -- * -- regulatory EEPROM limits for this channel -- * -- hardware capabilities (clip-powers) -- * -- spectrum management -- * -- user preference (e.g. iwconfig) -- * when requested power is set, base power index must also be set. */ --struct iwl3945_channel_power_info { -- struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ -- s8 power_table_index; /* actual (compenst'd) index into gain table */ -- s8 base_power_index; /* gain index for power at factory temp. */ -- s8 requested_power; /* power (dBm) requested for this chnl/rate */ --}; -- --/* current scan Tx power values to use, one for each scan rate for each -- * channel. */ --struct iwl3945_scan_power_info { -- struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ -- s8 power_table_index; /* actual (compenst'd) index into gain table */ -- s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ --}; -- - /* - * One for each channel, holds all channel setup data - * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant - * with one another! - */ - struct iwl_channel_info { -- struct iwl4965_channel_tgd_info tgd; -- struct iwl4965_channel_tgh_info tgh; - struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ - struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for - * HT40 channel */ -@@ -245,14 +203,6 @@ - s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ - u8 ht40_flags; /* flags copied from EEPROM */ - u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ -- -- /* Radio/DSP gain settings for each "normal" data Tx rate. -- * These include, in addition to RF and DSP gain, a few fields for -- * remembering/modifying gain settings (indexes). */ -- struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; -- -- /* Radio/DSP gain settings for each scan rate, for directed scans. */ -- struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; - }; - - #define IWL_TX_FIFO_BK 0 /* shared */ -@@ -309,6 +259,7 @@ - CMD_SIZE_HUGE = (1 << 0), - CMD_ASYNC = (1 << 1), - CMD_WANT_SKB = (1 << 2), -+ CMD_MAPPED = (1 << 3), - }; - - #define DEF_CMD_PAYLOAD_SIZE 320 -@@ -416,6 +367,7 @@ - #define IWL_EMPTYING_HW_QUEUE_ADDBA 2 - #define IWL_EMPTYING_HW_QUEUE_DELBA 3 - u8 state; -+ u8 tx_fifo; - }; - - -@@ -499,9 +451,6 @@ - * When mac80211 creates a station it reserves some space (hw->sta_data_size) - * in the structure for use by driver. This structure is places in that - * space. -- * -- * The common struct MUST be first because it is shared between -- * 3945 and agn! - */ - struct iwl_station_priv { - struct iwl_station_priv_common common; -@@ -530,6 +479,10 @@ - u32 len; /* bytes */ - }; - -+struct fw_img { -+ struct fw_desc code, data; -+}; -+ - /* v1/v2 uCode file layout */ - struct iwl_ucode_header { - __le32 ver; /* major/minor/API/serial */ -@@ -586,6 +539,22 @@ - IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, - IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, - IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, -+ /* 16 and 17 reserved for future use */ -+ IWL_UCODE_TLV_FLAGS = 18, -+}; -+ -+/** -+ * 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_NEWSCAN: new uCode scan behaviour on hidden SSID, -+ * treats good CRC threshold as a boolean -+ * @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_NEWSCAN = BIT(1), -+ IWL_UCODE_TLV_FLAGS_MFP = BIT(2), - }; - - struct iwl_ucode_tlv { -@@ -619,14 +588,6 @@ - u8 data[0]; - }; - --struct iwl4965_ibss_seq { -- u8 mac[ETH_ALEN]; -- u16 seq_num; -- u16 frag_num; -- unsigned long packet_time; -- struct list_head list; --}; -- - struct iwl_sensitivity_ranges { - u16 min_nrg_cck; - u16 max_nrg_cck; -@@ -700,7 +661,6 @@ - u8 max_beacon_itrvl; /* in 1024 ms */ - u32 max_inst_size; - u32 max_data_size; -- u32 max_bsm_size; - u32 ct_kill_threshold; /* value in hw-dependent units */ - u32 ct_kill_exit_threshold; /* value in hw-dependent units */ - /* for 1000, 6000 series and up */ -@@ -722,8 +682,6 @@ - * Naming convention -- - * iwl_ <-- Is part of iwlwifi - * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) -- * iwl4965_bg_ <-- Called from work queue context -- * iwl4965_mac_ <-- mac80211 callback - * - ****************************************************************************/ - extern void iwl_update_chain_flags(struct iwl_priv *priv); -@@ -772,7 +730,6 @@ - - /* Sensitivity and chain noise calibration */ - #define INITIALIZATION_VALUE 0xFFFF --#define IWL4965_CAL_NUM_BEACONS 20 - #define IWL_CAL_NUM_BEACONS 16 - #define MAXIMUM_ALLOWED_PATHLOSS 15 - -@@ -806,24 +763,19 @@ - #define NRG_NUM_PREV_STAT_L 20 - #define NUM_RX_CHAINS 3 - --enum iwl4965_false_alarm_state { -+enum iwlagn_false_alarm_state { - IWL_FA_TOO_MANY = 0, - IWL_FA_TOO_FEW = 1, - IWL_FA_GOOD_RANGE = 2, - }; - --enum iwl4965_chain_noise_state { -+enum iwlagn_chain_noise_state { - IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */ - IWL_CHAIN_NOISE_ACCUMULATE, - IWL_CHAIN_NOISE_CALIBRATED, - IWL_CHAIN_NOISE_DONE, - }; - --enum iwl4965_calib_enabled_state { -- IWL_CALIB_DISABLED = 0, /* must be 0 */ -- IWL_CALIB_ENABLED = 1, --}; -- - - /* - * enum iwl_calib -@@ -847,12 +799,6 @@ - size_t buf_len; - }; - --enum ucode_type { -- UCODE_NONE = 0, -- UCODE_INIT, -- UCODE_RT --}; -- - /* Sensitivity calib data */ - struct iwl_sensitivity_data { - u32 auto_corr_ofdm; -@@ -1131,12 +1077,6 @@ - - /* extend beacon time format bit shifting */ - /* -- * for _3945 devices -- * bits 31:24 - extended -- * bits 23:0 - interval -- */ --#define IWL3945_EXT_BEACON_TIME_POS 24 --/* - * for _agn devices - * bits 31:22 - extended - * bits 21:0 - interval -@@ -1164,10 +1104,12 @@ - struct iwl_notification_wait { - struct list_head list; - -- void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); -+ void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, -+ void *data); -+ void *fn_data; - - u8 cmd; -- bool triggered; -+ bool triggered, aborted; - }; - - enum iwl_rxon_context_id { -@@ -1228,6 +1170,8 @@ - bool enabled, is_40mhz; - u8 extension_chan_offset; - } ht; -+ -+ bool last_tx_rejected; - }; - - enum iwl_scan_type { -@@ -1249,7 +1193,6 @@ - int frames_count; - - enum ieee80211_band band; -- int alloc_rxb_page; - - void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -@@ -1305,16 +1248,12 @@ - spinlock_t hcmd_lock; /* protect hcmd */ - spinlock_t reg_lock; /* protect hw register access */ - struct mutex mutex; -- struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ - - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; - - /* pci hardware address support */ - void __iomem *hw_base; -- u32 hw_rev; -- u32 hw_wa_rev; -- u8 rev_id; - - /* microcode/device supports multiple contexts */ - u8 valid_contexts; -@@ -1325,6 +1264,8 @@ - /* max number of station keys */ - u8 sta_key_max_num; - -+ bool new_scan_threshold_behaviour; -+ - /* EEPROM MAC addresses */ - struct mac_address addresses[2]; - -@@ -1332,13 +1273,10 @@ - int fw_index; /* firmware we're trying to load */ - u32 ucode_ver; /* version of ucode, copy of - iwl_ucode.ver */ -- struct fw_desc ucode_code; /* runtime inst */ -- struct fw_desc ucode_data; /* runtime data original */ -- struct fw_desc ucode_data_backup; /* runtime data save/restore */ -- struct fw_desc ucode_init; /* initialization inst */ -- struct fw_desc ucode_init_data; /* initialization data */ -- struct fw_desc ucode_boot; /* bootstrap inst */ -- enum ucode_type ucode_type; -+ struct fw_img ucode_rt; -+ struct fw_img ucode_init; -+ -+ enum iwlagn_ucode_subtype ucode_type; - u8 ucode_write_complete; /* the image write is complete */ - char firmware_name[25]; - -@@ -1346,10 +1284,10 @@ - - struct iwl_switch_rxon switch_rxon; - -- /* 1st responses from initialize and runtime uCode images. -- * _agn's initialize alive response contains some calibration data. */ -- struct iwl_init_alive_resp card_alive_init; -- struct iwl_alive_resp card_alive; -+ struct { -+ u32 error_event_table; -+ u32 log_event_table; -+ } device_pointers; - - u16 active_rate; - -@@ -1390,15 +1328,12 @@ - struct iwl_power_mgr power_data; - struct iwl_tt_mgmt thermal_throttle; - -- /* context information */ -- u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ -- - /* station table variables */ - - /* Note: if lock and sta_lock are needed, lock must be acquired first */ - spinlock_t sta_lock; - int num_stations; -- struct iwl_station_entry stations[IWL_STATION_COUNT]; -+ struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; - unsigned long ucode_key_table; - - /* queue refcounts */ -@@ -1422,101 +1357,81 @@ - /* Last Rx'd beacon timestamp */ - u64 timestamp; - -- union { --#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) -- struct { -- void *shared_virt; -- dma_addr_t shared_phys; -- -- struct delayed_work thermal_periodic; -- struct delayed_work rfkill_poll; -- -- struct iwl3945_notif_statistics statistics; -+ 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 iwl3945_notif_statistics accum_statistics; -- struct iwl3945_notif_statistics delta_statistics; -- struct iwl3945_notif_statistics max_delta; -+ struct statistics_bt_activity bt_activity; -+ __le32 num_bt_kills, accum_num_bt_kills; - #endif -- -- u32 sta_supp_rates; -- int last_rx_rssi; /* From Rx packet statistics */ -- -- /* Rx'd packet timing information */ -- u32 last_beacon_time; -- u64 last_tsf; -- -- /* -- * each calibration channel group in the -- * EEPROM has a derived clip setting for -- * each rate. -- */ -- const struct iwl3945_clip_group clip_groups[5]; -- -- } _3945; --#endif --#if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) -- struct { -- /* INT ICT Table */ -- __le32 *ict_tbl; -- void *ict_tbl_vir; -- dma_addr_t ict_tbl_dma; -- dma_addr_t aligned_ict_tbl_dma; -- int ict_index; -- u32 inta; -- bool use_ict; -- /* -- * reporting the number of tids has AGG on. 0 means -- * no AGGREGATION -- */ -- u8 agg_tids_count; -- -- struct iwl_rx_phy_res last_phy_res; -- bool last_phy_res_valid; -- -- struct completion firmware_loading_complete; -- -- u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; -- u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; -- -- /* -- * chain noise reset and gain commands are the -- * two extra calibration commands follows the standard -- * phy calibration commands -- */ -- 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; -+ } statistics; - #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; -+ 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 - -- /* notification wait support */ -- struct list_head notif_waits; -- spinlock_t notif_wait_lock; -- wait_queue_head_t notif_waitq; -- -- /* remain-on-channel offload support */ -- struct ieee80211_channel *hw_roc_channel; -- struct delayed_work hw_roc_work; -- enum nl80211_channel_type hw_roc_chantype; -- int hw_roc_duration; -- -- struct sk_buff *offchan_tx_skb; -- int offchan_tx_timeout; -- struct ieee80211_channel *offchan_tx_chan; -- } _agn; --#endif -- }; -+ struct { -+ /* INT ICT Table */ -+ __le32 *ict_tbl; -+ void *ict_tbl_vir; -+ dma_addr_t ict_tbl_dma; -+ dma_addr_t aligned_ict_tbl_dma; -+ int ict_index; -+ u32 inta; -+ bool use_ict; -+ /* -+ * reporting the number of tids has AGG on. 0 means -+ * no AGGREGATION -+ */ -+ u8 agg_tids_count; -+ -+ struct iwl_rx_phy_res last_phy_res; -+ bool last_phy_res_valid; -+ -+ struct completion firmware_loading_complete; -+ -+ u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; -+ u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; -+ -+ /* -+ * chain noise reset and gain commands are the -+ * two extra calibration commands follows the standard -+ * phy calibration commands -+ */ -+ u8 phy_calib_chain_noise_reset_cmd; -+ u8 phy_calib_chain_noise_gain_cmd; -+ -+ /* counts reply_tx error */ -+ struct reply_tx_error_statistics reply_tx_stats; -+ struct reply_agg_tx_error_statistics reply_agg_tx_stats; -+ /* notification wait support */ -+ struct list_head notif_waits; -+ spinlock_t notif_wait_lock; -+ wait_queue_head_t notif_waitq; -+ -+ /* remain-on-channel offload support */ -+ struct ieee80211_channel *hw_roc_channel; -+ struct delayed_work hw_roc_work; -+ enum nl80211_channel_type hw_roc_chantype; -+ int hw_roc_duration; -+ bool hw_roc_setup; -+ -+ struct sk_buff *offchan_tx_skb; -+ int offchan_tx_timeout; -+ struct ieee80211_channel *offchan_tx_chan; -+ } _agn; - - /* bt coex */ - u8 bt_enable_flag; -@@ -1559,8 +1474,6 @@ - - struct tasklet_struct irq_tasklet; - -- struct delayed_work init_alive_start; -- struct delayed_work alive_start; - struct delayed_work scan_check; - - /* TX Power */ -@@ -1589,12 +1502,10 @@ - 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; - struct timer_list watchdog; -- bool hw_ready; - - struct iwl_event_log event_log; - -@@ -1710,12 +1621,10 @@ - static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) - { - __free_pages(page, priv->hw_params.rx_page_order); -- priv->alloc_rxb_page--; - } - - static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) - { - free_pages(page, priv->hw_params.rx_page_order); -- priv->alloc_rxb_page--; - } - #endif /* __iwl_dev_h__ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-devtrace.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-devtrace.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-devtrace.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-devtrace.c 2011-05-05 23:29:45.349440221 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2009 - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-devtrace.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-devtrace.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-devtrace.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-devtrace.h 2011-05-05 23:29:45.348440209 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2009 - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-eeprom.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-eeprom.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-eeprom.c 2011-05-05 23:29:45.340440113 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -142,6 +142,45 @@ - * - ******************************************************************************/ - -+/* -+ * The device's EEPROM semaphore prevents conflicts between driver and uCode -+ * when accessing the EEPROM; each access is a series of pulses to/from the -+ * EEPROM chip, not a single event, so even reads could conflict if they -+ * weren't arbitrated by the semaphore. -+ */ -+static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) -+{ -+ u16 count; -+ int ret; -+ -+ for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { -+ /* Request semaphore */ -+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -+ -+ /* See if we got it */ -+ ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, -+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, -+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, -+ EEPROM_SEM_TIMEOUT); -+ if (ret >= 0) { -+ IWL_DEBUG_EEPROM(priv, -+ "Acquired semaphore after %d tries.\n", -+ count+1); -+ return ret; -+ } -+ } -+ -+ return ret; -+} -+ -+static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) -+{ -+ iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, -+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -+ -+} -+ - static int iwl_eeprom_verify_signature(struct iwl_priv *priv) - { - u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; -@@ -188,18 +227,16 @@ - CSR_OTP_GP_REG_OTP_ACCESS_MODE); - } - --static int iwlcore_get_nvm_type(struct iwl_priv *priv) -+static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) - { - u32 otpgp; - int nvm_type; - - /* OTP only valid for CP/PP and after */ -- switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { -+ switch (hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_NONE: - IWL_ERR(priv, "Unknown hardware type\n"); - return -ENOENT; -- case CSR_HW_REV_TYPE_3945: -- case CSR_HW_REV_TYPE_4965: - case CSR_HW_REV_TYPE_5300: - case CSR_HW_REV_TYPE_5350: - case CSR_HW_REV_TYPE_5100: -@@ -217,26 +254,20 @@ - 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; - - /* Enable 40MHz radio clock */ -- _iwl_write32(priv, CSR_GP_CNTRL, -- _iwl_read32(priv, CSR_GP_CNTRL) | -- CSR_GP_CNTRL_REG_FLAG_INIT_DONE); -+ iwl_write32(priv, CSR_GP_CNTRL, -+ iwl_read32(priv, CSR_GP_CNTRL) | -+ CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* wait for clock to be ready */ - ret = iwl_poll_bit(priv, CSR_GP_CNTRL, -- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, -- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, -- 25000); -+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, -+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, -+ 25000); - if (ret < 0) - IWL_ERR(priv, "Time out access OTP\n"); - else { -@@ -263,17 +294,17 @@ - u32 r; - u32 otpgp; - -- _iwl_write32(priv, CSR_EEPROM_REG, -- CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); -+ iwl_write32(priv, CSR_EEPROM_REG, -+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(priv, CSR_EEPROM_REG, -- CSR_EEPROM_REG_READ_VALID_MSK, -- CSR_EEPROM_REG_READ_VALID_MSK, -- IWL_EEPROM_ACCESS_TIMEOUT); -+ CSR_EEPROM_REG_READ_VALID_MSK, -+ CSR_EEPROM_REG_READ_VALID_MSK, -+ IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); - return ret; - } -- r = _iwl_read_direct32(priv, CSR_EEPROM_REG); -+ r = iwl_read32(priv, CSR_EEPROM_REG); - /* check for ECC errors: */ - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); - if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { -@@ -396,7 +427,7 @@ - * - * NOTE: This routine uses the non-debug IO access functions. - */ --int iwl_eeprom_init(struct iwl_priv *priv) -+int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) - { - __le16 *e; - u32 gp = iwl_read32(priv, CSR_EEPROM_GP); -@@ -406,7 +437,7 @@ - u16 validblockaddr = 0; - u16 cache_addr = 0; - -- priv->nvm_device_type = iwlcore_get_nvm_type(priv); -+ priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); - if (priv->nvm_device_type == -ENOENT) - return -ENOENT; - /* allocate eeprom */ -@@ -429,7 +460,7 @@ - } - - /* Make sure driver (instead of uCode) is allowed to read EEPROM */ -- ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); -+ ret = iwl_eeprom_acquire_semaphore(priv); - if (ret < 0) { - IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); - ret = -ENOENT; -@@ -444,9 +475,9 @@ - ret = -ENOENT; - goto done; - } -- _iwl_write32(priv, CSR_EEPROM_GP, -- iwl_read32(priv, CSR_EEPROM_GP) & -- ~CSR_EEPROM_GP_IF_OWNER_MSK); -+ iwl_write32(priv, CSR_EEPROM_GP, -+ iwl_read32(priv, CSR_EEPROM_GP) & -+ ~CSR_EEPROM_GP_IF_OWNER_MSK); - - iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | -@@ -473,8 +504,8 @@ - for (addr = 0; addr < sz; addr += sizeof(u16)) { - u32 r; - -- _iwl_write32(priv, CSR_EEPROM_REG, -- CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); -+ iwl_write32(priv, CSR_EEPROM_REG, -+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - - ret = iwl_poll_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, -@@ -484,7 +515,7 @@ - IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); - goto done; - } -- r = _iwl_read_direct32(priv, CSR_EEPROM_REG); -+ r = iwl_read32(priv, CSR_EEPROM_REG); - e[addr / 2] = cpu_to_le16(r >> 16); - } - } -@@ -496,7 +527,7 @@ - - ret = 0; - done: -- priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); -+ iwl_eeprom_release_semaphore(priv); - - err: - if (ret) -@@ -719,13 +750,6 @@ - flags & EEPROM_CHANNEL_RADAR)) - ? "" : "not "); - -- /* Set the tx_power_user_lmt to the highest power -- * supported by any channel */ -- if (eeprom_ch_info[ch].max_power_avg > -- priv->tx_power_user_lmt) -- priv->tx_power_user_lmt = -- eeprom_ch_info[ch].max_power_avg; -- - ch_info++; - } - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-eeprom.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-eeprom.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-eeprom.h 2011-05-05 23:29:45.245438965 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -110,10 +110,6 @@ - }; - - /* SKU Capabilities */ --/* 3945 only */ --#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) --#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) -- - /* 5000 and up */ - #define EEPROM_SKU_CAP_BAND_POS (4) - #define EEPROM_SKU_CAP_BAND_SELECTION \ -@@ -168,28 +164,6 @@ - s8 mimo3_max; - } __packed; - --/* 3945 Specific */ --#define EEPROM_3945_EEPROM_VERSION (0x2f) -- --/* 4965 has two radio transmitters (and 3 radio receivers) */ --#define EEPROM_TX_POWER_TX_CHAINS (2) -- --/* 4965 has room for up to 8 sets of txpower calibration data */ --#define EEPROM_TX_POWER_BANDS (8) -- --/* 4965 factory calibration measures txpower gain settings for -- * each of 3 target output levels */ --#define EEPROM_TX_POWER_MEASUREMENTS (3) -- --/* 4965 Specific */ --/* 4965 driver does not work with txpower calibration version < 5 */ --#define EEPROM_4965_TX_POWER_VERSION (5) --#define EEPROM_4965_EEPROM_VERSION (0x2f) --#define EEPROM_4965_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ --#define EEPROM_4965_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ --#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ --#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ -- - /* 5000 Specific */ - #define EEPROM_5000_TX_POWER_VERSION (4) - #define EEPROM_5000_EEPROM_VERSION (0x11A) -@@ -282,90 +256,6 @@ - /* 2.4 GHz */ - extern const u8 iwl_eeprom_band_1[14]; - --/* -- * factory calibration data for one txpower level, on one channel, -- * measured on one of the 2 tx chains (radio transmitter and associated -- * antenna). EEPROM contains: -- * -- * 1) Temperature (degrees Celsius) of device when measurement was made. -- * -- * 2) Gain table index used to achieve the target measurement power. -- * This refers to the "well-known" gain tables (see iwl-4965-hw.h). -- * -- * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). -- * -- * 4) RF power amplifier detector level measurement (not used). -- */ --struct iwl_eeprom_calib_measure { -- u8 temperature; /* Device temperature (Celsius) */ -- u8 gain_idx; /* Index into gain table */ -- u8 actual_pow; /* Measured RF output power, half-dBm */ -- s8 pa_det; /* Power amp detector level (not used) */ --} __packed; -- -- --/* -- * measurement set for one channel. EEPROM contains: -- * -- * 1) Channel number measured -- * -- * 2) Measurements for each of 3 power levels for each of 2 radio transmitters -- * (a.k.a. "tx chains") (6 measurements altogether) -- */ --struct iwl_eeprom_calib_ch_info { -- u8 ch_num; -- struct iwl_eeprom_calib_measure -- measurements[EEPROM_TX_POWER_TX_CHAINS] -- [EEPROM_TX_POWER_MEASUREMENTS]; --} __packed; -- --/* -- * txpower subband info. -- * -- * For each frequency subband, EEPROM contains the following: -- * -- * 1) First and last channels within range of the subband. "0" values -- * indicate that this sample set is not being used. -- * -- * 2) Sample measurement sets for 2 channels close to the range endpoints. -- */ --struct iwl_eeprom_calib_subband_info { -- u8 ch_from; /* channel number of lowest channel in subband */ -- u8 ch_to; /* channel number of highest channel in subband */ -- struct iwl_eeprom_calib_ch_info ch1; -- struct iwl_eeprom_calib_ch_info ch2; --} __packed; -- -- --/* -- * txpower calibration info. EEPROM contains: -- * -- * 1) Factory-measured saturation power levels (maximum levels at which -- * tx power amplifier can output a signal without too much distortion). -- * There is one level for 2.4 GHz band and one for 5 GHz band. These -- * values apply to all channels within each of the bands. -- * -- * 2) Factory-measured power supply voltage level. This is assumed to be -- * constant (i.e. same value applies to all channels/bands) while the -- * factory measurements are being made. -- * -- * 3) Up to 8 sets of factory-measured txpower calibration values. -- * These are for different frequency ranges, since txpower gain -- * characteristics of the analog radio circuitry vary with frequency. -- * -- * Not all sets need to be filled with data; -- * struct iwl_eeprom_calib_subband_info contains range of channels -- * (0 if unused) for each set of data. -- */ --struct iwl_eeprom_calib_info { -- u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ -- u8 saturation_power52; /* half-dBm */ -- __le16 voltage; /* signed */ -- struct iwl_eeprom_calib_subband_info -- band_info[EEPROM_TX_POWER_BANDS]; --} __packed; -- -- - #define ADDRESS_MSK 0x0000FFFF - #define INDIRECT_TYPE_MSK 0x000F0000 - #define INDIRECT_HOST 0x00010000 -@@ -398,103 +288,24 @@ - #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ - #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ - --#define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 --#define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 -- --/* Radio Config for 5000 and up */ --#define EEPROM_RF_CONFIG_TYPE_R3x3 0x0 --#define EEPROM_RF_CONFIG_TYPE_R2x2 0x1 --#define EEPROM_RF_CONFIG_TYPE_R1x2 0x2 - #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 - --/* -- * Per-channel regulatory data. -- * -- * Each channel that *might* be supported by iwl has a fixed location -- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory -- * txpower (MSB). -- * -- * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) -- * channels (only for 4965, not supported by 3945) appear later in the EEPROM. -- * -- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 -- */ --#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ --#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ --#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ -- --/* -- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, -- * 5.0 GHz channels 7, 8, 11, 12, 16 -- * (4915-5080MHz) (none of these is ever supported) -- */ --#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ --#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ -- --/* -- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 -- * (5170-5320MHz) -- */ --#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ --#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ -- --/* -- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -- * (5500-5700MHz) -- */ --#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ --#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ -- --/* -- * 5.7 GHz channels 145, 149, 153, 157, 161, 165 -- * (5725-5825MHz) -- */ --#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ --#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ -- --/* -- * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) -- * -- * The channel listed is the center of the lower 20 MHz half of the channel. -- * The overall center frequency is actually 2 channels (10 MHz) above that, -- * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away -- * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5, -- * and the overall HT40 channel width centers on channel 3. -- * -- * NOTE: The RXON command uses 20 MHz channel numbers to specify the -- * control channel to which to tune. RXON also specifies whether the -- * control channel is the upper or lower half of a HT40 channel. -- * -- * NOTE: 4965 does not support HT40 channels on 2.4 GHz. -- */ --#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */ -- --/* -- * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64), -- * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) -- */ --#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */ -- - #define EEPROM_REGULATORY_BAND_NO_HT40 (0) - - struct iwl_eeprom_ops { - const u32 regulatory_bands[7]; -- int (*acquire_semaphore) (struct iwl_priv *priv); -- void (*release_semaphore) (struct iwl_priv *priv); -- u16 (*calib_version) (struct iwl_priv *priv); - const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset); - void (*update_enhanced_txpower) (struct iwl_priv *priv); - }; - - --int iwl_eeprom_init(struct iwl_priv *priv); -+int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); - void iwl_eeprom_free(struct iwl_priv *priv); - int iwl_eeprom_check_version(struct iwl_priv *priv); - 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( -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-fh.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-fh.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-fh.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-fh.h 2011-05-05 23:29:45.360440353 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 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 -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -77,14 +77,14 @@ - /** - * 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 -@@ -116,16 +116,16 @@ - /** - * 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). -@@ -140,20 +140,20 @@ - * 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 -@@ -162,12 +162,12 @@ - * 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 -@@ -176,7 +176,7 @@ - * 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 -@@ -303,7 +303,7 @@ - /** - * 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. - * -@@ -326,7 +326,6 @@ - #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 */ -@@ -424,7 +423,6 @@ - #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 @@ - __le16 closed_fr_num; - __le16 finished_rb_num; - __le16 finished_fr_nam; -- __le32 __unused; /* 3945 only */ -+ __le32 __unused; - } __packed; - - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-hcmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-hcmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-hcmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-hcmd.c 2011-05-05 23:29:45.340440113 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -@@ -51,9 +51,7 @@ - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_TXFIFO_FLUSH); - IWL_CMD(REPLY_WEPKEY); -- IWL_CMD(REPLY_3945_RX); - IWL_CMD(REPLY_TX); -- IWL_CMD(REPLY_RATE_SCALE); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(COEX_PRIORITY_TABLE_CMD); -@@ -145,10 +143,12 @@ - { - 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) -@@ -171,14 +171,15 @@ - int cmd_idx; - int ret; - -- BUG_ON(cmd->flags & CMD_ASYNC); -+ if (WARN_ON(cmd->flags & CMD_ASYNC)) -+ return -EINVAL; - - /* A synchronous command can not have a callback set. */ -- BUG_ON(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)); -- mutex_lock(&priv->sync_cmd_mutex); - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", -@@ -189,7 +190,7 @@ - ret = cmd_idx; - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); -- goto out; -+ return ret; - } - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, -@@ -229,8 +230,7 @@ - goto cancel; - } - -- ret = 0; -- goto out; -+ return 0; - - cancel: - if (cmd->flags & CMD_WANT_SKB) { -@@ -248,8 +248,7 @@ - iwl_free_pages(priv, cmd->reply_page); - cmd->reply_page = 0; - } --out: -- mutex_unlock(&priv->sync_cmd_mutex); -+ - return ret; - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-helpers.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-helpers.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-helpers.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-helpers.h 2011-05-05 23:29:45.349440221 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -64,30 +64,6 @@ - return --index & (n_bd - 1); - } - --/* TODO: Move fw_desc functions to iwl-pci.ko */ --static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, -- struct fw_desc *desc) --{ -- if (desc->v_addr) -- dma_free_coherent(&pci_dev->dev, desc->len, -- desc->v_addr, desc->p_addr); -- desc->v_addr = NULL; -- desc->len = 0; --} -- --static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, -- struct fw_desc *desc) --{ -- if (!desc->len) { -- desc->v_addr = NULL; -- return -EINVAL; -- } -- -- desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, -- &desc->p_addr, GFP_KERNEL); -- return (desc->v_addr != NULL) ? 0 : -ENOMEM; --} -- - /* - * we have 8 bits used like this: - * -@@ -131,6 +107,19 @@ - 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 - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-io.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-io.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-io.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-io.c 2011-05-05 23:29:45.375440535 +0200 -@@ -0,0 +1,294 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. -+ * -+ * Portions of this file are derived from the ipw3945 project. -+ * -+ * 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 -+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -+ * -+ *****************************************************************************/ -+ -+#include "iwl-io.h" -+ -+#define IWL_POLL_INTERVAL 10 /* microseconds */ -+ -+static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); -+} -+ -+static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); -+} -+ -+void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ __iwl_set_bit(priv, reg, mask); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ __iwl_clear_bit(priv, reg, mask); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+int iwl_poll_bit(struct iwl_priv *priv, u32 addr, -+ u32 bits, u32 mask, int timeout) -+{ -+ int t = 0; -+ -+ do { -+ if ((iwl_read32(priv, addr) & mask) == (bits & mask)) -+ return t; -+ udelay(IWL_POLL_INTERVAL); -+ t += IWL_POLL_INTERVAL; -+ } while (t < timeout); -+ -+ return -ETIMEDOUT; -+} -+ -+int iwl_grab_nic_access_silent(struct iwl_priv *priv) -+{ -+ int ret; -+ -+ lockdep_assert_held(&priv->reg_lock); -+ -+ /* this bit wakes up the NIC */ -+ __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -+ -+ /* -+ * These bits say the device is running, and should keep running for -+ * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), -+ * but they do not indicate that embedded SRAM is restored yet; -+ * 3945 and 4965 have volatile SRAM, and must save/restore contents -+ * to/from host DRAM when sleeping/waking for power-saving. -+ * Each direction takes approximately 1/4 millisecond; with this -+ * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a -+ * series of register accesses are expected (e.g. reading Event Log), -+ * to keep device from sleeping. -+ * -+ * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that -+ * SRAM is okay/restored. We don't check that here because this call -+ * is just for hardware register access; but GP1 MAC_SLEEP check is a -+ * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). -+ * -+ * 5000 series and later (including 1000 series) have non-volatile SRAM, -+ * and do not save/restore SRAM when power cycling. -+ */ -+ ret = iwl_poll_bit(priv, CSR_GP_CNTRL, -+ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, -+ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | -+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); -+ if (ret < 0) { -+ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+int iwl_grab_nic_access(struct iwl_priv *priv) -+{ -+ int ret = iwl_grab_nic_access_silent(priv); -+ if (ret) { -+ u32 val = iwl_read32(priv, CSR_GP_CNTRL); -+ IWL_ERR(priv, -+ "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); -+ } -+ -+ return ret; -+} -+ -+void iwl_release_nic_access(struct iwl_priv *priv) -+{ -+ lockdep_assert_held(&priv->reg_lock); -+ __iwl_clear_bit(priv, CSR_GP_CNTRL, -+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -+} -+ -+u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -+{ -+ u32 value; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ value = iwl_read32(priv, reg); -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+ -+ return value; -+} -+ -+void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ if (!iwl_grab_nic_access(priv)) { -+ iwl_write32(priv, reg, value); -+ iwl_release_nic_access(priv); -+ } -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, -+ int timeout) -+{ -+ int t = 0; -+ -+ do { -+ if ((iwl_read_direct32(priv, addr) & mask) == mask) -+ return t; -+ udelay(IWL_POLL_INTERVAL); -+ t += IWL_POLL_INTERVAL; -+ } while (t < timeout); -+ -+ return -ETIMEDOUT; -+} -+ -+static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) -+{ -+ iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); -+ rmb(); -+ return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); -+} -+ -+static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -+{ -+ iwl_write32(priv, HBUS_TARG_PRPH_WADDR, -+ ((addr & 0x0000FFFF) | (3 << 24))); -+ wmb(); -+ iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); -+} -+ -+u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) -+{ -+ unsigned long flags; -+ u32 val; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ val = __iwl_read_prph(priv, reg); -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+ return val; -+} -+ -+void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ if (!iwl_grab_nic_access(priv)) { -+ __iwl_write_prph(priv, addr, val); -+ iwl_release_nic_access(priv); -+ } -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, -+ u32 bits, u32 mask) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ __iwl_write_prph(priv, reg, -+ (__iwl_read_prph(priv, reg) & mask) | bits); -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -+{ -+ unsigned long flags; -+ u32 val; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ val = __iwl_read_prph(priv, reg); -+ __iwl_write_prph(priv, reg, (val & ~mask)); -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, -+ void *buf, int words) -+{ -+ unsigned long flags; -+ int offs; -+ u32 *vals = buf; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ iwl_grab_nic_access(priv); -+ -+ iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); -+ rmb(); -+ -+ for (offs = 0; offs < words; offs++) -+ vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); -+ -+ iwl_release_nic_access(priv); -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -+ -+u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) -+{ -+ u32 value; -+ -+ _iwl_read_targ_mem_words(priv, addr, &value, 1); -+ -+ return value; -+} -+ -+void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->reg_lock, flags); -+ if (!iwl_grab_nic_access(priv)) { -+ iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); -+ wmb(); -+ iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); -+ iwl_release_nic_access(priv); -+ } -+ spin_unlock_irqrestore(&priv->reg_lock, flags); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-io.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-io.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-io.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-io.h 2011-05-05 23:29:45.320439871 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * -@@ -35,494 +35,58 @@ - #include "iwl-debug.h" - #include "iwl-devtrace.h" - --/* -- * IO, register, and NIC memory access functions -- * -- * NOTE on naming convention and macro usage for these -- * -- * A single _ prefix before a an access function means that no state -- * check or debug information is printed when that function is called. -- * -- * A double __ prefix before an access function means that state is checked -- * and the current line number and caller function name are printed in addition -- * to any other debug output. -- * -- * The non-prefixed name is the #define that maps the caller into a -- * #define that provides the caller's name and __LINE__ to the double -- * prefix version. -- * -- * If you wish to call the function without any debug or state checking, -- * you should use the single _ prefix version (as is used by dependent IO -- * routines, for example _iwl_read_direct32 calls the non-check version of -- * _iwl_read32.) -- * -- * These declarations are *extremely* useful in quickly isolating code deltas -- * which result in misconfiguration of the hardware I/O. In combination with -- * git-bisect and the IO debug level you can quickly determine the specific -- * commit which breaks the IO sequence to the hardware. -- * -- */ -- --static inline void _iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) -+static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) - { - trace_iwlwifi_dev_iowrite8(priv, ofs, val); - iowrite8(val, priv->hw_base + ofs); - } - --#ifdef CONFIG_IWLWIFI_DEBUG --static inline void __iwl_write8(const char *f, u32 l, struct iwl_priv *priv, -- u32 ofs, u8 val) --{ -- IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l); -- _iwl_write8(priv, ofs, val); --} --#define iwl_write8(priv, ofs, val) \ -- __iwl_write8(__FILE__, __LINE__, priv, ofs, val) --#else --#define iwl_write8(priv, ofs, val) _iwl_write8(priv, ofs, val) --#endif -- -- --static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) -+static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) - { - trace_iwlwifi_dev_iowrite32(priv, ofs, val); - iowrite32(val, priv->hw_base + ofs); - } - --#ifdef CONFIG_IWLWIFI_DEBUG --static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, -- u32 ofs, u32 val) --{ -- IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); -- _iwl_write32(priv, ofs, val); --} --#define iwl_write32(priv, ofs, val) \ -- __iwl_write32(__FILE__, __LINE__, priv, ofs, val) --#else --#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) --#endif -- --static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) -+static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) - { - u32 val = ioread32(priv->hw_base + ofs); - trace_iwlwifi_dev_ioread32(priv, ofs, val); - return val; - } - --#ifdef CONFIG_IWLWIFI_DEBUG --static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) --{ -- IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); -- return _iwl_read32(priv, ofs); --} --#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) --#else --#define iwl_read32(p, o) _iwl_read32(p, o) --#endif -- --#define IWL_POLL_INTERVAL 10 /* microseconds */ --static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, -- u32 bits, u32 mask, int timeout) --{ -- int t = 0; -- -- do { -- if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) -- return t; -- udelay(IWL_POLL_INTERVAL); -- t += IWL_POLL_INTERVAL; -- } while (t < timeout); -- -- return -ETIMEDOUT; --} --#ifdef CONFIG_IWLWIFI_DEBUG --static inline int __iwl_poll_bit(const char *f, u32 l, -- struct iwl_priv *priv, u32 addr, -- u32 bits, u32 mask, int timeout) --{ -- int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); -- IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", -- addr, bits, mask, -- unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); -- return ret; --} --#define iwl_poll_bit(priv, addr, bits, mask, timeout) \ -- __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) --#else --#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) --#endif -- --static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) --{ -- _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); --} --#ifdef CONFIG_IWLWIFI_DEBUG --static inline void __iwl_set_bit(const char *f, u32 l, -- struct iwl_priv *priv, u32 reg, u32 mask) --{ -- u32 val = _iwl_read32(priv, reg) | mask; -- IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); -- _iwl_write32(priv, reg, val); --} --static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&p->reg_lock, reg_flags); -- __iwl_set_bit(__FILE__, __LINE__, p, r, m); -- spin_unlock_irqrestore(&p->reg_lock, reg_flags); --} --#else --static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&p->reg_lock, reg_flags); -- _iwl_set_bit(p, r, m); -- spin_unlock_irqrestore(&p->reg_lock, reg_flags); --} --#endif -- --static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) --{ -- _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); --} --#ifdef CONFIG_IWLWIFI_DEBUG --static inline void __iwl_clear_bit(const char *f, u32 l, -- struct iwl_priv *priv, u32 reg, u32 mask) --{ -- u32 val = _iwl_read32(priv, reg) & ~mask; -- IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); -- _iwl_write32(priv, reg, val); --} --static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&p->reg_lock, reg_flags); -- __iwl_clear_bit(__FILE__, __LINE__, p, r, m); -- spin_unlock_irqrestore(&p->reg_lock, reg_flags); --} --#else --static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&p->reg_lock, reg_flags); -- _iwl_clear_bit(p, r, m); -- spin_unlock_irqrestore(&p->reg_lock, reg_flags); --} --#endif -- --static inline int _iwl_grab_nic_access(struct iwl_priv *priv) --{ -- int ret; -- u32 val; -- -- /* this bit wakes up the NIC */ -- _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -- -- /* -- * These bits say the device is running, and should keep running for -- * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), -- * but they do not indicate that embedded SRAM is restored yet; -- * 3945 and 4965 have volatile SRAM, and must save/restore contents -- * to/from host DRAM when sleeping/waking for power-saving. -- * Each direction takes approximately 1/4 millisecond; with this -- * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a -- * series of register accesses are expected (e.g. reading Event Log), -- * to keep device from sleeping. -- * -- * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that -- * SRAM is okay/restored. We don't check that here because this call -- * is just for hardware register access; but GP1 MAC_SLEEP check is a -- * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). -- * -- * 5000 series and later (including 1000 series) have non-volatile SRAM, -- * and do not save/restore SRAM when power cycling. -- */ -- ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, -- CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, -- (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | -- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); -- if (ret < 0) { -- val = _iwl_read32(priv, CSR_GP_CNTRL); -- IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); -- _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); -- return -EIO; -- } -- -- return 0; --} -- --#ifdef CONFIG_IWLWIFI_DEBUG --static inline int __iwl_grab_nic_access(const char *f, u32 l, -- struct iwl_priv *priv) --{ -- IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); -- return _iwl_grab_nic_access(priv); --} --#define iwl_grab_nic_access(priv) \ -- __iwl_grab_nic_access(__FILE__, __LINE__, priv) --#else --#define iwl_grab_nic_access(priv) \ -- _iwl_grab_nic_access(priv) --#endif -- --static inline void _iwl_release_nic_access(struct iwl_priv *priv) --{ -- _iwl_clear_bit(priv, CSR_GP_CNTRL, -- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); --} --#ifdef CONFIG_IWLWIFI_DEBUG --static inline void __iwl_release_nic_access(const char *f, u32 l, -- struct iwl_priv *priv) --{ -- -- IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); -- _iwl_release_nic_access(priv); --} --#define iwl_release_nic_access(priv) \ -- __iwl_release_nic_access(__FILE__, __LINE__, priv) --#else --#define iwl_release_nic_access(priv) \ -- _iwl_release_nic_access(priv) --#endif -- --static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) --{ -- return _iwl_read32(priv, reg); --} --#ifdef CONFIG_IWLWIFI_DEBUG --static inline u32 __iwl_read_direct32(const char *f, u32 l, -- struct iwl_priv *priv, u32 reg) --{ -- u32 value = _iwl_read_direct32(priv, reg); -- IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, -- f, l); -- return value; --} --static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) --{ -- u32 value; -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -- return value; --} -- --#else --static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) --{ -- u32 value; -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- value = _iwl_read_direct32(priv, reg); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -- return value; -- --} --#endif -- --static inline void _iwl_write_direct32(struct iwl_priv *priv, -- u32 reg, u32 value) --{ -- _iwl_write32(priv, reg, value); --} --static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- if (!iwl_grab_nic_access(priv)) { -- _iwl_write_direct32(priv, reg, value); -- iwl_release_nic_access(priv); -- } -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -- --static inline void iwl_write_reg_buf(struct iwl_priv *priv, -- u32 reg, u32 len, u32 *values) --{ -- u32 count = sizeof(u32); -- -- if ((priv != NULL) && (values != NULL)) { -- for (; 0 < len; len -= count, reg += count, values++) -- iwl_write_direct32(priv, reg, *values); -- } --} -- --static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, -- u32 mask, int timeout) --{ -- int t = 0; -- -- do { -- if ((iwl_read_direct32(priv, addr) & mask) == mask) -- return t; -- udelay(IWL_POLL_INTERVAL); -- t += IWL_POLL_INTERVAL; -- } while (t < timeout); -- -- return -ETIMEDOUT; --} -- --#ifdef CONFIG_IWLWIFI_DEBUG --static inline int __iwl_poll_direct_bit(const char *f, u32 l, -- struct iwl_priv *priv, -- u32 addr, u32 mask, int timeout) --{ -- int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); -- -- if (unlikely(ret == -ETIMEDOUT)) -- IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " -- "timedout - %s %d\n", addr, mask, f, l); -- else -- IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " -- "- %s %d\n", addr, mask, ret, f, l); -- return ret; --} --#define iwl_poll_direct_bit(priv, addr, mask, timeout) \ -- __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) --#else --#define iwl_poll_direct_bit _iwl_poll_direct_bit --#endif -- --static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) --{ -- _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); -- rmb(); -- return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); --} --static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) --{ -- unsigned long reg_flags; -- u32 val; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- val = _iwl_read_prph(priv, reg); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -- return val; --} -- --static inline void _iwl_write_prph(struct iwl_priv *priv, -- u32 addr, u32 val) --{ -- _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, -- ((addr & 0x0000FFFF) | (3 << 24))); -- wmb(); -- _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); --} -- --static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- if (!iwl_grab_nic_access(priv)) { -- _iwl_write_prph(priv, addr, val); -- iwl_release_nic_access(priv); -- } -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -- --#define _iwl_set_bits_prph(priv, reg, mask) \ -- _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) -+void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); -+void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); - --static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- _iwl_set_bits_prph(priv, reg, mask); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -+int iwl_poll_bit(struct iwl_priv *priv, u32 addr, -+ u32 bits, u32 mask, int timeout); -+int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, -+ int timeout); -+ -+int iwl_grab_nic_access_silent(struct iwl_priv *priv); -+int iwl_grab_nic_access(struct iwl_priv *priv); -+void iwl_release_nic_access(struct iwl_priv *priv); -+ -+u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); -+void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); -+ -+ -+u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); -+void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); -+void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -+void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, -+ u32 bits, u32 mask); -+void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -+ -+void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, -+ void *buf, int words); -+ -+#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ -+ do { \ -+ BUILD_BUG_ON((bufsize) % sizeof(u32)); \ -+ _iwl_read_targ_mem_words(priv, addr, buf, \ -+ (bufsize) / sizeof(u32));\ -+ } while (0) - --#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ -- _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) -- --static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, -- u32 bits, u32 mask) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- _iwl_set_bits_mask_prph(priv, reg, bits, mask); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -- --static inline void iwl_clear_bits_prph(struct iwl_priv -- *priv, u32 reg, u32 mask) --{ -- unsigned long reg_flags; -- u32 val; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- val = _iwl_read_prph(priv, reg); -- _iwl_write_prph(priv, reg, (val & ~mask)); -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -- --static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) --{ -- unsigned long reg_flags; -- u32 value; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- iwl_grab_nic_access(priv); -- -- _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); -- rmb(); -- value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); -- -- iwl_release_nic_access(priv); -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -- return value; --} -- --static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- if (!iwl_grab_nic_access(priv)) { -- _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); -- wmb(); -- _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); -- iwl_release_nic_access(priv); -- } -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -- --static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, -- u32 len, u32 *values) --{ -- unsigned long reg_flags; -- -- spin_lock_irqsave(&priv->reg_lock, reg_flags); -- if (!iwl_grab_nic_access(priv)) { -- _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); -- wmb(); -- for (; 0 < len; len -= sizeof(u32), values++) -- _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); -- -- iwl_release_nic_access(priv); -- } -- spin_unlock_irqrestore(&priv->reg_lock, reg_flags); --} -+u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); -+void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-led.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-led.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-led.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-led.c 2011-05-05 23:29:45.325439931 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * 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 -@@ -61,10 +61,16 @@ - { .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 @@ - 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 @@ - 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-led.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-led.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-led.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-led.h 2011-05-05 23:29:45.406440909 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * 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 -@@ -50,6 +50,7 @@ - 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); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-power.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-power.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-power.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-power.c 2011-05-05 23:29:45.282439411 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -188,9 +188,10 @@ - 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 @@ - - 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) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-power.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-power.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-power.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-power.h 2011-05-05 23:29:45.389440705 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-prph.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-prph.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-prph.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-prph.h 2011-05-05 23:29:45.347440197 +0200 -@@ -5,7 +5,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 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 -@@ -30,7 +30,7 @@ - * - * BSD LICENSE - * -- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without -@@ -91,7 +91,6 @@ - #define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) - #define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) - #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) --#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ - #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) - #define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ - #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) -@@ -99,152 +98,6 @@ - #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) - - /** -- * BSM (Bootstrap State Machine) -- * -- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program -- * in special SRAM that does not power down when the embedded control -- * processor is sleeping (e.g. for periodic power-saving shutdowns of radio). -- * -- * When powering back up after sleeps (or during initial uCode load), the BSM -- * internally loads the short bootstrap program from the special SRAM into the -- * embedded processor's instruction SRAM, and starts the processor so it runs -- * the bootstrap program. -- * -- * This bootstrap program loads (via PCI busmaster DMA) instructions and data -- * images for a uCode program from host DRAM locations. The host driver -- * indicates DRAM locations and sizes for instruction and data images via the -- * four BSM_DRAM_* registers. Once the bootstrap program loads the new program, -- * the new program starts automatically. -- * -- * The uCode used for open-source drivers includes two programs: -- * -- * 1) Initialization -- performs hardware calibration and sets up some -- * internal data, then notifies host via "initialize alive" notification -- * (struct iwl_init_alive_resp) that it has completed all of its work. -- * After signal from host, it then loads and starts the runtime program. -- * The initialization program must be used when initially setting up the -- * NIC after loading the driver. -- * -- * 2) Runtime/Protocol -- performs all normal runtime operations. This -- * notifies host via "alive" notification (struct iwl_alive_resp) that it -- * is ready to be used. -- * -- * When initializing the NIC, the host driver does the following procedure: -- * -- * 1) Load bootstrap program (instructions only, no data image for bootstrap) -- * into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND -- * -- * 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction -- * images in host DRAM. -- * -- * 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked: -- * BSM_WR_MEM_SRC_REG = 0 -- * BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND -- * BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image -- * -- * 4) Load bootstrap into instruction SRAM: -- * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START -- * -- * 5) Wait for load completion: -- * Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0 -- * -- * 6) Enable future boot loads whenever NIC's power management triggers it: -- * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN -- * -- * 7) Start the NIC by removing all reset bits: -- * CSR_RESET = 0 -- * -- * The bootstrap uCode (already in instruction SRAM) loads initialization -- * uCode. Initialization uCode performs data initialization, sends -- * "initialize alive" notification to host, and waits for a signal from -- * host to load runtime code. -- * -- * 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction -- * images in host DRAM. The last register loaded must be the instruction -- * byte count register ("1" in MSbit tells initialization uCode to load -- * the runtime uCode): -- * BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD -- * -- * 5) Wait for "alive" notification, then issue normal runtime commands. -- * -- * Data caching during power-downs: -- * -- * Just before the embedded controller powers down (e.g for automatic -- * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA) -- * a current snapshot of the embedded processor's data SRAM into host DRAM. -- * This caches the data while the embedded processor's memory is powered down. -- * Location and size are controlled by BSM_DRAM_DATA_* registers. -- * -- * NOTE: Instruction SRAM does not need to be saved, since that doesn't -- * change during operation; the original image (from uCode distribution -- * file) can be used for reload. -- * -- * When powering back up, the BSM loads the bootstrap program. Bootstrap looks -- * at the BSM_DRAM_* registers, which now point to the runtime instruction -- * image and the cached (modified) runtime data (*not* the initialization -- * uCode). Bootstrap reloads these runtime images into SRAM, and restarts the -- * uCode from where it left off before the power-down. -- * -- * NOTE: Initialization uCode does *not* run as part of the save/restore -- * procedure. -- * -- * This save/restore method is mostly for autonomous power management during -- * normal operation (result of POWER_TABLE_CMD). Platform suspend/resume and -- * RFKILL should use complete restarts (with total re-initialization) of uCode, -- * allowing total shutdown (including BSM memory). -- * -- * Note that, during normal operation, the host DRAM that held the initial -- * startup data for the runtime code is now being used as a backup data cache -- * for modified data! If you need to completely re-initialize the NIC, make -- * sure that you use the runtime data image from the uCode distribution file, -- * not the modified/saved runtime data. You may want to store a separate -- * "clean" runtime data image in DRAM to avoid disk reads of distribution file. -- */ -- --/* BSM bit fields */ --#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ --#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ --#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */ -- --/* BSM addresses */ --#define BSM_BASE (PRPH_BASE + 0x3400) --#define BSM_END (PRPH_BASE + 0x3800) -- --#define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */ --#define BSM_WR_MEM_SRC_REG (BSM_BASE + 0x004) /* source in BSM mem */ --#define BSM_WR_MEM_DST_REG (BSM_BASE + 0x008) /* dest in SRAM mem */ --#define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */ --#define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */ -- --/* -- * Pointers and size regs for bootstrap load and data SRAM save/restore. -- * NOTE: 3945 pointers use bits 31:0 of DRAM address. -- * 4965 pointers use bits 35:4 of DRAM address. -- */ --#define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090) --#define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094) --#define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098) --#define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C) -- --/* -- * BSM special memory, stays powered on during power-save sleeps. -- * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1) -- */ --#define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800) --#define BSM_SRAM_SIZE (1024) /* bytes */ -- -- --/* 3945 Tx scheduler registers */ --#define ALM_SCD_BASE (PRPH_BASE + 0x2E00) --#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000) --#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004) --#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010) --#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014) --#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020) --#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C) --#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030) -- --/** - * Tx Scheduler - * - * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs -@@ -254,17 +107,7 @@ - * 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): -@@ -298,7 +141,7 @@ - * 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. -@@ -311,7 +154,7 @@ - * - * 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: -@@ -330,201 +173,10 @@ - * Max Tx window size is the max number of contiguous TFDs that the scheduler - * can keep track of at one time when creating block-ack chains of frames. - * Note that "64" matches the number of ack bits in a block-ack packet. -- * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize -- * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values. - */ - #define SCD_WIN_SIZE 64 - #define SCD_FRAME_LIMIT 64 - --/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */ --#define IWL49_SCD_START_OFFSET 0xa02c00 -- --/* -- * 4965 tells driver SRAM address for internal scheduler structs via this reg. -- * Value is valid only after "Alive" response from uCode. -- */ --#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x0) -- --/* -- * Driver may need to update queue-empty bits after changing queue's -- * write and read pointers (indexes) during (re-)initialization (i.e. when -- * scheduler is not tracking what's happening). -- * Bit fields: -- * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit -- * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty -- * NOTE: This register is not used by Linux driver. -- */ --#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_START_OFFSET + 0x4) -- --/* -- * Physical base address of array of byte count (BC) circular buffers (CBs). -- * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode. -- * This register points to BC CB for queue 0, must be on 1024-byte boundary. -- * Others are spaced by 1024 bytes. -- * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad. -- * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff). -- * Bit fields: -- * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned. -- */ --#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x10) -- --/* -- * Enables any/all Tx DMA/FIFO channels. -- * Scheduler generates requests for only the active channels. -- * Set this to 0xff to enable all 8 channels (normal usage). -- * Bit fields: -- * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 -- */ --#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c) --/* -- * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. -- * Initialized and updated by driver as new TFDs are added to queue. -- * NOTE: If using Block Ack, index must correspond to frame's -- * Start Sequence Number; index = (SSN & 0xff) -- * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses? -- */ --#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4) -- --/* -- * Queue (x) Read Pointers (indexes, really!), one for each Tx queue. -- * For FIFO mode, index indicates next frame to transmit. -- * For Scheduler-ACK mode, index indicates first frame in Tx window. -- * Initialized by driver, updated by scheduler. -- */ --#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4) -- --/* -- * Select which queues work in chain mode (1) vs. not (0). -- * Use chain mode to build chains of aggregated frames. -- * Bit fields: -- * 31-16: Reserved -- * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time -- * NOTE: If driver sets up queue for chain mode, it should be also set up -- * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x). -- */ --#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_START_OFFSET + 0xd0) -- --/* -- * Select which queues interrupt driver when scheduler increments -- * a queue's read pointer (index). -- * Bit fields: -- * 31-16: Reserved -- * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled -- * NOTE: This functionality is apparently a no-op; driver relies on interrupts -- * from Rx queue to read Tx command responses and update Tx queues. -- */ --#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_START_OFFSET + 0xe4) -- --/* -- * Queue search status registers. One for each queue. -- * Sets up queue mode and assigns queue to Tx DMA channel. -- * Bit fields: -- * 19-10: Write mask/enable bits for bits 0-9 -- * 9: Driver should init to "0" -- * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0). -- * Driver should init to "1" for aggregation mode, or "0" otherwise. -- * 7-6: Driver should init to "0" -- * 5: Window Size Left; indicates whether scheduler can request -- * another TFD, based on window size, etc. Driver should init -- * this bit to "1" for aggregation mode, or "0" for non-agg. -- * 4-1: Tx FIFO to use (range 0-7). -- * 0: Queue is active (1), not active (0). -- * Other bits should be written as "0" -- * -- * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled -- * via SCD_QUEUECHAIN_SEL. -- */ --#define IWL49_SCD_QUEUE_STATUS_BITS(x)\ -- (IWL49_SCD_START_OFFSET + 0x104 + (x) * 4) -- --/* Bit field positions */ --#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE (0) --#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF (1) --#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL (5) --#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK (8) -- --/* Write masks */ --#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) --#define IWL49_SCD_QUEUE_STTS_REG_MSK (0x0007FC00) -- --/** -- * 4965 internal SRAM structures for scheduler, shared with driver ... -- * -- * Driver should clear and initialize the following areas after receiving -- * "Alive" response from 4965 uCode, i.e. after initial -- * uCode load, or after a uCode load done for error recovery: -- * -- * SCD_CONTEXT_DATA_OFFSET (size 128 bytes) -- * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes) -- * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes) -- * -- * Driver accesses SRAM via HBUS_TARG_MEM_* registers. -- * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR. -- * All OFFSET values must be added to this base address. -- */ -- --/* -- * Queue context. One 8-byte entry for each of 16 queues. -- * -- * Driver should clear this entire area (size 0x80) to 0 after receiving -- * "Alive" notification from uCode. Additionally, driver should init -- * each queue's entry as follows: -- * -- * LS Dword bit fields: -- * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64. -- * -- * MS Dword bit fields: -- * 16-22: Frame limit. Driver should init to 10 (0xa). -- * -- * Driver should init all other bits to 0. -- * -- * Init must be done after driver receives "Alive" response from 4965 uCode, -- * and when setting up queue for aggregation. -- */ --#define IWL49_SCD_CONTEXT_DATA_OFFSET 0x380 --#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \ -- (IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) -- --#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) --#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) --#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) --#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) -- --/* -- * Tx Status Bitmap -- * -- * Driver should clear this entire area (size 0x100) to 0 after receiving -- * "Alive" notification from uCode. Area is used only by device itself; -- * no other support (besides clearing) is required from driver. -- */ --#define IWL49_SCD_TX_STTS_BITMAP_OFFSET 0x400 -- --/* -- * RAxTID to queue translation mapping. -- * -- * When queue is in Scheduler-ACK mode, frames placed in a that queue must be -- * for only one combination of receiver address (RA) and traffic ID (TID), i.e. -- * one QOS priority level destined for one station (for this wireless link, -- * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit -- * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK -- * mode, the device ignores the mapping value. -- * -- * Bit fields, for each 16-bit map: -- * 15-9: Reserved, set to 0 -- * 8-4: Index into device's station table for recipient station -- * 3-0: Traffic ID (tid), range 0-15 -- * -- * Driver should clear this entire area (size 32 bytes) to 0 after receiving -- * "Alive" notification from uCode. To update a 16-bit map value, driver -- * must read a dword-aligned value from device SRAM, replace the 16-bit map -- * value of interest, and write the dword value back into device SRAM. -- */ --#define IWL49_SCD_TRANSLATE_TBL_OFFSET 0x500 -- --/* Find translation table dword to read/write for given queue */ --#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ -- ((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) -- - #define IWL_SCD_TXFIFO_POS_TID (0) - #define IWL_SCD_TXFIFO_POS_RA (4) - #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-rx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-rx.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-rx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-rx.c 2011-05-05 23:29:45.373440511 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -225,55 +225,6 @@ - * - ******************************************************************************/ - --static void iwl_rx_reply_alive(struct iwl_priv *priv, -- struct iwl_rx_mem_buffer *rxb) --{ -- struct iwl_rx_packet *pkt = rxb_addr(rxb); -- struct iwl_alive_resp *palive; -- struct delayed_work *pwork; -- -- palive = &pkt->u.alive_frame; -- -- IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " -- "0x%01X 0x%01X\n", -- palive->is_valid, palive->ver_type, -- palive->ver_subtype); -- -- if (palive->ver_subtype == INITIALIZE_SUBTYPE) { -- IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); -- memcpy(&priv->card_alive_init, -- &pkt->u.alive_frame, -- sizeof(struct iwl_init_alive_resp)); -- pwork = &priv->init_alive_start; -- } else { -- IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); -- memcpy(&priv->card_alive, &pkt->u.alive_frame, -- sizeof(struct iwl_alive_resp)); -- pwork = &priv->alive_start; -- } -- -- /* We delay the ALIVE response by 5ms to -- * give the HW RF Kill time to activate... */ -- if (palive->is_valid == UCODE_VALID_OK) -- queue_delayed_work(priv->workqueue, pwork, -- msecs_to_jiffies(5)); -- else { -- IWL_WARN(priv, "%s uCode did not respond OK.\n", -- (palive->ver_subtype == INITIALIZE_SUBTYPE) ? -- "init" : "runtime"); -- /* -- * If fail to load init uCode, -- * let's try to load the init uCode again. -- * We should not get into this situation, but if it -- * does happen, we should not move on and loading "runtime" -- * without proper calibrate the device. -- */ -- if (palive->ver_subtype == INITIALIZE_SUBTYPE) -- priv->ucode_type = UCODE_NONE; -- queue_work(priv->workqueue, &priv->restart); -- } --} -- - static void iwl_rx_reply_error(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) - { -@@ -390,21 +341,16 @@ - * 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 +376,10 @@ - * 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 +396,9 @@ - * 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 +408,12 @@ - return true; - } - -- if (iwl_bt_statistics(priv)) { -- struct statistics_rx_bt *cur, *old; -+ 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); - -- 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(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 +428,35 @@ - } - - 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 (iwlagn_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 (iwlagn_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 +470,8 @@ - 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 +503,153 @@ - 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 +676,12 @@ - - 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 +835,7 @@ - { - 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)) { -@@ -882,7 +845,7 @@ - } - - /* In case of HW accelerated crypto and bad decryption, drop */ -- if (!priv->cfg->mod_params->sw_crypto && -+ if (!iwlagn_mod_params.sw_crypto && - iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) - return; - -@@ -895,10 +858,29 @@ - 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); -- priv->alloc_rxb_page--; - rxb->page = NULL; - } - -@@ -1093,7 +1075,6 @@ - - handlers = priv->rx_handlers; - -- handlers[REPLY_ALIVE] = iwl_rx_reply_alive; - handlers[REPLY_ERROR] = iwl_rx_reply_error; - handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; - handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-scan.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-scan.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-scan.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-scan.c 2011-05-05 23:29:45.237438867 +0200 -@@ -2,7 +2,7 @@ - * - * GPL LICENSE SUMMARY - * -- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-spectrum.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-spectrum.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-spectrum.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-spectrum.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,92 +0,0 @@ --/****************************************************************************** -- * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -- * -- * Portions of this file are derived from the ieee80211 subsystem header files. -- * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of version 2 of the GNU General Public License as -- * published by the Free Software Foundation. -- * -- * This program is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- * more details. -- * -- * You should have received a copy of the GNU General Public License along with -- * this program; if not, write to the Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA -- * -- * The full GNU General Public License is included in this distribution in the -- * file called LICENSE. -- * -- * Contact Information: -- * Intel Linux Wireless -- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -- * -- *****************************************************************************/ -- --#ifndef __iwl_spectrum_h__ --#define __iwl_spectrum_h__ --enum { /* ieee80211_basic_report.map */ -- IEEE80211_BASIC_MAP_BSS = (1 << 0), -- IEEE80211_BASIC_MAP_OFDM = (1 << 1), -- IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2), -- IEEE80211_BASIC_MAP_RADAR = (1 << 3), -- IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4), -- /* Bits 5-7 are reserved */ -- --}; --struct ieee80211_basic_report { -- u8 channel; -- __le64 start_time; -- __le16 duration; -- u8 map; --} __packed; -- --enum { /* ieee80211_measurement_request.mode */ -- /* Bit 0 is reserved */ -- IEEE80211_MEASUREMENT_ENABLE = (1 << 1), -- IEEE80211_MEASUREMENT_REQUEST = (1 << 2), -- IEEE80211_MEASUREMENT_REPORT = (1 << 3), -- /* Bits 4-7 are reserved */ --}; -- --enum { -- IEEE80211_REPORT_BASIC = 0, /* required */ -- IEEE80211_REPORT_CCA = 1, /* optional */ -- IEEE80211_REPORT_RPI = 2, /* optional */ -- /* 3-255 reserved */ --}; -- --struct ieee80211_measurement_params { -- u8 channel; -- __le64 start_time; -- __le16 duration; --} __packed; -- --struct ieee80211_info_element { -- u8 id; -- u8 len; -- u8 data[0]; --} __packed; -- --struct ieee80211_measurement_request { -- struct ieee80211_info_element ie; -- u8 token; -- u8 mode; -- u8 type; -- struct ieee80211_measurement_params params[0]; --} __packed; -- --struct ieee80211_measurement_report { -- struct ieee80211_info_element ie; -- u8 token; -- u8 mode; -- u8 type; -- union { -- struct ieee80211_basic_report basic[0]; -- } u; --} __packed; -- --#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-sta.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-sta.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-sta.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-sta.c 2011-05-05 23:29:45.267439231 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -233,7 +233,6 @@ - struct iwl_station_entry *station; - int i; - u8 sta_id = IWL_INVALID_STATION; -- u16 rate; - - if (is_ap) - sta_id = ctx->ap_sta_id; -@@ -306,12 +305,6 @@ - */ - iwl_set_ht_add_station(priv, sta_id, sta, ctx); - -- /* 3945 only */ -- rate = (priv->band == IEEE80211_BAND_5GHZ) ? -- IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP; -- /* Turn on both antennas for the station... */ -- station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); -- - return sta_id; - - } -@@ -501,7 +494,8 @@ - - 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); - -@@ -686,7 +680,8 @@ - - 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; - } -@@ -782,7 +777,8 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-sta.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-sta.h ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-sta.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-sta.h 2011-05-05 23:29:45.374440523 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/iwl-tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/iwl-tx.c 2011-05-05 23:29:45.257439109 +0200 -@@ -1,6 +1,6 @@ - /****************************************************************************** - * -- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. -+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. -@@ -149,32 +149,31 @@ - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; - struct iwl_queue *q = &txq->q; - int i; -- bool huge = false; - - if (q->n_bd == 0) - return; - - while (q->read_ptr != q->write_ptr) { -- /* we have no way to tell if it is a huge cmd ATM */ - i = get_cmd_index(q, q->read_ptr, 0); - -- if (txq->meta[i].flags & CMD_SIZE_HUGE) -- huge = true; -- else -+ if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); -+ txq->meta[i].flags = 0; -+ } - -- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); -+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); - } - -- if (huge) { -- i = q->n_window; -+ i = q->n_window; -+ if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); -+ txq->meta[i].flags = 0; - } - } - -@@ -233,7 +232,6 @@ - * 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) -@@ -265,11 +263,13 @@ - - /* 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) -@@ -386,7 +386,9 @@ - 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); -@@ -448,14 +450,19 @@ - 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", -@@ -463,35 +470,39 @@ - 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"); -- queue_work(priv->workqueue, &priv->restart); -+ iwlagn_fw_error(priv, false); - } - return -ENOSPC; - } - -- spin_lock_irqsave(&priv->hcmd_lock, flags); -- -- /* If this is a huge cmd, mark the huge flag also on the meta.flags -- * of the _original_ cmd. This is used for DMA mapping clean up. -- */ -- if (cmd->flags & CMD_SIZE_HUGE) { -- idx = get_cmd_index(q, q->write_ptr, 0); -- txq->meta[idx].flags = CMD_SIZE_HUGE; -- } -- - idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); - out_cmd = txq->cmd[idx]; - out_meta = &txq->meta[idx]; - -+ if (WARN_ON(out_meta->flags & CMD_MAPPED)) { -+ spin_unlock_irqrestore(&priv->hcmd_lock, flags); -+ return -ENOSPC; -+ } -+ - memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ -- out_meta->flags = cmd->flags; -+ out_meta->flags = cmd->flags | CMD_MAPPED; - if (cmd->flags & CMD_WANT_SKB) - out_meta->source = cmd; - if (cmd->flags & CMD_ASYNC) -@@ -584,7 +595,7 @@ - if (nfreed++ > 0) { - IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, - q->write_ptr, q->read_ptr); -- queue_work(priv->workqueue, &priv->restart); -+ iwlagn_fw_error(priv, false); - } - - } -@@ -609,6 +620,7 @@ - struct iwl_device_cmd *cmd; - struct iwl_cmd_meta *meta; - struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; -+ unsigned long flags; - - /* If a Tx command is being handled and it isn't in the actual - * command queue then there a command routing bug has been introduced -@@ -622,14 +634,6 @@ - return; - } - -- /* If this is a huge cmd, clear the huge flag on the meta.flags -- * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap -- * the DMA buffer for the scan (huge) command. -- */ -- if (huge) { -- cmd_index = get_cmd_index(&txq->q, index, 0); -- txq->meta[cmd_index].flags = 0; -- } - cmd_index = get_cmd_index(&txq->q, index, huge); - cmd = txq->cmd[cmd_index]; - meta = &txq->meta[cmd_index]; -@@ -646,6 +650,8 @@ - } else if (meta->callback) - meta->callback(priv, cmd, pkt); - -+ spin_lock_irqsave(&priv->hcmd_lock, flags); -+ - iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); - - if (!(meta->flags & CMD_ASYNC)) { -@@ -654,5 +660,9 @@ - get_cmd_string(cmd->hdr.cmd)); - wake_up_interruptible(&priv->wait_command_queue); - } -+ -+ /* Mark as unmapped */ - meta->flags = 0; -+ -+ spin_unlock_irqrestore(&priv->hcmd_lock, flags); - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/iwlwifi/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/iwlwifi/Makefile 2011-05-05 23:29:45.339440101 +0200 -@@ -1,8 +1,8 @@ - # 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 -+iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o - iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o - - iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o -@@ -14,7 +14,6 @@ - iwlagn-objs += iwl-1000.o - iwlagn-objs += iwl-2000.o - --iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o - iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o - iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/Kconfig 2011-05-05 23:29:49.211486883 +0200 -@@ -284,5 +284,6 @@ - source "drivers/net/wireless/wl1251/Kconfig" - source "drivers/net/wireless/wl12xx/Kconfig" - source "drivers/net/wireless/zd1211rw/Kconfig" -+source "drivers/net/wireless/mwifiex/Kconfig" - - endif # WLAN -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/cfg.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cfg.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/cfg.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cfg.c 2011-05-05 23:29:46.522454393 +0200 -@@ -122,8 +122,10 @@ - } - - --/* Various firmware commands need the list of supported rates, but with -- the hight-bit set for basic rates */ -+/* -+ * Various firmware commands need the list of supported rates, but with -+ * the hight-bit set for basic rates -+ */ - static int lbs_add_rates(u8 *rates) - { - size_t i; -@@ -425,7 +427,7 @@ - return ie_len + 2; - } - --/*************************************************************************** -+/* - * Set Channel - */ - -@@ -452,7 +454,7 @@ - - - --/*************************************************************************** -+/* - * Scanning - */ - -@@ -538,8 +540,10 @@ - goto done; - } - -- /* Validity check: the TLV holds TSF values with 8 bytes each, so -- * the size in the TLV must match the nr_sets value */ -+ /* -+ * Validity check: the TLV holds TSF values with 8 bytes each, so -+ * the size in the TLV must match the nr_sets value -+ */ - i = get_unaligned_le16(tsfdesc); - tsfdesc += 2; - if (i / 8 != scanresp->nr_sets) { -@@ -581,8 +585,10 @@ - - /* To find out the channel, we must parse the IEs */ - ie = pos; -- /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon -- interval, capabilities */ -+ /* -+ * 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon -+ * interval, capabilities -+ */ - ielen = left = len - (6 + 1 + 8 + 2 + 2); - while (left >= 2) { - u8 id, elen; -@@ -790,7 +796,7 @@ - - - --/*************************************************************************** -+/* - * Events - */ - -@@ -825,7 +831,7 @@ - - - --/*************************************************************************** -+/* - * Connect/disconnect - */ - -@@ -950,8 +956,10 @@ - * Set WPA/WPA key material - */ - --/* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we -- * get rid of WEXT, this should go into host.h */ -+/* -+ * like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we -+ * get rid of WEXT, this should go into host.h -+ */ - - struct cmd_key_material { - struct cmd_header hdr; -@@ -1536,7 +1544,7 @@ - } - - --/*************************************************************************** -+/* - * Get station - */ - -@@ -1581,7 +1589,7 @@ - - - --/*************************************************************************** -+/* - * "Site survey", here just current channel and noise level - */ - -@@ -1614,7 +1622,7 @@ - - - --/*************************************************************************** -+/* - * Change interface - */ - -@@ -1656,11 +1664,12 @@ - - - --/*************************************************************************** -+/* - * IBSS (Ad-Hoc) - */ - --/* The firmware needs the following bits masked out of the beacon-derived -+/* -+ * The firmware needs the following bits masked out of the beacon-derived - * capability field when associating/joining to a BSS: - * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) - */ -@@ -1999,7 +2008,7 @@ - - - --/*************************************************************************** -+/* - * Initialization - */ - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/cmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/cmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cmd.c 2011-05-05 23:29:46.547454696 +0200 -@@ -1,7 +1,7 @@ --/** -- * This file contains the handling of command. -- * It prepares command and sends it to firmware when it is ready. -- */ -+/* -+ * This file contains the handling of command. -+ * It prepares command and sends it to firmware when it is ready. -+ */ - - #include - #include -@@ -16,14 +16,14 @@ - #define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf))) - - /** -- * @brief Simple callback that copies response back into command -+ * lbs_cmd_copyback - Simple callback that copies response back into command - * -- * @param priv A pointer to struct lbs_private structure -- * @param extra A pointer to the original command structure for which -- * 'resp' is a response -- * @param resp A pointer to the command response -+ * @priv: A pointer to &struct lbs_private structure -+ * @extra: A pointer to the original command structure for which -+ * 'resp' is a response -+ * @resp: A pointer to the command response - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp) -@@ -38,15 +38,15 @@ - EXPORT_SYMBOL_GPL(lbs_cmd_copyback); - - /** -- * @brief Simple callback that ignores the result. Use this if -- * you just want to send a command to the hardware, but don't -+ * lbs_cmd_async_callback - Simple callback that ignores the result. -+ * Use this if you just want to send a command to the hardware, but don't - * care for the result. - * -- * @param priv ignored -- * @param extra ignored -- * @param resp ignored -+ * @priv: ignored -+ * @extra: ignored -+ * @resp: ignored - * -- * @return 0 for success -+ * returns: 0 for success - */ - static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp) -@@ -56,10 +56,11 @@ - - - /** -- * @brief Checks whether a command is allowed in Power Save mode -+ * is_command_allowed_in_ps - tests if a command is allowed in Power Save mode -+ * -+ * @cmd: the command ID - * -- * @param command the command ID -- * @return 1 if allowed, 0 if not allowed -+ * returns: 1 if allowed, 0 if not allowed - */ - static u8 is_command_allowed_in_ps(u16 cmd) - { -@@ -75,11 +76,12 @@ - } - - /** -- * @brief Updates the hardware details like MAC address and regulatory region -+ * lbs_update_hw_spec - Updates the hardware details like MAC address -+ * and regulatory region - * -- * @param priv A pointer to struct lbs_private structure -+ * @priv: A pointer to &struct lbs_private structure - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_update_hw_spec(struct lbs_private *priv) - { -@@ -217,14 +219,14 @@ - EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); - - /** -- * @brief Sets the Power Save mode -+ * lbs_set_ps_mode - Sets the Power Save mode - * -- * @param priv A pointer to struct lbs_private structure -- * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or -+ * @priv: A pointer to &struct lbs_private structure -+ * @cmd_action: The Power Save operation (PS_MODE_ACTION_ENTER_PS or - * PS_MODE_ACTION_EXIT_PS) -- * @param block Whether to block on a response or not -+ * @block: Whether to block on a response or not - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block) - { -@@ -417,13 +419,13 @@ - } - - /** -- * @brief Set an SNMP MIB value -+ * lbs_set_snmp_mib - Set an SNMP MIB value - * -- * @param priv A pointer to struct lbs_private structure -- * @param oid The OID to set in the firmware -- * @param val Value to set the OID to -+ * @priv: A pointer to &struct lbs_private structure -+ * @oid: The OID to set in the firmware -+ * @val: Value to set the OID to - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) - { -@@ -467,13 +469,13 @@ - } - - /** -- * @brief Get an SNMP MIB value -+ * lbs_get_snmp_mib - Get an SNMP MIB value - * -- * @param priv A pointer to struct lbs_private structure -- * @param oid The OID to retrieve from the firmware -- * @param out_val Location for the returned value -+ * @priv: A pointer to &struct lbs_private structure -+ * @oid: The OID to retrieve from the firmware -+ * @out_val: Location for the returned value - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) - { -@@ -510,14 +512,14 @@ - } - - /** -- * @brief Get the min, max, and current TX power -+ * lbs_get_tx_power - Get the min, max, and current TX power - * -- * @param priv A pointer to struct lbs_private structure -- * @param curlevel Current power level in dBm -- * @param minlevel Minimum supported power level in dBm (optional) -- * @param maxlevel Maximum supported power level in dBm (optional) -+ * @priv: A pointer to &struct lbs_private structure -+ * @curlevel: Current power level in dBm -+ * @minlevel: Minimum supported power level in dBm (optional) -+ * @maxlevel: Maximum supported power level in dBm (optional) - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, - s16 *maxlevel) -@@ -545,12 +547,12 @@ - } - - /** -- * @brief Set the TX power -+ * lbs_set_tx_power - Set the TX power - * -- * @param priv A pointer to struct lbs_private structure -- * @param dbm The desired power level in dBm -+ * @priv: A pointer to &struct lbs_private structure -+ * @dbm: The desired power level in dBm - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) - { -@@ -573,12 +575,13 @@ - } - - /** -- * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW) -+ * lbs_set_monitor_mode - Enable or disable monitor mode -+ * (only implemented on OLPC usb8388 FW) - * -- * @param priv A pointer to struct lbs_private structure -- * @param enable 1 to enable monitor mode, 0 to disable -+ * @priv: A pointer to &struct lbs_private structure -+ * @enable: 1 to enable monitor mode, 0 to disable - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_set_monitor_mode(struct lbs_private *priv, int enable) - { -@@ -604,11 +607,11 @@ - } - - /** -- * @brief Get the radio channel -+ * lbs_get_channel - Get the radio channel - * -- * @param priv A pointer to struct lbs_private structure -+ * @priv: A pointer to &struct lbs_private structure - * -- * @return The channel on success, error on failure -+ * returns: The channel on success, error on failure - */ - static int lbs_get_channel(struct lbs_private *priv) - { -@@ -650,12 +653,12 @@ - } - - /** -- * @brief Set the radio channel -+ * lbs_set_channel - Set the radio channel - * -- * @param priv A pointer to struct lbs_private structure -- * @param channel The desired channel, or 0 to clear a locked channel -+ * @priv: A pointer to &struct lbs_private structure -+ * @channel: The desired channel, or 0 to clear a locked channel - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_set_channel(struct lbs_private *priv, u8 channel) - { -@@ -686,12 +689,13 @@ - } - - /** -- * @brief Get current RSSI and noise floor -+ * lbs_get_rssi - Get current RSSI and noise floor - * -- * @param priv A pointer to struct lbs_private structure -- * @param rssi On successful return, signal level in mBm -+ * @priv: A pointer to &struct lbs_private structure -+ * @rssi: On successful return, signal level in mBm -+ * @nf: On successful return, Noise floor - * -- * @return The channel on success, error on failure -+ * returns: The channel on success, error on failure - */ - int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) - { -@@ -719,13 +723,14 @@ - } - - /** -- * @brief Send regulatory and 802.11d domain information to the firmware -+ * lbs_set_11d_domain_info - Send regulatory and 802.11d domain information -+ * to the firmware - * -- * @param priv pointer to struct lbs_private -- * @param request cfg80211 regulatory request structure -- * @param bands the device's supported bands and channels -+ * @priv: pointer to &struct lbs_private -+ * @request: cfg80211 regulatory request structure -+ * @bands: the device's supported bands and channels - * -- * @return 0 on success, error code on failure -+ * returns: 0 on success, error code on failure - */ - int lbs_set_11d_domain_info(struct lbs_private *priv, - struct regulatory_request *request, -@@ -842,15 +847,15 @@ - } - - /** -- * @brief Read a MAC, Baseband, or RF register -+ * lbs_get_reg - Read a MAC, Baseband, or RF register - * -- * @param priv pointer to struct lbs_private -- * @param cmd register command, one of CMD_MAC_REG_ACCESS, -- * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS -- * @param offset byte offset of the register to get -- * @param value on success, the value of the register at 'offset' -+ * @priv: pointer to &struct lbs_private -+ * @reg: register command, one of CMD_MAC_REG_ACCESS, -+ * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS -+ * @offset: byte offset of the register to get -+ * @value: on success, the value of the register at 'offset' - * -- * @return 0 on success, error code on failure -+ * returns: 0 on success, error code on failure - */ - int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value) - { -@@ -886,15 +891,15 @@ - } - - /** -- * @brief Write a MAC, Baseband, or RF register -+ * lbs_set_reg - Write a MAC, Baseband, or RF register - * -- * @param priv pointer to struct lbs_private -- * @param cmd register command, one of CMD_MAC_REG_ACCESS, -- * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS -- * @param offset byte offset of the register to set -- * @param value the value to write to the register at 'offset' -+ * @priv: pointer to &struct lbs_private -+ * @reg: register command, one of CMD_MAC_REG_ACCESS, -+ * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS -+ * @offset: byte offset of the register to set -+ * @value: the value to write to the register at 'offset' - * -- * @return 0 on success, error code on failure -+ * returns: 0 on success, error code on failure - */ - int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value) - { -@@ -1023,7 +1028,7 @@ - lbs_deb_leave(LBS_DEB_HOST); - } - --/** -+/* - * This function inserts command node to cmdfreeq - * after cleans it. Requires priv->driver_lock held. - */ -@@ -1125,11 +1130,12 @@ - } - - /** -- * @brief This function allocates the command buffer and link -- * it to command free queue. -+ * lbs_allocate_cmd_buffer - allocates the command buffer and links -+ * it to command free queue -+ * -+ * @priv: A pointer to &struct lbs_private structure - * -- * @param priv A pointer to struct lbs_private structure -- * @return 0 or -1 -+ * returns: 0 for success or -1 on error - */ - int lbs_allocate_cmd_buffer(struct lbs_private *priv) - { -@@ -1171,10 +1177,11 @@ - } - - /** -- * @brief This function frees the command buffer. -+ * lbs_free_cmd_buffer - free the command buffer - * -- * @param priv A pointer to struct lbs_private structure -- * @return 0 or -1 -+ * @priv: A pointer to &struct lbs_private structure -+ * -+ * returns: 0 for success - */ - int lbs_free_cmd_buffer(struct lbs_private *priv) - { -@@ -1211,11 +1218,13 @@ - } - - /** -- * @brief This function gets a free command node if available in -- * command free queue. -+ * lbs_get_free_cmd_node - gets a free command node if available in -+ * command free queue -+ * -+ * @priv: A pointer to &struct lbs_private structure - * -- * @param priv A pointer to struct lbs_private structure -- * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL -+ * returns: A pointer to &cmd_ctrl_node structure on success -+ * or %NULL on error - */ - static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv) - { -@@ -1245,12 +1254,12 @@ - } - - /** -- * @brief This function executes next command in command -- * pending queue. It will put firmware back to PS mode -- * if applicable. -+ * lbs_execute_next_command - execute next command in command -+ * pending queue. Will put firmware back to PS mode if applicable. - * -- * @param priv A pointer to struct lbs_private structure -- * @return 0 or -1 -+ * @priv: A pointer to &struct lbs_private structure -+ * -+ * returns: 0 on success or -1 on error - */ - int lbs_execute_next_command(struct lbs_private *priv) - { -@@ -1454,12 +1463,12 @@ - } - - /** -- * @brief This function checks condition and prepares to -- * send sleep confirm command to firmware if ok. -+ * lbs_ps_confirm_sleep - checks condition and prepares to -+ * send sleep confirm command to firmware if ok -+ * -+ * @priv: A pointer to &struct lbs_private structure - * -- * @param priv A pointer to struct lbs_private structure -- * @param psmode Power Saving mode -- * @return n/a -+ * returns: n/a - */ - void lbs_ps_confirm_sleep(struct lbs_private *priv) - { -@@ -1499,16 +1508,16 @@ - - - /** -- * @brief Configures the transmission power control functionality. -+ * lbs_set_tpc_cfg - Configures the transmission power control functionality - * -- * @param priv A pointer to struct lbs_private structure -- * @param enable Transmission power control enable -- * @param p0 Power level when link quality is good (dBm). -- * @param p1 Power level when link quality is fair (dBm). -- * @param p2 Power level when link quality is poor (dBm). -- * @param usesnr Use Signal to Noise Ratio in TPC -+ * @priv: A pointer to &struct lbs_private structure -+ * @enable: Transmission power control enable -+ * @p0: Power level when link quality is good (dBm). -+ * @p1: Power level when link quality is fair (dBm). -+ * @p2: Power level when link quality is poor (dBm). -+ * @usesnr: Use Signal to Noise Ratio in TPC - * -- * @return 0 on success -+ * returns: 0 on success - */ - int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, - int8_t p2, int usesnr) -@@ -1531,15 +1540,15 @@ - } - - /** -- * @brief Configures the power adaptation settings. -+ * lbs_set_power_adapt_cfg - Configures the power adaptation settings - * -- * @param priv A pointer to struct lbs_private structure -- * @param enable Power adaptation enable -- * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm). -- * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). -- * @param p2 Power level for 48 and 54 Mbps (dBm). -+ * @priv: A pointer to &struct lbs_private structure -+ * @enable: Power adaptation enable -+ * @p0: Power level for 1, 2, 5.5 and 11 Mbps (dBm). -+ * @p1: Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). -+ * @p2: Power level for 48 and 54 Mbps (dBm). - * -- * @return 0 on Success -+ * returns: 0 on Success - */ - - int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/cmdresp.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cmdresp.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/cmdresp.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/cmdresp.c 2011-05-05 23:29:46.554454781 +0200 -@@ -1,7 +1,7 @@ --/** -- * This file contains the handling of command -- * responses as well as events generated by firmware. -- */ -+/* -+ * This file contains the handling of command -+ * responses as well as events generated by firmware. -+ */ - #include - #include - #include -@@ -12,12 +12,13 @@ - #include "cmd.h" - - /** -- * @brief This function handles disconnect event. it -- * reports disconnect to upper layer, clean tx/rx packets, -- * reset link state etc. -+ * lbs_mac_event_disconnected - handles disconnect event. It -+ * reports disconnect to upper layer, clean tx/rx packets, -+ * reset link state etc. -+ * -+ * @priv: A pointer to struct lbs_private structure - * -- * @param priv A pointer to struct lbs_private structure -- * @return n/a -+ * returns: n/a - */ - void lbs_mac_event_disconnected(struct lbs_private *priv) - { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/debugfs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/debugfs.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/debugfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/debugfs.c 2011-05-05 23:29:46.555454793 +0200 -@@ -849,15 +849,14 @@ - static int num_of_items = ARRAY_SIZE(items); - - /** -- * @brief proc read function -+ * lbs_debugfs_read - proc read function - * -- * @param page pointer to buffer -- * @param s read data starting position -- * @param off offset -- * @param cnt counter -- * @param eof end of file flag -- * @param data data to output -- * @return number of output data -+ * @file: file to read -+ * @userbuf: pointer to buffer -+ * @count: number of bytes to read -+ * @ppos: read data starting position -+ * -+ * returns: amount of data read or negative error code - */ - static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -@@ -897,13 +896,14 @@ - } - - /** -- * @brief proc write function -+ * lbs_debugfs_write - proc write function -+ * -+ * @f: file pointer -+ * @buf: pointer to data buffer -+ * @cnt: data number to write -+ * @ppos: file position - * -- * @param f file pointer -- * @param buf pointer to data buffer -- * @param cnt data number to write -- * @param data data to write -- * @return number of data -+ * returns: amount of data written - */ - static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, - size_t cnt, loff_t *ppos) -@@ -966,11 +966,11 @@ - }; - - /** -- * @brief create debug proc file -+ * lbs_debug_init - create debug proc file -+ * -+ * @priv: pointer to &struct lbs_private - * -- * @param priv pointer struct lbs_private -- * @param dev pointer net_device -- * @return N/A -+ * returns: N/A - */ - static void lbs_debug_init(struct lbs_private *priv) - { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/decl.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/decl.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/decl.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/decl.h 2011-05-05 23:29:46.553454769 +0200 -@@ -1,8 +1,8 @@ - --/** -- * This file contains declaration referring to -- * functions defined in other source files -- */ -+/* -+ * This file contains declaration referring to -+ * functions defined in other source files -+ */ - - #ifndef _LBS_DECL_H_ - #define _LBS_DECL_H_ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/defs.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/defs.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/defs.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/defs.h 2011-05-05 23:29:46.556454805 +0200 -@@ -1,7 +1,7 @@ --/** -- * This header file contains global constant/enum definitions, -- * global variable declaration. -- */ -+/* -+ * This header file contains global constant/enum definitions, -+ * global variable declaration. -+ */ - #ifndef _LBS_DEFS_H_ - #define _LBS_DEFS_H_ - -@@ -123,19 +123,19 @@ - - - --/** Buffer Constants */ -+/* Buffer Constants */ - - /* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical --* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas --* driver has more local TxPDs. Each TxPD on the host memory is associated --* with a Tx control node. The driver maintains 8 RxPD descriptors for --* station firmware to store Rx packet information. --* --* Current version of MAC has a 32x6 multicast address buffer. --* --* 802.11b can have up to 14 channels, the driver keeps the --* BSSID(MAC address) of each APs or Ad hoc stations it has sensed. --*/ -+ * addresses of TxPD buffers. Station has only 8 TxPD available, Whereas -+ * driver has more local TxPDs. Each TxPD on the host memory is associated -+ * with a Tx control node. The driver maintains 8 RxPD descriptors for -+ * station firmware to store Rx packet information. -+ * -+ * Current version of MAC has a 32x6 multicast address buffer. -+ * -+ * 802.11b can have up to 14 channels, the driver keeps the -+ * BSSID(MAC address) of each APs or Ad hoc stations it has sensed. -+ */ - - #define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 - #define LBS_NUM_CMD_BUFFERS 10 -@@ -166,7 +166,7 @@ - #define WOL_RESULT_NOSPC_ERR 1 - #define WOL_RESULT_EEXIST_ERR 2 - --/** Misc constants */ -+/* Misc constants */ - /* This section defines 802.11 specific contants */ - - #define MRVDRV_MAX_BSS_DESCRIPTS 16 -@@ -183,7 +183,8 @@ - - #define MARVELL_MESH_IE_LENGTH 9 - --/* Values used to populate the struct mrvl_mesh_ie. The only time you need this -+/* -+ * Values used to populate the struct mrvl_mesh_ie. The only time you need this - * is when enabling the mesh using CMD_MESH_CONFIG. - */ - #define MARVELL_MESH_IE_TYPE 4 -@@ -193,7 +194,7 @@ - #define MARVELL_MESH_METRIC_ID 0 - #define MARVELL_MESH_CAPABILITY 0 - --/** INT status Bit Definition*/ -+/* INT status Bit Definition */ - #define MRVDRV_TX_DNLD_RDY 0x0001 - #define MRVDRV_RX_UPLD_RDY 0x0002 - #define MRVDRV_CMD_DNLD_RDY 0x0004 -@@ -208,59 +209,63 @@ - #define TPC_DEFAULT_P1 10 - #define TPC_DEFAULT_P2 13 - --/** TxPD status */ -+/* TxPD status */ - --/* Station firmware use TxPD status field to report final Tx transmit --* result, Bit masks are used to present combined situations. --*/ -+/* -+ * Station firmware use TxPD status field to report final Tx transmit -+ * result, Bit masks are used to present combined situations. -+ */ - - #define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01 - #define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08 - --/** Tx mesh flag */ --/* Currently we are using normal WDS flag as mesh flag. -+/* Tx mesh flag */ -+/* -+ * Currently we are using normal WDS flag as mesh flag. - * TODO: change to proper mesh flag when MAC understands it. - */ - #define TxPD_CONTROL_WDS_FRAME (1<<17) - #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME - --/** Mesh interface ID */ -+/* Mesh interface ID */ - #define MESH_IFACE_ID 0x0001 --/** Mesh id should be in bits 14-13-12 */ -+/* Mesh id should be in bits 14-13-12 */ - #define MESH_IFACE_BIT_OFFSET 0x000c --/** Mesh enable bit in FW capability */ -+/* Mesh enable bit in FW capability */ - #define MESH_CAPINFO_ENABLE_MASK (1<<16) - --/** FW definition from Marvell v4 */ -+/* FW definition from Marvell v4 */ - #define MRVL_FW_V4 (0x04) --/** FW definition from Marvell v5 */ -+/* FW definition from Marvell v5 */ - #define MRVL_FW_V5 (0x05) --/** FW definition from Marvell v10 */ -+/* FW definition from Marvell v10 */ - #define MRVL_FW_V10 (0x0a) --/** FW major revision definition */ -+/* FW major revision definition */ - #define MRVL_FW_MAJOR_REV(x) ((x)>>24) - --/** RxPD status */ -+/* RxPD status */ - - #define MRVDRV_RXPD_STATUS_OK 0x0001 - --/** RxPD status - Received packet types */ --/** Rx mesh flag */ --/* Currently we are using normal WDS flag as mesh flag. -+/* RxPD status - Received packet types */ -+/* Rx mesh flag */ -+/* -+ * Currently we are using normal WDS flag as mesh flag. - * TODO: change to proper mesh flag when MAC understands it. - */ - #define RxPD_CONTROL_WDS_FRAME (0x40) - #define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME - --/** RSSI-related defines */ --/* RSSI constants are used to implement 802.11 RSSI threshold --* indication. if the Rx packet signal got too weak for 5 consecutive --* times, miniport driver (driver) will report this event to wrapper --*/ -+/* RSSI-related defines */ -+/* -+ * RSSI constants are used to implement 802.11 RSSI threshold -+ * indication. if the Rx packet signal got too weak for 5 consecutive -+ * times, miniport driver (driver) will report this event to wrapper -+ */ - - #define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96) - --/** RTS/FRAG related defines */ -+/* RTS/FRAG related defines */ - #define MRVDRV_RTS_MIN_VALUE 0 - #define MRVDRV_RTS_MAX_VALUE 2347 - #define MRVDRV_FRAG_MIN_VALUE 256 -@@ -300,36 +305,36 @@ - - #define MAX_LEDS 8 - --/** Global Variable Declaration */ -+/* Global Variable Declaration */ - extern const char lbs_driver_version[]; - extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; - - --/** ENUM definition*/ --/** SNRNF_TYPE */ -+/* ENUM definition */ -+/* SNRNF_TYPE */ - enum SNRNF_TYPE { - TYPE_BEACON = 0, - TYPE_RXPD, - MAX_TYPE_B - }; - --/** SNRNF_DATA*/ -+/* SNRNF_DATA */ - enum SNRNF_DATA { - TYPE_NOAVG = 0, - TYPE_AVG, - MAX_TYPE_AVG - }; - --/** LBS_802_11_POWER_MODE */ -+/* LBS_802_11_POWER_MODE */ - enum LBS_802_11_POWER_MODE { - LBS802_11POWERMODECAM, - LBS802_11POWERMODEMAX_PSP, - LBS802_11POWERMODEFAST_PSP, -- /*not a real mode, defined as an upper bound */ -+ /* not a real mode, defined as an upper bound */ - LBS802_11POWEMODEMAX - }; - --/** PS_STATE */ -+/* PS_STATE */ - enum PS_STATE { - PS_STATE_FULL_POWER, - PS_STATE_AWAKE, -@@ -337,7 +342,7 @@ - PS_STATE_SLEEP - }; - --/** DNLD_STATE */ -+/* DNLD_STATE */ - enum DNLD_STATE { - DNLD_RES_RECEIVED, - DNLD_DATA_SENT, -@@ -345,19 +350,19 @@ - DNLD_BOOTCMD_SENT, - }; - --/** LBS_MEDIA_STATE */ -+/* LBS_MEDIA_STATE */ - enum LBS_MEDIA_STATE { - LBS_CONNECTED, - LBS_DISCONNECTED - }; - --/** LBS_802_11_PRIVACY_FILTER */ -+/* LBS_802_11_PRIVACY_FILTER */ - enum LBS_802_11_PRIVACY_FILTER { - LBS802_11PRIVFILTERACCEPTALL, - LBS802_11PRIVFILTER8021XWEP - }; - --/** mv_ms_type */ -+/* mv_ms_type */ - enum mv_ms_type { - MVMS_DAT = 0, - MVMS_CMD = 1, -@@ -365,14 +370,14 @@ - MVMS_EVENT - }; - --/** KEY_TYPE_ID */ -+/* KEY_TYPE_ID */ - enum KEY_TYPE_ID { - KEY_TYPE_ID_WEP = 0, - KEY_TYPE_ID_TKIP, - KEY_TYPE_ID_AES - }; - --/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ -+/* KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ - enum KEY_INFO_WPA { - KEY_INFO_WPA_MCAST = 0x01, - KEY_INFO_WPA_UNICAST = 0x02, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/dev.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/dev.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/dev.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/dev.h 2011-05-05 23:29:46.551454745 +0200 -@@ -1,8 +1,8 @@ --/** -- * This file contains definitions and data structures specific -- * to Marvell 802.11 NIC. It contains the Device Information -- * structure struct lbs_private.. -- */ -+/* -+ * This file contains definitions and data structures specific -+ * to Marvell 802.11 NIC. It contains the Device Information -+ * structure struct lbs_private.. -+ */ - #ifndef _LBS_DEV_H_ - #define _LBS_DEV_H_ - -@@ -12,7 +12,7 @@ - - #include - --/** sleep_params */ -+/* sleep_params */ - struct sleep_params { - uint16_t sp_error; - uint16_t sp_offset; -@@ -23,7 +23,7 @@ - }; - - --/** Private structure for the MV device */ -+/* Private structure for the MV device */ - struct lbs_private { - - /* Basic networking */ -@@ -125,12 +125,12 @@ - /* Events sent from hardware to driver */ - struct kfifo event_fifo; - -- /** thread to service interrupts */ -+ /* thread to service interrupts */ - struct task_struct *main_thread; - wait_queue_head_t waitq; - struct workqueue_struct *work_thread; - -- /** Encryption stuff */ -+ /* Encryption stuff */ - u8 authtype_auto; - u8 wep_tx_key; - u8 wep_key[4][WLAN_KEY_LEN_WEP104]; -@@ -162,7 +162,7 @@ - s16 txpower_min; - s16 txpower_max; - -- /** Scanning */ -+ /* Scanning */ - struct delayed_work scan_work; - int scan_channel; - /* Queue of things waiting for scan completion */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/ethtool.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/ethtool.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/ethtool.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/ethtool.c 2011-05-05 23:29:46.548454709 +0200 -@@ -20,7 +20,8 @@ - strcpy(info->version, lbs_driver_version); - } - --/* All 8388 parts have 16KiB EEPROM size at the time of writing. -+/* -+ * All 8388 parts have 16KiB EEPROM size at the time of writing. - * In case that changes this needs fixing. - */ - #define LBS_EEPROM_LEN 16384 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/host.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/host.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/host.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/host.h 2011-05-05 23:29:46.545454671 +0200 -@@ -1,7 +1,7 @@ --/** -- * This file function prototypes, data structure -- * and definitions for all the host/station commands -- */ -+/* -+ * This file function prototypes, data structure -+ * and definitions for all the host/station commands -+ */ - - #ifndef _LBS_HOST_H_ - #define _LBS_HOST_H_ -@@ -13,9 +13,10 @@ - - #define CMD_OPTION_WAITFORRSP 0x0002 - --/** Host command IDs */ -+/* Host command IDs */ - --/* Return command are almost always the same as the host command, but with -+/* -+ * Return command are almost always the same as the host command, but with - * bit 15 set high. There are a few exceptions, though... - */ - #define CMD_RET(cmd) (0x8000 | cmd) -@@ -251,7 +252,7 @@ - CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */ - }; - --/** Card Event definition */ -+/* Card Event definition */ - #define MACREG_INT_CODE_TX_PPA_FREE 0 - #define MACREG_INT_CODE_TX_DMA_DONE 1 - #define MACREG_INT_CODE_LINK_LOST_W_SCAN 2 -@@ -624,12 +625,14 @@ - struct cmd_ds_802_11_rssi { - struct cmd_header hdr; - -- /* request: number of beacons (N) to average the SNR and NF over -+ /* -+ * request: number of beacons (N) to average the SNR and NF over - * response: SNR of most recent beacon - */ - __le16 n_or_snr; - -- /* The following fields are only set in the response. -+ /* -+ * The following fields are only set in the response. - * In the request these are reserved and should be set to 0. - */ - __le16 nf; /* most recent beacon noise floor */ -@@ -680,14 +683,16 @@ - - __le16 action; - -- /* Interval for keepalive in PS mode: -+ /* -+ * Interval for keepalive in PS mode: - * 0x0000 = don't change - * 0x001E = firmware default - * 0xFFFF = disable - */ - __le16 nullpktinterval; - -- /* Number of DTIM intervals to wake up for: -+ /* -+ * Number of DTIM intervals to wake up for: - * 0 = don't change - * 1 = firmware default - * 5 = max -@@ -697,7 +702,8 @@ - __le16 reserved; - __le16 locallisteninterval; - -- /* AdHoc awake period (FW v9+ only): -+ /* -+ * AdHoc awake period (FW v9+ only): - * 0 = don't change - * 1 = always awake (IEEE standard behavior) - * 2 - 31 = sleep for (n - 1) periods and awake for 1 period -@@ -771,7 +777,8 @@ - __le16 capability; - u8 rates[MAX_RATES]; - -- /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the -+ /* -+ * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the - * Adhoc join command and will cause a binary layout mismatch with - * the firmware - */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/if_cs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_cs.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/if_cs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_cs.c 2011-05-05 23:29:46.637455783 +0200 -@@ -312,7 +312,8 @@ - #define CF8385_MANFID 0x02df - #define CF8385_CARDID 0x8103 - --/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when -+/* -+ * FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when - * that gets fixed. Currently there's no way to access it from the probe hook. - */ - static inline u32 get_model(u16 manf_id, u16 card_id) -@@ -621,8 +622,10 @@ - if (remain < count) - count = remain; - -- /* "write the number of bytes to be sent to the I/O Command -- * write length register" */ -+ /* -+ * "write the number of bytes to be sent to the I/O Command -+ * write length register" -+ */ - if_cs_write16(card, IF_CS_CMD_LEN, count); - - /* "write this to I/O Command port register as 16 bit writes */ -@@ -631,16 +634,22 @@ - &fw->data[sent], - count >> 1); - -- /* "Assert the download over interrupt command in the Host -- * status register" */ -+ /* -+ * "Assert the download over interrupt command in the Host -+ * status register" -+ */ - if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - -- /* "Assert the download over interrupt command in the Card -- * interrupt case register" */ -+ /* -+ * "Assert the download over interrupt command in the Card -+ * interrupt case register" -+ */ - if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - -- /* "The host polls the Card Status register ... for 50 ms before -- declaring a failure */ -+ /* -+ * "The host polls the Card Status register ... for 50 ms before -+ * declaring a failure" -+ */ - ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, - IF_CS_BIT_COMMAND); - if (ret < 0) { -@@ -841,7 +850,7 @@ - - /* - * Most of the libertas cards can do unaligned register access, but some -- * weird ones can not. That's especially true for the CF8305 card. -+ * weird ones cannot. That's especially true for the CF8305 card. - */ - card->align_regs = 0; - -@@ -913,8 +922,10 @@ - goto out3; - } - -- /* Clear any interrupt cause that happened while sending -- * firmware/initializing card */ -+ /* -+ * Clear any interrupt cause that happened while sending -+ * firmware/initializing card -+ */ - if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); - if_cs_enable_ints(card); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/if_spi.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_spi.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/if_spi.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_spi.c 2011-05-05 23:29:46.552454757 +0200 -@@ -57,6 +57,7 @@ - /* Handles all SPI communication (except for FW load) */ - struct workqueue_struct *workqueue; - struct work_struct packet_work; -+ struct work_struct resume_work; - - u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; - -@@ -68,6 +69,9 @@ - - /* Protects cmd_packet_list and data_packet_list */ - spinlock_t buffer_lock; -+ -+ /* True is card suspended */ -+ u8 suspended; - }; - - static void free_if_spi_card(struct if_spi_card *card) -@@ -139,8 +143,10 @@ - card->prev_xfer_time = jiffies; - } - --/* Write out a byte buffer to an SPI register, -- * using a series of 16-bit transfers. */ -+/* -+ * Write out a byte buffer to an SPI register, -+ * using a series of 16-bit transfers. -+ */ - static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) - { - int err = 0; -@@ -204,8 +210,10 @@ - struct spi_transfer dummy_trans; - struct spi_transfer data_trans; - -- /* You must take an even number of bytes from the SPU, even if you -- * don't care about the last one. */ -+ /* -+ * You must take an even number of bytes from the SPU, even if you -+ * don't care about the last one. -+ */ - BUG_ON(len & 0x1); - - spu_transaction_init(card); -@@ -254,8 +262,10 @@ - return ret; - } - --/* Read 32 bits from an SPI register. -- * The low 16 bits are read first. */ -+/* -+ * Read 32 bits from an SPI register. -+ * The low 16 bits are read first. -+ */ - static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) - { - __le32 buf; -@@ -267,13 +277,15 @@ - return err; - } - --/* Keep reading 16 bits from an SPI register until you get the correct result. -+/* -+ * Keep reading 16 bits from an SPI register until you get the correct result. - * - * If mask = 0, the correct result is any non-zero number. - * If mask != 0, the correct result is any number where - * number & target_mask == target - * -- * Returns -ETIMEDOUT if a second passes without the correct result. */ -+ * Returns -ETIMEDOUT if a second passes without the correct result. -+ */ - static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, - u16 target_mask, u16 target) - { -@@ -301,8 +313,10 @@ - } - } - --/* Read 16 bits from an SPI register until you receive a specific value. -- * Returns -ETIMEDOUT if a 4 tries pass without success. */ -+/* -+ * Read 16 bits from an SPI register until you receive a specific value. -+ * Returns -ETIMEDOUT if a 4 tries pass without success. -+ */ - static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) - { - int err, try; -@@ -324,8 +338,10 @@ - { - int err = 0; - -- /* We can suppress a host interrupt by clearing the appropriate -- * bit in the "host interrupt status mask" register */ -+ /* -+ * We can suppress a host interrupt by clearing the appropriate -+ * bit in the "host interrupt status mask" register -+ */ - if (suppress_host_int) { - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); - if (err) -@@ -341,10 +357,12 @@ - return err; - } - -- /* If auto-interrupts are on, the completion of certain transactions -+ /* -+ * If auto-interrupts are on, the completion of certain transactions - * will trigger an interrupt automatically. If auto-interrupts - * are off, we need to set the "Card Interrupt Cause" register to -- * trigger a card interrupt. */ -+ * trigger a card interrupt. -+ */ - if (auto_int) { - err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, - IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | -@@ -398,8 +416,10 @@ - int err = 0; - u32 delay; - -- /* We have to start up in timed delay mode so that we can safely -- * read the Delay Read Register. */ -+ /* -+ * We have to start up in timed delay mode so that we can safely -+ * read the Delay Read Register. -+ */ - card->use_dummy_writes = 0; - err = spu_set_bus_mode(card, - IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | -@@ -455,8 +475,10 @@ - - /* Load helper firmware image */ - while (bytes_remaining > 0) { -- /* Scratch pad 1 should contain the number of bytes we -- * want to download to the firmware */ -+ /* -+ * Scratch pad 1 should contain the number of bytes we -+ * want to download to the firmware -+ */ - err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, - HELPER_FW_LOAD_CHUNK_SZ); - if (err) -@@ -468,8 +490,10 @@ - if (err) - goto out; - -- /* Feed the data into the command read/write port reg -- * in chunks of 64 bytes */ -+ /* -+ * Feed the data into the command read/write port reg -+ * in chunks of 64 bytes -+ */ - memset(temp, 0, sizeof(temp)); - memcpy(temp, fw, - min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); -@@ -491,9 +515,11 @@ - fw += HELPER_FW_LOAD_CHUNK_SZ; - } - -- /* Once the helper / single stage firmware download is complete, -+ /* -+ * Once the helper / single stage firmware download is complete, - * write 0 to scratch pad 1 and interrupt the -- * bootloader. This completes the helper download. */ -+ * bootloader. This completes the helper download. -+ */ - err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); - if (err) - goto out; -@@ -513,16 +539,20 @@ - return err; - } - --/* Returns the length of the next packet the firmware expects us to send -- * Sets crc_err if the previous transfer had a CRC error. */ -+/* -+ * Returns the length of the next packet the firmware expects us to send. -+ * Sets crc_err if the previous transfer had a CRC error. -+ */ - static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, - int *crc_err) - { - u16 len; - int err = 0; - -- /* wait until the host interrupt status register indicates -- * that we are ready to download */ -+ /* -+ * wait until the host interrupt status register indicates -+ * that we are ready to download -+ */ - err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, - IF_SPI_HIST_CMD_DOWNLOAD_RDY, - IF_SPI_HIST_CMD_DOWNLOAD_RDY); -@@ -583,8 +613,10 @@ - goto out; - } - if (bytes < 0) { -- /* If there are no more bytes left, we would normally -- * expect to have terminated with len = 0 */ -+ /* -+ * If there are no more bytes left, we would normally -+ * expect to have terminated with len = 0 -+ */ - lbs_pr_err("Firmware load wants more bytes " - "than we have to offer.\n"); - break; -@@ -656,14 +688,18 @@ - u16 len; - u8 i; - -- /* We need a buffer big enough to handle whatever people send to -- * hw_host_to_card */ -+ /* -+ * We need a buffer big enough to handle whatever people send to -+ * hw_host_to_card -+ */ - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); - -- /* It's just annoying if the buffer size isn't a multiple of 4, because -- * then we might have len < IF_SPI_CMD_BUF_SIZE but -- * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ -+ /* -+ * It's just annoying if the buffer size isn't a multiple of 4, because -+ * then we might have len < IF_SPI_CMD_BUF_SIZE but -+ * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE -+ */ - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); - - lbs_deb_enter(LBS_DEB_SPI); -@@ -834,8 +870,10 @@ - - lbs_deb_enter(LBS_DEB_SPI); - -- /* Read the host interrupt status register to see what we -- * can do. */ -+ /* -+ * Read the host interrupt status register to see what we -+ * can do. -+ */ - err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, - &hiStatus); - if (err) { -@@ -854,12 +892,15 @@ - goto err; - } - -- /* workaround: in PS mode, the card does not set the Command -- * Download Ready bit, but it sets TX Download Ready. */ -+ /* -+ * workaround: in PS mode, the card does not set the Command -+ * Download Ready bit, but it sets TX Download Ready. -+ */ - if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || - (card->priv->psstate != PS_STATE_FULL_POWER && - (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { -- /* This means two things. First of all, -+ /* -+ * This means two things. First of all, - * if there was a previous command sent, the card has - * successfully received it. - * Secondly, it is now ready to download another -@@ -867,8 +908,7 @@ - */ - lbs_host_to_card_done(card->priv); - -- /* Do we have any command packets from the host to -- * send? */ -+ /* Do we have any command packets from the host to send? */ - packet = NULL; - spin_lock_irqsave(&card->buffer_lock, flags); - if (!list_empty(&card->cmd_packet_list)) { -@@ -882,8 +922,7 @@ - if_spi_h2c(card, packet, MVMS_CMD); - } - if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { -- /* Do we have any data packets from the host to -- * send? */ -+ /* Do we have any data packets from the host to send? */ - packet = NULL; - spin_lock_irqsave(&card->buffer_lock, flags); - if (!list_empty(&card->data_packet_list)) { -@@ -910,7 +949,8 @@ - * Host to Card - * - * Called from Libertas to transfer some data to the WLAN device -- * We can't sleep here. */ -+ * We can't sleep here. -+ */ - static int if_spi_host_to_card(struct lbs_private *priv, - u8 type, u8 *buf, u16 nb) - { -@@ -1057,6 +1097,28 @@ - return err; - } - -+static void if_spi_resume_worker(struct work_struct *work) -+{ -+ struct if_spi_card *card; -+ -+ card = container_of(work, struct if_spi_card, resume_work); -+ -+ if (card->suspended) { -+ if (card->pdata->setup) -+ card->pdata->setup(card->spi); -+ -+ /* Init card ... */ -+ if_spi_init_card(card); -+ -+ enable_irq(card->spi->irq); -+ -+ /* And resume it ... */ -+ lbs_resume(card->priv); -+ -+ card->suspended = 0; -+ } -+} -+ - static int __devinit if_spi_probe(struct spi_device *spi) - { - struct if_spi_card *card; -@@ -1099,14 +1161,17 @@ - if (err) - goto free_card; - -- /* Register our card with libertas. -- * This will call alloc_etherdev */ -+ /* -+ * Register our card with libertas. -+ * This will call alloc_etherdev. -+ */ - priv = lbs_add_card(card, &spi->dev); - if (!priv) { - err = -ENOMEM; - goto free_card; - } - card->priv = priv; -+ priv->setup_fw_on_resume = 1; - priv->card = card; - priv->hw_host_to_card = if_spi_host_to_card; - priv->enter_deep_sleep = NULL; -@@ -1117,6 +1182,7 @@ - /* Initialize interrupt handling stuff. */ - card->workqueue = create_workqueue("libertas_spi"); - INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); -+ INIT_WORK(&card->resume_work, if_spi_resume_worker); - - err = request_irq(spi->irq, if_spi_host_interrupt, - IRQF_TRIGGER_FALLING, "libertas_spi", card); -@@ -1125,9 +1191,11 @@ - goto terminate_workqueue; - } - -- /* Start the card. -+ /* -+ * Start the card. - * This will call register_netdev, and we'll start -- * getting interrupts... */ -+ * getting interrupts... -+ */ - err = lbs_start_card(priv); - if (err) - goto release_irq; -@@ -1161,6 +1229,8 @@ - lbs_deb_spi("libertas_spi_remove\n"); - lbs_deb_enter(LBS_DEB_SPI); - -+ cancel_work_sync(&card->resume_work); -+ - lbs_stop_card(priv); - lbs_remove_card(priv); /* will call free_netdev */ - -@@ -1174,6 +1244,40 @@ - return 0; - } - -+static int if_spi_suspend(struct device *dev) -+{ -+ struct spi_device *spi = to_spi_device(dev); -+ struct if_spi_card *card = spi_get_drvdata(spi); -+ -+ if (!card->suspended) { -+ lbs_suspend(card->priv); -+ flush_workqueue(card->workqueue); -+ disable_irq(spi->irq); -+ -+ if (card->pdata->teardown) -+ card->pdata->teardown(spi); -+ card->suspended = 1; -+ } -+ -+ return 0; -+} -+ -+static int if_spi_resume(struct device *dev) -+{ -+ struct spi_device *spi = to_spi_device(dev); -+ struct if_spi_card *card = spi_get_drvdata(spi); -+ -+ /* Schedule delayed work */ -+ schedule_work(&card->resume_work); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops if_spi_pm_ops = { -+ .suspend = if_spi_suspend, -+ .resume = if_spi_resume, -+}; -+ - static struct spi_driver libertas_spi_driver = { - .probe = if_spi_probe, - .remove = __devexit_p(libertas_spi_remove), -@@ -1181,6 +1285,7 @@ - .name = "libertas_spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, -+ .pm = &if_spi_pm_ops, - }, - }; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/if_spi.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_spi.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/if_spi.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_spi.h 2011-05-05 23:29:46.548454709 +0200 -@@ -86,34 +86,34 @@ - #define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) - - /***************** IF_SPI_HOST_INT_CTRL_REG *****************/ --/** Host Interrupt Control bit : Wake up */ -+/* Host Interrupt Control bit : Wake up */ - #define IF_SPI_HICT_WAKE_UP (1<<0) --/** Host Interrupt Control bit : WLAN ready */ -+/* Host Interrupt Control bit : WLAN ready */ - #define IF_SPI_HICT_WLAN_READY (1<<1) - /*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ - /*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ - /*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ --/** Host Interrupt Control bit : Tx auto download */ -+/* Host Interrupt Control bit : Tx auto download */ - #define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) --/** Host Interrupt Control bit : Rx auto upload */ -+/* Host Interrupt Control bit : Rx auto upload */ - #define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) --/** Host Interrupt Control bit : Command auto download */ -+/* Host Interrupt Control bit : Command auto download */ - #define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) --/** Host Interrupt Control bit : Command auto upload */ -+/* Host Interrupt Control bit : Command auto upload */ - #define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) - - /***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ --/** Card Interrupt Case bit : Tx download over */ -+/* Card Interrupt Case bit : Tx download over */ - #define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) --/** Card Interrupt Case bit : Rx upload over */ -+/* Card Interrupt Case bit : Rx upload over */ - #define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) --/** Card Interrupt Case bit : Command download over */ -+/* Card Interrupt Case bit : Command download over */ - #define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) --/** Card Interrupt Case bit : Host event */ -+/* Card Interrupt Case bit : Host event */ - #define IF_SPI_CIC_HOST_EVENT (1<<3) --/** Card Interrupt Case bit : Command upload over */ -+/* Card Interrupt Case bit : Command upload over */ - #define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) --/** Card Interrupt Case bit : Power down */ -+/* Card Interrupt Case bit : Power down */ - #define IF_SPI_CIC_POWER_DOWN (1<<5) - - /***************** IF_SPI_CARD_INT_STATUS_REG *****************/ -@@ -138,51 +138,51 @@ - #define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) - - /***************** IF_SPI_HOST_INT_STATUS_REG *****************/ --/** Host Interrupt Status bit : Tx download ready */ -+/* Host Interrupt Status bit : Tx download ready */ - #define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) --/** Host Interrupt Status bit : Rx upload ready */ -+/* Host Interrupt Status bit : Rx upload ready */ - #define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) --/** Host Interrupt Status bit : Command download ready */ -+/* Host Interrupt Status bit : Command download ready */ - #define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) --/** Host Interrupt Status bit : Card event */ -+/* Host Interrupt Status bit : Card event */ - #define IF_SPI_HIST_CARD_EVENT (1<<3) --/** Host Interrupt Status bit : Command upload ready */ -+/* Host Interrupt Status bit : Command upload ready */ - #define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) --/** Host Interrupt Status bit : I/O write FIFO overflow */ -+/* Host Interrupt Status bit : I/O write FIFO overflow */ - #define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) --/** Host Interrupt Status bit : I/O read FIFO underflow */ -+/* Host Interrupt Status bit : I/O read FIFO underflow */ - #define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) --/** Host Interrupt Status bit : Data write FIFO overflow */ -+/* Host Interrupt Status bit : Data write FIFO overflow */ - #define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) --/** Host Interrupt Status bit : Data read FIFO underflow */ -+/* Host Interrupt Status bit : Data read FIFO underflow */ - #define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) --/** Host Interrupt Status bit : Command write FIFO overflow */ -+/* Host Interrupt Status bit : Command write FIFO overflow */ - #define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) --/** Host Interrupt Status bit : Command read FIFO underflow */ -+/* Host Interrupt Status bit : Command read FIFO underflow */ - #define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) - - /***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ --/** Host Interrupt Status Mask bit : Tx download ready */ -+/* Host Interrupt Status Mask bit : Tx download ready */ - #define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) --/** Host Interrupt Status Mask bit : Rx upload ready */ -+/* Host Interrupt Status Mask bit : Rx upload ready */ - #define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) --/** Host Interrupt Status Mask bit : Command download ready */ -+/* Host Interrupt Status Mask bit : Command download ready */ - #define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) --/** Host Interrupt Status Mask bit : Card event */ -+/* Host Interrupt Status Mask bit : Card event */ - #define IF_SPI_HISM_CARDEVENT (1<<3) --/** Host Interrupt Status Mask bit : Command upload ready */ -+/* Host Interrupt Status Mask bit : Command upload ready */ - #define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) --/** Host Interrupt Status Mask bit : I/O write FIFO overflow */ -+/* Host Interrupt Status Mask bit : I/O write FIFO overflow */ - #define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) --/** Host Interrupt Status Mask bit : I/O read FIFO underflow */ -+/* Host Interrupt Status Mask bit : I/O read FIFO underflow */ - #define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) --/** Host Interrupt Status Mask bit : Data write FIFO overflow */ -+/* Host Interrupt Status Mask bit : Data write FIFO overflow */ - #define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) --/** Host Interrupt Status Mask bit : Data write FIFO underflow */ -+/* Host Interrupt Status Mask bit : Data write FIFO underflow */ - #define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) --/** Host Interrupt Status Mask bit : Command write FIFO overflow */ -+/* Host Interrupt Status Mask bit : Command write FIFO overflow */ - #define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) --/** Host Interrupt Status Mask bit : Command write FIFO underflow */ -+/* Host Interrupt Status Mask bit : Command write FIFO underflow */ - #define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) - - /***************** IF_SPI_SPU_BUS_MODE_REG *****************/ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/if_usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/if_usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_usb.c 2011-05-05 23:29:46.556454805 +0200 -@@ -1,6 +1,6 @@ --/** -- * This file contains functions used in USB interface module. -- */ -+/* -+ * This file contains functions used in USB interface module. -+ */ - #include - #include - #include -@@ -66,7 +66,7 @@ - - /* sysfs hooks */ - --/** -+/* - * Set function to write firmware to device's persistent memory - */ - static ssize_t if_usb_firmware_set(struct device *dev, -@@ -85,7 +85,7 @@ - return ret; - } - --/** -+/* - * lbs_flash_fw attribute to be exported per ethX interface through sysfs - * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to - * the device's persistent memory: -@@ -94,7 +94,14 @@ - static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); - - /** -- * Set function to write firmware to device's persistent memory -+ * if_usb_boot2_set - write firmware to device's persistent memory -+ * -+ * @dev: target device -+ * @attr: device attributes -+ * @buf: firmware buffer to write -+ * @count: number of bytes to write -+ * -+ * returns: number of bytes written or negative error code - */ - static ssize_t if_usb_boot2_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -@@ -112,7 +119,7 @@ - return ret; - } - --/** -+/* - * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs - * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware - * to the device's persistent memory: -@@ -121,9 +128,10 @@ - static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); - - /** -- * @brief call back function to handle the status of the URB -- * @param urb pointer to urb structure -- * @return N/A -+ * if_usb_write_bulk_callback - callback function to handle the status -+ * of the URB -+ * @urb: pointer to &urb structure -+ * returns: N/A - */ - static void if_usb_write_bulk_callback(struct urb *urb) - { -@@ -150,9 +158,9 @@ - } - - /** -- * @brief free tx/rx urb, skb and rx buffer -- * @param cardp pointer if_usb_card -- * @return N/A -+ * if_usb_free - free tx/rx urb, skb and rx buffer -+ * @cardp: pointer to &if_usb_card -+ * returns: N/A - */ - static void if_usb_free(struct if_usb_card *cardp) - { -@@ -231,10 +239,10 @@ - #endif - - /** -- * @brief sets the configuration values -- * @param ifnum interface number -- * @param id pointer to usb_device_id -- * @return 0 on success, error code on failure -+ * if_usb_probe - sets the configuration values -+ * @intf: &usb_interface pointer -+ * @id: pointer to usb_device_id -+ * returns: 0 on success, error code on failure - */ - static int if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -@@ -366,9 +374,9 @@ - } - - /** -- * @brief free resource and cleanup -- * @param intf USB interface structure -- * @return N/A -+ * if_usb_disconnect - free resource and cleanup -+ * @intf: USB interface structure -+ * returns: N/A - */ - static void if_usb_disconnect(struct usb_interface *intf) - { -@@ -398,9 +406,9 @@ - } - - /** -- * @brief This function download FW -- * @param priv pointer to struct lbs_private -- * @return 0 -+ * if_usb_send_fw_pkt - download FW -+ * @cardp: pointer to &struct if_usb_card -+ * returns: 0 - */ - static int if_usb_send_fw_pkt(struct if_usb_card *cardp) - { -@@ -486,11 +494,11 @@ - } - - /** -- * @brief This function transfer the data to the device. -- * @param priv pointer to struct lbs_private -- * @param payload pointer to payload data -- * @param nb data length -- * @return 0 or -1 -+ * usb_tx_block - transfer the data to the device -+ * @cardp: pointer to &struct if_usb_card -+ * @payload: pointer to payload data -+ * @nb: data length -+ * returns: 0 for success or negative error code - */ - static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb) - { -@@ -727,11 +735,11 @@ - } - - /** -- * @brief This function reads of the packet into the upload buff, -- * wake up the main thread and initialise the Rx callack. -+ * if_usb_receive - read the packet into the upload buffer, -+ * wake up the main thread and initialise the Rx callack - * -- * @param urb pointer to struct urb -- * @return N/A -+ * @urb: pointer to &struct urb -+ * returns: N/A - */ - static void if_usb_receive(struct urb *urb) - { -@@ -802,12 +810,12 @@ - } - - /** -- * @brief This function downloads data to FW -- * @param priv pointer to struct lbs_private structure -- * @param type type of data -- * @param buf pointer to data buffer -- * @param len number of bytes -- * @return 0 or -1 -+ * if_usb_host_to_card - downloads data to FW -+ * @priv: pointer to &struct lbs_private structure -+ * @type: type of data -+ * @payload: pointer to data buffer -+ * @nb: number of bytes -+ * returns: 0 for success or negative error code - */ - static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, - uint8_t *payload, uint16_t nb) -@@ -831,10 +839,11 @@ - } - - /** -- * @brief This function issues Boot command to the Boot2 code -- * @param ivalue 1:Boot from FW by USB-Download -- * 2:Boot from FW in EEPROM -- * @return 0 -+ * if_usb_issue_boot_command - issues Boot command to the Boot2 code -+ * @cardp: pointer to &if_usb_card -+ * @ivalue: 1:Boot from FW by USB-Download -+ * 2:Boot from FW in EEPROM -+ * returns: 0 for success or negative error code - */ - static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) - { -@@ -853,11 +862,11 @@ - - - /** -- * @brief This function checks the validity of Boot2/FW image. -+ * check_fwfile_format - check the validity of Boot2/FW image - * -- * @param data pointer to image -- * len image length -- * @return 0 or -1 -+ * @data: pointer to image -+ * @totlen: image length -+ * returns: 0 (good) or 1 (failure) - */ - static int check_fwfile_format(const uint8_t *data, uint32_t totlen) - { -@@ -901,13 +910,13 @@ - - - /** --* @brief This function programs the firmware subject to cmd -+* if_usb_prog_firmware - programs the firmware subject to cmd - * --* @param cardp the if_usb_card descriptor --* fwname firmware or boot2 image file name --* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, --* or BOOT_CMD_UPDATE_BOOT2. --* @return 0 or error code -+* @cardp: the if_usb_card descriptor -+* @fwname: firmware or boot2 image file name -+* @cmd: either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, -+* or BOOT_CMD_UPDATE_BOOT2. -+* returns: 0 or error code - */ - static int if_usb_prog_firmware(struct if_usb_card *cardp, - const char *fwname, int cmd) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/if_usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/if_usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/if_usb.h 2011-05-05 23:29:46.546454683 +0200 -@@ -6,9 +6,9 @@ - - struct lbs_private; - --/** -- * This file contains definition for USB interface. -- */ -+/* -+ * This file contains definition for USB interface. -+ */ - #define CMD_TYPE_REQUEST 0xF00DFACE - #define CMD_TYPE_DATA 0xBEADC0DE - #define CMD_TYPE_INDICATION 0xBEEFFACE -@@ -40,7 +40,7 @@ - uint8_t pad[2]; - }; - --/** USB card description structure*/ -+/* USB card description structure*/ - struct if_usb_card { - struct usb_device *udev; - uint32_t model; /* MODEL_* */ -@@ -77,7 +77,7 @@ - __le16 boot2_version; - }; - --/** fwheader */ -+/* fwheader */ - struct fwheader { - __le32 dnldcmd; - __le32 baseaddr; -@@ -86,14 +86,14 @@ - }; - - #define FW_MAX_DATA_BLK_SIZE 600 --/** FWData */ -+/* FWData */ - struct fwdata { - struct fwheader hdr; - __le32 seqnum; - uint8_t data[0]; - }; - --/** fwsyncheader */ -+/* fwsyncheader */ - struct fwsyncheader { - __le32 cmd; - __le32 seqnum; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/main.c 2011-05-05 23:29:46.555454793 +0200 -@@ -1,8 +1,8 @@ --/** -- * This file contains the major functions in WLAN -- * driver. It includes init, exit, open, close and main -- * thread etc.. -- */ -+/* -+ * This file contains the major functions in WLAN -+ * driver. It includes init, exit, open, close and main -+ * thread etc.. -+ */ - - #include - #include -@@ -35,18 +35,20 @@ - module_param_named(libertas_debug, lbs_debug, int, 0644); - - --/* This global structure is used to send the confirm_sleep command as -- * fast as possible down to the firmware. */ -+/* -+ * This global structure is used to send the confirm_sleep command as -+ * fast as possible down to the firmware. -+ */ - struct cmd_confirm_sleep confirm_sleep; - - --/** -+/* - * the table to keep region code - */ - u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = - { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; - --/** -+/* - * FW rate table. FW refers to rates by their index in this table, not by the - * rate value itself. Values of 0x00 are - * reserved positions. -@@ -57,10 +59,10 @@ - }; - - /** -- * @brief use index to get the data rate -+ * lbs_fw_index_to_data_rate - use index to get the data rate - * -- * @param idx The index of data rate -- * @return data rate or 0 -+ * @idx: The index of data rate -+ * returns: data rate or 0 - */ - u32 lbs_fw_index_to_data_rate(u8 idx) - { -@@ -70,10 +72,10 @@ - } - - /** -- * @brief use rate to get the index -+ * lbs_data_rate_to_fw_index - use rate to get the index - * -- * @param rate data rate -- * @return index or 0 -+ * @rate: data rate -+ * returns: index or 0 - */ - u8 lbs_data_rate_to_fw_index(u32 rate) - { -@@ -91,10 +93,10 @@ - - - /** -- * @brief This function opens the ethX interface -+ * lbs_dev_open - open the ethX interface - * -- * @param dev A pointer to net_device structure -- * @return 0 or -EBUSY if monitor mode active -+ * @dev: A pointer to &net_device structure -+ * returns: 0 or -EBUSY if monitor mode active - */ - static int lbs_dev_open(struct net_device *dev) - { -@@ -120,10 +122,10 @@ - } - - /** -- * @brief This function closes the ethX interface -+ * lbs_eth_stop - close the ethX interface - * -- * @param dev A pointer to net_device structure -- * @return 0 -+ * @dev: A pointer to &net_device structure -+ * returns: 0 - */ - static int lbs_eth_stop(struct net_device *dev) - { -@@ -336,12 +338,12 @@ - } - - /** -- * @brief This function handles the major jobs in the LBS driver. -+ * lbs_thread - handles the major jobs in the LBS driver. - * It handles all events generated by firmware, RX data received - * from firmware and TX data sent from kernel. - * -- * @param data A pointer to lbs_thread structure -- * @return 0 -+ * @data: A pointer to &lbs_thread structure -+ * returns: 0 - */ - static int lbs_thread(void *data) - { -@@ -540,11 +542,11 @@ - } - - /** -- * @brief This function gets the HW spec from the firmware and sets -- * some basic parameters. -+ * lbs_setup_firmware - gets the HW spec from the firmware and sets -+ * some basic parameters - * -- * @param priv A pointer to struct lbs_private structure -- * @return 0 or -1 -+ * @priv: A pointer to &struct lbs_private structure -+ * returns: 0 or -1 - */ - static int lbs_setup_firmware(struct lbs_private *priv) - { -@@ -630,8 +632,10 @@ - EXPORT_SYMBOL_GPL(lbs_resume); - - /** -- * This function handles the timeout of command sending. -- * It will re-send the same command again. -+ * lbs_cmd_timeout_handler - handles the timeout of command sending. -+ * It will re-send the same command again. -+ * -+ * @data: &struct lbs_private pointer - */ - static void lbs_cmd_timeout_handler(unsigned long data) - { -@@ -655,8 +659,10 @@ - } - - /** -- * This function put the device back to deep sleep mode when timer expires -- * and no activity (command, event, data etc.) is detected. -+ * auto_deepsleep_timer_fn - put the device back to deep sleep mode when -+ * timer expires and no activity (command, event, data etc.) is detected. -+ * @data: &struct lbs_private pointer -+ * returns: N/A - */ - static void auto_deepsleep_timer_fn(unsigned long data) - { -@@ -792,11 +798,12 @@ - }; - - /** -- * @brief This function adds the card. it will probe the -+ * lbs_add_card - adds the card. It will probe the - * card, allocate the lbs_priv and initialize the device. - * -- * @param card A pointer to card -- * @return A pointer to struct lbs_private structure -+ * @card: A pointer to card -+ * @dmdev: A pointer to &struct device -+ * returns: A pointer to &struct lbs_private structure - */ - struct lbs_private *lbs_add_card(void *card, struct device *dmdev) - { -@@ -1057,19 +1064,19 @@ - EXPORT_SYMBOL_GPL(lbs_notify_command_response); - - /** -- * @brief Retrieves two-stage firmware -+ * lbs_get_firmware - Retrieves two-stage firmware - * -- * @param dev A pointer to device structure -- * @param user_helper User-defined helper firmware file -- * @param user_mainfw User-defined main firmware file -- * @param card_model Bus-specific card model ID used to filter firmware table -- * elements -- * @param fw_table Table of firmware file names and device model numbers -- * terminated by an entry with a NULL helper name -- * @param helper On success, the helper firmware; caller must free -- * @param mainfw On success, the main firmware; caller must free -+ * @dev: A pointer to &device structure -+ * @user_helper: User-defined helper firmware file -+ * @user_mainfw: User-defined main firmware file -+ * @card_model: Bus-specific card model ID used to filter firmware table -+ * elements -+ * @fw_table: Table of firmware file names and device model numbers -+ * terminated by an entry with a NULL helper name -+ * @helper: On success, the helper firmware; caller must free -+ * @mainfw: On success, the main firmware; caller must free - * -- * @return 0 on success, non-zero on failure -+ * returns: 0 on success, non-zero on failure - */ - int lbs_get_firmware(struct device *dev, const char *user_helper, - const char *user_mainfw, u32 card_model, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/mesh.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/mesh.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/mesh.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/mesh.c 2011-05-05 23:29:46.546454683 +0200 -@@ -16,12 +16,15 @@ - * Mesh sysfs support - */ - --/** -+/* - * Attributes exported through sysfs - */ - - /** -- * @brief Get function for sysfs attribute anycast_mask -+ * lbs_anycast_get - Get function for sysfs attribute anycast_mask -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t lbs_anycast_get(struct device *dev, - struct device_attribute *attr, char * buf) -@@ -40,7 +43,11 @@ - } - - /** -- * @brief Set function for sysfs attribute anycast_mask -+ * lbs_anycast_set - Set function for sysfs attribute anycast_mask -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t lbs_anycast_set(struct device *dev, - struct device_attribute *attr, const char * buf, size_t count) -@@ -62,7 +69,10 @@ - } - - /** -- * @brief Get function for sysfs attribute prb_rsp_limit -+ * lbs_prb_rsp_limit_get - Get function for sysfs attribute prb_rsp_limit -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t lbs_prb_rsp_limit_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -85,7 +95,11 @@ - } - - /** -- * @brief Set function for sysfs attribute prb_rsp_limit -+ * lbs_prb_rsp_limit_set - Set function for sysfs attribute prb_rsp_limit -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t lbs_prb_rsp_limit_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -@@ -114,7 +128,10 @@ - } - - /** -- * Get function for sysfs attribute mesh -+ * lbs_mesh_get - Get function for sysfs attribute mesh -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t lbs_mesh_get(struct device *dev, - struct device_attribute *attr, char * buf) -@@ -124,7 +141,11 @@ - } - - /** -- * Set function for sysfs attribute mesh -+ * lbs_mesh_set - Set function for sysfs attribute mesh -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t lbs_mesh_set(struct device *dev, - struct device_attribute *attr, const char * buf, size_t count) -@@ -151,19 +172,19 @@ - return count; - } - --/** -+/* - * lbs_mesh attribute to be exported per ethX interface - * through sysfs (/sys/class/net/ethX/lbs_mesh) - */ - static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); - --/** -+/* - * anycast_mask attribute to be exported per mshX interface - * through sysfs (/sys/class/net/mshX/anycast_mask) - */ - static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); - --/** -+/* - * prb_rsp_limit attribute to be exported per mshX interface - * through sysfs (/sys/class/net/mshX/prb_rsp_limit) - */ -@@ -274,10 +295,10 @@ - - - /** -- * @brief This function closes the mshX interface -+ * lbs_mesh_stop - close the mshX interface - * -- * @param dev A pointer to net_device structure -- * @return 0 -+ * @dev: A pointer to &net_device structure -+ * returns: 0 - */ - static int lbs_mesh_stop(struct net_device *dev) - { -@@ -301,10 +322,10 @@ - } - - /** -- * @brief This function opens the mshX interface -+ * lbs_mesh_dev_open - open the mshX interface - * -- * @param dev A pointer to net_device structure -- * @return 0 or -EBUSY if monitor mode active -+ * @dev: A pointer to &net_device structure -+ * returns: 0 or -EBUSY if monitor mode active - */ - static int lbs_mesh_dev_open(struct net_device *dev) - { -@@ -342,10 +363,10 @@ - }; - - /** -- * @brief This function adds mshX interface -+ * lbs_add_mesh - add mshX interface - * -- * @param priv A pointer to the struct lbs_private structure -- * @return 0 if successful, -X otherwise -+ * @priv: A pointer to the &struct lbs_private structure -+ * returns: 0 if successful, -X otherwise - */ - int lbs_add_mesh(struct lbs_private *priv) - { -@@ -456,13 +477,13 @@ - */ - - /** -- * @brief Add or delete Mesh Blinding Table entries -+ * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries - * -- * @param priv A pointer to struct lbs_private structure -- * @param add TRUE to add the entry, FALSE to delete it -- * @param addr1 Destination address to blind or unblind -+ * @priv: A pointer to &struct lbs_private structure -+ * @add: TRUE to add the entry, FALSE to delete it -+ * @addr1: Destination address to blind or unblind - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1) - { -@@ -493,11 +514,11 @@ - } - - /** -- * @brief Reset/clear the mesh blinding table -+ * lbs_mesh_bt_reset - Reset/clear the mesh blinding table - * -- * @param priv A pointer to struct lbs_private structure -+ * @priv: A pointer to &struct lbs_private structure - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_mesh_bt_reset(struct lbs_private *priv) - { -@@ -517,17 +538,18 @@ - } - - /** -- * @brief Gets the inverted status of the mesh blinding table -+ * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh -+ * blinding table - * -- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the -- * table, but an inverted table allows *only* traffic from nodes listed in -- * the table. -+ * Normally the firmware "blinds" or ignores traffic from mesh nodes in the -+ * table, but an inverted table allows *only* traffic from nodes listed in -+ * the table. - * -- * @param priv A pointer to struct lbs_private structure -- * @param invert On success, TRUE if the blinding table is inverted, -- * FALSE if it is not inverted -+ * @priv: A pointer to &struct lbs_private structure -+ * @inverted: On success, TRUE if the blinding table is inverted, -+ * FALSE if it is not inverted - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted) - { -@@ -551,18 +573,19 @@ - } - - /** -- * @brief Sets the inverted status of the mesh blinding table -+ * lbs_mesh_bt_set_inverted - Sets the inverted status of the mesh -+ * blinding table - * -- * Normally the firmware "blinds" or ignores traffic from mesh nodes in the -- * table, but an inverted table allows *only* traffic from nodes listed in -- * the table. -+ * Normally the firmware "blinds" or ignores traffic from mesh nodes in the -+ * table, but an inverted table allows *only* traffic from nodes listed in -+ * the table. - * -- * @param priv A pointer to struct lbs_private structure -- * @param invert TRUE to invert the blinding table (only traffic from -- * listed nodes allowed), FALSE to return it -- * to normal state (listed nodes ignored) -+ * @priv: A pointer to &struct lbs_private structure -+ * @inverted: TRUE to invert the blinding table (only traffic from -+ * listed nodes allowed), FALSE to return it -+ * to normal state (listed nodes ignored) - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted) - { -@@ -583,13 +606,13 @@ - } - - /** -- * @brief List an entry in the mesh blinding table -+ * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table - * -- * @param priv A pointer to struct lbs_private structure -- * @param id The ID of the entry to list -- * @param addr1 MAC address associated with the table entry -+ * @priv: A pointer to &struct lbs_private structure -+ * @id: The ID of the entry to list -+ * @addr1: MAC address associated with the table entry - * -- * @return 0 on success, error on failure -+ * returns: 0 on success, error on failure - */ - int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1) - { -@@ -614,14 +637,14 @@ - } - - /** -- * @brief Access the mesh forwarding table -+ * lbs_cmd_fwt_access - Access the mesh forwarding table - * -- * @param priv A pointer to struct lbs_private structure -- * @param cmd_action The forwarding table action to perform -- * @param cmd The pre-filled FWT_ACCESS command -+ * @priv: A pointer to &struct lbs_private structure -+ * @cmd_action: The forwarding table action to perform -+ * @cmd: The pre-filled FWT_ACCESS command - * -- * @return 0 on success and 'cmd' will be filled with the -- * firmware's response -+ * returns: 0 on success and 'cmd' will be filled with the -+ * firmware's response - */ - int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action, - struct cmd_ds_fwt_access *cmd) -@@ -774,7 +797,10 @@ - } - - /** -- * @brief Get function for sysfs attribute bootflag -+ * bootflag_get - Get function for sysfs attribute bootflag -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t bootflag_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -791,7 +817,11 @@ - } - - /** -- * @brief Set function for sysfs attribute bootflag -+ * bootflag_set - Set function for sysfs attribute bootflag -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -@@ -817,7 +847,10 @@ - } - - /** -- * @brief Get function for sysfs attribute boottime -+ * boottime_get - Get function for sysfs attribute boottime -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t boottime_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -834,7 +867,11 @@ - } - - /** -- * @brief Set function for sysfs attribute boottime -+ * boottime_set - Set function for sysfs attribute boottime -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t boottime_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -@@ -869,7 +906,10 @@ - } - - /** -- * @brief Get function for sysfs attribute channel -+ * channel_get - Get function for sysfs attribute channel -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t channel_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -886,7 +926,11 @@ - } - - /** -- * @brief Set function for sysfs attribute channel -+ * channel_set - Set function for sysfs attribute channel -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t channel_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -@@ -912,7 +956,10 @@ - } - - /** -- * @brief Get function for sysfs attribute mesh_id -+ * mesh_id_get - Get function for sysfs attribute mesh_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, - char *buf) -@@ -938,7 +985,11 @@ - } - - /** -- * @brief Set function for sysfs attribute mesh_id -+ * mesh_id_set - Set function for sysfs attribute mesh_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -@@ -980,7 +1031,10 @@ - } - - /** -- * @brief Get function for sysfs attribute protocol_id -+ * protocol_id_get - Get function for sysfs attribute protocol_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t protocol_id_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -997,7 +1051,11 @@ - } - - /** -- * @brief Set function for sysfs attribute protocol_id -+ * protocol_id_set - Set function for sysfs attribute protocol_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t protocol_id_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -@@ -1034,7 +1092,10 @@ - } - - /** -- * @brief Get function for sysfs attribute metric_id -+ * metric_id_get - Get function for sysfs attribute metric_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t metric_id_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -1051,7 +1112,11 @@ - } - - /** -- * @brief Set function for sysfs attribute metric_id -+ * metric_id_set - Set function for sysfs attribute metric_id -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -@@ -1088,7 +1153,10 @@ - } - - /** -- * @brief Get function for sysfs attribute capability -+ * capability_get - Get function for sysfs attribute capability -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer where data will be returned - */ - static ssize_t capability_get(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -1105,7 +1173,11 @@ - } - - /** -- * @brief Set function for sysfs attribute capability -+ * capability_set - Set function for sysfs attribute capability -+ * @dev: the &struct device -+ * @attr: device attributes -+ * @buf: buffer that contains new attribute value -+ * @count: size of buffer - */ - static ssize_t capability_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/mesh.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/mesh.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/mesh.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/mesh.h 2011-05-05 23:29:46.760457269 +0200 -@@ -1,6 +1,6 @@ --/** -- * Contains all definitions needed for the Libertas' MESH implementation. -- */ -+/* -+ * Contains all definitions needed for the Libertas' MESH implementation. -+ */ - #ifndef _LBS_MESH_H_ - #define _LBS_MESH_H_ - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/rx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/rx.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/rx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/rx.c 2011-05-05 23:29:46.553454769 +0200 -@@ -1,6 +1,6 @@ --/** -- * This file contains the handling of RX in wlan driver. -- */ -+/* -+ * This file contains the handling of RX in wlan driver. -+ */ - #include - #include - #include -@@ -40,12 +40,12 @@ - struct sk_buff *skb); - - /** -- * @brief This function processes received packet and forwards it -- * to kernel/upper layer -+ * lbs_process_rxed_packet - processes received packet and forwards it -+ * to kernel/upper layer - * -- * @param priv A pointer to struct lbs_private -- * @param skb A pointer to skb which includes the received packet -- * @return 0 or -1 -+ * @priv: A pointer to &struct lbs_private -+ * @skb: A pointer to skb which includes the received packet -+ * returns: 0 or -1 - */ - int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) - { -@@ -156,11 +156,11 @@ - EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); - - /** -- * @brief This function converts Tx/Rx rates from the Marvell WLAN format -- * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) -+ * convert_mv_rate_to_radiotap - converts Tx/Rx rates from Marvell WLAN format -+ * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) - * -- * @param rate Input rate -- * @return Output Rate (0 if invalid) -+ * @rate: Input rate -+ * returns: Output Rate (0 if invalid) - */ - static u8 convert_mv_rate_to_radiotap(u8 rate) - { -@@ -196,12 +196,12 @@ - } - - /** -- * @brief This function processes a received 802.11 packet and forwards it -- * to kernel/upper layer -+ * process_rxed_802_11_packet - processes a received 802.11 packet and forwards -+ * it to kernel/upper layer - * -- * @param priv A pointer to struct lbs_private -- * @param skb A pointer to skb which includes the received packet -- * @return 0 or -1 -+ * @priv: A pointer to &struct lbs_private -+ * @skb: A pointer to skb which includes the received packet -+ * returns: 0 or -1 - */ - static int process_rxed_802_11_packet(struct lbs_private *priv, - struct sk_buff *skb) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/tx.c 2011-05-05 23:29:46.514454297 +0200 -@@ -1,6 +1,6 @@ --/** -- * This file contains the handling of TX in wlan driver. -- */ -+/* -+ * This file contains the handling of TX in wlan driver. -+ */ - #include - #include - #include -@@ -13,11 +13,11 @@ - #include "dev.h" - - /** -- * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE -- * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) -+ * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE -+ * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) - * -- * @param rate Input rate -- * @return Output Rate (0 if invalid) -+ * @rate: Input rate -+ * returns: Output Rate (0 if invalid) - */ - static u32 convert_radiotap_rate_to_mv(u8 rate) - { -@@ -51,12 +51,12 @@ - } - - /** -- * @brief This function checks the conditions and sends packet to IF -- * layer if everything is ok. -+ * lbs_hard_start_xmit - checks the conditions and sends packet to IF -+ * layer if everything is ok - * -- * @param priv A pointer to struct lbs_private structure -- * @param skb A pointer to skb which includes TX packet -- * @return 0 or -1 -+ * @skb: A pointer to skb which includes TX packet -+ * @dev: A pointer to the &struct net_device -+ * returns: 0 or -1 - */ - netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) - { -@@ -168,13 +168,13 @@ - } - - /** -- * @brief This function sends to the host the last transmitted packet, -- * filling the radiotap headers with transmission information. -+ * lbs_send_tx_feedback - sends to the host the last transmitted packet, -+ * filling the radiotap headers with transmission information. - * -- * @param priv A pointer to struct lbs_private structure -- * @param status A 32 bit value containing transmission status. -+ * @priv: A pointer to &struct lbs_private structure -+ * @try_count: A 32-bit value containing transmission retry status. - * -- * @returns void -+ * returns: void - */ - void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) - { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/libertas/types.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/types.h ---- linux-2.6.39-rc6/drivers/net/wireless/libertas/types.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/libertas/types.h 2011-05-05 23:29:46.737456991 +0200 -@@ -1,6 +1,6 @@ --/** -- * This header file contains definition for global types -- */ -+/* -+ * This header file contains definition for global types -+ */ - #ifndef _LBS_TYPES_H_ - #define _LBS_TYPES_H_ - -@@ -54,7 +54,7 @@ - struct ieee_ie_ds_param_set ds; - } __packed; - --/** TLV type ID definition */ -+/* TLV type ID definition */ - #define PROPRIETARY_TLV_BASE_ID 0x0100 - - /* Terminating TLV type */ -@@ -96,7 +96,7 @@ - #define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) - #define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) - --/** TLV related data structures*/ -+/* TLV related data structures */ - struct mrvl_ie_header { - __le16 type; - __le16 len; -@@ -177,7 +177,7 @@ - __le16 auth; - } __packed; - --/** Local Power capability */ -+/* Local Power capability */ - struct mrvl_ie_power_capability { - struct mrvl_ie_header header; - s8 minpower; -@@ -235,9 +235,11 @@ - struct led_bhv ledbhv[1]; - } __packed; - --/* Meant to be packed as the value member of a struct ieee80211_info_element. -+/* -+ * Meant to be packed as the value member of a struct ieee80211_info_element. - * Note that the len member of the ieee80211_info_element varies depending on -- * the mesh_id_len */ -+ * the mesh_id_len -+ */ - struct mrvl_meshie_val { - uint8_t oui[3]; - uint8_t type; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/Makefile 2011-05-05 23:29:45.782445453 +0200 -@@ -56,3 +56,5 @@ - obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/ - - obj-$(CONFIG_IWM) += iwmc3200wifi/ -+ -+obj-$(CONFIG_MWIFIEX) += mwifiex/ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_aggr.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_aggr.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_aggr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_aggr.c 2011-05-05 23:29:45.470441683 +0200 -@@ -0,0 +1,422 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n Aggregation -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+#include "11n_aggr.h" -+ -+/* -+ * Creates an AMSDU subframe for aggregation into one AMSDU packet. -+ * -+ * The resultant AMSDU subframe format is - -+ * -+ * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ -+ * | DA | SA | Length | SNAP header | MSDU | -+ * | data[0..5] | data[6..11] | | | data[14..] | -+ * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ -+ * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes--> -+ * -+ * This function also computes the amount of padding required to make the -+ * buffer length multiple of 4 bytes. -+ * -+ * Data => |DA|SA|SNAP-TYPE|........ .| -+ * MSDU => |DA|SA|Length|SNAP|...... ..| -+ */ -+static int -+mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, -+ struct sk_buff *skb_src, int *pad) -+ -+{ -+ int dt_offset; -+ struct rfc_1042_hdr snap = { -+ 0xaa, /* LLC DSAP */ -+ 0xaa, /* LLC SSAP */ -+ 0x03, /* LLC CTRL */ -+ {0x00, 0x00, 0x00}, /* SNAP OUI */ -+ 0x0000 /* SNAP type */ -+ /* -+ * This field will be overwritten -+ * later with ethertype -+ */ -+ }; -+ struct tx_packet_hdr *tx_header = NULL; -+ -+ skb_put(skb_aggr, sizeof(*tx_header)); -+ -+ tx_header = (struct tx_packet_hdr *) skb_aggr->data; -+ -+ /* Copy DA and SA */ -+ dt_offset = 2 * ETH_ALEN; -+ memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); -+ -+ /* Copy SNAP header */ -+ snap.snap_type = *(u16 *) ((u8 *)skb_src->data + dt_offset); -+ dt_offset += sizeof(u16); -+ -+ memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); -+ -+ skb_pull(skb_src, dt_offset); -+ -+ /* Update Length field */ -+ tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN); -+ -+ /* Add payload */ -+ skb_put(skb_aggr, skb_src->len); -+ memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data, -+ skb_src->len); -+ *pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len + -+ LLC_SNAP_LEN)) & 3)) : 0; -+ skb_put(skb_aggr, *pad); -+ -+ return skb_aggr->len + *pad; -+} -+ -+/* -+ * Adds TxPD to AMSDU header. -+ * -+ * Each AMSDU packet will contain one TxPD at the beginning, -+ * followed by multiple AMSDU subframes. -+ */ -+static void -+mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, -+ struct sk_buff *skb) -+{ -+ struct txpd *local_tx_pd; -+ -+ skb_push(skb, sizeof(*local_tx_pd)); -+ -+ local_tx_pd = (struct txpd *) skb->data; -+ memset(local_tx_pd, 0, sizeof(struct txpd)); -+ -+ /* Original priority has been overwritten */ -+ local_tx_pd->priority = (u8) skb->priority; -+ local_tx_pd->pkt_delay_2ms = -+ mwifiex_wmm_compute_drv_pkt_delay(priv, skb); -+ local_tx_pd->bss_num = priv->bss_num; -+ local_tx_pd->bss_type = priv->bss_type; -+ /* Always zero as the data is followed by struct txpd */ -+ local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); -+ local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); -+ local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - -+ sizeof(*local_tx_pd)); -+ -+ if (local_tx_pd->tx_control == 0) -+ /* TxCtrl set by user or default */ -+ local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); -+ -+ if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && -+ (priv->adapter->pps_uapsd_mode)) { -+ if (true == mwifiex_check_last_packet_indication(priv)) { -+ priv->adapter->tx_lock_flag = true; -+ local_tx_pd->flags = -+ MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; -+ } -+ } -+} -+ -+/* -+ * Counts the number of subframes in an aggregate packet. -+ * -+ * This function parses an aggregate packet buffer, looking for -+ * subframes and counting the number of such subframe found. The -+ * function automatically skips the DA/SA fields at the beginning -+ * of each subframe and padding at the end. -+ */ -+static int -+mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len) -+{ -+ int pkt_count = 0, pkt_len, pad; -+ -+ while (total_pkt_len > 0) { -+ /* Length will be in network format, change it to host */ -+ pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN))); -+ pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? -+ (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; -+ data += pkt_len + pad + sizeof(struct ethhdr); -+ total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); -+ ++pkt_count; -+ } -+ -+ return pkt_count; -+} -+ -+/* -+ * De-aggregate received packets. -+ * -+ * This function parses the received aggregate buffer, extracts each subframe, -+ * strips off the SNAP header from them and sends the data portion for further -+ * processing. -+ * -+ * Each subframe body is copied onto a separate buffer, which are freed by -+ * upper layer after processing. The function also performs sanity tests on -+ * the received buffer. -+ */ -+int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, -+ struct sk_buff *skb) -+{ -+ u16 pkt_len; -+ int total_pkt_len; -+ u8 *data; -+ int pad; -+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); -+ struct rxpd *local_rx_pd = (struct rxpd *) skb->data; -+ struct sk_buff *skb_daggr; -+ struct mwifiex_rxinfo *rx_info_daggr = NULL; -+ int ret = -1; -+ struct rx_packet_hdr *rx_pkt_hdr; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; -+ -+ data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset); -+ total_pkt_len = local_rx_pd->rx_pkt_length; -+ -+ /* Sanity test */ -+ if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) { -+ dev_err(adapter->dev, "total pkt len greater than buffer" -+ " size %d\n", total_pkt_len); -+ return -1; -+ } -+ -+ rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len); -+ -+ while (total_pkt_len > 0) { -+ rx_pkt_hdr = (struct rx_packet_hdr *) data; -+ /* Length will be in network format, change it to host */ -+ pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN))); -+ if (pkt_len > total_pkt_len) { -+ dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n", -+ total_pkt_len, pkt_len); -+ break; -+ } -+ -+ pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? -+ (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; -+ -+ total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); -+ -+ if (memcmp(&rx_pkt_hdr->rfc1042_hdr, -+ rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { -+ memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN); -+ data += LLC_SNAP_LEN; -+ pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN; -+ } else { -+ *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0; -+ pkt_len += sizeof(struct ethhdr); -+ } -+ -+ skb_daggr = dev_alloc_skb(pkt_len); -+ if (!skb_daggr) { -+ dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n", -+ __func__); -+ return -1; -+ } -+ rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr); -+ -+ rx_info_daggr->bss_index = rx_info->bss_index; -+ skb_daggr->tstamp = skb->tstamp; -+ rx_info_daggr->parent = skb; -+ skb_daggr->priority = skb->priority; -+ skb_put(skb_daggr, pkt_len); -+ memcpy(skb_daggr->data, data, pkt_len); -+ -+ ret = mwifiex_recv_packet(adapter, skb_daggr); -+ -+ switch (ret) { -+ case -EINPROGRESS: -+ break; -+ case -1: -+ dev_err(adapter->dev, "deaggr: host_to_card failed\n"); -+ case 0: -+ mwifiex_recv_packet_complete(adapter, skb_daggr, ret); -+ break; -+ default: -+ break; -+ } -+ -+ data += pkt_len + pad; -+ } -+ -+ return ret; -+} -+ -+/* -+ * Create aggregated packet. -+ * -+ * This function creates an aggregated MSDU packet, by combining buffers -+ * from the RA list. Each individual buffer is encapsulated as an AMSDU -+ * subframe and all such subframes are concatenated together to form the -+ * AMSDU packet. -+ * -+ * A TxPD is also added to the front of the resultant AMSDU packets for -+ * transmission. The resultant packets format is - -+ * -+ * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+ -+ * | TxPD |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame| -+ * | | 1 | 2 | .. | n | -+ * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+ -+ */ -+int -+mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *pra_list, int headroom, -+ int ptrindex, unsigned long ra_list_flags) -+ __releases(&priv->wmm.ra_list_spinlock) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct sk_buff *skb_aggr, *skb_src; -+ struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; -+ int pad = 0; -+ int ret = 0; -+ struct mwifiex_tx_param tx_param; -+ struct txpd *ptx_pd = NULL; -+ -+ if (skb_queue_empty(&pra_list->skb_head)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ return 0; -+ } -+ skb_src = skb_peek(&pra_list->skb_head); -+ tx_info_src = MWIFIEX_SKB_TXCB(skb_src); -+ skb_aggr = dev_alloc_skb(adapter->tx_buf_size); -+ if (!skb_aggr) { -+ dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ return -1; -+ } -+ skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); -+ tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); -+ -+ tx_info_aggr->bss_index = tx_info_src->bss_index; -+ skb_aggr->priority = skb_src->priority; -+ -+ while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len -+ + LLC_SNAP_LEN) -+ <= adapter->tx_buf_size)) { -+ -+ if (!skb_queue_empty(&pra_list->skb_head)) -+ skb_src = skb_dequeue(&pra_list->skb_head); -+ else -+ skb_src = NULL; -+ -+ pra_list->total_pkts_size -= skb_src->len; -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); -+ -+ mwifiex_write_data_complete(adapter, skb_src, 0); -+ -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ -+ if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ return -1; -+ } -+ -+ if (!skb_queue_empty(&pra_list->skb_head)) -+ skb_src = skb_peek(&pra_list->skb_head); -+ else -+ skb_src = NULL; -+ } -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ -+ /* Last AMSDU packet does not need padding */ -+ skb_trim(skb_aggr, skb_aggr->len - pad); -+ -+ /* Form AMSDU */ -+ mwifiex_11n_form_amsdu_txpd(priv, skb_aggr); -+ if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) -+ ptx_pd = (struct txpd *)skb_aggr->data; -+ -+ skb_push(skb_aggr, headroom); -+ -+ tx_param.next_pkt_len = ((pra_list->total_pkts_size) ? -+ (((pra_list->total_pkts_size) > -+ adapter->tx_buf_size) ? adapter-> -+ tx_buf_size : pra_list->total_pkts_size + -+ LLC_SNAP_LEN + sizeof(struct txpd)) : 0); -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, -+ skb_aggr->data, -+ skb_aggr->len, &tx_param); -+ switch (ret) { -+ case -EBUSY: -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ mwifiex_write_data_complete(adapter, skb_aggr, -1); -+ return -1; -+ } -+ if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && -+ (adapter->pps_uapsd_mode) && -+ (adapter->tx_lock_flag)) { -+ priv->adapter->tx_lock_flag = false; -+ ptx_pd->flags = 0; -+ } -+ -+ skb_queue_tail(&pra_list->skb_head, skb_aggr); -+ -+ pra_list->total_pkts_size += skb_aggr->len; -+ -+ tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); -+ break; -+ case -1: -+ adapter->data_sent = false; -+ dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", -+ __func__, ret); -+ adapter->dbg.num_tx_host_to_card_failure++; -+ mwifiex_write_data_complete(adapter, skb_aggr, ret); -+ return 0; -+ case -EINPROGRESS: -+ adapter->data_sent = false; -+ break; -+ case 0: -+ mwifiex_write_data_complete(adapter, skb_aggr, ret); -+ break; -+ default: -+ break; -+ } -+ if (ret != -EBUSY) { -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { -+ priv->wmm.packets_out[ptrindex]++; -+ priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; -+ } -+ /* Now bss_prio_cur pointer points to next node */ -+ adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = -+ list_first_entry( -+ &adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_cur->list, -+ struct mwifiex_bss_prio_node, list); -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ } -+ -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_aggr.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_aggr.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_aggr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_aggr.h 2011-05-05 23:29:45.488441901 +0200 -@@ -0,0 +1,32 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n Aggregation -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_11N_AGGR_H_ -+#define _MWIFIEX_11N_AGGR_H_ -+ -+#define PKT_TYPE_AMSDU 0xE6 -+ -+int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, -+ struct sk_buff *skb); -+int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr, int headroom, -+ int ptr_index, unsigned long flags) -+ __releases(&priv->wmm.ra_list_spinlock); -+ -+#endif /* !_MWIFIEX_11N_AGGR_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n.c 2011-05-05 23:29:45.488441901 +0200 -@@ -0,0 +1,745 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * Fills HT capability information field, AMPDU Parameters field, HT extended -+ * capability field, and supported MCS set fields. -+ * -+ * HT capability information field, AMPDU Parameters field, supported MCS set -+ * fields are retrieved from cfg80211 stack -+ * -+ * RD responder bit to set to clear in the extended capability header. -+ */ -+void -+mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, -+ struct mwifiex_ie_types_htcap *ht_cap) -+{ -+ uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); -+ struct ieee80211_supported_band *sband = -+ priv->wdev->wiphy->bands[radio_type]; -+ -+ ht_cap->ht_cap.ampdu_params_info = -+ (sband->ht_cap.ampdu_factor & -+ IEEE80211_HT_AMPDU_PARM_FACTOR)| -+ ((sband->ht_cap.ampdu_density << -+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & -+ IEEE80211_HT_AMPDU_PARM_DENSITY); -+ -+ memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs, -+ sizeof(sband->ht_cap.mcs)); -+ -+ if (priv->bss_mode == NL80211_IFTYPE_STATION || -+ (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ -+ SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); -+ -+ /* Clear RD responder bit */ -+ ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; -+ -+ ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap); -+ ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); -+} -+ -+/* -+ * This function returns the pointer to an entry in BA Stream -+ * table which matches the requested BA status. -+ */ -+static struct mwifiex_tx_ba_stream_tbl * -+mwifiex_11n_get_tx_ba_stream_status(struct mwifiex_private *priv, -+ enum mwifiex_ba_status ba_status) -+{ -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { -+ if (tx_ba_tsr_tbl->ba_status == ba_status) { -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, -+ flags); -+ return tx_ba_tsr_tbl; -+ } -+ } -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ return NULL; -+} -+ -+/* -+ * This function handles the command response of delete a block -+ * ack request. -+ * -+ * The function checks the response success status and takes action -+ * accordingly (send an add BA request in case of success, or recreate -+ * the deleted stream in case of failure, if the add BA was also -+ * initiated by us). -+ */ -+int mwifiex_ret_11n_delba(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ int tid; -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; -+ struct host_cmd_ds_11n_delba *del_ba = -+ (struct host_cmd_ds_11n_delba *) &resp->params.del_ba; -+ uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set); -+ -+ tid = del_ba_param_set >> DELBA_TID_POS; -+ if (del_ba->del_result == BA_RESULT_SUCCESS) { -+ mwifiex_11n_delete_ba_stream_tbl(priv, tid, -+ del_ba->peer_mac_addr, TYPE_DELBA_SENT, -+ INITIATOR_BIT(del_ba_param_set)); -+ -+ tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, -+ BA_STREAM_SETUP_INPROGRESS); -+ if (tx_ba_tbl) -+ mwifiex_send_addba(priv, tx_ba_tbl->tid, -+ tx_ba_tbl->ra); -+ } else { /* -+ * In case of failure, recreate the deleted stream in case -+ * we initiated the ADDBA -+ */ -+ if (INITIATOR_BIT(del_ba_param_set)) { -+ mwifiex_11n_create_tx_ba_stream_tbl(priv, -+ del_ba->peer_mac_addr, tid, -+ BA_STREAM_SETUP_INPROGRESS); -+ -+ tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_status(priv, -+ BA_STREAM_SETUP_INPROGRESS); -+ if (tx_ba_tbl) -+ mwifiex_11n_delete_ba_stream_tbl(priv, -+ tx_ba_tbl->tid, tx_ba_tbl->ra, -+ TYPE_DELBA_SENT, true); -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of add a block -+ * ack request. -+ * -+ * Handling includes changing the header fields to CPU formats, checking -+ * the response success status and taking actions accordingly (delete the -+ * BA stream table in case of failure). -+ */ -+int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ int tid; -+ struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = -+ (struct host_cmd_ds_11n_addba_rsp *) &resp->params.add_ba_rsp; -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; -+ -+ add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) -+ & SSN_MASK); -+ -+ tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) -+ & IEEE80211_ADDBA_PARAM_TID_MASK) -+ >> BLOCKACKPARAM_TID_POS; -+ if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { -+ tx_ba_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, -+ add_ba_rsp->peer_mac_addr); -+ if (tx_ba_tbl) { -+ dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); -+ tx_ba_tbl->ba_status = BA_STREAM_SETUP_COMPLETE; -+ } else { -+ dev_err(priv->adapter->dev, "BA stream not created\n"); -+ } -+ } else { -+ mwifiex_11n_delete_ba_stream_tbl(priv, tid, -+ add_ba_rsp->peer_mac_addr, -+ TYPE_DELBA_SENT, true); -+ if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) -+ priv->aggr_prio_tbl[tid].ampdu_ap = -+ BA_STREAM_NOT_ALLOWED; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of 11n configuration request. -+ * -+ * Handling includes changing the header fields into CPU format. -+ */ -+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; -+ -+ if (data_buf) { -+ tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf; -+ tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap); -+ tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info); -+ } -+ return 0; -+} -+ -+/* -+ * This function prepares command of reconfigure Tx buffer. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting Tx buffer size (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, int cmd_action, -+ void *data_buf) -+{ -+ struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf; -+ u16 action = (u16) cmd_action; -+ u16 buf_size = *((u16 *) data_buf); -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF); -+ cmd->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN); -+ tx_buf->action = cpu_to_le16(action); -+ switch (action) { -+ case HostCmd_ACT_GEN_SET: -+ dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size); -+ tx_buf->buff_size = cpu_to_le16(buf_size); -+ break; -+ case HostCmd_ACT_GEN_GET: -+ default: -+ tx_buf->buff_size = 0; -+ break; -+ } -+ return 0; -+} -+ -+/* -+ * This function prepares command of AMSDU aggregation control. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting AMSDU control parameters (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+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 = -+ &cmd->params.amsdu_aggr_ctrl; -+ u16 action = (u16) cmd_action; -+ struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl = -+ (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) -+ + S_DS_GEN); -+ amsdu_ctrl->action = cpu_to_le16(action); -+ switch (action) { -+ case HostCmd_ACT_GEN_SET: -+ amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable); -+ amsdu_ctrl->curr_buf_size = 0; -+ break; -+ case HostCmd_ACT_GEN_GET: -+ default: -+ amsdu_ctrl->curr_buf_size = 0; -+ break; -+ } -+ return 0; -+} -+ -+/* -+ * This function handles the command response of AMSDU aggregation -+ * control request. -+ * -+ * Handling includes changing the header fields into CPU format. -+ */ -+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; -+ struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = -+ &resp->params.amsdu_aggr_ctrl; -+ -+ if (data_buf) { -+ amsdu_aggr_ctrl = -+ (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; -+ amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable); -+ amsdu_aggr_ctrl->curr_buf_size = -+ le16_to_cpu(amsdu_ctrl->curr_buf_size); -+ } -+ return 0; -+} -+ -+/* -+ * This function prepares 11n configuration command. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting HT Tx capability and HT Tx information fields -+ * - Ensuring correct endian-ness -+ */ -+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; -+ struct mwifiex_ds_11n_tx_cfg *txcfg = -+ (struct mwifiex_ds_11n_tx_cfg *) data_buf; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); -+ htcfg->action = cpu_to_le16(cmd_action); -+ htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); -+ htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); -+ return 0; -+} -+ -+/* -+ * This function appends an 11n TLV to a buffer. -+ * -+ * Buffer allocation is responsibility of the calling -+ * function. No size validation is made here. -+ * -+ * The function fills up the following sections, if applicable - -+ * - HT capability IE -+ * - HT information IE (with channel list) -+ * - 20/40 BSS Coexistence IE -+ * - HT Extended Capabilities IE -+ */ -+int -+mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc, -+ u8 **buffer) -+{ -+ struct mwifiex_ie_types_htcap *ht_cap; -+ struct mwifiex_ie_types_htinfo *ht_info; -+ struct mwifiex_ie_types_chan_list_param_set *chan_list; -+ struct mwifiex_ie_types_2040bssco *bss_co_2040; -+ struct mwifiex_ie_types_extcap *ext_cap; -+ int ret_len = 0; -+ struct ieee80211_supported_band *sband; -+ u8 radio_type; -+ -+ if (!buffer || !*buffer) -+ return ret_len; -+ -+ radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); -+ sband = priv->wdev->wiphy->bands[radio_type]; -+ -+ if (bss_desc->bcn_ht_cap) { -+ ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; -+ memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); -+ ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); -+ ht_cap->header.len = -+ cpu_to_le16(sizeof(struct ieee80211_ht_cap)); -+ memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header), -+ (u8 *) bss_desc->bcn_ht_cap + -+ sizeof(struct ieee_types_header), -+ le16_to_cpu(ht_cap->header.len)); -+ -+ mwifiex_fill_cap_info(priv, radio_type, ht_cap); -+ -+ *buffer += sizeof(struct mwifiex_ie_types_htcap); -+ ret_len += sizeof(struct mwifiex_ie_types_htcap); -+ } -+ -+ if (bss_desc->bcn_ht_info) { -+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; -+ memset(ht_info, 0, -+ sizeof(struct mwifiex_ie_types_htinfo)); -+ ht_info->header.type = -+ cpu_to_le16(WLAN_EID_HT_INFORMATION); -+ ht_info->header.len = -+ cpu_to_le16(sizeof(struct ieee80211_ht_info)); -+ -+ memcpy((u8 *) ht_info + -+ sizeof(struct mwifiex_ie_types_header), -+ (u8 *) bss_desc->bcn_ht_info + -+ sizeof(struct ieee_types_header), -+ le16_to_cpu(ht_info->header.len)); -+ -+ if (!(sband->ht_cap.cap & -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ ht_info->ht_info.ht_param &= -+ ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | -+ IEEE80211_HT_PARAM_CHA_SEC_OFFSET); -+ -+ *buffer += sizeof(struct mwifiex_ie_types_htinfo); -+ ret_len += sizeof(struct mwifiex_ie_types_htinfo); -+ } -+ -+ chan_list = -+ (struct mwifiex_ie_types_chan_list_param_set *) *buffer; -+ memset(chan_list, 0, -+ sizeof(struct mwifiex_ie_types_chan_list_param_set)); -+ chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); -+ chan_list->header.len = cpu_to_le16( -+ sizeof(struct mwifiex_ie_types_chan_list_param_set) - -+ sizeof(struct mwifiex_ie_types_header)); -+ chan_list->chan_scan_param[0].chan_number = -+ bss_desc->bcn_ht_info->control_chan; -+ chan_list->chan_scan_param[0].radio_type = -+ mwifiex_band_to_radio_type((u8) bss_desc->bss_band); -+ -+ if ((sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) -+ && (bss_desc->bcn_ht_info->ht_param & -+ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) -+ SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. -+ radio_type, -+ (bss_desc->bcn_ht_info->ht_param & -+ IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); -+ -+ *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); -+ ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set); -+ } -+ -+ if (bss_desc->bcn_bss_co_2040) { -+ bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer; -+ memset(bss_co_2040, 0, -+ sizeof(struct mwifiex_ie_types_2040bssco)); -+ bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040); -+ bss_co_2040->header.len = -+ cpu_to_le16(sizeof(bss_co_2040->bss_co_2040)); -+ -+ memcpy((u8 *) bss_co_2040 + -+ sizeof(struct mwifiex_ie_types_header), -+ (u8 *) bss_desc->bcn_bss_co_2040 + -+ sizeof(struct ieee_types_header), -+ le16_to_cpu(bss_co_2040->header.len)); -+ -+ *buffer += sizeof(struct mwifiex_ie_types_2040bssco); -+ ret_len += sizeof(struct mwifiex_ie_types_2040bssco); -+ } -+ -+ if (bss_desc->bcn_ext_cap) { -+ ext_cap = (struct mwifiex_ie_types_extcap *) *buffer; -+ memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap)); -+ ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY); -+ ext_cap->header.len = cpu_to_le16(sizeof(ext_cap->ext_cap)); -+ -+ memcpy((u8 *) ext_cap + -+ sizeof(struct mwifiex_ie_types_header), -+ (u8 *) bss_desc->bcn_ext_cap + -+ sizeof(struct ieee_types_header), -+ le16_to_cpu(ext_cap->header.len)); -+ -+ *buffer += sizeof(struct mwifiex_ie_types_extcap); -+ ret_len += sizeof(struct mwifiex_ie_types_extcap); -+ } -+ -+ return ret_len; -+} -+ -+/* -+ * This function reconfigures the Tx buffer size in firmware. -+ * -+ * This function prepares a firmware command and issues it, if -+ * the current Tx buffer size is different from the one requested. -+ * Maximum configurable Tx buffer size is limited by the HT capability -+ * field value. -+ */ -+void -+mwifiex_cfg_tx_buf(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; -+ u16 tx_buf = 0; -+ u16 curr_tx_buf_size = 0; -+ -+ if (bss_desc->bcn_ht_cap) { -+ if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & -+ IEEE80211_HT_CAP_MAX_AMSDU) -+ max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; -+ else -+ max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; -+ } -+ -+ tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu); -+ -+ dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n", -+ max_amsdu, priv->adapter->max_tx_buf_size); -+ -+ if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K) -+ curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; -+ else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_4K) -+ curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; -+ 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_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, -+ HostCmd_ACT_GEN_SET, 0, &tx_buf); -+} -+ -+/* -+ * This function checks if the given pointer is valid entry of -+ * Tx BA Stream table. -+ */ -+static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv, -+ struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr) -+{ -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; -+ -+ list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { -+ if (tx_ba_tsr_tbl == tx_tbl_ptr) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* -+ * This function deletes the given entry in Tx BA Stream table. -+ * -+ * The function also performs a validity check on the supplied -+ * pointer before trying to delete. -+ */ -+void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl) -+{ -+ if (!tx_ba_tsr_tbl && -+ mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl)) -+ return; -+ -+ dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl); -+ -+ list_del(&tx_ba_tsr_tbl->list); -+ -+ kfree(tx_ba_tsr_tbl); -+} -+ -+/* -+ * This function deletes all the entries in Tx BA Stream table. -+ */ -+void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv) -+{ -+ int i; -+ struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_for_each_entry_safe(del_tbl_ptr, tmp_node, -+ &priv->tx_ba_stream_tbl_ptr, list) -+ mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr); -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ -+ INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); -+ -+ for (i = 0; i < MAX_NUM_TID; ++i) -+ priv->aggr_prio_tbl[i].ampdu_ap = -+ priv->aggr_prio_tbl[i].ampdu_user; -+} -+ -+/* -+ * This function returns the pointer to an entry in BA Stream -+ * table which matches the given RA/TID pair. -+ */ -+struct mwifiex_tx_ba_stream_tbl * -+mwifiex_11n_get_tx_ba_stream_tbl(struct mwifiex_private *priv, -+ int tid, u8 *ra) -+{ -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { -+ if ((!memcmp(tx_ba_tsr_tbl->ra, ra, ETH_ALEN)) -+ && (tx_ba_tsr_tbl->tid == tid)) { -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, -+ flags); -+ return tx_ba_tsr_tbl; -+ } -+ } -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ return NULL; -+} -+ -+/* -+ * This function creates an entry in Tx BA stream table for the -+ * given RA/TID pair. -+ */ -+void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, -+ u8 *ra, int tid, -+ enum mwifiex_ba_status ba_status) -+{ -+ struct mwifiex_tx_ba_stream_tbl *new_node; -+ unsigned long flags; -+ -+ if (!mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ra)) { -+ new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), -+ GFP_ATOMIC); -+ if (!new_node) { -+ dev_err(priv->adapter->dev, -+ "%s: failed to alloc new_node\n", __func__); -+ return; -+ } -+ -+ INIT_LIST_HEAD(&new_node->list); -+ -+ new_node->tid = tid; -+ new_node->ba_status = ba_status; -+ memcpy(new_node->ra, ra, ETH_ALEN); -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ } -+} -+ -+/* -+ * This function sends an add BA request to the given TID/RA pair. -+ */ -+int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) -+{ -+ struct host_cmd_ds_11n_addba_req add_ba_req; -+ static u8 dialog_tok; -+ int ret; -+ -+ dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); -+ -+ add_ba_req.block_ack_param_set = cpu_to_le16( -+ (u16) ((tid << BLOCKACKPARAM_TID_POS) | -+ (priv->add_ba_param. -+ tx_win_size << BLOCKACKPARAM_WINSIZE_POS) | -+ IMMEDIATE_BLOCK_ACK)); -+ add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); -+ -+ ++dialog_tok; -+ -+ if (dialog_tok == 0) -+ dialog_tok = 1; -+ -+ add_ba_req.dialog_token = dialog_tok; -+ memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); -+ -+ /* We don't wait for the response of this command */ -+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ, -+ 0, 0, &add_ba_req); -+ -+ return ret; -+} -+ -+/* -+ * This function sends a delete BA request to the given TID/RA pair. -+ */ -+int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, -+ int initiator) -+{ -+ struct host_cmd_ds_11n_delba delba; -+ int ret; -+ uint16_t del_ba_param_set; -+ -+ memset(&delba, 0, sizeof(delba)); -+ delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); -+ -+ del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); -+ if (initiator) -+ del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; -+ else -+ del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; -+ -+ memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); -+ -+ /* We don't wait for the response of this command */ -+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, -+ HostCmd_ACT_GEN_SET, 0, &delba); -+ -+ return ret; -+} -+ -+/* -+ * This function handles the command response of a delete BA request. -+ */ -+void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) -+{ -+ struct host_cmd_ds_11n_delba *cmd_del_ba = -+ (struct host_cmd_ds_11n_delba *) del_ba; -+ uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set); -+ int tid; -+ -+ tid = del_ba_param_set >> DELBA_TID_POS; -+ -+ mwifiex_11n_delete_ba_stream_tbl(priv, tid, cmd_del_ba->peer_mac_addr, -+ TYPE_DELBA_RECEIVE, -+ INITIATOR_BIT(del_ba_param_set)); -+} -+ -+/* -+ * This function retrieves the Rx reordering table. -+ */ -+int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, -+ struct mwifiex_ds_rx_reorder_tbl *buf) -+{ -+ int i; -+ struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf; -+ struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr; -+ int count = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); -+ list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr, -+ list) { -+ rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid; -+ memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN); -+ rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win; -+ rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size; -+ for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) { -+ if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) -+ rx_reo_tbl->buffer[i] = true; -+ else -+ rx_reo_tbl->buffer[i] = false; -+ } -+ rx_reo_tbl++; -+ count++; -+ -+ if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED) -+ break; -+ } -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -+ -+ return count; -+} -+ -+/* -+ * This function retrieves the Tx BA stream table. -+ */ -+int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, -+ struct mwifiex_ds_tx_ba_stream_tbl *buf) -+{ -+ struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; -+ struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf; -+ int count = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { -+ rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid; -+ dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", -+ __func__, rx_reo_tbl->tid); -+ memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); -+ rx_reo_tbl++; -+ count++; -+ if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) -+ break; -+ } -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ -+ return count; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n.h 2011-05-05 23:29:45.493441961 +0200 -@@ -0,0 +1,161 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_11N_H_ -+#define _MWIFIEX_11N_H_ -+ -+#include "11n_aggr.h" -+#include "11n_rxreorder.h" -+#include "wmm.h" -+ -+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 host_cmd_ds_command *resp, -+ void *data_buf); -+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, -+ struct mwifiex_bssdescriptor *bss_desc, -+ u8 **buffer); -+void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc); -+void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, -+ struct mwifiex_ie_types_htcap *); -+int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, -+ u16 action, int *htcap_cfg); -+void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, -+ struct mwifiex_tx_ba_stream_tbl -+ *tx_tbl); -+void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv); -+struct mwifiex_tx_ba_stream_tbl *mwifiex_11n_get_tx_ba_stream_tbl(struct -+ mwifiex_private -+ *priv, int tid, -+ u8 *ra); -+void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv, u8 *ra, -+ int tid, -+ enum mwifiex_ba_status ba_status); -+int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac); -+int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, -+ int initiator); -+void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba); -+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 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 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, int tid) -+{ -+ return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) -+ ? true : false); -+} -+ -+/* -+ * This function checks whether AMSDU is allowed or not for a particular TID. -+ */ -+static inline u8 -+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) -+ || !((priv->bitmap_rates[2]) & 0x03))) -+ ? true : false); -+} -+ -+/* -+ * This function checks whether a space is available for new BA stream or not. -+ */ -+static inline u8 mwifiex_space_avail_for_new_ba_stream( -+ struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_private *priv; -+ u8 i; -+ u32 ba_stream_num = 0; -+ -+ 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 < -+ MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) ? true : false); -+} -+ -+/* -+ * This function finds the correct Tx BA stream to delete. -+ * -+ * Upon successfully locating, both the TID and the RA are returned. -+ */ -+static inline u8 -+mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, -+ int *ptid, u8 *ra) -+{ -+ int tid; -+ u8 ret = false; -+ struct mwifiex_tx_ba_stream_tbl *tx_tbl; -+ unsigned long flags; -+ -+ tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user; -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { -+ if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { -+ tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; -+ *ptid = tx_tbl->tid; -+ memcpy(ra, tx_tbl->ra, ETH_ALEN); -+ ret = true; -+ } -+ } -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ -+ return ret; -+} -+ -+/* -+ * This function checks whether BA stream is set up or not. -+ */ -+static inline int -+mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr, int tid) -+{ -+ struct mwifiex_tx_ba_stream_tbl *tx_tbl; -+ -+ tx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, ptr->ra); -+ if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl)) -+ return true; -+ -+ return false; -+} -+#endif /* !_MWIFIEX_11N_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_rxreorder.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_rxreorder.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_rxreorder.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_rxreorder.c 2011-05-05 23:29:45.473441719 +0200 -@@ -0,0 +1,617 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n RX Re-ordering -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+#include "11n_rxreorder.h" -+ -+/* -+ * This function dispatches all packets in the Rx reorder table. -+ * -+ * There could be holes in the buffer, which are skipped by the function. -+ * Since the buffer is linear, the function uses rotation to simulate -+ * circular buffer. -+ */ -+static int -+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; -+ void *rx_tmp_ptr = NULL; -+ unsigned long flags; -+ -+ no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? -+ min((start_win - rx_reor_tbl_ptr->start_win), -+ rx_reor_tbl_ptr->win_size) : rx_reor_tbl_ptr->win_size; -+ -+ for (i = 0; i < no_pkt_to_send; ++i) { -+ spin_lock_irqsave(&priv->rx_pkt_lock, flags); -+ rx_tmp_ptr = NULL; -+ if (rx_reor_tbl_ptr->rx_reorder_ptr[i]) { -+ 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); -+ if (rx_tmp_ptr) -+ mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); -+ } -+ -+ spin_lock_irqsave(&priv->rx_pkt_lock, flags); -+ /* -+ * We don't have a circular buffer, hence use rotation to simulate -+ * circular buffer -+ */ -+ 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; -+ } -+ -+ rx_reor_tbl_ptr->start_win = start_win; -+ spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -+ -+ return 0; -+} -+ -+/* -+ * This function dispatches all packets in the Rx reorder table until -+ * a hole is found. -+ * -+ * The start window is adjusted automatically when a hole is located. -+ * Since the buffer is linear, the function uses rotation to simulate -+ * circular buffer. -+ */ -+static int -+mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) -+{ -+ int i, j, xchg; -+ void *rx_tmp_ptr = NULL; -+ unsigned long flags; -+ -+ for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { -+ spin_lock_irqsave(&priv->rx_pkt_lock, flags); -+ if (!rx_reor_tbl_ptr->rx_reorder_ptr[i]) { -+ spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -+ break; -+ } -+ 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_process_rx_packet(priv->adapter, rx_tmp_ptr); -+ } -+ -+ spin_lock_irqsave(&priv->rx_pkt_lock, flags); -+ /* -+ * We don't have a circular buffer, hence use rotation to simulate -+ * circular buffer -+ */ -+ if (i > 0) { -+ xchg = rx_reor_tbl_ptr->win_size - i; -+ for (j = 0; j < xchg; ++j) { -+ rx_reor_tbl_ptr->rx_reorder_ptr[j] = -+ rx_reor_tbl_ptr->rx_reorder_ptr[i + j]; -+ rx_reor_tbl_ptr->rx_reorder_ptr[i + j] = NULL; -+ } -+ } -+ rx_reor_tbl_ptr->start_win = (rx_reor_tbl_ptr->start_win + i) -+ &(MAX_TID_VALUE - 1); -+ spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -+ return 0; -+} -+ -+/* -+ * This function deletes the Rx reorder table and frees the memory. -+ * -+ * The function stops the associated timer and dispatches all the -+ * pending packets in the Rx reorder table before deletion. -+ */ -+static void -+mwifiex_11n_delete_rx_reorder_tbl_entry(struct mwifiex_private *priv, -+ struct mwifiex_rx_reorder_tbl -+ *rx_reor_tbl_ptr) -+{ -+ unsigned long flags; -+ -+ if (!rx_reor_tbl_ptr) -+ return; -+ -+ mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, -+ (rx_reor_tbl_ptr->start_win + -+ rx_reor_tbl_ptr->win_size) -+ &(MAX_TID_VALUE - 1)); -+ -+ del_timer(&rx_reor_tbl_ptr->timer_context.timer); -+ -+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); -+ list_del(&rx_reor_tbl_ptr->list); -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -+ -+ kfree(rx_reor_tbl_ptr->rx_reorder_ptr); -+ kfree(rx_reor_tbl_ptr); -+} -+ -+/* -+ * This function returns the pointer to an entry in Rx reordering -+ * table which matches the given TA/TID pair. -+ */ -+static struct mwifiex_rx_reorder_tbl * -+mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) -+{ -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); -+ list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { -+ if ((!memcmp(rx_reor_tbl_ptr->ta, ta, ETH_ALEN)) -+ && (rx_reor_tbl_ptr->tid == tid)) { -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, -+ flags); -+ return rx_reor_tbl_ptr; -+ } -+ } -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -+ -+ return NULL; -+} -+ -+/* -+ * This function finds the last sequence number used in the packets -+ * buffered in Rx reordering table. -+ */ -+static int -+mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr) -+{ -+ int i; -+ -+ for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i) -+ if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) -+ return i; -+ -+ return -1; -+} -+ -+/* -+ * This function flushes all the packets in Rx reordering table. -+ * -+ * The function checks if any packets are currently buffered in the -+ * table or not. In case there are packets available, it dispatches -+ * them and then dumps the Rx reordering table. -+ */ -+static void -+mwifiex_flush_data(unsigned long context) -+{ -+ struct reorder_tmr_cnxt *reorder_cnxt = -+ (struct reorder_tmr_cnxt *) context; -+ int start_win; -+ -+ start_win = mwifiex_11n_find_last_seq_num(reorder_cnxt->ptr); -+ if (start_win >= 0) { -+ dev_dbg(reorder_cnxt->priv->adapter->dev, -+ "info: flush data %d\n", start_win); -+ mwifiex_11n_dispatch_pkt_until_start_win(reorder_cnxt->priv, -+ reorder_cnxt->ptr, -+ ((reorder_cnxt->ptr->start_win + -+ start_win + 1) & (MAX_TID_VALUE - 1))); -+ } -+} -+ -+/* -+ * This function creates an entry in Rx reordering table for the -+ * given TA/TID. -+ * -+ * The function also initializes the entry with sequence number, window -+ * size as well as initializes the timer. -+ * -+ * If the received TA/TID pair is already present, all the packets are -+ * dispatched and the window size is moved until the SSN. -+ */ -+static void -+mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, -+ int tid, int win_size, int seq_num) -+{ -+ int i; -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr, *new_node; -+ u16 last_seq = 0; -+ unsigned long flags; -+ -+ /* -+ * If we get a TID, ta pair which is already present dispatch all the -+ * the packets and move the window size until the ssn -+ */ -+ rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); -+ if (rx_reor_tbl_ptr) { -+ mwifiex_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, -+ seq_num); -+ return; -+ } -+ /* if !rx_reor_tbl_ptr then create one */ -+ new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL); -+ if (!new_node) { -+ dev_err(priv->adapter->dev, "%s: failed to alloc new_node\n", -+ __func__); -+ return; -+ } -+ -+ INIT_LIST_HEAD(&new_node->list); -+ new_node->tid = tid; -+ memcpy(new_node->ta, ta, ETH_ALEN); -+ new_node->start_win = seq_num; -+ if (mwifiex_queuing_ra_based(priv)) -+ /* TODO for adhoc */ -+ dev_dbg(priv->adapter->dev, -+ "info: ADHOC:last_seq=%d start_win=%d\n", -+ last_seq, new_node->start_win); -+ else -+ last_seq = priv->rx_seq[tid]; -+ -+ if (last_seq >= new_node->start_win) -+ new_node->start_win = last_seq + 1; -+ -+ new_node->win_size = win_size; -+ -+ new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, -+ GFP_KERNEL); -+ if (!new_node->rx_reorder_ptr) { -+ kfree((u8 *) new_node); -+ dev_err(priv->adapter->dev, -+ "%s: failed to alloc reorder_ptr\n", __func__); -+ return; -+ } -+ -+ new_node->timer_context.ptr = new_node; -+ new_node->timer_context.priv = priv; -+ -+ init_timer(&new_node->timer_context.timer); -+ new_node->timer_context.timer.function = mwifiex_flush_data; -+ new_node->timer_context.timer.data = -+ (unsigned long) &new_node->timer_context; -+ -+ for (i = 0; i < win_size; ++i) -+ new_node->rx_reorder_ptr[i] = NULL; -+ -+ 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); -+} -+ -+/* -+ * This function prepares command for adding a BA request. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting add BA request buffer -+ * - Ensuring correct endian-ness -+ */ -+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 *) -+ &cmd->params.add_ba_req; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ); -+ cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN); -+ memcpy(add_ba_req, data_buf, sizeof(*add_ba_req)); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command for adding a BA response. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting add BA response buffer -+ * - Ensuring correct endian-ness -+ */ -+int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ void *data_buf) -+{ -+ struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = -+ (struct host_cmd_ds_11n_addba_rsp *) -+ &cmd->params.add_ba_rsp; -+ struct host_cmd_ds_11n_addba_req *cmd_addba_req = -+ (struct host_cmd_ds_11n_addba_req *) data_buf; -+ u8 tid = 0; -+ int win_size = 0; -+ uint16_t block_ack_param_set; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); -+ cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); -+ -+ memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr, -+ ETH_ALEN); -+ add_ba_rsp->dialog_token = cmd_addba_req->dialog_token; -+ add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo; -+ add_ba_rsp->ssn = cmd_addba_req->ssn; -+ -+ block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set); -+ tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) -+ >> BLOCKACKPARAM_TID_POS; -+ add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); -+ block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; -+ /* We donot support AMSDU inside AMPDU, hence reset the bit */ -+ block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; -+ block_ack_param_set |= (priv->add_ba_param.rx_win_size << -+ BLOCKACKPARAM_WINSIZE_POS); -+ add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); -+ win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) -+ & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) -+ >> BLOCKACKPARAM_WINSIZE_POS; -+ cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set); -+ -+ mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr, -+ tid, win_size, le16_to_cpu(cmd_addba_req->ssn)); -+ return 0; -+} -+ -+/* -+ * This function prepares command for deleting a BA request. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting del BA request buffer -+ * - Ensuring correct endian-ness -+ */ -+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; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA); -+ cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN); -+ memcpy(del_ba, data_buf, sizeof(*del_ba)); -+ -+ return 0; -+} -+ -+/* -+ * This function identifies if Rx reordering is needed for a received packet. -+ * -+ * In case reordering is required, the function will do the reordering -+ * before sending it to kernel. -+ * -+ * The Rx reorder table is checked first with the received TID/TA pair. If -+ * not found, the received packet is dispatched immediately. But if found, -+ * the packet is reordered and all the packets in the updated Rx reordering -+ * table is dispatched until a hole is found. -+ * -+ * For sequence number less than the starting window, the packet is dropped. -+ */ -+int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, -+ u16 seq_num, u16 tid, -+ u8 *ta, u8 pkt_type, void *payload) -+{ -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; -+ int start_win, end_win, win_size; -+ int ret = 0; -+ u16 pkt_index = 0; -+ -+ rx_reor_tbl_ptr = -+ mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, -+ tid, ta); -+ if (!rx_reor_tbl_ptr) { -+ if (pkt_type != PKT_TYPE_BAR) -+ mwifiex_process_rx_packet(priv->adapter, payload); -+ return 0; -+ } -+ start_win = rx_reor_tbl_ptr->start_win; -+ win_size = rx_reor_tbl_ptr->win_size; -+ end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); -+ del_timer(&rx_reor_tbl_ptr->timer_context.timer); -+ mod_timer(&rx_reor_tbl_ptr->timer_context.timer, jiffies -+ + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000); -+ -+ /* -+ * If seq_num is less then starting win then ignore and drop the -+ * packet -+ */ -+ if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */ -+ if (seq_num >= ((start_win + (TWOPOW11)) & (MAX_TID_VALUE - 1)) -+ && (seq_num < start_win)) -+ return -1; -+ } else if ((seq_num < start_win) -+ || (seq_num > (start_win + (TWOPOW11)))) { -+ return -1; -+ } -+ -+ /* -+ * If this packet is a BAR we adjust seq_num as -+ * WinStart = seq_num -+ */ -+ if (pkt_type == PKT_TYPE_BAR) -+ seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); -+ -+ if (((end_win < start_win) -+ && (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) -+ && (seq_num > end_win)) || ((end_win > start_win) -+ && ((seq_num > end_win) || (seq_num < start_win)))) { -+ end_win = seq_num; -+ if (((seq_num - win_size) + 1) >= 0) -+ start_win = (end_win - win_size) + 1; -+ else -+ start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; -+ ret = mwifiex_11n_dispatch_pkt_until_start_win(priv, -+ rx_reor_tbl_ptr, start_win); -+ -+ if (ret) -+ return ret; -+ } -+ -+ if (pkt_type != PKT_TYPE_BAR) { -+ if (seq_num >= start_win) -+ pkt_index = seq_num - start_win; -+ else -+ pkt_index = (seq_num+MAX_TID_VALUE) - start_win; -+ -+ if (rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index]) -+ return -1; -+ -+ rx_reor_tbl_ptr->rx_reorder_ptr[pkt_index] = payload; -+ } -+ -+ /* -+ * Dispatch all packets sequentially from start_win until a -+ * hole is found and adjust the start_win appropriately -+ */ -+ ret = mwifiex_11n_scan_and_dispatch(priv, rx_reor_tbl_ptr); -+ -+ return ret; -+} -+ -+/* -+ * This function deletes an entry for a given TID/TA pair. -+ * -+ * The TID/TA are taken from del BA event body. -+ */ -+void -+mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int tid, -+ u8 *peer_mac, u8 type, int initiator) -+{ -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; -+ struct mwifiex_tx_ba_stream_tbl *ptx_tbl; -+ u8 cleanup_rx_reorder_tbl; -+ unsigned long flags; -+ -+ if (type == TYPE_DELBA_RECEIVE) -+ cleanup_rx_reorder_tbl = (initiator) ? true : false; -+ else -+ cleanup_rx_reorder_tbl = (initiator) ? false : true; -+ -+ dev_dbg(priv->adapter->dev, "event: DELBA: %pM tid=%d, " -+ "initiator=%d\n", peer_mac, tid, initiator); -+ -+ if (cleanup_rx_reorder_tbl) { -+ rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, tid, -+ peer_mac); -+ if (!rx_reor_tbl_ptr) { -+ dev_dbg(priv->adapter->dev, -+ "event: TID, TA not found in table\n"); -+ return; -+ } -+ mwifiex_11n_delete_rx_reorder_tbl_entry(priv, rx_reor_tbl_ptr); -+ } else { -+ ptx_tbl = mwifiex_11n_get_tx_ba_stream_tbl(priv, tid, peer_mac); -+ if (!ptx_tbl) { -+ dev_dbg(priv->adapter->dev, -+ "event: TID, RA not found in table\n"); -+ return; -+ } -+ -+ spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); -+ mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); -+ spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); -+ } -+} -+ -+/* -+ * This function handles the command response of an add BA response. -+ * -+ * Handling includes changing the header fields into CPU format and -+ * creating the stream, provided the add BA is accepted. -+ */ -+int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = -+ (struct host_cmd_ds_11n_addba_rsp *) -+ &resp->params.add_ba_rsp; -+ int tid, win_size; -+ struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr = NULL; -+ uint16_t block_ack_param_set; -+ -+ block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); -+ -+ tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) -+ >> BLOCKACKPARAM_TID_POS; -+ /* -+ * Check if we had rejected the ADDBA, if yes then do not create -+ * the stream -+ */ -+ if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { -+ win_size = (block_ack_param_set & -+ IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) -+ >> BLOCKACKPARAM_WINSIZE_POS; -+ -+ dev_dbg(priv->adapter->dev, "cmd: ADDBA RSP: %pM" -+ " tid=%d ssn=%d win_size=%d\n", -+ add_ba_rsp->peer_mac_addr, -+ tid, add_ba_rsp->ssn, win_size); -+ } else { -+ dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", -+ add_ba_rsp->peer_mac_addr, tid); -+ -+ rx_reor_tbl_ptr = mwifiex_11n_get_rx_reorder_tbl(priv, -+ tid, add_ba_rsp->peer_mac_addr); -+ if (rx_reor_tbl_ptr) -+ mwifiex_11n_delete_rx_reorder_tbl_entry(priv, -+ rx_reor_tbl_ptr); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles BA stream timeout event by preparing and sending -+ * a command to the firmware. -+ */ -+void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, -+ struct host_cmd_ds_11n_batimeout *event) -+{ -+ struct host_cmd_ds_11n_delba delba; -+ -+ memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba)); -+ memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN); -+ -+ delba.del_ba_param_set |= -+ cpu_to_le16((u16) event->tid << DELBA_TID_POS); -+ 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_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba); -+} -+ -+/* -+ * This function cleans up the Rx reorder table by deleting all the entries -+ * and re-initializing. -+ */ -+void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) -+{ -+ struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); -+ list_for_each_entry_safe(del_tbl_ptr, tmp_node, -+ &priv->rx_reorder_tbl_ptr, list) { -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -+ mwifiex_11n_delete_rx_reorder_tbl_entry(priv, del_tbl_ptr); -+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); -+ } -+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -+ -+ INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); -+ memset(priv->rx_seq, 0, sizeof(priv->rx_seq)); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_rxreorder.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_rxreorder.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/11n_rxreorder.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/11n_rxreorder.h 2011-05-05 23:29:45.440441321 +0200 -@@ -0,0 +1,65 @@ -+/* -+ * Marvell Wireless LAN device driver: 802.11n RX Re-ordering -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_11N_RXREORDER_H_ -+#define _MWIFIEX_11N_RXREORDER_H_ -+ -+#define MIN_FLUSH_TIMER_MS 50 -+ -+#define PKT_TYPE_BAR 0xE7 -+#define MAX_TID_VALUE (2 << 11) -+#define TWOPOW11 (2 << 10) -+ -+#define BLOCKACKPARAM_TID_POS 2 -+#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1 -+#define BLOCKACKPARAM_WINSIZE_POS 6 -+#define DELBA_TID_POS 12 -+#define DELBA_INITIATOR_POS 11 -+#define TYPE_DELBA_SENT 1 -+#define TYPE_DELBA_RECEIVE 2 -+#define IMMEDIATE_BLOCK_ACK 0x2 -+ -+#define ADDBA_RSP_STATUS_ACCEPT 0 -+ -+int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, -+ u16 seqNum, -+ u16 tid, u8 *ta, -+ u8 pkttype, void *payload); -+void mwifiex_11n_delete_ba_stream_tbl(struct mwifiex_private *priv, int Tid, -+ u8 *PeerMACAddr, u8 type, -+ int initiator); -+void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, -+ struct host_cmd_ds_11n_batimeout *event); -+int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, -+ struct host_cmd_ds_command -+ *resp); -+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 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 -+ mwifiex_private -+ *priv, int tid, -+ u8 *ta); -+ -+#endif /* _MWIFIEX_11N_RXREORDER_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfg80211.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfg80211.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfg80211.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfg80211.c 2011-05-05 23:29:45.476441755 +0200 -@@ -0,0 +1,1421 @@ -+/* -+ * Marvell Wireless LAN device driver: CFG80211 -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "cfg80211.h" -+#include "main.h" -+ -+/* -+ * This function maps the nl802.11 channel type into driver channel type. -+ * -+ * The mapping is as follows - -+ * NL80211_CHAN_NO_HT -> NO_SEC_CHANNEL -+ * NL80211_CHAN_HT20 -> NO_SEC_CHANNEL -+ * NL80211_CHAN_HT40PLUS -> SEC_CHANNEL_ABOVE -+ * NL80211_CHAN_HT40MINUS -> SEC_CHANNEL_BELOW -+ * Others -> NO_SEC_CHANNEL -+ */ -+static int -+mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type -+ channel_type) -+{ -+ switch (channel_type) { -+ case NL80211_CHAN_NO_HT: -+ case NL80211_CHAN_HT20: -+ return NO_SEC_CHANNEL; -+ case NL80211_CHAN_HT40PLUS: -+ return SEC_CHANNEL_ABOVE; -+ case NL80211_CHAN_HT40MINUS: -+ return SEC_CHANNEL_BELOW; -+ default: -+ return NO_SEC_CHANNEL; -+ } -+} -+ -+/* -+ * This function maps the driver channel type into nl802.11 channel type. -+ * -+ * The mapping is as follows - -+ * NO_SEC_CHANNEL -> NL80211_CHAN_HT20 -+ * SEC_CHANNEL_ABOVE -> NL80211_CHAN_HT40PLUS -+ * SEC_CHANNEL_BELOW -> NL80211_CHAN_HT40MINUS -+ * Others -> NL80211_CHAN_HT20 -+ */ -+static enum nl80211_channel_type -+mwifiex_channels_to_cfg80211_channel_type(int channel_type) -+{ -+ switch (channel_type) { -+ case NO_SEC_CHANNEL: -+ return NL80211_CHAN_HT20; -+ case SEC_CHANNEL_ABOVE: -+ return NL80211_CHAN_HT40PLUS; -+ case SEC_CHANNEL_BELOW: -+ return NL80211_CHAN_HT40MINUS; -+ default: -+ return NL80211_CHAN_HT20; -+ } -+} -+ -+/* -+ * This function checks whether WEP is set. -+ */ -+static int -+mwifiex_is_alg_wep(u32 cipher) -+{ -+ int alg = 0; -+ -+ switch (cipher) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ case WLAN_CIPHER_SUITE_WEP104: -+ alg = 1; -+ break; -+ default: -+ alg = 0; -+ break; -+ } -+ return alg; -+} -+ -+/* -+ * This function retrieves the private structure from kernel wiphy structure. -+ */ -+static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) -+{ -+ return (void *) (*(unsigned long *) wiphy_priv(wiphy)); -+} -+ -+/* -+ * CFG802.11 operation handler to delete a network key. -+ */ -+static int -+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); -+ -+ if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { -+ wiphy_err(wiphy, "deleting the crypto keys\n"); -+ return -EFAULT; -+ } -+ -+ wiphy_dbg(wiphy, "info: crypto keys deleted\n"); -+ return 0; -+} -+ -+/* -+ * CFG802.11 operation handler to set Tx power. -+ */ -+static int -+mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, -+ enum nl80211_tx_power_setting type, -+ int dbm) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ struct mwifiex_power_cfg power_cfg; -+ -+ 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 mwifiex_set_tx_power(priv, &power_cfg); -+} -+ -+/* -+ * CFG802.11 operation handler to set Power Save option. -+ * -+ * The timeout value, if provided, is currently ignored. -+ */ -+static int -+mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, -+ struct net_device *dev, -+ bool enabled, int timeout) -+{ -+ 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"); -+ -+ ps_mode = enabled; -+ -+ return mwifiex_drv_set_power(priv, &ps_mode); -+} -+ -+/* -+ * CFG802.11 operation handler to set the default network key. -+ */ -+static int -+mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, -+ u8 key_index, bool unicast, -+ bool multicast) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ /* Return if WEP key not configured */ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED) -+ return 0; -+ -+ if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { -+ wiphy_err(wiphy, "set default Tx key index\n"); -+ return -EFAULT; -+ } -+ -+ return 0; -+} -+ -+/* -+ * CFG802.11 operation handler to add a network key. -+ */ -+static int -+mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, -+ u8 key_index, bool pairwise, const u8 *mac_addr, -+ struct key_params *params) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ if (mwifiex_set_encode(priv, params->key, params->key_len, -+ key_index, 0)) { -+ wiphy_err(wiphy, "crypto keys added\n"); -+ return -EFAULT; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function sends domain information to the firmware. -+ * -+ * The following information are passed to the firmware - -+ * - Country codes -+ * - Sub bands (first channel, number of channels, maximum Tx power) -+ */ -+static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) -+{ -+ u8 no_of_triplet = 0; -+ struct ieee80211_country_ie_triplet *t; -+ u8 no_of_parsed_chan = 0; -+ u8 first_chan = 0, next_chan = 0, max_pwr = 0; -+ u8 i, flag = 0; -+ enum ieee80211_band band; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_channel *ch; -+ 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; -+ -+ /* Set country code */ -+ domain_info->country_code[0] = priv->country_code[0]; -+ domain_info->country_code[1] = priv->country_code[1]; -+ domain_info->country_code[2] = ' '; -+ -+ band = mwifiex_band_to_radio_type(adapter->config_bands); -+ if (!wiphy->bands[band]) { -+ wiphy_err(wiphy, "11D: setting domain info in FW\n"); -+ return -1; -+ } -+ -+ sband = wiphy->bands[band]; -+ -+ for (i = 0; i < sband->n_channels ; i++) { -+ ch = &sband->channels[i]; -+ if (ch->flags & IEEE80211_CHAN_DISABLED) -+ continue; -+ -+ if (!flag) { -+ flag = 1; -+ first_chan = (u32) ch->hw_value; -+ next_chan = first_chan; -+ max_pwr = ch->max_power; -+ no_of_parsed_chan = 1; -+ continue; -+ } -+ -+ if (ch->hw_value == next_chan + 1 && -+ ch->max_power == max_pwr) { -+ next_chan++; -+ no_of_parsed_chan++; -+ } else { -+ t = &domain_info->triplet[no_of_triplet]; -+ t->chans.first_channel = first_chan; -+ t->chans.num_channels = no_of_parsed_chan; -+ t->chans.max_power = max_pwr; -+ no_of_triplet++; -+ first_chan = (u32) ch->hw_value; -+ next_chan = first_chan; -+ max_pwr = ch->max_power; -+ no_of_parsed_chan = 1; -+ } -+ } -+ -+ if (flag) { -+ t = &domain_info->triplet[no_of_triplet]; -+ t->chans.first_channel = first_chan; -+ t->chans.num_channels = no_of_parsed_chan; -+ t->chans.max_power = max_pwr; -+ no_of_triplet++; -+ } -+ -+ domain_info->no_of_triplet = no_of_triplet; -+ -+ 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 0; -+} -+ -+/* -+ * CFG802.11 regulatory domain callback function. -+ * -+ * This function is called when the regulatory domain is changed due to the -+ * following reasons - -+ * - Set by driver -+ * - Set by system core -+ * - Set by user -+ * - Set bt Country IE -+ */ -+static int mwifiex_reg_notifier(struct wiphy *wiphy, -+ struct regulatory_request *request) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" -+ " %c%c\n", request->alpha2[0], request->alpha2[1]); -+ -+ memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); -+ -+ switch (request->initiator) { -+ case NL80211_REGDOM_SET_BY_DRIVER: -+ case NL80211_REGDOM_SET_BY_CORE: -+ case NL80211_REGDOM_SET_BY_USER: -+ break; -+ /* Todo: apply driver specific changes in channel flags based -+ on the request initiator if necessary. */ -+ case NL80211_REGDOM_SET_BY_COUNTRY_IE: -+ break; -+ } -+ mwifiex_send_domain_info_cmd_fw(wiphy); -+ -+ return 0; -+} -+ -+/* -+ * This function sets the RF channel. -+ * -+ * This function creates multiple IOCTL requests, populates them accordingly -+ * and issues them to set the band/channel and frequency. -+ */ -+static int -+mwifiex_set_rf_channel(struct mwifiex_private *priv, -+ struct ieee80211_channel *chan, -+ enum nl80211_channel_type channel_type) -+{ -+ struct mwifiex_chan_freq_power cfp; -+ struct mwifiex_ds_band_cfg band_cfg; -+ u32 config_bands = 0; -+ struct wiphy *wiphy = priv->wdev->wiphy; -+ -+ if (chan) { -+ memset(&band_cfg, 0, sizeof(band_cfg)); -+ /* Set appropriate bands */ -+ if (chan->band == IEEE80211_BAND_2GHZ) -+ config_bands = BAND_B | BAND_G | BAND_GN; -+ else -+ config_bands = BAND_AN | BAND_A; -+ if (priv->bss_mode == NL80211_IFTYPE_STATION -+ || priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) { -+ band_cfg.config_bands = config_bands; -+ } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ band_cfg.config_bands = config_bands; -+ band_cfg.adhoc_start_band = config_bands; -+ } -+ -+ band_cfg.sec_chan_offset = -+ mwifiex_cfg80211_channel_type_to_mwifiex_channels -+ (channel_type); -+ -+ if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) -+ return -EFAULT; -+ -+ mwifiex_send_domain_info_cmd_fw(wiphy); -+ } -+ -+ wiphy_dbg(wiphy, "info: setting band %d, channel offset %d and " -+ "mode %d\n", config_bands, band_cfg.sec_chan_offset, -+ priv->bss_mode); -+ if (!chan) -+ return 0; -+ -+ memset(&cfp, 0, sizeof(cfp)); -+ cfp.freq = chan->center_freq; -+ cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); -+ -+ if (mwifiex_bss_set_channel(priv, &cfp)) -+ return -EFAULT; -+ -+ return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); -+} -+ -+/* -+ * CFG802.11 operation handler to set channel. -+ * -+ * This function can only be used when station is not connected. -+ */ -+static int -+mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, -+ struct ieee80211_channel *chan, -+ enum nl80211_channel_type channel_type) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ if (priv->media_connected) { -+ wiphy_err(wiphy, "This setting is valid only when station " -+ "is not connected\n"); -+ return -EINVAL; -+ } -+ -+ return mwifiex_set_rf_channel(priv, chan, channel_type); -+} -+ -+/* -+ * This function sets the fragmentation threshold. -+ * -+ * 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; -+ -+ if (frag_thr < MWIFIEX_FRAG_MIN_VALUE -+ || frag_thr > MWIFIEX_FRAG_MAX_VALUE) -+ return -EINVAL; -+ -+ /* 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); -+ -+ return ret; -+} -+ -+/* -+ * This function sets the RTS threshold. -+ -+ * 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) -+{ -+ if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) -+ rts_thr = MWIFIEX_RTS_MAX_VALUE; -+ -+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, -+ HostCmd_ACT_GEN_SET, RTS_THRESH_I, -+ &rts_thr); -+} -+ -+/* -+ * CFG802.11 operation handler to set wiphy parameters. -+ * -+ * This function can be used to set the RTS threshold and the -+ * Fragmentation threshold of the driver. -+ */ -+static int -+mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ int ret = 0; -+ -+ 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); -+ -+ return ret; -+} -+ -+/* -+ * CFG802.11 operation handler to change interface type. -+ */ -+static int -+mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, -+ struct net_device *dev, -+ enum nl80211_iftype type, u32 *flags, -+ struct vif_params *params) -+{ -+ int ret = 0; -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ -+ if (priv->bss_mode == type) { -+ wiphy_warn(wiphy, "already set to required type\n"); -+ return 0; -+ } -+ -+ priv->bss_mode = type; -+ -+ switch (type) { -+ case NL80211_IFTYPE_ADHOC: -+ dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; -+ wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); -+ break; -+ case NL80211_IFTYPE_STATION: -+ dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; -+ wiphy_dbg(wiphy, "info: setting interface type to managed\n"); -+ break; -+ case NL80211_IFTYPE_UNSPECIFIED: -+ dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; -+ wiphy_dbg(wiphy, "info: setting interface type to auto\n"); -+ return 0; -+ default: -+ wiphy_err(wiphy, "unknown interface type: %d\n", type); -+ return -EINVAL; -+ } -+ -+ mwifiex_deauthenticate(priv, NULL); -+ -+ priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; -+ -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, -+ HostCmd_ACT_GEN_SET, 0, NULL); -+ -+ return ret; -+} -+ -+/* -+ * This function dumps the station information on a buffer. -+ * -+ * The following information are shown - -+ * - Total bytes transmitted -+ * - Total bytes received -+ * - Total packets transmitted -+ * - Total packets received -+ * - Signal quality level -+ * - Transmission rate -+ */ -+static int -+mwifiex_dump_station_info(struct mwifiex_private *priv, -+ struct station_info *sinfo) -+{ -+ struct mwifiex_ds_get_signal signal; -+ struct mwifiex_rate_cfg rate; -+ int ret = 0; -+ -+ sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | -+ STATION_INFO_RX_PACKETS | -+ STATION_INFO_TX_PACKETS -+ | STATION_INFO_SIGNAL | STATION_INFO_TX_BITRATE; -+ -+ /* Get signal information from the firmware */ -+ memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); -+ if (mwifiex_get_signal_info(priv, &signal)) { -+ dev_err(priv->adapter->dev, "getting signal information\n"); -+ ret = -EFAULT; -+ } -+ -+ if (mwifiex_drv_get_data_rate(priv, &rate)) { -+ dev_err(priv->adapter->dev, "getting data rate\n"); -+ ret = -EFAULT; -+ } -+ -+ sinfo->rx_bytes = priv->stats.rx_bytes; -+ sinfo->tx_bytes = priv->stats.tx_bytes; -+ sinfo->rx_packets = priv->stats.rx_packets; -+ sinfo->tx_packets = priv->stats.tx_packets; -+ sinfo->signal = priv->w_stats.qual.level; -+ sinfo->txrate.legacy = rate.rate; -+ -+ return ret; -+} -+ -+/* -+ * CFG802.11 operation handler to get station information. -+ * -+ * This function only works in connected mode, and dumps the -+ * requested station information, if available. -+ */ -+static int -+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); -+ -+ mwifiex_dump_station_info(priv, sinfo); -+ -+ if (!priv->media_connected) -+ return -ENOENT; -+ if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) -+ return -ENOENT; -+ -+ return mwifiex_dump_station_info(priv, sinfo); -+} -+ -+/* Supported rates to be advertised to the cfg80211 */ -+ -+static struct ieee80211_rate mwifiex_rates[] = { -+ {.bitrate = 10, .hw_value = 2, }, -+ {.bitrate = 20, .hw_value = 4, }, -+ {.bitrate = 55, .hw_value = 11, }, -+ {.bitrate = 110, .hw_value = 22, }, -+ {.bitrate = 220, .hw_value = 44, }, -+ {.bitrate = 60, .hw_value = 12, }, -+ {.bitrate = 90, .hw_value = 18, }, -+ {.bitrate = 120, .hw_value = 24, }, -+ {.bitrate = 180, .hw_value = 36, }, -+ {.bitrate = 240, .hw_value = 48, }, -+ {.bitrate = 360, .hw_value = 72, }, -+ {.bitrate = 480, .hw_value = 96, }, -+ {.bitrate = 540, .hw_value = 108, }, -+ {.bitrate = 720, .hw_value = 144, }, -+}; -+ -+/* Channel definitions to be advertised to cfg80211 */ -+ -+static struct ieee80211_channel mwifiex_channels_2ghz[] = { -+ {.center_freq = 2412, .hw_value = 1, }, -+ {.center_freq = 2417, .hw_value = 2, }, -+ {.center_freq = 2422, .hw_value = 3, }, -+ {.center_freq = 2427, .hw_value = 4, }, -+ {.center_freq = 2432, .hw_value = 5, }, -+ {.center_freq = 2437, .hw_value = 6, }, -+ {.center_freq = 2442, .hw_value = 7, }, -+ {.center_freq = 2447, .hw_value = 8, }, -+ {.center_freq = 2452, .hw_value = 9, }, -+ {.center_freq = 2457, .hw_value = 10, }, -+ {.center_freq = 2462, .hw_value = 11, }, -+ {.center_freq = 2467, .hw_value = 12, }, -+ {.center_freq = 2472, .hw_value = 13, }, -+ {.center_freq = 2484, .hw_value = 14, }, -+}; -+ -+static struct ieee80211_supported_band mwifiex_band_2ghz = { -+ .channels = mwifiex_channels_2ghz, -+ .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz), -+ .bitrates = mwifiex_rates, -+ .n_bitrates = 14, -+}; -+ -+static struct ieee80211_channel mwifiex_channels_5ghz[] = { -+ {.center_freq = 5040, .hw_value = 8, }, -+ {.center_freq = 5060, .hw_value = 12, }, -+ {.center_freq = 5080, .hw_value = 16, }, -+ {.center_freq = 5170, .hw_value = 34, }, -+ {.center_freq = 5190, .hw_value = 38, }, -+ {.center_freq = 5210, .hw_value = 42, }, -+ {.center_freq = 5230, .hw_value = 46, }, -+ {.center_freq = 5180, .hw_value = 36, }, -+ {.center_freq = 5200, .hw_value = 40, }, -+ {.center_freq = 5220, .hw_value = 44, }, -+ {.center_freq = 5240, .hw_value = 48, }, -+ {.center_freq = 5260, .hw_value = 52, }, -+ {.center_freq = 5280, .hw_value = 56, }, -+ {.center_freq = 5300, .hw_value = 60, }, -+ {.center_freq = 5320, .hw_value = 64, }, -+ {.center_freq = 5500, .hw_value = 100, }, -+ {.center_freq = 5520, .hw_value = 104, }, -+ {.center_freq = 5540, .hw_value = 108, }, -+ {.center_freq = 5560, .hw_value = 112, }, -+ {.center_freq = 5580, .hw_value = 116, }, -+ {.center_freq = 5600, .hw_value = 120, }, -+ {.center_freq = 5620, .hw_value = 124, }, -+ {.center_freq = 5640, .hw_value = 128, }, -+ {.center_freq = 5660, .hw_value = 132, }, -+ {.center_freq = 5680, .hw_value = 136, }, -+ {.center_freq = 5700, .hw_value = 140, }, -+ {.center_freq = 5745, .hw_value = 149, }, -+ {.center_freq = 5765, .hw_value = 153, }, -+ {.center_freq = 5785, .hw_value = 157, }, -+ {.center_freq = 5805, .hw_value = 161, }, -+ {.center_freq = 5825, .hw_value = 165, }, -+}; -+ -+static struct ieee80211_supported_band mwifiex_band_5ghz = { -+ .channels = mwifiex_channels_5ghz, -+ .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz), -+ .bitrates = mwifiex_rates - 4, -+ .n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4, -+}; -+ -+ -+/* Supported crypto cipher suits to be advertised to cfg80211 */ -+ -+static const u32 mwifiex_cipher_suites[] = { -+ WLAN_CIPHER_SUITE_WEP40, -+ WLAN_CIPHER_SUITE_WEP104, -+ WLAN_CIPHER_SUITE_TKIP, -+ WLAN_CIPHER_SUITE_CCMP, -+}; -+ -+/* -+ * CFG802.11 operation handler for disconnection request. -+ * -+ * This function does not work when there is already a disconnection -+ * procedure going on. -+ */ -+static int -+mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, -+ u16 reason_code) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ -+ if (priv->disconnect) -+ return -EBUSY; -+ -+ priv->disconnect = 1; -+ if (mwifiex_deauthenticate(priv, NULL)) -+ return -EFAULT; -+ -+ wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" -+ " reason code %d\n", priv->cfg_bssid, reason_code); -+ -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ -+ return 0; -+} -+ -+/* -+ * This function informs the CFG802.11 subsystem of a new IBSS. -+ * -+ * The following information are sent to the CFG802.11 subsystem -+ * to register the new IBSS. If we do not register the new IBSS, -+ * a kernel panic will result. -+ * - SSID -+ * - SSID length -+ * - BSSID -+ * - Channel -+ */ -+static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) -+{ -+ 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)]; -+ -+ if (mwifiex_get_bss_info(priv, &bss_info)) -+ return -1; -+ -+ ie_buf[0] = WLAN_EID_SSID; -+ ie_buf[1] = bss_info.ssid.ssid_len; -+ -+ memcpy(&ie_buf[sizeof(struct ieee_types_header)], -+ &bss_info.ssid.ssid, -+ bss_info.ssid.ssid_len); -+ ie_len = ie_buf[1] + sizeof(struct ieee_types_header); -+ -+ chan = __ieee80211_get_channel(priv->wdev->wiphy, -+ ieee80211_channel_to_frequency(bss_info.bss_chan, -+ priv->curr_bss_params.band)); -+ -+ cfg80211_inform_bss(priv->wdev->wiphy, chan, -+ bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, -+ 0, ie_buf, ie_len, 0, GFP_KERNEL); -+ memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); -+ -+ return 0; -+} -+ -+/* -+ * This function informs the CFG802.11 subsystem of a new BSS connection. -+ * -+ * The following information are sent to the CFG802.11 subsystem -+ * to register the new BSS connection. If we do not register the new BSS, -+ * a kernel panic will result. -+ * - MAC address -+ * - Capabilities -+ * - Beacon period -+ * - RSSI value -+ * - Channel -+ * - Supported rates IE -+ * - Extended capabilities IE -+ * - DS parameter set IE -+ * - HT Capability IE -+ * - Vendor Specific IE (221) -+ * - WPA IE -+ * - RSN IE -+ */ -+static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *ssid) -+{ -+ struct mwifiex_scan_resp scan_resp; -+ struct mwifiex_bssdescriptor *scan_table; -+ int i, j; -+ struct ieee80211_channel *chan; -+ u8 *ie, *ie_buf; -+ u32 ie_len; -+ u8 *beacon; -+ int beacon_size; -+ u8 element_id, element_len; -+ -+ memset(&scan_resp, 0, sizeof(scan_resp)); -+ 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); -+ if (!ie_buf) { -+ dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n", -+ __func__); -+ return -ENOMEM; -+ } -+ -+ scan_table = (struct mwifiex_bssdescriptor *) scan_resp.scan_table; -+ for (i = 0; i < scan_resp.num_in_scan_table; i++) { -+ if (ssid) { -+ /* Inform specific BSS only */ -+ if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, -+ ssid->ssid_len)) -+ continue; -+ } -+ memset(ie_buf, 0, MAX_IE_BUF); -+ ie_buf[0] = WLAN_EID_SSID; -+ ie_buf[1] = scan_table[i].ssid.ssid_len; -+ memcpy(&ie_buf[sizeof(struct ieee_types_header)], -+ scan_table[i].ssid.ssid, ie_buf[1]); -+ -+ ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header); -+ ie_len = ie_buf[1] + sizeof(struct ieee_types_header); -+ -+ ie[0] = WLAN_EID_SUPP_RATES; -+ -+ for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) { -+ if (!scan_table[i].supported_rates[j]) -+ break; -+ else -+ ie[j + sizeof(struct ieee_types_header)] = -+ scan_table[i].supported_rates[j]; -+ } -+ -+ ie[1] = j; -+ ie_len += ie[1] + sizeof(struct ieee_types_header); -+ -+ beacon = scan_table[i].beacon_buf; -+ beacon_size = scan_table[i].beacon_buf_size; -+ -+ /* Skip time stamp, beacon interval and capability */ -+ -+ if (beacon) { -+ beacon += sizeof(scan_table[i].beacon_period) -+ + sizeof(scan_table[i].time_stamp) + -+ +sizeof(scan_table[i].cap_info_bitmap); -+ -+ beacon_size -= sizeof(scan_table[i].beacon_period) -+ + sizeof(scan_table[i].time_stamp) -+ + sizeof(scan_table[i].cap_info_bitmap); -+ } -+ -+ while (beacon_size >= sizeof(struct ieee_types_header)) { -+ ie = ie_buf + ie_len; -+ element_id = *beacon; -+ element_len = *(beacon + 1); -+ if (beacon_size < (int) element_len + -+ sizeof(struct ieee_types_header)) { -+ dev_err(priv->adapter->dev, "%s: in processing" -+ " IE, bytes left < IE length\n", -+ __func__); -+ break; -+ } -+ switch (element_id) { -+ case WLAN_EID_EXT_CAPABILITY: -+ case WLAN_EID_DS_PARAMS: -+ case WLAN_EID_HT_CAPABILITY: -+ case WLAN_EID_VENDOR_SPECIFIC: -+ case WLAN_EID_RSN: -+ case WLAN_EID_BSS_AC_ACCESS_DELAY: -+ ie[0] = element_id; -+ ie[1] = element_len; -+ memcpy(&ie[sizeof(struct ieee_types_header)], -+ (u8 *) beacon -+ + sizeof(struct ieee_types_header), -+ element_len); -+ ie_len += ie[1] + -+ sizeof(struct ieee_types_header); -+ break; -+ default: -+ break; -+ } -+ beacon += element_len + -+ sizeof(struct ieee_types_header); -+ beacon_size -= element_len + -+ sizeof(struct ieee_types_header); -+ } -+ chan = ieee80211_get_channel(priv->wdev->wiphy, -+ scan_table[i].freq); -+ cfg80211_inform_bss(priv->wdev->wiphy, chan, -+ scan_table[i].mac_address, -+ 0, scan_table[i].cap_info_bitmap, -+ scan_table[i].beacon_period, -+ ie_buf, ie_len, -+ scan_table[i].rssi, GFP_KERNEL); -+ } -+ -+ kfree(ie_buf); -+ return 0; -+} -+ -+/* -+ * This function connects with a BSS. -+ * -+ * This function handles both Infra and Ad-Hoc modes. It also performs -+ * validity checking on the provided parameters, disconnects from the -+ * current BSS (if any), sets up the association/scan parameters, -+ * including security settings, and performs specific SSID scan before -+ * trying to connect. -+ * -+ * For Infra mode, the function returns failure if the specified SSID -+ * is not found in scan table. However, for Ad-Hoc mode, it can create -+ * the IBSS if it does not exist. On successful completion in either case, -+ * the function notifies the CFG802.11 subsystem of the new BSS connection, -+ * otherwise the kernel will panic. -+ */ -+static int -+mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, -+ u8 *bssid, int mode, struct ieee80211_channel *channel, -+ struct cfg80211_connect_params *sme, bool privacy) -+{ -+ struct mwifiex_802_11_ssid req_ssid; -+ struct mwifiex_ssid_bssid ssid_bssid; -+ int ret = 0; -+ int auth_type = 0; -+ -+ memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); -+ memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); -+ -+ req_ssid.ssid_len = ssid_len; -+ if (ssid_len > IEEE80211_MAX_SSID_LEN) { -+ dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); -+ return -EINVAL; -+ } -+ -+ memcpy(req_ssid.ssid, ssid, ssid_len); -+ if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { -+ dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); -+ return -EINVAL; -+ } -+ -+ /* disconnect before try to associate */ -+ mwifiex_deauthenticate(priv, NULL); -+ -+ if (channel) -+ ret = mwifiex_set_rf_channel(priv, channel, -+ mwifiex_channels_to_cfg80211_channel_type -+ (priv->adapter->chan_offset)); -+ -+ ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ -+ -+ if (mode == NL80211_IFTYPE_ADHOC) { -+ /* "privacy" is set only for ad-hoc mode */ -+ if (privacy) { -+ /* -+ * Keep WLAN_CIPHER_SUITE_WEP104 for now so that -+ * the firmware can find a matching network from the -+ * scan. The cfg80211 does not give us the encryption -+ * mode at this stage so just setting it to WEP here. -+ */ -+ priv->sec_info.encryption_mode = -+ WLAN_CIPHER_SUITE_WEP104; -+ priv->sec_info.authentication_mode = -+ NL80211_AUTHTYPE_OPEN_SYSTEM; -+ } -+ -+ goto done; -+ } -+ -+ /* Now handle infra mode. "sme" is valid for infra mode only */ -+ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC -+ || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) -+ auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; -+ else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) -+ auth_type = NL80211_AUTHTYPE_SHARED_KEY; -+ -+ if (sme->crypto.n_ciphers_pairwise) { -+ priv->sec_info.encryption_mode = -+ sme->crypto.ciphers_pairwise[0]; -+ priv->sec_info.authentication_mode = auth_type; -+ } -+ -+ if (sme->crypto.cipher_group) { -+ priv->sec_info.encryption_mode = sme->crypto.cipher_group; -+ priv->sec_info.authentication_mode = auth_type; -+ } -+ if (sme->ie) -+ ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); -+ -+ if (sme->key) { -+ 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); -+ ret = mwifiex_set_encode(priv, sme->key, sme->key_len, -+ sme->key_idx, 0); -+ } -+ } -+done: -+ /* Do specific SSID scanning */ -+ if (mwifiex_request_scan(priv, &req_ssid)) { -+ dev_err(priv->adapter->dev, "scan error\n"); -+ return -EFAULT; -+ } -+ -+ -+ memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); -+ -+ if (mode != NL80211_IFTYPE_ADHOC) { -+ 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 */ -+ if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) -+ return -EFAULT; -+ } -+ -+ dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", -+ (char *) req_ssid.ssid, ssid_bssid.bssid); -+ -+ memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6); -+ -+ /* Connect to BSS by ESSID */ -+ memset(&ssid_bssid.bssid, 0, ETH_ALEN); -+ -+ 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) { -+ /* Inform the BSS information to kernel, otherwise -+ * kernel will give a panic after successful assoc */ -+ if (mwifiex_cfg80211_inform_ibss_bss(priv)) -+ return -EFAULT; -+ } -+ -+ return ret; -+} -+ -+/* -+ * CFG802.11 operation handler for association request. -+ * -+ * This function does not work when the current mode is set to Ad-Hoc, or -+ * when there is already an association procedure going on. The given BSS -+ * information is used to associate. -+ */ -+static int -+mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_connect_params *sme) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ int ret = 0; -+ -+ if (priv->assoc_request) -+ return -EBUSY; -+ -+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ wiphy_err(wiphy, "received infra assoc request " -+ "when station is in ibss mode\n"); -+ goto done; -+ } -+ -+ priv->assoc_request = 1; -+ -+ wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", -+ (char *) sme->ssid, sme->bssid); -+ -+ ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, -+ priv->bss_mode, sme->channel, sme, 0); -+ -+done: -+ priv->assoc_result = ret; -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ return ret; -+} -+ -+/* -+ * CFG802.11 operation handler to join an IBSS. -+ * -+ * This function does not work in any mode other than Ad-Hoc, or if -+ * a join operation is already in progress. -+ */ -+static int -+mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_ibss_params *params) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ int ret = 0; -+ -+ if (priv->ibss_join_request) -+ return -EBUSY; -+ -+ if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { -+ wiphy_err(wiphy, "request to join ibss received " -+ "when station is not in ibss mode\n"); -+ goto done; -+ } -+ -+ priv->ibss_join_request = 1; -+ -+ wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", -+ (char *) params->ssid, params->bssid); -+ -+ ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, -+ params->bssid, priv->bss_mode, -+ params->channel, NULL, params->privacy); -+done: -+ priv->ibss_join_result = ret; -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ return ret; -+} -+ -+/* -+ * CFG802.11 operation handler to leave an IBSS. -+ * -+ * This function does not work if a leave operation is -+ * already in progress. -+ */ -+static int -+mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -+{ -+ struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -+ -+ if (priv->disconnect) -+ return -EBUSY; -+ -+ priv->disconnect = 1; -+ -+ wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n", -+ priv->cfg_bssid); -+ if (mwifiex_deauthenticate(priv, NULL)) -+ return -EFAULT; -+ -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ -+ return 0; -+} -+ -+/* -+ * CFG802.11 operation handler for scan request. -+ * -+ * This function issues a scan request to the firmware based upon -+ * the user specified scan configuration. On successfull completion, -+ * it also informs the results. -+ */ -+static int -+mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_scan_request *request) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ -+ wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); -+ -+ if (priv->scan_request && priv->scan_request != request) -+ return -EBUSY; -+ -+ priv->scan_request = request; -+ -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ return 0; -+} -+ -+/* -+ * This function sets up the CFG802.11 specific HT capability fields -+ * with default values. -+ * -+ * The following default values are set - -+ * - HT Supported = True -+ * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K -+ * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE -+ * - HT Capabilities supported by firmware -+ * - MCS information, Rx mask = 0xff -+ * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) -+ */ -+static void -+mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, -+ struct mwifiex_private *priv) -+{ -+ int rx_mcs_supp; -+ struct ieee80211_mcs_info mcs_set; -+ u8 *mcs = (u8 *)&mcs_set; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ ht_info->ht_supported = true; -+ ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; -+ ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; -+ -+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); -+ -+ /* Fill HT capability information */ -+ if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) -+ ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ else -+ ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ -+ if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) -+ ht_info->cap |= IEEE80211_HT_CAP_SGI_20; -+ else -+ ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; -+ -+ if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) -+ ht_info->cap |= IEEE80211_HT_CAP_SGI_40; -+ else -+ ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; -+ -+ if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) -+ ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; -+ else -+ ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); -+ -+ if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) -+ ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; -+ else -+ ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; -+ -+ ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; -+ ht_info->cap |= IEEE80211_HT_CAP_SM_PS; -+ -+ rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); -+ /* Set MCS for 1x1 */ -+ memset(mcs, 0xff, rx_mcs_supp); -+ /* Clear all the other values */ -+ memset(&mcs[rx_mcs_supp], 0, -+ sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); -+ if (priv->bss_mode == NL80211_IFTYPE_STATION || -+ ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) -+ /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ -+ SETHT_MCS32(mcs_set.rx_mask); -+ -+ memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); -+ -+ ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; -+} -+ -+/* station cfg80211 operations */ -+static struct cfg80211_ops mwifiex_cfg80211_ops = { -+ .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, -+ .scan = mwifiex_cfg80211_scan, -+ .connect = mwifiex_cfg80211_connect, -+ .disconnect = mwifiex_cfg80211_disconnect, -+ .get_station = mwifiex_cfg80211_get_station, -+ .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, -+ .set_channel = mwifiex_cfg80211_set_channel, -+ .join_ibss = mwifiex_cfg80211_join_ibss, -+ .leave_ibss = mwifiex_cfg80211_leave_ibss, -+ .add_key = mwifiex_cfg80211_add_key, -+ .del_key = mwifiex_cfg80211_del_key, -+ .set_default_key = mwifiex_cfg80211_set_default_key, -+ .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, -+ .set_tx_power = mwifiex_cfg80211_set_tx_power, -+}; -+ -+/* -+ * This function registers the device with CFG802.11 subsystem. -+ * -+ * The function creates the wireless device/wiphy, populates it with -+ * default parameters and handler function pointers, and finally -+ * registers the device. -+ */ -+int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, -+ struct mwifiex_private *priv) -+{ -+ int ret = 0; -+ void *wdev_priv = NULL; -+ struct wireless_dev *wdev; -+ -+ wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); -+ if (!wdev) { -+ dev_err(priv->adapter->dev, "%s: allocating wireless device\n", -+ __func__); -+ return -ENOMEM; -+ } -+ wdev->wiphy = -+ wiphy_new(&mwifiex_cfg80211_ops, -+ sizeof(struct mwifiex_private *)); -+ if (!wdev->wiphy) -+ return -ENOMEM; -+ wdev->iftype = NL80211_IFTYPE_STATION; -+ wdev->wiphy->max_scan_ssids = 10; -+ wdev->wiphy->interface_modes = -+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -+ -+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; -+ mwifiex_setup_ht_caps( -+ &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); -+ -+ if (priv->adapter->config_bands & BAND_A) { -+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; -+ mwifiex_setup_ht_caps( -+ &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); -+ } else { -+ wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; -+ } -+ -+ /* Initialize cipher suits */ -+ wdev->wiphy->cipher_suites = mwifiex_cipher_suites; -+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); -+ -+ memcpy(wdev->wiphy->perm_addr, mac, 6); -+ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; -+ -+ /* We are using custom domains */ -+ wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; -+ -+ wdev->wiphy->reg_notifier = mwifiex_reg_notifier; -+ -+ /* Set struct mwifiex_private pointer in wiphy_priv */ -+ wdev_priv = wiphy_priv(wdev->wiphy); -+ -+ *(unsigned long *) wdev_priv = (unsigned long) priv; -+ -+ ret = wiphy_register(wdev->wiphy); -+ if (ret < 0) { -+ dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", -+ __func__); -+ wiphy_free(wdev->wiphy); -+ return ret; -+ } else { -+ dev_dbg(priv->adapter->dev, -+ "info: successfully registered wiphy device\n"); -+ } -+ -+ dev_net_set(dev, wiphy_net(wdev->wiphy)); -+ dev->ieee80211_ptr = wdev; -+ memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6); -+ memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6); -+ SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); -+ priv->wdev = wdev; -+ -+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST; -+ dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; -+ dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; -+ -+ return ret; -+} -+ -+/* -+ * This function handles the result of different pending network operations. -+ * -+ * The following operations are handled and CFG802.11 subsystem is -+ * notified accordingly - -+ * - Scan request completion -+ * - Association request completion -+ * - IBSS join request completion -+ * - Disconnect request completion -+ */ -+void -+mwifiex_cfg80211_results(struct work_struct *work) -+{ -+ struct mwifiex_private *priv = -+ container_of(work, struct mwifiex_private, cfg_workqueue); -+ struct mwifiex_user_scan_cfg *scan_req; -+ int ret = 0, i; -+ struct ieee80211_channel *chan; -+ -+ if (priv->scan_request) { -+ scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg), -+ GFP_KERNEL); -+ if (!scan_req) { -+ dev_err(priv->adapter->dev, "failed to alloc " -+ "scan_req\n"); -+ return; -+ } -+ for (i = 0; i < priv->scan_request->n_ssids; i++) { -+ memcpy(scan_req->ssid_list[i].ssid, -+ priv->scan_request->ssids[i].ssid, -+ priv->scan_request->ssids[i].ssid_len); -+ scan_req->ssid_list[i].max_len = -+ priv->scan_request->ssids[i].ssid_len; -+ } -+ for (i = 0; i < priv->scan_request->n_channels; i++) { -+ chan = priv->scan_request->channels[i]; -+ scan_req->chan_list[i].chan_number = chan->hw_value; -+ scan_req->chan_list[i].radio_type = chan->band; -+ if (chan->flags & IEEE80211_CHAN_DISABLED) -+ scan_req->chan_list[i].scan_type = -+ MWIFIEX_SCAN_TYPE_PASSIVE; -+ else -+ scan_req->chan_list[i].scan_type = -+ MWIFIEX_SCAN_TYPE_ACTIVE; -+ scan_req->chan_list[i].scan_time = 0; -+ } -+ if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { -+ ret = -EFAULT; -+ goto done; -+ } -+ if (mwifiex_inform_bss_from_scan_result(priv, NULL)) -+ ret = -EFAULT; -+done: -+ priv->scan_result_status = ret; -+ dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", -+ __func__); -+ cfg80211_scan_done(priv->scan_request, -+ (priv->scan_result_status < 0)); -+ priv->scan_request = NULL; -+ kfree(scan_req); -+ } -+ -+ if (priv->assoc_request) { -+ if (!priv->assoc_result) { -+ cfg80211_connect_result(priv->netdev, priv->cfg_bssid, -+ NULL, 0, NULL, 0, -+ WLAN_STATUS_SUCCESS, -+ GFP_KERNEL); -+ dev_dbg(priv->adapter->dev, -+ "info: associated to bssid %pM successfully\n", -+ priv->cfg_bssid); -+ } else { -+ dev_dbg(priv->adapter->dev, -+ "info: association to bssid %pM failed\n", -+ priv->cfg_bssid); -+ memset(priv->cfg_bssid, 0, ETH_ALEN); -+ } -+ priv->assoc_request = 0; -+ priv->assoc_result = 0; -+ } -+ -+ if (priv->ibss_join_request) { -+ if (!priv->ibss_join_result) { -+ cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, -+ GFP_KERNEL); -+ dev_dbg(priv->adapter->dev, -+ "info: joined/created adhoc network with bssid" -+ " %pM successfully\n", priv->cfg_bssid); -+ } else { -+ dev_dbg(priv->adapter->dev, -+ "info: failed creating/joining adhoc network\n"); -+ } -+ priv->ibss_join_request = 0; -+ priv->ibss_join_result = 0; -+ } -+ -+ if (priv->disconnect) { -+ memset(priv->cfg_bssid, 0, ETH_ALEN); -+ priv->disconnect = 0; -+ } -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfg80211.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfg80211.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfg80211.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfg80211.h 2011-05-05 23:29:45.474441731 +0200 -@@ -0,0 +1,31 @@ -+/* -+ * Marvell Wireless LAN device driver: CFG80211 -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef __MWIFIEX_CFG80211__ -+#define __MWIFIEX_CFG80211__ -+ -+#include -+ -+#include "main.h" -+ -+int mwifiex_register_cfg80211(struct net_device *, u8 *, -+ struct mwifiex_private *); -+ -+void mwifiex_cfg80211_results(struct work_struct *work); -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfp.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfp.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cfp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cfp.c 2011-05-05 23:29:45.477441767 +0200 -@@ -0,0 +1,360 @@ -+/* -+ * Marvell Wireless LAN device driver: Channel, Frequence and Power -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "cfg80211.h" -+ -+/* 100mW */ -+#define MWIFIEX_TX_PWR_DEFAULT 20 -+/* 100mW */ -+#define MWIFIEX_TX_PWR_US_DEFAULT 20 -+/* 50mW */ -+#define MWIFIEX_TX_PWR_JP_DEFAULT 16 -+/* 100mW */ -+#define MWIFIEX_TX_PWR_FR_100MW 20 -+/* 10mW */ -+#define MWIFIEX_TX_PWR_FR_10MW 10 -+/* 100mW */ -+#define MWIFIEX_TX_PWR_EMEA_DEFAULT 20 -+ -+static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 }; -+ -+static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, -+ 0xb0, 0x48, 0x60, 0x6c, 0 }; -+ -+static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, -+ 0x0c, 0x12, 0x18, 0x24, -+ 0x30, 0x48, 0x60, 0x6c, 0 }; -+ -+static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, -+ 0xb0, 0x48, 0x60, 0x6c, 0 }; -+u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, -+ 0xb0, 0x48, 0x60, 0x6c, 0 }; -+static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04, -+ 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, -+ 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, -+ 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, -+ 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, -+ 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; -+ -+u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 }; -+ -+u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, -+ 0x30, 0x48, 0x60, 0x6c, 0 }; -+ -+u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, -+ 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, -+ 0x60, 0x6c, 0 }; -+ -+u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, -+ 0x32, 0x40, 0x41, 0xff }; -+ -+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(u8 index, u8 ht_info) -+{ -+ u16 mcs_rate[4][8] = { -+ {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} -+ , /* LG 40M */ -+ {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c} -+ , /* SG 40M */ -+ {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82} -+ , /* LG 20M */ -+ {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90} -+ }; /* SG 20M */ -+ -+ u32 rate; -+ -+ if (ht_info & BIT(0)) { -+ if (index == MWIFIEX_RATE_BITMAP_MCS0) { -+ if (ht_info & BIT(2)) -+ rate = 0x0D; /* MCS 32 SGI rate */ -+ else -+ rate = 0x0C; /* MCS 32 LGI rate */ -+ } else if (index < 8) { -+ if (ht_info & BIT(1)) { -+ if (ht_info & BIT(2)) -+ /* SGI, 40M */ -+ rate = mcs_rate[1][index]; -+ else -+ /* LGI, 40M */ -+ rate = mcs_rate[0][index]; -+ } else { -+ if (ht_info & BIT(2)) -+ /* SGI, 20M */ -+ rate = mcs_rate[3][index]; -+ else -+ /* LGI, 20M */ -+ rate = mcs_rate[2][index]; -+ } -+ } else -+ rate = mwifiex_data_rates[0]; -+ } else { -+ if (index >= MWIFIEX_SUPPORTED_RATES_EXT) -+ index = 0; -+ rate = mwifiex_data_rates[index]; -+ } -+ return rate; -+} -+ -+/* -+ * This function maps a data rate value into corresponding index in supported -+ * rates table. -+ */ -+u8 mwifiex_data_rate_to_index(u32 rate) -+{ -+ u16 *ptr; -+ -+ if (rate) { -+ ptr = memchr(mwifiex_data_rates, rate, -+ sizeof(mwifiex_data_rates)); -+ if (ptr) -+ return (u8) (ptr - mwifiex_data_rates); -+ } -+ return 0; -+} -+ -+/* -+ * This function returns the current active data rates. -+ * -+ * The result may vary depending upon connection status. -+ */ -+u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates) -+{ -+ if (!priv->media_connected) -+ return mwifiex_get_supported_rates(priv, rates); -+ else -+ return mwifiex_copy_rates(rates, 0, -+ priv->curr_bss_params.data_rates, -+ priv->curr_bss_params.num_of_rates); -+} -+ -+/* -+ * This function locates the Channel-Frequency-Power triplet based upon -+ * band and channel parameters. -+ */ -+struct mwifiex_chan_freq_power * -+mwifiex_get_cfp_by_band_and_channel_from_cfg80211(struct mwifiex_private -+ *priv, u8 band, u16 channel) -+{ -+ struct mwifiex_chan_freq_power *cfp = NULL; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_channel *ch; -+ int i; -+ -+ if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) -+ sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; -+ else -+ sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; -+ -+ if (!sband) { -+ dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" -+ " & channel %d\n", __func__, band, channel); -+ return cfp; -+ } -+ -+ for (i = 0; i < sband->n_channels; i++) { -+ ch = &sband->channels[i]; -+ if (((ch->hw_value == channel) || -+ (channel == FIRST_VALID_CHANNEL)) -+ && !(ch->flags & IEEE80211_CHAN_DISABLED)) { -+ priv->cfp.channel = channel; -+ priv->cfp.freq = ch->center_freq; -+ priv->cfp.max_tx_power = ch->max_power; -+ cfp = &priv->cfp; -+ break; -+ } -+ } -+ if (i == sband->n_channels) -+ dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" -+ " & channel %d\n", __func__, band, channel); -+ -+ return cfp; -+} -+ -+/* -+ * This function locates the Channel-Frequency-Power triplet based upon -+ * band and frequency parameters. -+ */ -+struct mwifiex_chan_freq_power * -+mwifiex_get_cfp_by_band_and_freq_from_cfg80211(struct mwifiex_private *priv, -+ u8 band, u32 freq) -+{ -+ struct mwifiex_chan_freq_power *cfp = NULL; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_channel *ch; -+ int i; -+ -+ if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) -+ sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; -+ else -+ sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; -+ -+ if (!sband) { -+ dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" -+ " & freq %d\n", __func__, band, freq); -+ return cfp; -+ } -+ -+ for (i = 0; i < sband->n_channels; i++) { -+ ch = &sband->channels[i]; -+ if ((ch->center_freq == freq) && -+ !(ch->flags & IEEE80211_CHAN_DISABLED)) { -+ priv->cfp.channel = ch->hw_value; -+ priv->cfp.freq = freq; -+ priv->cfp.max_tx_power = ch->max_power; -+ cfp = &priv->cfp; -+ break; -+ } -+ } -+ if (i == sband->n_channels) -+ dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d" -+ " & freq %d\n", __func__, band, freq); -+ -+ return cfp; -+} -+ -+/* -+ * This function checks if the data rate is set to auto. -+ */ -+u8 -+mwifiex_is_rate_auto(struct mwifiex_private *priv) -+{ -+ u32 i; -+ int rate_num = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) -+ if (priv->bitmap_rates[i]) -+ rate_num++; -+ -+ if (rate_num > 1) -+ return true; -+ else -+ return false; -+} -+ -+/* -+ * This function converts rate bitmap into rate index. -+ */ -+int mwifiex_get_rate_index(u16 *rate_bitmap, int size) -+{ -+ int i; -+ -+ for (i = 0; i < size * 8; i++) -+ if (rate_bitmap[i / 16] & (1 << (i % 16))) -+ return i; -+ -+ return 0; -+} -+ -+/* -+ * This function gets the supported data rates. -+ * -+ * The function works in both Ad-Hoc and infra mode by printing the -+ * band and returning the data rates. -+ */ -+u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) -+{ -+ u32 k = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ if (priv->bss_mode == NL80211_IFTYPE_STATION) { -+ switch (adapter->config_bands) { -+ case BAND_B: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_b\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_b, -+ sizeof(supported_rates_b)); -+ break; -+ case BAND_G: -+ case BAND_G | BAND_GN: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_g\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_g, -+ sizeof(supported_rates_g)); -+ break; -+ case BAND_B | BAND_G: -+ case BAND_A | BAND_B | BAND_G: -+ case BAND_A | BAND_B: -+ case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: -+ case BAND_B | BAND_G | BAND_GN: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_bg\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_bg, -+ sizeof(supported_rates_bg)); -+ break; -+ case BAND_A: -+ case BAND_A | BAND_G: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_a\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_a, -+ sizeof(supported_rates_a)); -+ break; -+ case BAND_A | BAND_AN: -+ case BAND_A | BAND_G | BAND_AN | BAND_GN: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_a\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_a, -+ sizeof(supported_rates_a)); -+ break; -+ case BAND_GN: -+ dev_dbg(adapter->dev, "info: infra band=%d " -+ "supported_rates_n\n", adapter->config_bands); -+ k = mwifiex_copy_rates(rates, k, supported_rates_n, -+ sizeof(supported_rates_n)); -+ break; -+ } -+ } else { -+ /* Ad-hoc mode */ -+ switch (adapter->adhoc_start_band) { -+ case BAND_B: -+ dev_dbg(adapter->dev, "info: adhoc B\n"); -+ k = mwifiex_copy_rates(rates, k, adhoc_rates_b, -+ sizeof(adhoc_rates_b)); -+ break; -+ case BAND_G: -+ case BAND_G | BAND_GN: -+ dev_dbg(adapter->dev, "info: adhoc G only\n"); -+ k = mwifiex_copy_rates(rates, k, adhoc_rates_g, -+ sizeof(adhoc_rates_g)); -+ break; -+ case BAND_B | BAND_G: -+ case BAND_B | BAND_G | BAND_GN: -+ dev_dbg(adapter->dev, "info: adhoc BG\n"); -+ k = mwifiex_copy_rates(rates, k, adhoc_rates_bg, -+ sizeof(adhoc_rates_bg)); -+ break; -+ case BAND_A: -+ case BAND_A | BAND_AN: -+ dev_dbg(adapter->dev, "info: adhoc A\n"); -+ k = mwifiex_copy_rates(rates, k, adhoc_rates_a, -+ sizeof(adhoc_rates_a)); -+ break; -+ } -+ } -+ -+ return k; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cmdevt.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cmdevt.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/cmdevt.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/cmdevt.c 2011-05-05 23:29:45.474441731 +0200 -@@ -0,0 +1,1415 @@ -+/* -+ * Marvell Wireless LAN device driver: commands and events -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * This function initializes a command node. -+ * -+ * The actual allocation of the node is not done by this function. It only -+ * initiates a node by filling it with default parameters. Similarly, -+ * allocation of the different buffers used (IOCTL buffer, data buffer) are -+ * not done by this function either. -+ */ -+static void -+mwifiex_init_cmd_node(struct mwifiex_private *priv, -+ struct cmd_ctrl_node *cmd_node, -+ u32 cmd_oid, void *data_buf) -+{ -+ cmd_node->priv = priv; -+ cmd_node->cmd_oid = cmd_oid; -+ 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; -+} -+ -+/* -+ * This function returns a command node from the free queue depending upon -+ * availability. -+ */ -+static struct cmd_ctrl_node * -+mwifiex_get_cmd_node(struct mwifiex_adapter *adapter) -+{ -+ struct cmd_ctrl_node *cmd_node; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); -+ if (list_empty(&adapter->cmd_free_q)) { -+ dev_err(adapter->dev, "GET_CMD_NODE: cmd node not available\n"); -+ spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -+ return NULL; -+ } -+ cmd_node = list_first_entry(&adapter->cmd_free_q, -+ struct cmd_ctrl_node, list); -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -+ -+ return cmd_node; -+} -+ -+/* -+ * This function cleans up a command node. -+ * -+ * The function resets the fields including the buffer pointers. -+ * This function does not try to free the buffers. They must be -+ * freed before calling this function. -+ * -+ * This function will however call the receive completion callback -+ * in case a response buffer is still available before resetting -+ * the pointer. -+ */ -+static void -+mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, -+ struct cmd_ctrl_node *cmd_node) -+{ -+ cmd_node->cmd_oid = 0; -+ cmd_node->cmd_flag = 0; -+ 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; -+ } -+} -+ -+/* -+ * This function sends a host command to the firmware. -+ * -+ * The function copies the host command into the driver command -+ * buffer, which will be transferred to the firmware later by the -+ * main thread. -+ */ -+static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, void *data_buf) -+{ -+ struct mwifiex_ds_misc_cmd *pcmd_ptr = -+ (struct mwifiex_ds_misc_cmd *) data_buf; -+ -+ /* Copy the HOST command to command buffer */ -+ memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len); -+ dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len); -+ return 0; -+} -+ -+/* -+ * This function downloads a command to the firmware. -+ * -+ * The function performs sanity tests, sets the command sequence -+ * number and size, converts the header fields to CPU format before -+ * sending. Afterwards, it logs the command ID and action for debugging -+ * and sets up the command timeout timer. -+ */ -+static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, -+ struct cmd_ctrl_node *cmd_node) -+{ -+ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int ret = 0; -+ struct host_cmd_ds_command *host_cmd; -+ uint16_t cmd_code; -+ uint16_t cmd_size; -+ struct timeval tstamp; -+ unsigned long flags; -+ -+ if (!adapter || !cmd_node) -+ return -1; -+ -+ host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); -+ -+ /* 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 (cmd_node->wait_q_enabled) -+ adapter->cmd_wait_q.status = -1; -+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ return -1; -+ } -+ -+ /* Set command sequence number */ -+ adapter->seq_num++; -+ host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO -+ (adapter->seq_num, cmd_node->priv->bss_num, -+ cmd_node->priv->bss_type)); -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->curr_cmd = cmd_node; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ -+ cmd_code = le16_to_cpu(host_cmd->command); -+ cmd_size = le16_to_cpu(host_cmd->size); -+ -+ skb_trim(cmd_node->cmd_skb, cmd_size); -+ -+ do_gettimeofday(&tstamp); -+ dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," -+ " seqno %#x\n", -+ tstamp.tv_sec, tstamp.tv_usec, cmd_code, -+ le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size, -+ le16_to_cpu(host_cmd->seq_num)); -+ -+ skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); -+ -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, -+ 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 (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); -+ adapter->curr_cmd = NULL; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ -+ adapter->dbg.num_cmd_host_to_card_failure++; -+ return -1; -+ } -+ -+ /* Save the last command id and action to debug log */ -+ adapter->dbg.last_cmd_index = -+ (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; -+ adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; -+ adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = -+ le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)); -+ -+ /* Clear BSS_NO_BITS from HostCmd */ -+ cmd_code &= HostCmd_CMD_ID_MASK; -+ -+ /* Setup the timer after transmit command */ -+ mod_timer(&adapter->cmd_timer, -+ jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000); -+ -+ return 0; -+} -+ -+/* -+ * This function downloads a sleep confirm command to the firmware. -+ * -+ * The function performs sanity tests, sets the command sequence -+ * number and size, converts the header fields to CPU format before -+ * sending. -+ * -+ * No responses are needed for sleep confirm command. -+ */ -+static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ u16 cmd_len = 0; -+ struct mwifiex_private *priv; -+ struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = -+ (struct mwifiex_opt_sleep_confirm_buffer *) -+ adapter->sleep_cfm->data; -+ cmd_len = sizeof(struct mwifiex_opt_sleep_confirm); -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ -+ sleep_cfm_buf->ps_cfm_sleep.seq_num = -+ cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO -+ (adapter->seq_num, priv->bss_num, -+ priv->bss_type))); -+ adapter->seq_num++; -+ -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, -+ adapter->sleep_cfm->data, -+ adapter->sleep_cfm->len + -+ INTF_HEADER_LEN, NULL); -+ -+ if (ret == -1) { -+ dev_err(adapter->dev, "SLEEP_CFM: failed\n"); -+ adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; -+ return -1; -+ } -+ if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) -+ == MWIFIEX_BSS_ROLE_STA) { -+ if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl) -+ /* Response is not needed for sleep -+ confirm command */ -+ adapter->ps_state = PS_STATE_SLEEP; -+ else -+ adapter->ps_state = PS_STATE_SLEEP_CFM; -+ -+ if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl -+ && (adapter->is_hs_configured -+ && !adapter->sleep_period.period)) { -+ adapter->pm_wakeup_card_req = true; -+ mwifiex_hs_activated_event(mwifiex_get_priv(adapter, -+ MWIFIEX_BSS_ROLE_STA), true); -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function allocates the command buffers and links them to -+ * the command free queue. -+ * -+ * The driver uses a pre allocated number of command buffers, which -+ * are created at driver initializations and freed at driver cleanup. -+ * Every command needs to obtain a command buffer from this pool before -+ * it can be issued. The command free queue lists the command buffers -+ * currently free to use, while the command pending queue lists the -+ * command buffers already in use and awaiting handling. Command buffers -+ * are returned to the free queue after use. -+ */ -+int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) -+{ -+ struct cmd_ctrl_node *cmd_array; -+ u32 buf_size; -+ u32 i; -+ -+ /* Allocate and initialize struct cmd_ctrl_node */ -+ buf_size = sizeof(struct cmd_ctrl_node) * MWIFIEX_NUM_OF_CMD_BUFFER; -+ cmd_array = kzalloc(buf_size, GFP_KERNEL); -+ if (!cmd_array) { -+ dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", -+ __func__); -+ return -1; -+ } -+ -+ adapter->cmd_pool = cmd_array; -+ memset(adapter->cmd_pool, 0, buf_size); -+ -+ /* Allocate and initialize command buffers */ -+ for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { -+ cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); -+ if (!cmd_array[i].skb) { -+ dev_err(adapter->dev, "ALLOC_CMD_BUF: out of memory\n"); -+ return -1; -+ } -+ } -+ -+ for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) -+ mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]); -+ -+ return 0; -+} -+ -+/* -+ * This function frees the command buffers. -+ * -+ * The function calls the completion callback for all the command -+ * buffers that still have response buffers associated with them. -+ */ -+int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) -+{ -+ struct cmd_ctrl_node *cmd_array; -+ u32 i; -+ -+ /* Need to check if cmd pool is allocated or not */ -+ if (!adapter->cmd_pool) { -+ dev_dbg(adapter->dev, "info: FREE_CMD_BUF: cmd_pool is null\n"); -+ return 0; -+ } -+ -+ cmd_array = adapter->cmd_pool; -+ -+ /* Release shared memory buffers */ -+ for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { -+ if (cmd_array[i].skb) { -+ dev_dbg(adapter->dev, "cmd: free cmd buffer %d\n", i); -+ dev_kfree_skb_any(cmd_array[i].skb); -+ } -+ if (!cmd_array[i].resp_skb) -+ continue; -+ mwifiex_recv_complete(adapter, cmd_array[i].resp_skb, 0); -+ } -+ /* Release struct cmd_ctrl_node */ -+ if (adapter->cmd_pool) { -+ dev_dbg(adapter->dev, "cmd: free cmd pool\n"); -+ kfree(adapter->cmd_pool); -+ adapter->cmd_pool = NULL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles events generated by firmware. -+ * -+ * Event body of events received from firmware are not used (though they are -+ * saved), only the event ID is used. Some events are re-invoked by -+ * the driver, with a new event body. -+ * -+ * After processing, the function calls the completion callback -+ * for cleanup. -+ */ -+int mwifiex_process_event(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ struct mwifiex_private *priv = -+ mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ struct sk_buff *skb = adapter->event_skb; -+ u32 eventcause = adapter->event_cause; -+ struct timeval tstamp; -+ struct mwifiex_rxinfo *rx_info = NULL; -+ -+ /* Save the last event to debug log */ -+ adapter->dbg.last_event_index = -+ (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; -+ adapter->dbg.last_event[adapter->dbg.last_event_index] = -+ (u16) eventcause; -+ -+ /* Get BSS number and corresponding priv */ -+ priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), -+ EVENT_GET_BSS_TYPE(eventcause)); -+ if (!priv) -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ /* Clear BSS_NO_BITS from event */ -+ eventcause &= EVENT_ID_MASK; -+ adapter->event_cause = eventcause; -+ -+ if (skb) { -+ rx_info = MWIFIEX_SKB_RXCB(skb); -+ rx_info->bss_index = priv->bss_index; -+ } -+ -+ if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) { -+ do_gettimeofday(&tstamp); -+ dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", -+ tstamp.tv_sec, tstamp.tv_usec, eventcause); -+ } -+ -+ ret = mwifiex_process_sta_event(priv); -+ -+ adapter->event_cause = 0; -+ adapter->event_skb = NULL; -+ -+ mwifiex_recv_complete(adapter, skb, 0); -+ -+ return ret; -+} -+ -+/* -+ * 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 -+ * is not reset -+ * - Getting a new command node from the command free queue -+ * - Initializing the command node for default parameters -+ * - Fill up the non-default parameters and buffer pointers -+ * - Add the command to pending queue -+ */ -+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; -+ struct cmd_ctrl_node *cmd_node = NULL; -+ struct host_cmd_ds_command *cmd_ptr = NULL; -+ -+ if (!adapter) { -+ pr_err("PREP_CMD: adapter is NULL\n"); -+ return -1; -+ } -+ -+ if (adapter->is_suspended) { -+ dev_err(adapter->dev, "PREP_CMD: device in suspended state\n"); -+ return -1; -+ } -+ -+ if (adapter->surprise_removed) { -+ dev_err(adapter->dev, "PREP_CMD: card is removed\n"); -+ return -1; -+ } -+ -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { -+ if (cmd_no != HostCmd_CMD_FUNC_INIT) { -+ dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); -+ return -1; -+ } -+ } -+ -+ /* Get a new command node */ -+ cmd_node = mwifiex_get_cmd_node(adapter); -+ -+ if (!cmd_node) { -+ dev_err(adapter->dev, "PREP_CMD: no free cmd node\n"); -+ return -1; -+ } -+ -+ /* Initialize the command node */ -+ 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"); -+ return -1; -+ } -+ -+ memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)), -+ 0, sizeof(struct host_cmd_ds_command)); -+ -+ cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); -+ cmd_ptr->command = cpu_to_le16(cmd_no); -+ cmd_ptr->result = 0; -+ -+ /* Prepare command */ -+ if (cmd_no) { -+ ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, -+ cmd_oid, data_buf, cmd_ptr); -+ } else { -+ ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); -+ cmd_node->cmd_flag |= CMD_F_HOSTCMD; -+ } -+ -+ /* Return error, since the command preparation failed */ -+ if (ret) { -+ dev_err(adapter->dev, "PREP_CMD: cmd %#x preparation failed\n", -+ cmd_no); -+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ return -1; -+ } -+ -+ /* Send command */ -+ if (cmd_no == HostCmd_CMD_802_11_SCAN) -+ mwifiex_queue_scan_cmd(priv, cmd_node); -+ else -+ mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); -+ -+ return ret; -+} -+ -+/* -+ * This function returns a command to the command free queue. -+ * -+ * The function also calls the completion callback if required, before -+ * cleaning the command node and re-inserting it into the free queue. -+ */ -+void -+mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, -+ struct cmd_ctrl_node *cmd_node) -+{ -+ unsigned long flags; -+ -+ if (!cmd_node) -+ return; -+ -+ if (cmd_node->wait_q_enabled) -+ mwifiex_complete_cmd(adapter); -+ /* Clean the node */ -+ mwifiex_clean_cmd_node(adapter, cmd_node); -+ -+ /* Insert node into cmd_free_q */ -+ 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); -+} -+ -+/* -+ * This function queues a command to the command pending queue. -+ * -+ * This in effect adds the command to the command list to be executed. -+ * Exit PS command is handled specially, by placing it always to the -+ * front of the command queue. -+ */ -+void -+mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, -+ struct cmd_ctrl_node *cmd_node, u32 add_tail) -+{ -+ struct host_cmd_ds_command *host_cmd = NULL; -+ u16 command; -+ unsigned long flags; -+ -+ host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); -+ if (!host_cmd) { -+ dev_err(adapter->dev, "QUEUE_CMD: host_cmd is NULL\n"); -+ return; -+ } -+ -+ command = le16_to_cpu(host_cmd->command); -+ -+ /* Exit_PS command needs to be queued in the header always. */ -+ if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { -+ struct host_cmd_ds_802_11_ps_mode_enh *pm = -+ &host_cmd->params.psmode_enh; -+ if ((le16_to_cpu(pm->action) == DIS_PS) -+ || (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { -+ if (adapter->ps_state != PS_STATE_AWAKE) -+ add_tail = false; -+ } -+ } -+ -+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); -+ if (add_tail) -+ list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); -+ else -+ list_add(&cmd_node->list, &adapter->cmd_pending_q); -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -+ -+ dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); -+} -+ -+/* -+ * This function executes the next command in command pending queue. -+ * -+ * This function will fail if a command is already in processing stage, -+ * otherwise it will dequeue the first command from the command pending -+ * queue and send to the firmware. -+ * -+ * If the device is currently in host sleep mode, any commands, except the -+ * host sleep configuration command will de-activate the host sleep. For PS -+ * mode, the function will put the firmware back to sleep if applicable. -+ */ -+int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_private *priv = NULL; -+ struct cmd_ctrl_node *cmd_node = NULL; -+ int ret = 0; -+ struct host_cmd_ds_command *host_cmd; -+ unsigned long cmd_flags; -+ unsigned long cmd_pending_q_flags; -+ -+ /* Check if already in processing */ -+ if (adapter->curr_cmd) { -+ dev_err(adapter->dev, "EXEC_NEXT_CMD: cmd in processing\n"); -+ return -1; -+ } -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); -+ /* Check if any command is pending */ -+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); -+ if (list_empty(&adapter->cmd_pending_q)) { -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, -+ cmd_pending_q_flags); -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); -+ return 0; -+ } -+ cmd_node = list_first_entry(&adapter->cmd_pending_q, -+ struct cmd_ctrl_node, list); -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, -+ cmd_pending_q_flags); -+ -+ host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); -+ priv = cmd_node->priv; -+ -+ if (adapter->ps_state != PS_STATE_AWAKE) { -+ dev_err(adapter->dev, "%s: cannot send cmd in sleep state," -+ " this should not happen\n", __func__); -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); -+ return ret; -+ } -+ -+ 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); -+ -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); -+ ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node); -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ /* Any command sent to the firmware when host is in sleep -+ * mode should de-configure host sleep. We should skip the -+ * host sleep configuration command itself though -+ */ -+ if (priv && (host_cmd->command != -+ cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { -+ if (adapter->hs_activated) { -+ adapter->is_hs_configured = false; -+ mwifiex_hs_activated_event(priv, false); -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function handles the command response. -+ * -+ * After processing, the function cleans the command node and puts -+ * it back to the command free queue. -+ */ -+int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) -+{ -+ struct host_cmd_ds_command *resp = NULL; -+ struct mwifiex_private *priv = -+ mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ int ret = 0; -+ uint16_t orig_cmdresp_no; -+ uint16_t cmdresp_no; -+ uint16_t cmdresp_result; -+ struct timeval tstamp; -+ unsigned long flags; -+ -+ /* Now we got response from FW, cancel the command timer */ -+ del_timer(&adapter->cmd_timer); -+ -+ if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { -+ resp = (struct host_cmd_ds_command *) adapter->upld_buf; -+ dev_err(adapter->dev, "CMD_RESP: NULL curr_cmd, %#x\n", -+ le16_to_cpu(resp->command)); -+ return -1; -+ } -+ -+ adapter->num_cmd_timeout = 0; -+ -+ resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; -+ if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { -+ dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", -+ le16_to_cpu(resp->command)); -+ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->curr_cmd = NULL; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ return -1; -+ } -+ -+ if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { -+ /* Copy original response back to response buffer */ -+ struct mwifiex_ds_misc_cmd *hostcmd = NULL; -+ uint16_t size = le16_to_cpu(resp->size); -+ dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size); -+ size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER); -+ if (adapter->curr_cmd->data_buf) { -+ hostcmd = (struct mwifiex_ds_misc_cmd *) -+ adapter->curr_cmd->data_buf; -+ hostcmd->len = size; -+ memcpy(hostcmd->cmd, (void *) resp, size); -+ } -+ } -+ orig_cmdresp_no = le16_to_cpu(resp->command); -+ -+ /* Get BSS number and corresponding priv */ -+ priv = mwifiex_get_priv_by_id(adapter, -+ HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)), -+ HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); -+ if (!priv) -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ /* Clear RET_BIT from HostCmd */ -+ resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK); -+ -+ cmdresp_no = le16_to_cpu(resp->command); -+ cmdresp_result = le16_to_cpu(resp->result); -+ -+ /* Save the last command response to debug log */ -+ adapter->dbg.last_cmd_resp_index = -+ (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; -+ adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = -+ orig_cmdresp_no; -+ -+ do_gettimeofday(&tstamp); -+ dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d," -+ " len %d, seqno 0x%x\n", -+ tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result, -+ le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); -+ -+ if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { -+ dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); -+ 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); -+ adapter->curr_cmd = NULL; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ return -1; -+ } -+ -+ if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { -+ adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; -+ if ((cmdresp_result == HostCmd_RESULT_OK) -+ && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)) -+ ret = mwifiex_ret_802_11_hs_cfg(priv, resp); -+ } else { -+ /* handle response */ -+ ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); -+ } -+ -+ /* Check init command response */ -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { -+ if (ret == -1) { -+ dev_err(adapter->dev, "%s: cmd %#x failed during " -+ "initialization\n", __func__, cmdresp_no); -+ mwifiex_init_fw_complete(adapter); -+ return -1; -+ } else if (adapter->last_init_cmd == cmdresp_no) -+ adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE; -+ } -+ -+ if (adapter->curr_cmd) { -+ 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); -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->curr_cmd = NULL; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function handles the timeout of command sending. -+ * -+ * It will re-send the same command again. -+ */ -+void -+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 timeval tstamp; -+ -+ adapter->num_cmd_timeout++; -+ adapter->dbg.num_cmd_timeout++; -+ if (!adapter->curr_cmd) { -+ dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); -+ return; -+ } -+ cmd_node = adapter->curr_cmd; -+ if (cmd_node->wait_q_enabled) -+ adapter->cmd_wait_q.status = -ETIMEDOUT; -+ -+ if (cmd_node) { -+ adapter->dbg.timeout_cmd_id = -+ adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; -+ adapter->dbg.timeout_cmd_act = -+ adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; -+ do_gettimeofday(&tstamp); -+ dev_err(adapter->dev, "%s: Timeout cmd id (%lu.%lu) = %#x," -+ " act = %#x\n", __func__, -+ tstamp.tv_sec, tstamp.tv_usec, -+ adapter->dbg.timeout_cmd_id, -+ adapter->dbg.timeout_cmd_act); -+ -+ dev_err(adapter->dev, "num_data_h2c_failure = %d\n", -+ adapter->dbg.num_tx_host_to_card_failure); -+ dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", -+ adapter->dbg.num_cmd_host_to_card_failure); -+ -+ dev_err(adapter->dev, "num_cmd_timeout = %d\n", -+ adapter->dbg.num_cmd_timeout); -+ dev_err(adapter->dev, "num_tx_timeout = %d\n", -+ adapter->dbg.num_tx_timeout); -+ -+ dev_err(adapter->dev, "last_cmd_index = %d\n", -+ adapter->dbg.last_cmd_index); -+ print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET, -+ adapter->dbg.last_cmd_id, DBG_CMD_NUM); -+ print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET, -+ adapter->dbg.last_cmd_act, DBG_CMD_NUM); -+ -+ dev_err(adapter->dev, "last_cmd_resp_index = %d\n", -+ adapter->dbg.last_cmd_resp_index); -+ print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET, -+ adapter->dbg.last_cmd_resp_id, DBG_CMD_NUM); -+ -+ dev_err(adapter->dev, "last_event_index = %d\n", -+ adapter->dbg.last_event_index); -+ print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET, -+ adapter->dbg.last_event, DBG_CMD_NUM); -+ -+ dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", -+ adapter->data_sent, adapter->cmd_sent); -+ -+ dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", -+ adapter->ps_mode, adapter->ps_state); -+ } -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) -+ mwifiex_init_fw_complete(adapter); -+} -+ -+/* -+ * This function cancels all the pending commands. -+ * -+ * The current command, all commands in command pending queue and all scan -+ * commands in scan pending queue are cancelled. All the completion callbacks -+ * are called with failure status to ensure cleanup. -+ */ -+void -+mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) -+{ -+ struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; -+ unsigned long flags; -+ -+ /* Cancel current cmd */ -+ if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->curr_cmd->wait_q_enabled = false; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ adapter->cmd_wait_q.status = -1; -+ mwifiex_complete_cmd(adapter); -+ } -+ /* Cancel all pending command */ -+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); -+ list_for_each_entry_safe(cmd_node, tmp_node, -+ &adapter->cmd_pending_q, list) { -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -+ -+ 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); -+ } -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -+ -+ /* Cancel all pending scan command */ -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ list_for_each_entry_safe(cmd_node, tmp_node, -+ &adapter->scan_pending_q, list) { -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -+ -+ cmd_node->wait_q_enabled = false; -+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ } -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->scan_processing = false; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+} -+ -+/* -+ * This function cancels all pending commands that matches with -+ * the given IOCTL request. -+ * -+ * Both the current command buffer and the pending command queue are -+ * searched for matching IOCTL request. The completion callback of -+ * the matched command is called with failure status to ensure cleanup. -+ * In case of scan commands, all pending commands in scan pending queue -+ * are cancelled. -+ */ -+void -+mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) -+{ -+ struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; -+ unsigned long cmd_flags; -+ unsigned long cmd_pending_q_flags; -+ unsigned long scan_pending_q_flags; -+ uint16_t cancel_scan_cmd = false; -+ -+ if ((adapter->curr_cmd) && -+ (adapter->curr_cmd->wait_q_enabled)) { -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); -+ cmd_node = adapter->curr_cmd; -+ cmd_node->wait_q_enabled = false; -+ cmd_node->cmd_flag |= CMD_F_CANCELED; -+ 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); -+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ 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) { -+ 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); -+ -+ if (cancel_scan_cmd) { -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); -+ adapter->scan_processing = false; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); -+ } -+ adapter->cmd_wait_q.status = -1; -+ mwifiex_complete_cmd(adapter); -+} -+ -+/* -+ * This function sends the sleep confirm command to firmware, if -+ * possible. -+ * -+ * The sleep confirm command cannot be issued if command response, -+ * data response or event response is awaiting handling, or if we -+ * are in the middle of sending a command, or expecting a command -+ * response. -+ */ -+void -+mwifiex_check_ps_cond(struct mwifiex_adapter *adapter) -+{ -+ if (!adapter->cmd_sent && -+ !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) -+ mwifiex_dnld_sleep_confirm_cmd(adapter); -+ else -+ dev_dbg(adapter->dev, -+ "cmd: Delay Sleep Confirm (%s%s%s)\n", -+ (adapter->cmd_sent) ? "D" : "", -+ (adapter->curr_cmd) ? "C" : "", -+ (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); -+} -+ -+/* -+ * This function sends a Host Sleep activated event to applications. -+ * -+ * This event is generated by the driver, with a blank event body. -+ */ -+void -+mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) -+{ -+ if (activated) { -+ if (priv->adapter->is_hs_configured) { -+ priv->adapter->hs_activated = true; -+ dev_dbg(priv->adapter->dev, "event: hs_activated\n"); -+ priv->adapter->hs_activate_wait_q_woken = true; -+ wake_up_interruptible( -+ &priv->adapter->hs_activate_wait_q); -+ } else { -+ dev_dbg(priv->adapter->dev, "event: HS not configured\n"); -+ } -+ } else { -+ dev_dbg(priv->adapter->dev, "event: hs_deactivated\n"); -+ priv->adapter->hs_activated = false; -+ } -+} -+ -+/* -+ * This function handles the command response of a Host Sleep configuration -+ * command. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and setting the current host sleep activation status in driver. -+ * -+ * In case host sleep status change, the function generates an event to -+ * notify the applications. -+ */ -+int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = -+ &resp->params.opt_hs_cfg; -+ uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); -+ -+ if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE)) { -+ mwifiex_hs_activated_event(priv, true); -+ return 0; -+ } else { -+ dev_dbg(adapter->dev, "cmd: CMD_RESP: HS_CFG cmd reply" -+ " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", -+ resp->result, conditions, -+ phs_cfg->params.hs_config.gpio, -+ phs_cfg->params.hs_config.gap); -+ } -+ if (conditions != HOST_SLEEP_CFG_CANCEL) { -+ adapter->is_hs_configured = true; -+ } else { -+ adapter->is_hs_configured = false; -+ if (adapter->hs_activated) -+ mwifiex_hs_activated_event(priv, false); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function wakes up the adapter and generates a Host Sleep -+ * cancel event on receiving the power up interrupt. -+ */ -+void -+mwifiex_process_hs_config(struct mwifiex_adapter *adapter) -+{ -+ dev_dbg(adapter->dev, "info: %s: auto cancelling host sleep" -+ " since there is interrupt from the firmware\n", __func__); -+ -+ adapter->if_ops.wakeup(adapter); -+ adapter->hs_activated = false; -+ adapter->is_hs_configured = false; -+ mwifiex_hs_activated_event(mwifiex_get_priv(adapter, -+ MWIFIEX_BSS_ROLE_ANY), false); -+} -+ -+/* -+ * This function handles the command response of a sleep confirm command. -+ * -+ * The function sets the card state to SLEEP if the response indicates success. -+ */ -+void -+mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, -+ u8 *pbuf, u32 upld_len) -+{ -+ struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf; -+ struct mwifiex_private *priv = -+ mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ uint16_t result = le16_to_cpu(cmd->result); -+ uint16_t command = le16_to_cpu(cmd->command); -+ uint16_t seq_num = le16_to_cpu(cmd->seq_num); -+ -+ if (!upld_len) { -+ dev_err(adapter->dev, "%s: cmd size is 0\n", __func__); -+ return; -+ } -+ -+ /* Get BSS number and corresponding priv */ -+ priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), -+ HostCmd_GET_BSS_TYPE(seq_num)); -+ if (!priv) -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ -+ /* Update sequence number */ -+ seq_num = HostCmd_GET_SEQ_NO(seq_num); -+ /* Clear RET_BIT from HostCmd */ -+ command &= HostCmd_CMD_ID_MASK; -+ -+ if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { -+ dev_err(adapter->dev, "%s: received unexpected response for" -+ " cmd %x, result = %x\n", __func__, command, result); -+ return; -+ } -+ -+ if (result) { -+ dev_err(adapter->dev, "%s: sleep confirm cmd failed\n", -+ __func__); -+ adapter->pm_wakeup_card_req = false; -+ adapter->ps_state = PS_STATE_AWAKE; -+ return; -+ } -+ adapter->pm_wakeup_card_req = true; -+ if (adapter->is_hs_configured) -+ mwifiex_hs_activated_event(mwifiex_get_priv(adapter, -+ MWIFIEX_BSS_ROLE_ANY), true); -+ adapter->ps_state = PS_STATE_SLEEP; -+ cmd->command = cpu_to_le16(command); -+ cmd->seq_num = cpu_to_le16(seq_num); -+} -+EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp); -+ -+/* -+ * This function prepares an enhanced power mode command. -+ * -+ * This function can be used to disable power save or to configure -+ * power save with auto PS or STA PS or auto deep sleep. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting Power Save bitmap, PS parameters TLV, PS mode TLV, -+ * auto deep sleep TLV (as required) -+ * - Ensuring correct endian-ness -+ */ -+int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, uint16_t ps_bitmap, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = -+ &cmd->params.psmode_enh; -+ u8 *tlv = NULL; -+ u16 cmd_size = 0; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); -+ if (cmd_action == DIS_AUTO_PS) { -+ psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); -+ psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); -+ cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + -+ sizeof(psmode_enh->params.ps_bitmap)); -+ } else if (cmd_action == GET_PS) { -+ psmode_enh->action = cpu_to_le16(GET_PS); -+ psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); -+ cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + -+ sizeof(psmode_enh->params.ps_bitmap)); -+ } else if (cmd_action == EN_AUTO_PS) { -+ psmode_enh->action = cpu_to_le16(EN_AUTO_PS); -+ psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); -+ cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + -+ sizeof(psmode_enh->params.ps_bitmap); -+ tlv = (u8 *) cmd + cmd_size; -+ if (ps_bitmap & BITMAP_STA_PS) { -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_ie_types_ps_param *ps_tlv = -+ (struct mwifiex_ie_types_ps_param *) tlv; -+ struct mwifiex_ps_param *ps_mode = &ps_tlv->param; -+ ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); -+ ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - -+ sizeof(struct mwifiex_ie_types_header)); -+ cmd_size += sizeof(*ps_tlv); -+ tlv += sizeof(*ps_tlv); -+ dev_dbg(adapter->dev, "cmd: PS Command: Enter PS\n"); -+ ps_mode->null_pkt_interval = -+ cpu_to_le16(adapter->null_pkt_interval); -+ ps_mode->multiple_dtims = -+ cpu_to_le16(adapter->multiple_dtim); -+ ps_mode->bcn_miss_timeout = -+ cpu_to_le16(adapter->bcn_miss_time_out); -+ ps_mode->local_listen_interval = -+ cpu_to_le16(adapter->local_listen_interval); -+ ps_mode->adhoc_wake_period = -+ cpu_to_le16(adapter->adhoc_awake_period); -+ ps_mode->delay_to_ps = -+ cpu_to_le16(adapter->delay_to_ps); -+ ps_mode->mode = -+ cpu_to_le16(adapter->enhanced_ps_mode); -+ -+ } -+ if (ps_bitmap & BITMAP_AUTO_DS) { -+ struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv = -+ (struct mwifiex_ie_types_auto_ds_param *) tlv; -+ u16 idletime = 0; -+ -+ auto_ds_tlv->header.type = -+ cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); -+ auto_ds_tlv->header.len = -+ cpu_to_le16(sizeof(*auto_ds_tlv) - -+ sizeof(struct mwifiex_ie_types_header)); -+ cmd_size += sizeof(*auto_ds_tlv); -+ tlv += sizeof(*auto_ds_tlv); -+ if (data_buf) -+ idletime = ((struct mwifiex_ds_auto_ds *) -+ data_buf)->idle_time; -+ dev_dbg(priv->adapter->dev, -+ "cmd: PS Command: Enter Auto Deep Sleep\n"); -+ auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); -+ } -+ cmd->size = cpu_to_le16(cmd_size); -+ } -+ return 0; -+} -+ -+/* -+ * This function handles the command response of an enhanced power mode -+ * command. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and setting the current enhanced power mode in driver. -+ */ -+int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = -+ &resp->params.psmode_enh; -+ uint16_t action = le16_to_cpu(ps_mode->action); -+ uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); -+ uint16_t auto_ps_bitmap = -+ le16_to_cpu(ps_mode->params.ps_bitmap); -+ -+ dev_dbg(adapter->dev, "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", -+ __func__, resp->result, action); -+ if (action == EN_AUTO_PS) { -+ if (auto_ps_bitmap & BITMAP_AUTO_DS) { -+ dev_dbg(adapter->dev, "cmd: Enabled auto deep sleep\n"); -+ priv->adapter->is_deep_sleep = true; -+ } -+ if (auto_ps_bitmap & BITMAP_STA_PS) { -+ dev_dbg(adapter->dev, "cmd: Enabled STA power save\n"); -+ if (adapter->sleep_period.period) -+ dev_dbg(adapter->dev, "cmd: set to uapsd/pps mode\n"); -+ } -+ } else if (action == DIS_AUTO_PS) { -+ if (ps_bitmap & BITMAP_AUTO_DS) { -+ priv->adapter->is_deep_sleep = false; -+ dev_dbg(adapter->dev, "cmd: Disabled auto deep sleep\n"); -+ } -+ if (ps_bitmap & BITMAP_STA_PS) { -+ dev_dbg(adapter->dev, "cmd: Disabled STA power save\n"); -+ if (adapter->sleep_period.period) { -+ adapter->delay_null_pkt = false; -+ adapter->tx_lock_flag = false; -+ adapter->pps_uapsd_mode = false; -+ } -+ } -+ } else if (action == GET_PS) { -+ if (ps_bitmap & BITMAP_STA_PS) -+ adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; -+ else -+ adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; -+ -+ dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap); -+ -+ if (data_buf) { -+ /* This section is for get power save mode */ -+ struct mwifiex_ds_pm_cfg *pm_cfg = -+ (struct mwifiex_ds_pm_cfg *)data_buf; -+ if (ps_bitmap & BITMAP_STA_PS) -+ pm_cfg->param.ps_mode = 1; -+ else -+ pm_cfg->param.ps_mode = 0; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * This function prepares command to get hardware specifications. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting permanent address parameter -+ * - Ensuring correct endian-ness -+ */ -+int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd) -+{ -+ struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC); -+ cmd->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN); -+ memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get hardware -+ * specifications. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving/updating the following parameters in driver - -+ * - Firmware capability information -+ * - Firmware band settings -+ * - Ad-hoc start band and channel -+ * - Ad-hoc 11n activation status -+ * - Firmware release number -+ * - Number of antennas -+ * - Hardware address -+ * - Hardware interface version -+ * - Firmware version -+ * - Region code -+ * - 11n capabilities -+ * - MCS support fields -+ * - MP end port -+ */ -+int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int i; -+ -+ adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); -+ -+ if (IS_SUPPORT_MULTI_BANDS(adapter)) -+ adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter); -+ else -+ adapter->fw_bands = BAND_B; -+ -+ adapter->config_bands = adapter->fw_bands; -+ -+ if (adapter->fw_bands & BAND_A) { -+ if (adapter->fw_bands & BAND_GN) { -+ adapter->config_bands |= BAND_AN; -+ adapter->fw_bands |= BAND_AN; -+ } -+ if (adapter->fw_bands & BAND_AN) { -+ adapter->adhoc_start_band = BAND_A | BAND_AN; -+ adapter->adhoc_11n_enabled = true; -+ } else { -+ adapter->adhoc_start_band = BAND_A; -+ } -+ priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; -+ } else if (adapter->fw_bands & BAND_GN) { -+ adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; -+ priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; -+ adapter->adhoc_11n_enabled = true; -+ } else if (adapter->fw_bands & BAND_G) { -+ adapter->adhoc_start_band = BAND_G | BAND_B; -+ priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; -+ } else if (adapter->fw_bands & BAND_B) { -+ adapter->adhoc_start_band = BAND_B; -+ priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; -+ } -+ -+ adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); -+ adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); -+ -+ dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", -+ adapter->fw_release_number); -+ dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", -+ hw_spec->permanent_addr); -+ dev_dbg(adapter->dev, "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", -+ le16_to_cpu(hw_spec->hw_if_version), -+ le16_to_cpu(hw_spec->version)); -+ -+ if (priv->curr_addr[0] == 0xff) -+ memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN); -+ -+ adapter->region_code = le16_to_cpu(hw_spec->region_code); -+ -+ for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) -+ /* Use the region code to search for the index */ -+ if (adapter->region_code == region_code_index[i]) -+ break; -+ -+ /* If it's unidentified region code, use the default (USA) */ -+ if (i >= MWIFIEX_MAX_REGION_CODE) { -+ adapter->region_code = 0x10; -+ dev_dbg(adapter->dev, "cmd: unknown region code, use default (USA)\n"); -+ } -+ -+ adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); -+ adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; -+ -+ if (adapter->if_ops.update_mp_end_port) -+ adapter->if_ops.update_mp_end_port(adapter, -+ le16_to_cpu(hw_spec->mp_end_port)); -+ -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/debugfs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/debugfs.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/debugfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/debugfs.c 2011-05-05 23:29:45.477441767 +0200 -@@ -0,0 +1,770 @@ -+/* -+ * Marvell Wireless LAN device driver: debugfs -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include -+ -+#include "main.h" -+#include "11n.h" -+ -+ -+static struct dentry *mwifiex_dfs_dir; -+ -+static char *bss_modes[] = { -+ "Unknown", -+ "Managed", -+ "Ad-hoc", -+ "Auto" -+}; -+ -+/* size/addr for mwifiex_debug_info */ -+#define item_size(n) (FIELD_SIZEOF(struct mwifiex_debug_info, n)) -+#define item_addr(n) (offsetof(struct mwifiex_debug_info, n)) -+ -+/* size/addr for struct mwifiex_adapter */ -+#define adapter_item_size(n) (FIELD_SIZEOF(struct mwifiex_adapter, n)) -+#define adapter_item_addr(n) (offsetof(struct mwifiex_adapter, n)) -+ -+struct mwifiex_debug_data { -+ char name[32]; /* variable/array name */ -+ u32 size; /* size of the variable/array */ -+ size_t addr; /* address of the variable/array */ -+ int num; /* number of variables in an array */ -+}; -+ -+static struct mwifiex_debug_data items[] = { -+ {"int_counter", item_size(int_counter), -+ item_addr(int_counter), 1}, -+ {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]), -+ item_addr(packets_out[WMM_AC_VO]), 1}, -+ {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]), -+ item_addr(packets_out[WMM_AC_VI]), 1}, -+ {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]), -+ item_addr(packets_out[WMM_AC_BE]), 1}, -+ {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), -+ item_addr(packets_out[WMM_AC_BK]), 1}, -+ {"max_tx_buf_size", item_size(max_tx_buf_size), -+ item_addr(max_tx_buf_size), 1}, -+ {"tx_buf_size", item_size(tx_buf_size), -+ item_addr(tx_buf_size), 1}, -+ {"curr_tx_buf_size", item_size(curr_tx_buf_size), -+ item_addr(curr_tx_buf_size), 1}, -+ {"ps_mode", item_size(ps_mode), -+ item_addr(ps_mode), 1}, -+ {"ps_state", item_size(ps_state), -+ item_addr(ps_state), 1}, -+ {"is_deep_sleep", item_size(is_deep_sleep), -+ item_addr(is_deep_sleep), 1}, -+ {"wakeup_dev_req", item_size(pm_wakeup_card_req), -+ item_addr(pm_wakeup_card_req), 1}, -+ {"wakeup_tries", item_size(pm_wakeup_fw_try), -+ item_addr(pm_wakeup_fw_try), 1}, -+ {"hs_configured", item_size(is_hs_configured), -+ item_addr(is_hs_configured), 1}, -+ {"hs_activated", item_size(hs_activated), -+ item_addr(hs_activated), 1}, -+ {"num_tx_timeout", item_size(num_tx_timeout), -+ item_addr(num_tx_timeout), 1}, -+ {"num_cmd_timeout", item_size(num_cmd_timeout), -+ item_addr(num_cmd_timeout), 1}, -+ {"timeout_cmd_id", item_size(timeout_cmd_id), -+ item_addr(timeout_cmd_id), 1}, -+ {"timeout_cmd_act", item_size(timeout_cmd_act), -+ item_addr(timeout_cmd_act), 1}, -+ {"last_cmd_id", item_size(last_cmd_id), -+ item_addr(last_cmd_id), DBG_CMD_NUM}, -+ {"last_cmd_act", item_size(last_cmd_act), -+ item_addr(last_cmd_act), DBG_CMD_NUM}, -+ {"last_cmd_index", item_size(last_cmd_index), -+ item_addr(last_cmd_index), 1}, -+ {"last_cmd_resp_id", item_size(last_cmd_resp_id), -+ item_addr(last_cmd_resp_id), DBG_CMD_NUM}, -+ {"last_cmd_resp_index", item_size(last_cmd_resp_index), -+ item_addr(last_cmd_resp_index), 1}, -+ {"last_event", item_size(last_event), -+ item_addr(last_event), DBG_CMD_NUM}, -+ {"last_event_index", item_size(last_event_index), -+ item_addr(last_event_index), 1}, -+ {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), -+ item_addr(num_cmd_host_to_card_failure), 1}, -+ {"num_cmd_sleep_cfm_fail", -+ item_size(num_cmd_sleep_cfm_host_to_card_failure), -+ item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1}, -+ {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure), -+ item_addr(num_tx_host_to_card_failure), 1}, -+ {"num_evt_deauth", item_size(num_event_deauth), -+ item_addr(num_event_deauth), 1}, -+ {"num_evt_disassoc", item_size(num_event_disassoc), -+ item_addr(num_event_disassoc), 1}, -+ {"num_evt_link_lost", item_size(num_event_link_lost), -+ item_addr(num_event_link_lost), 1}, -+ {"num_cmd_deauth", item_size(num_cmd_deauth), -+ item_addr(num_cmd_deauth), 1}, -+ {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success), -+ item_addr(num_cmd_assoc_success), 1}, -+ {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure), -+ item_addr(num_cmd_assoc_failure), 1}, -+ {"cmd_sent", item_size(cmd_sent), -+ item_addr(cmd_sent), 1}, -+ {"data_sent", item_size(data_sent), -+ item_addr(data_sent), 1}, -+ {"cmd_resp_received", item_size(cmd_resp_received), -+ item_addr(cmd_resp_received), 1}, -+ {"event_received", item_size(event_received), -+ item_addr(event_received), 1}, -+ -+ /* variables defined in struct mwifiex_adapter */ -+ {"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), -+ adapter_item_addr(rx_pending), 1}, -+}; -+ -+static int num_of_items = ARRAY_SIZE(items); -+ -+/* -+ * Generic proc file open handler. -+ * -+ * This function is called every time a file is accessed for read or write. -+ */ -+static int -+mwifiex_open_generic(struct inode *inode, struct file *file) -+{ -+ file->private_data = inode->i_private; -+ return 0; -+} -+ -+/* -+ * Proc info file read handler. -+ * -+ * This function is called when the 'info' file is opened for reading. -+ * It prints the following driver related information - -+ * - Driver name -+ * - Driver version -+ * - Driver extended version -+ * - Interface name -+ * - BSS mode -+ * - Media state (connected or disconnected) -+ * - MAC address -+ * - Total number of Tx bytes -+ * - Total number of Rx bytes -+ * - Total number of Tx packets -+ * - Total number of Rx packets -+ * - Total number of dropped Tx packets -+ * - Total number of dropped Rx packets -+ * - Total number of corrupted Tx packets -+ * - Total number of corrupted Rx packets -+ * - Carrier status (on or off) -+ * - Tx queue status (started or stopped) -+ * -+ * For STA mode drivers, it also prints the following extra - -+ * - ESSID -+ * - BSSID -+ * - Channel -+ * - Region code -+ * - Multicast count -+ * - Multicast addresses -+ */ -+static ssize_t -+mwifiex_info_read(struct file *file, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct mwifiex_private *priv = -+ (struct mwifiex_private *) file->private_data; -+ struct net_device *netdev = priv->netdev; -+ struct netdev_hw_addr *ha; -+ unsigned long page = get_zeroed_page(GFP_KERNEL); -+ char *p = (char *) page, fmt[64]; -+ struct mwifiex_bss_info info; -+ ssize_t ret = 0; -+ int i = 0; -+ -+ if (!p) -+ return -ENOMEM; -+ -+ memset(&info, 0, sizeof(info)); -+ ret = mwifiex_get_bss_info(priv, &info); -+ if (ret) -+ goto free_and_exit; -+ -+ mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); -+ -+ if (!priv->version_str[0]) -+ mwifiex_get_ver_ext(priv); -+ -+ p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); -+ p += sprintf(p, "driver_version = %s", fmt); -+ p += sprintf(p, "\nverext = %s", priv->version_str); -+ p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); -+ p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); -+ p += sprintf(p, "media_state=\"%s\"\n", -+ (!priv->media_connected ? "Disconnected" : "Connected")); -+ p += sprintf(p, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", -+ netdev->dev_addr[0], netdev->dev_addr[1], -+ netdev->dev_addr[2], netdev->dev_addr[3], -+ netdev->dev_addr[4], netdev->dev_addr[5]); -+ -+ if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { -+ p += sprintf(p, "multicast_count=\"%d\"\n", -+ netdev_mc_count(netdev)); -+ p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); -+ p += sprintf(p, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", -+ info.bssid[0], info.bssid[1], -+ info.bssid[2], info.bssid[3], -+ info.bssid[4], info.bssid[5]); -+ p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); -+ p += sprintf(p, "region_code = \"%02x\"\n", info.region_code); -+ -+ netdev_for_each_mc_addr(ha, netdev) -+ p += sprintf(p, "multicast_address[%d]=" -+ "\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", i++, -+ ha->addr[0], ha->addr[1], -+ ha->addr[2], ha->addr[3], -+ ha->addr[4], ha->addr[5]); -+ } -+ -+ p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); -+ p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); -+ p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); -+ p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); -+ p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); -+ p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); -+ p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); -+ p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); -+ p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) -+ ? "on" : "off")); -+ p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev)) -+ ? "stopped" : "started")); -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, -+ (unsigned long) p - page); -+ -+free_and_exit: -+ free_page(page); -+ return ret; -+} -+ -+/* -+ * Proc getlog file read handler. -+ * -+ * This function is called when the 'getlog' file is opened for reading -+ * It prints the following log information - -+ * - Number of multicast Tx frames -+ * - Number of failed packets -+ * - Number of Tx retries -+ * - Number of multicast Tx retries -+ * - Number of duplicate frames -+ * - Number of RTS successes -+ * - Number of RTS failures -+ * - Number of ACK failures -+ * - Number of fragmented Rx frames -+ * - Number of multicast Rx frames -+ * - Number of FCS errors -+ * - Number of Tx frames -+ * - WEP ICV error counts -+ */ -+static ssize_t -+mwifiex_getlog_read(struct file *file, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct mwifiex_private *priv = -+ (struct mwifiex_private *) file->private_data; -+ unsigned long page = get_zeroed_page(GFP_KERNEL); -+ char *p = (char *) page; -+ ssize_t ret = 0; -+ struct mwifiex_ds_get_stats stats; -+ -+ if (!p) -+ return -ENOMEM; -+ -+ memset(&stats, 0, sizeof(stats)); -+ ret = mwifiex_get_stats_info(priv, &stats); -+ if (ret) -+ goto free_and_exit; -+ -+ p += sprintf(p, "\n" -+ "mcasttxframe %u\n" -+ "failed %u\n" -+ "retry %u\n" -+ "multiretry %u\n" -+ "framedup %u\n" -+ "rtssuccess %u\n" -+ "rtsfailure %u\n" -+ "ackfailure %u\n" -+ "rxfrag %u\n" -+ "mcastrxframe %u\n" -+ "fcserror %u\n" -+ "txframe %u\n" -+ "wepicverrcnt-1 %u\n" -+ "wepicverrcnt-2 %u\n" -+ "wepicverrcnt-3 %u\n" -+ "wepicverrcnt-4 %u\n", -+ stats.mcast_tx_frame, -+ stats.failed, -+ stats.retry, -+ stats.multi_retry, -+ stats.frame_dup, -+ stats.rts_success, -+ stats.rts_failure, -+ stats.ack_failure, -+ stats.rx_frag, -+ stats.mcast_rx_frame, -+ stats.fcs_error, -+ stats.tx_frame, -+ stats.wep_icv_error[0], -+ stats.wep_icv_error[1], -+ stats.wep_icv_error[2], -+ stats.wep_icv_error[3]); -+ -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, -+ (unsigned long) p - page); -+ -+free_and_exit: -+ free_page(page); -+ return ret; -+} -+ -+static struct mwifiex_debug_info info; -+ -+/* -+ * Proc debug file read handler. -+ * -+ * This function is called when the 'debug' file is opened for reading -+ * It prints the following log information - -+ * - Interrupt count -+ * - WMM AC VO packets count -+ * - WMM AC VI packets count -+ * - WMM AC BE packets count -+ * - WMM AC BK packets count -+ * - Maximum Tx buffer size -+ * - Tx buffer size -+ * - Current Tx buffer size -+ * - Power Save mode -+ * - Power Save state -+ * - Deep Sleep status -+ * - Device wakeup required status -+ * - Number of wakeup tries -+ * - Host Sleep configured status -+ * - Host Sleep activated status -+ * - Number of Tx timeouts -+ * - Number of command timeouts -+ * - Last timed out command ID -+ * - Last timed out command action -+ * - Last command ID -+ * - Last command action -+ * - Last command index -+ * - Last command response ID -+ * - Last command response index -+ * - Last event -+ * - Last event index -+ * - Number of host to card command failures -+ * - Number of sleep confirm command failures -+ * - Number of host to card data failure -+ * - Number of deauthentication events -+ * - Number of disassociation events -+ * - Number of link lost events -+ * - Number of deauthentication commands -+ * - Number of association success commands -+ * - Number of association failure commands -+ * - Number of commands sent -+ * - Number of data packets sent -+ * - Number of command responses received -+ * - Number of events received -+ * - Tx BA stream table (TID, RA) -+ * - Rx reorder table (TID, TA, Start window, Window size, Buffer) -+ */ -+static ssize_t -+mwifiex_debug_read(struct file *file, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct mwifiex_private *priv = -+ (struct mwifiex_private *) file->private_data; -+ struct mwifiex_debug_data *d = &items[0]; -+ unsigned long page = get_zeroed_page(GFP_KERNEL); -+ char *p = (char *) page; -+ ssize_t ret = 0; -+ size_t size, addr; -+ long val; -+ int i, j; -+ -+ if (!p) -+ return -ENOMEM; -+ -+ ret = mwifiex_get_debug_info(priv, &info); -+ if (ret) -+ goto free_and_exit; -+ -+ for (i = 0; i < num_of_items; i++) { -+ p += sprintf(p, "%s=", d[i].name); -+ -+ size = d[i].size / d[i].num; -+ -+ if (i < (num_of_items - 3)) -+ addr = d[i].addr + (size_t) &info; -+ else /* The last 3 items are struct mwifiex_adapter variables */ -+ addr = d[i].addr + (size_t) priv->adapter; -+ -+ for (j = 0; j < d[i].num; j++) { -+ switch (size) { -+ case 1: -+ val = *((u8 *) addr); -+ break; -+ case 2: -+ val = *((u16 *) addr); -+ break; -+ case 4: -+ val = *((u32 *) addr); -+ break; -+ case 8: -+ val = *((long long *) addr); -+ break; -+ default: -+ val = -1; -+ break; -+ } -+ -+ p += sprintf(p, "%#lx ", val); -+ addr += size; -+ } -+ -+ p += sprintf(p, "\n"); -+ } -+ -+ if (info.tx_tbl_num) { -+ p += sprintf(p, "Tx BA stream table:\n"); -+ for (i = 0; i < info.tx_tbl_num; i++) -+ p += sprintf(p, "tid = %d, " -+ "ra = %02x:%02x:%02x:%02x:%02x:%02x\n", -+ info.tx_tbl[i].tid, info.tx_tbl[i].ra[0], -+ info.tx_tbl[i].ra[1], info.tx_tbl[i].ra[2], -+ info.tx_tbl[i].ra[3], info.tx_tbl[i].ra[4], -+ info.tx_tbl[i].ra[5]); -+ } -+ -+ if (info.rx_tbl_num) { -+ p += sprintf(p, "Rx reorder table:\n"); -+ for (i = 0; i < info.rx_tbl_num; i++) { -+ -+ p += sprintf(p, "tid = %d, " -+ "ta = %02x:%02x:%02x:%02x:%02x:%02x, " -+ "start_win = %d, " -+ "win_size = %d, buffer: ", -+ info.rx_tbl[i].tid, -+ info.rx_tbl[i].ta[0], info.rx_tbl[i].ta[1], -+ info.rx_tbl[i].ta[2], info.rx_tbl[i].ta[3], -+ info.rx_tbl[i].ta[4], info.rx_tbl[i].ta[5], -+ info.rx_tbl[i].start_win, -+ info.rx_tbl[i].win_size); -+ -+ for (j = 0; j < info.rx_tbl[i].win_size; j++) -+ p += sprintf(p, "%c ", -+ info.rx_tbl[i].buffer[j] ? -+ '1' : '0'); -+ -+ p += sprintf(p, "\n"); -+ } -+ } -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, -+ (unsigned long) p - page); -+ -+free_and_exit: -+ free_page(page); -+ return ret; -+} -+ -+static u32 saved_reg_type, saved_reg_offset, saved_reg_value; -+ -+/* -+ * Proc regrdwr file write handler. -+ * -+ * This function is called when the 'regrdwr' file is opened for writing -+ * -+ * This function can be used to write to a register. -+ */ -+static ssize_t -+mwifiex_regrdwr_write(struct file *file, -+ const char __user *ubuf, size_t count, loff_t *ppos) -+{ -+ unsigned long addr = get_zeroed_page(GFP_KERNEL); -+ char *buf = (char *) addr; -+ size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); -+ int ret = 0; -+ u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; -+ -+ if (!buf) -+ return -ENOMEM; -+ -+ -+ if (copy_from_user(buf, ubuf, buf_size)) { -+ ret = -EFAULT; -+ goto done; -+ } -+ -+ sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); -+ -+ if (reg_type == 0 || reg_offset == 0) { -+ ret = -EINVAL; -+ goto done; -+ } else { -+ saved_reg_type = reg_type; -+ saved_reg_offset = reg_offset; -+ saved_reg_value = reg_value; -+ ret = count; -+ } -+done: -+ free_page(addr); -+ return ret; -+} -+ -+/* -+ * Proc regrdwr file read handler. -+ * -+ * This function is called when the 'regrdwr' file is opened for reading -+ * -+ * This function can be used to read from a register. -+ */ -+static ssize_t -+mwifiex_regrdwr_read(struct file *file, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct mwifiex_private *priv = -+ (struct mwifiex_private *) file->private_data; -+ unsigned long addr = get_zeroed_page(GFP_KERNEL); -+ char *buf = (char *) addr; -+ int pos = 0, ret = 0; -+ u32 reg_value; -+ -+ if (!buf) -+ return -ENOMEM; -+ -+ if (!saved_reg_type) { -+ /* No command has been given */ -+ pos += snprintf(buf, PAGE_SIZE, "0"); -+ goto done; -+ } -+ /* Set command has been given */ -+ if (saved_reg_value != UINT_MAX) { -+ ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset, -+ saved_reg_value); -+ -+ pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", -+ saved_reg_type, saved_reg_offset, -+ saved_reg_value); -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); -+ -+ goto done; -+ } -+ /* Get command has been given */ -+ ret = mwifiex_reg_read(priv, saved_reg_type, -+ saved_reg_offset, ®_value); -+ if (ret) { -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, -+ saved_reg_offset, reg_value); -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); -+ -+done: -+ free_page(addr); -+ return ret; -+} -+ -+static u32 saved_offset = -1, saved_bytes = -1; -+ -+/* -+ * Proc rdeeprom file write handler. -+ * -+ * This function is called when the 'rdeeprom' file is opened for writing -+ * -+ * This function can be used to write to a RDEEPROM location. -+ */ -+static ssize_t -+mwifiex_rdeeprom_write(struct file *file, -+ const char __user *ubuf, size_t count, loff_t *ppos) -+{ -+ unsigned long addr = get_zeroed_page(GFP_KERNEL); -+ char *buf = (char *) addr; -+ size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); -+ int ret = 0; -+ int offset = -1, bytes = -1; -+ -+ if (!buf) -+ return -ENOMEM; -+ -+ -+ if (copy_from_user(buf, ubuf, buf_size)) { -+ ret = -EFAULT; -+ goto done; -+ } -+ -+ sscanf(buf, "%d %d", &offset, &bytes); -+ -+ if (offset == -1 || bytes == -1) { -+ ret = -EINVAL; -+ goto done; -+ } else { -+ saved_offset = offset; -+ saved_bytes = bytes; -+ ret = count; -+ } -+done: -+ free_page(addr); -+ return ret; -+} -+ -+/* -+ * Proc rdeeprom read write handler. -+ * -+ * This function is called when the 'rdeeprom' file is opened for reading -+ * -+ * This function can be used to read from a RDEEPROM location. -+ */ -+static ssize_t -+mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct mwifiex_private *priv = -+ (struct mwifiex_private *) file->private_data; -+ unsigned long addr = get_zeroed_page(GFP_KERNEL); -+ char *buf = (char *) addr; -+ int pos = 0, ret = 0, i = 0; -+ u8 value[MAX_EEPROM_DATA]; -+ -+ if (!buf) -+ return -ENOMEM; -+ -+ if (saved_offset == -1) { -+ /* No command has been given */ -+ pos += snprintf(buf, PAGE_SIZE, "0"); -+ goto done; -+ } -+ -+ /* Get command has been given */ -+ ret = mwifiex_eeprom_read(priv, (u16) saved_offset, -+ (u16) saved_bytes, value); -+ if (ret) { -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); -+ -+ for (i = 0; i < saved_bytes; i++) -+ pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); -+ -+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); -+ -+done: -+ free_page(addr); -+ return ret; -+} -+ -+ -+#define MWIFIEX_DFS_ADD_FILE(name) do { \ -+ if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ -+ priv, &mwifiex_dfs_##name##_fops)) \ -+ return; \ -+} while (0); -+ -+#define MWIFIEX_DFS_FILE_OPS(name) \ -+static const struct file_operations mwifiex_dfs_##name##_fops = { \ -+ .read = mwifiex_##name##_read, \ -+ .write = mwifiex_##name##_write, \ -+ .open = mwifiex_open_generic, \ -+}; -+ -+#define MWIFIEX_DFS_FILE_READ_OPS(name) \ -+static const struct file_operations mwifiex_dfs_##name##_fops = { \ -+ .read = mwifiex_##name##_read, \ -+ .open = mwifiex_open_generic, \ -+}; -+ -+#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ -+static const struct file_operations mwifiex_dfs_##name##_fops = { \ -+ .write = mwifiex_##name##_write, \ -+ .open = mwifiex_open_generic, \ -+}; -+ -+ -+MWIFIEX_DFS_FILE_READ_OPS(info); -+MWIFIEX_DFS_FILE_READ_OPS(debug); -+MWIFIEX_DFS_FILE_READ_OPS(getlog); -+MWIFIEX_DFS_FILE_OPS(regrdwr); -+MWIFIEX_DFS_FILE_OPS(rdeeprom); -+ -+/* -+ * This function creates the debug FS directory structure and the files. -+ */ -+void -+mwifiex_dev_debugfs_init(struct mwifiex_private *priv) -+{ -+ if (!mwifiex_dfs_dir || !priv) -+ return; -+ -+ priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name, -+ mwifiex_dfs_dir); -+ -+ if (!priv->dfs_dev_dir) -+ return; -+ -+ MWIFIEX_DFS_ADD_FILE(info); -+ MWIFIEX_DFS_ADD_FILE(debug); -+ MWIFIEX_DFS_ADD_FILE(getlog); -+ MWIFIEX_DFS_ADD_FILE(regrdwr); -+ MWIFIEX_DFS_ADD_FILE(rdeeprom); -+} -+ -+/* -+ * This function removes the debug FS directory structure and the files. -+ */ -+void -+mwifiex_dev_debugfs_remove(struct mwifiex_private *priv) -+{ -+ if (!priv) -+ return; -+ -+ debugfs_remove_recursive(priv->dfs_dev_dir); -+} -+ -+/* -+ * This function creates the top level proc directory. -+ */ -+void -+mwifiex_debugfs_init(void) -+{ -+ if (!mwifiex_dfs_dir) -+ mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL); -+} -+ -+/* -+ * This function removes the top level proc directory. -+ */ -+void -+mwifiex_debugfs_remove(void) -+{ -+ if (mwifiex_dfs_dir) -+ debugfs_remove(mwifiex_dfs_dir); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/decl.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/decl.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/decl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/decl.h 2011-05-05 23:29:45.474441731 +0200 -@@ -0,0 +1,129 @@ -+/* -+ * Marvell Wireless LAN device driver: generic data structures and APIs -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_DECL_H_ -+#define _MWIFIEX_DECL_H_ -+ -+#undef pr_fmt -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+ -+ -+#define MWIFIEX_MAX_BSS_NUM (1) -+ -+#define MWIFIEX_MIN_DATA_HEADER_LEN 32 /* (sizeof(mwifiex_txpd)) */ -+ -+#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 -+#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 -+ -+#define MWIFIEX_AMPDU_DEF_TXWINSIZE 32 -+#define MWIFIEX_AMPDU_DEF_RXWINSIZE 16 -+#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff -+ -+#define MWIFIEX_RATE_INDEX_HRDSSS0 0 -+#define MWIFIEX_RATE_INDEX_HRDSSS3 3 -+#define MWIFIEX_RATE_INDEX_OFDM0 4 -+#define MWIFIEX_RATE_INDEX_OFDM7 11 -+#define MWIFIEX_RATE_INDEX_MCS0 12 -+ -+#define MWIFIEX_RATE_BITMAP_OFDM0 16 -+#define MWIFIEX_RATE_BITMAP_OFDM7 23 -+#define MWIFIEX_RATE_BITMAP_MCS0 32 -+#define MWIFIEX_RATE_BITMAP_MCS127 159 -+ -+#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) -+ -+#define MWIFIEX_RTS_MIN_VALUE (0) -+#define MWIFIEX_RTS_MAX_VALUE (2347) -+#define MWIFIEX_FRAG_MIN_VALUE (256) -+#define MWIFIEX_FRAG_MAX_VALUE (2346) -+ -+#define MWIFIEX_SDIO_BLOCK_SIZE 256 -+ -+#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) -+ -+enum mwifiex_bss_type { -+ MWIFIEX_BSS_TYPE_STA = 0, -+ MWIFIEX_BSS_TYPE_UAP = 1, -+ MWIFIEX_BSS_TYPE_ANY = 0xff, -+}; -+ -+enum mwifiex_bss_role { -+ MWIFIEX_BSS_ROLE_STA = 0, -+ MWIFIEX_BSS_ROLE_UAP = 1, -+ MWIFIEX_BSS_ROLE_ANY = 0xff, -+}; -+ -+#define BSS_ROLE_BIT_MASK BIT(0) -+ -+#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) -+ -+enum mwifiex_data_frame_type { -+ MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0, -+ MWIFIEX_DATA_FRAME_TYPE_802_11, -+}; -+ -+struct mwifiex_fw_image { -+ u8 *helper_buf; -+ u32 helper_len; -+ u8 *fw_buf; -+ u32 fw_len; -+}; -+ -+struct mwifiex_802_11_ssid { -+ u32 ssid_len; -+ u8 ssid[IEEE80211_MAX_SSID_LEN]; -+}; -+ -+struct mwifiex_wait_queue { -+ wait_queue_head_t wait; -+ u16 condition; -+ int status; -+}; -+ -+struct mwifiex_rxinfo { -+ u8 bss_index; -+ struct sk_buff *parent; -+ u8 use_count; -+}; -+ -+struct mwifiex_txinfo { -+ u32 status_code; -+ u8 flags; -+ u8 bss_index; -+}; -+ -+struct mwifiex_bss_attr { -+ u8 bss_type; -+ u8 frame_type; -+ u8 active; -+ u8 bss_priority; -+ u8 bss_num; -+}; -+ -+enum mwifiex_wmm_ac_e { -+ WMM_AC_BK, -+ WMM_AC_BE, -+ WMM_AC_VI, -+ WMM_AC_VO -+} __packed; -+#endif /* !_MWIFIEX_DECL_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/fw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/fw.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/fw.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/fw.h 2011-05-05 23:29:45.440441321 +0200 -@@ -0,0 +1,1206 @@ -+/* -+ * Marvell Wireless LAN device driver: Firmware specific macros & structures -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_FW_H_ -+#define _MWIFIEX_FW_H_ -+ -+#include -+ -+ -+#define INTF_HEADER_LEN 4 -+ -+struct rfc_1042_hdr { -+ u8 llc_dsap; -+ u8 llc_ssap; -+ u8 llc_ctrl; -+ u8 snap_oui[3]; -+ u16 snap_type; -+}; -+ -+struct rx_packet_hdr { -+ struct ethhdr eth803_hdr; -+ struct rfc_1042_hdr rfc1042_hdr; -+}; -+ -+struct tx_packet_hdr { -+ struct ethhdr eth803_hdr; -+ struct rfc_1042_hdr rfc1042_hdr; -+}; -+ -+#define B_SUPPORTED_RATES 5 -+#define G_SUPPORTED_RATES 9 -+#define BG_SUPPORTED_RATES 13 -+#define A_SUPPORTED_RATES 9 -+#define HOSTCMD_SUPPORTED_RATES 14 -+#define N_SUPPORTED_RATES 3 -+#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN) -+ -+#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11)) -+#define IS_SUPPORT_MULTI_BANDS(adapter) \ -+ (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) -+#define GET_FW_DEFAULT_BANDS(adapter) \ -+ ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) -+ -+extern u8 supported_rates_b[B_SUPPORTED_RATES]; -+extern u8 supported_rates_g[G_SUPPORTED_RATES]; -+extern u8 supported_rates_bg[BG_SUPPORTED_RATES]; -+extern u8 supported_rates_a[A_SUPPORTED_RATES]; -+extern u8 supported_rates_n[N_SUPPORTED_RATES]; -+ -+#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff -+ -+#define KEY_INFO_ENABLED 0x01 -+enum KEY_TYPE_ID { -+ KEY_TYPE_ID_WEP = 0, -+ KEY_TYPE_ID_TKIP, -+ KEY_TYPE_ID_AES, -+ KEY_TYPE_ID_WAPI, -+}; -+#define KEY_MCAST BIT(0) -+#define KEY_UNICAST BIT(1) -+#define KEY_ENABLED BIT(2) -+ -+#define WAPI_KEY_LEN 50 -+ -+#define MAX_POLL_TRIES 100 -+ -+#define MAX_MULTI_INTERFACE_POLL_TRIES 1000 -+ -+#define MAX_FIRMWARE_POLL_TRIES 100 -+ -+#define FIRMWARE_READY 0xfedc -+ -+enum MWIFIEX_802_11_PRIVACY_FILTER { -+ MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, -+ MWIFIEX_802_11_PRIV_FILTER_8021X_WEP -+}; -+ -+enum MWIFIEX_802_11_WEP_STATUS { -+ MWIFIEX_802_11_WEP_ENABLED, -+ MWIFIEX_802_11_WEP_DISABLED, -+}; -+ -+#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) -+ -+#define PROPRIETARY_TLV_BASE_ID 0x0100 -+#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) -+#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) -+#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) -+#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -+#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) -+#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) -+#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) -+#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) -+#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) -+#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) -+#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) -+#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) -+#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) -+#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) -+#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) -+ -+#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 -+ -+#define SSN_MASK 0xfff0 -+ -+#define BA_RESULT_SUCCESS 0x0 -+#define BA_RESULT_TIMEOUT 0x2 -+ -+#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status) -+ -+#define BA_STREAM_NOT_ALLOWED 0xff -+ -+#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \ -+ priv->adapter->config_bands & BAND_AN) \ -+ && priv->curr_bss_params.bss_descriptor.bcn_ht_cap) -+#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\ -+ BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS) -+ -+#define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 -+#define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 -+ -+#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) -+ -+/* dev_cap bitmap -+ * BIT -+ * 0-16 reserved -+ * 17 IEEE80211_HT_CAP_SUP_WIDTH_20_40 -+ * 18-22 reserved -+ * 23 IEEE80211_HT_CAP_SGI_20 -+ * 24 IEEE80211_HT_CAP_SGI_40 -+ * 25 IEEE80211_HT_CAP_TX_STBC -+ * 26 IEEE80211_HT_CAP_RX_STBC -+ * 27-28 reserved -+ * 29 IEEE80211_HT_CAP_GRN_FLD -+ * 30-31 reserved -+ */ -+#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) -+#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) -+#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) -+#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) -+#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) -+#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) -+ -+#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -+#define SETHT_MCS32(x) (x[4] |= 1) -+ -+#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) -+ -+#define LLC_SNAP_LEN 8 -+ -+#define MOD_CLASS_HR_DSSS 0x03 -+#define MOD_CLASS_OFDM 0x07 -+#define MOD_CLASS_HT 0x08 -+#define HT_BW_20 0 -+#define HT_BW_40 1 -+ -+#define HostCmd_CMD_GET_HW_SPEC 0x0003 -+#define HostCmd_CMD_802_11_SCAN 0x0006 -+#define HostCmd_CMD_802_11_GET_LOG 0x000b -+#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010 -+#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 -+#define HostCmd_CMD_802_11_ASSOCIATE 0x0012 -+#define HostCmd_CMD_802_11_SNMP_MIB 0x0016 -+#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 -+#define HostCmd_CMD_BBP_REG_ACCESS 0x001a -+#define HostCmd_CMD_RF_REG_ACCESS 0x001b -+#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad -+#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d -+#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 -+#define HostCmd_CMD_MAC_CONTROL 0x0028 -+#define HostCmd_CMD_802_11_AD_HOC_START 0x002b -+#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c -+#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040 -+#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D -+#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b -+#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e -+#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c -+#define HostCmd_CMD_WMM_GET_STATUS 0x0071 -+#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f -+#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 -+#define HostCmd_CMD_VERSION_EXT 0x0097 -+#define HostCmd_CMD_RSSI_INFO 0x00a4 -+#define HostCmd_CMD_FUNC_INIT 0x00a9 -+#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa -+#define HostCmd_CMD_11N_CFG 0x00cd -+#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce -+#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf -+#define HostCmd_CMD_11N_DELBA 0x00d0 -+#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 -+#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df -+#define HostCmd_CMD_TXPWR_CFG 0x00d1 -+#define HostCmd_CMD_TX_RATE_CFG 0x00d6 -+#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 -+#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 -+#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed -+#define HostCmd_CMD_SET_BSS_MODE 0x00f7 -+ -+ -+enum ENH_PS_MODES { -+ EN_PS = 1, -+ DIS_PS = 2, -+ EN_AUTO_DS = 3, -+ DIS_AUTO_DS = 4, -+ SLEEP_CONFIRM = 5, -+ GET_PS = 0, -+ EN_AUTO_PS = 0xff, -+ DIS_AUTO_PS = 0xfe, -+}; -+ -+#define HostCmd_RET_BIT 0x8000 -+#define HostCmd_ACT_GEN_GET 0x0000 -+#define HostCmd_ACT_GEN_SET 0x0001 -+#define HostCmd_RESULT_OK 0x0000 -+ -+#define HostCmd_ACT_MAC_RX_ON 0x0001 -+#define HostCmd_ACT_MAC_TX_ON 0x0002 -+#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008 -+#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 -+#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 -+#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 -+#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 -+ -+#define HostCmd_BSS_MODE_IBSS 0x0002 -+#define HostCmd_BSS_MODE_ANY 0x0003 -+ -+#define HostCmd_SCAN_RADIO_TYPE_BG 0 -+#define HostCmd_SCAN_RADIO_TYPE_A 1 -+ -+#define HOST_SLEEP_CFG_CANCEL 0xffffffff -+#define HOST_SLEEP_CFG_COND_DEF 0x0000000f -+#define HOST_SLEEP_CFG_GPIO_DEF 0xff -+#define HOST_SLEEP_CFG_GAP_DEF 0 -+ -+#define CMD_F_HOSTCMD (1 << 0) -+#define CMD_F_CANCELED (1 << 1) -+ -+#define HostCmd_CMD_ID_MASK 0x0fff -+ -+#define HostCmd_SEQ_NUM_MASK 0x00ff -+ -+#define HostCmd_BSS_NUM_MASK 0x0f00 -+ -+#define HostCmd_BSS_TYPE_MASK 0xf000 -+ -+#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ -+ (((seq) & 0x00ff) | \ -+ (((num) & 0x000f) << 8)) | \ -+ (((type) & 0x000f) << 12); } -+ -+#define HostCmd_GET_SEQ_NO(seq) \ -+ ((seq) & HostCmd_SEQ_NUM_MASK) -+ -+#define HostCmd_GET_BSS_NO(seq) \ -+ (((seq) & HostCmd_BSS_NUM_MASK) >> 8) -+ -+#define HostCmd_GET_BSS_TYPE(seq) \ -+ (((seq) & HostCmd_BSS_TYPE_MASK) >> 12) -+ -+#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 -+#define EVENT_LINK_LOST 0x00000003 -+#define EVENT_LINK_SENSED 0x00000004 -+#define EVENT_MIB_CHANGED 0x00000006 -+#define EVENT_INIT_DONE 0x00000007 -+#define EVENT_DEAUTHENTICATED 0x00000008 -+#define EVENT_DISASSOCIATED 0x00000009 -+#define EVENT_PS_AWAKE 0x0000000a -+#define EVENT_PS_SLEEP 0x0000000b -+#define EVENT_MIC_ERR_MULTICAST 0x0000000d -+#define EVENT_MIC_ERR_UNICAST 0x0000000e -+#define EVENT_DEEP_SLEEP_AWAKE 0x00000010 -+#define EVENT_ADHOC_BCN_LOST 0x00000011 -+ -+#define EVENT_WMM_STATUS_CHANGE 0x00000017 -+#define EVENT_BG_SCAN_REPORT 0x00000018 -+#define EVENT_RSSI_LOW 0x00000019 -+#define EVENT_SNR_LOW 0x0000001a -+#define EVENT_MAX_FAIL 0x0000001b -+#define EVENT_RSSI_HIGH 0x0000001c -+#define EVENT_SNR_HIGH 0x0000001d -+#define EVENT_IBSS_COALESCED 0x0000001e -+#define EVENT_DATA_RSSI_LOW 0x00000024 -+#define EVENT_DATA_SNR_LOW 0x00000025 -+#define EVENT_DATA_RSSI_HIGH 0x00000026 -+#define EVENT_DATA_SNR_HIGH 0x00000027 -+#define EVENT_LINK_QUALITY 0x00000028 -+#define EVENT_PORT_RELEASE 0x0000002b -+#define EVENT_PRE_BEACON_LOST 0x00000031 -+#define EVENT_ADDBA 0x00000033 -+#define EVENT_DELBA 0x00000034 -+#define EVENT_BA_STREAM_TIEMOUT 0x00000037 -+#define EVENT_AMSDU_AGGR_CTRL 0x00000042 -+#define EVENT_WEP_ICV_ERR 0x00000046 -+#define EVENT_HS_ACT_REQ 0x00000047 -+#define EVENT_BW_CHANGE 0x00000048 -+ -+#define EVENT_HOSTWAKE_STAIE 0x0000004d -+ -+#define EVENT_ID_MASK 0xffff -+#define BSS_NUM_MASK 0xf -+ -+#define EVENT_GET_BSS_NUM(event_cause) \ -+ (((event_cause) >> 16) & BSS_NUM_MASK) -+ -+#define EVENT_GET_BSS_TYPE(event_cause) \ -+ (((event_cause) >> 24) & 0x00ff) -+ -+struct mwifiex_ie_types_header { -+ __le16 type; -+ __le16 len; -+} __packed; -+ -+struct mwifiex_ie_types_data { -+ struct mwifiex_ie_types_header header; -+ u8 data[1]; -+} __packed; -+ -+#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 -+#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 -+ -+struct txpd { -+ u8 bss_type; -+ u8 bss_num; -+ __le16 tx_pkt_length; -+ __le16 tx_pkt_offset; -+ __le16 tx_pkt_type; -+ __le32 tx_control; -+ u8 priority; -+ u8 flags; -+ u8 pkt_delay_2ms; -+ u8 reserved1; -+} __packed; -+ -+struct rxpd { -+ u8 bss_type; -+ u8 bss_num; -+ u16 rx_pkt_length; -+ u16 rx_pkt_offset; -+ u16 rx_pkt_type; -+ u16 seq_num; -+ u8 priority; -+ u8 rx_rate; -+ s8 snr; -+ s8 nf; -+ /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 -+ * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 -+ * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ -+ u8 ht_info; -+ u8 reserved; -+} __packed; -+ -+enum mwifiex_chan_scan_mode_bitmasks { -+ MWIFIEX_PASSIVE_SCAN = BIT(0), -+ MWIFIEX_DISABLE_CHAN_FILT = BIT(1), -+}; -+ -+#define SECOND_CHANNEL_BELOW 0x30 -+#define SECOND_CHANNEL_ABOVE 0x10 -+struct mwifiex_chan_scan_param_set { -+ u8 radio_type; -+ u8 chan_number; -+ u8 chan_scan_mode_bitmap; -+ __le16 min_scan_time; -+ __le16 max_scan_time; -+} __packed; -+ -+struct mwifiex_ie_types_chan_list_param_set { -+ struct mwifiex_ie_types_header header; -+ struct mwifiex_chan_scan_param_set chan_scan_param[1]; -+} __packed; -+ -+struct chan_band_param_set { -+ u8 radio_type; -+ u8 chan_number; -+}; -+ -+struct mwifiex_ie_types_chan_band_list_param_set { -+ struct mwifiex_ie_types_header header; -+ struct chan_band_param_set chan_band_param[1]; -+} __packed; -+ -+struct mwifiex_ie_types_rates_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 rates[1]; -+} __packed; -+ -+struct mwifiex_ie_types_ssid_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 ssid[1]; -+} __packed; -+ -+struct mwifiex_ie_types_num_probes { -+ struct mwifiex_ie_types_header header; -+ __le16 num_probes; -+} __packed; -+ -+struct mwifiex_ie_types_wildcard_ssid_params { -+ struct mwifiex_ie_types_header header; -+ u8 max_ssid_length; -+ u8 ssid[1]; -+} __packed; -+ -+#define TSF_DATA_SIZE 8 -+struct mwifiex_ie_types_tsf_timestamp { -+ struct mwifiex_ie_types_header header; -+ u8 tsf_data[1]; -+} __packed; -+ -+struct mwifiex_cf_param_set { -+ u8 cfp_cnt; -+ u8 cfp_period; -+ u16 cfp_max_duration; -+ u16 cfp_duration_remaining; -+} __packed; -+ -+struct mwifiex_ibss_param_set { -+ u16 atim_window; -+} __packed; -+ -+struct mwifiex_ie_types_ss_param_set { -+ struct mwifiex_ie_types_header header; -+ union { -+ struct mwifiex_cf_param_set cf_param_set[1]; -+ struct mwifiex_ibss_param_set ibss_param_set[1]; -+ } cf_ibss; -+} __packed; -+ -+struct mwifiex_fh_param_set { -+ u16 dwell_time; -+ u8 hop_set; -+ u8 hop_pattern; -+ u8 hop_index; -+} __packed; -+ -+struct mwifiex_ds_param_set { -+ u8 current_chan; -+} __packed; -+ -+struct mwifiex_ie_types_phy_param_set { -+ struct mwifiex_ie_types_header header; -+ union { -+ struct mwifiex_fh_param_set fh_param_set[1]; -+ struct mwifiex_ds_param_set ds_param_set[1]; -+ } fh_ds; -+} __packed; -+ -+struct mwifiex_ie_types_auth_type { -+ struct mwifiex_ie_types_header header; -+ __le16 auth_type; -+} __packed; -+ -+struct mwifiex_ie_types_vendor_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 ie[MWIFIEX_MAX_VSIE_LEN]; -+}; -+ -+struct mwifiex_ie_types_rsn_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 rsn_ie[1]; -+} __packed; -+ -+#define KEYPARAMSET_FIXED_LEN 6 -+ -+struct mwifiex_ie_type_key_param_set { -+ __le16 type; -+ __le16 length; -+ __le16 key_type_id; -+ __le16 key_info; -+ __le16 key_len; -+ u8 key[50]; -+} __packed; -+ -+struct host_cmd_ds_802_11_key_material { -+ __le16 action; -+ struct mwifiex_ie_type_key_param_set key_param_set; -+} __packed; -+ -+struct host_cmd_ds_gen { -+ u16 command; -+ u16 size; -+ u16 seq_num; -+ u16 result; -+}; -+ -+#define S_DS_GEN sizeof(struct host_cmd_ds_gen) -+ -+enum sleep_resp_ctrl { -+ RESP_NOT_NEEDED = 0, -+ RESP_NEEDED, -+}; -+ -+struct mwifiex_ps_param { -+ __le16 null_pkt_interval; -+ __le16 multiple_dtims; -+ __le16 bcn_miss_timeout; -+ __le16 local_listen_interval; -+ __le16 adhoc_wake_period; -+ __le16 mode; -+ __le16 delay_to_ps; -+}; -+ -+#define BITMAP_AUTO_DS 0x01 -+#define BITMAP_STA_PS 0x10 -+ -+struct mwifiex_ie_types_auto_ds_param { -+ struct mwifiex_ie_types_header header; -+ __le16 deep_sleep_timeout; -+} __packed; -+ -+struct mwifiex_ie_types_ps_param { -+ struct mwifiex_ie_types_header header; -+ struct mwifiex_ps_param param; -+} __packed; -+ -+struct host_cmd_ds_802_11_ps_mode_enh { -+ __le16 action; -+ -+ union { -+ struct mwifiex_ps_param opt_ps; -+ __le16 ps_bitmap; -+ } params; -+} __packed; -+ -+struct host_cmd_ds_get_hw_spec { -+ __le16 hw_if_version; -+ __le16 version; -+ __le16 reserved; -+ __le16 num_of_mcast_adr; -+ u8 permanent_addr[ETH_ALEN]; -+ __le16 region_code; -+ __le16 number_of_antenna; -+ __le32 fw_release_number; -+ __le32 reserved_1; -+ __le32 reserved_2; -+ __le32 reserved_3; -+ __le32 fw_cap_info; -+ __le32 dot_11n_dev_cap; -+ u8 dev_mcs_support; -+ __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ -+ __le16 reserved_4; -+} __packed; -+ -+struct host_cmd_ds_802_11_rssi_info { -+ __le16 action; -+ __le16 ndata; -+ __le16 nbcn; -+ __le16 reserved[9]; -+ long long reserved_1; -+}; -+ -+struct host_cmd_ds_802_11_rssi_info_rsp { -+ __le16 action; -+ __le16 ndata; -+ __le16 nbcn; -+ __le16 data_rssi_last; -+ __le16 data_nf_last; -+ __le16 data_rssi_avg; -+ __le16 data_nf_avg; -+ __le16 bcn_rssi_last; -+ __le16 bcn_nf_last; -+ __le16 bcn_rssi_avg; -+ __le16 bcn_nf_avg; -+ long long tsf_bcn; -+}; -+ -+struct host_cmd_ds_802_11_mac_address { -+ __le16 action; -+ u8 mac_addr[ETH_ALEN]; -+}; -+ -+struct host_cmd_ds_mac_control { -+ __le16 action; -+ __le16 reserved; -+}; -+ -+struct host_cmd_ds_mac_multicast_adr { -+ __le16 action; -+ __le16 num_of_adrs; -+ u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -+} __packed; -+ -+struct host_cmd_ds_802_11_deauthenticate { -+ u8 mac_addr[ETH_ALEN]; -+ __le16 reason_code; -+} __packed; -+ -+struct host_cmd_ds_802_11_associate { -+ u8 peer_sta_addr[ETH_ALEN]; -+ __le16 cap_info_bitmap; -+ __le16 listen_interval; -+ __le16 beacon_period; -+ u8 dtim_period; -+} __packed; -+ -+struct ieee_types_assoc_rsp { -+ __le16 cap_info_bitmap; -+ __le16 status_code; -+ __le16 a_id; -+ u8 ie_buffer[1]; -+} __packed; -+ -+struct host_cmd_ds_802_11_associate_rsp { -+ struct ieee_types_assoc_rsp assoc_rsp; -+} __packed; -+ -+struct ieee_types_cf_param_set { -+ u8 element_id; -+ u8 len; -+ u8 cfp_cnt; -+ u8 cfp_period; -+ u16 cfp_max_duration; -+ u16 cfp_duration_remaining; -+} __packed; -+ -+struct ieee_types_ibss_param_set { -+ u8 element_id; -+ u8 len; -+ __le16 atim_window; -+} __packed; -+ -+union ieee_types_ss_param_set { -+ struct ieee_types_cf_param_set cf_param_set; -+ struct ieee_types_ibss_param_set ibss_param_set; -+} __packed; -+ -+struct ieee_types_fh_param_set { -+ u8 element_id; -+ u8 len; -+ __le16 dwell_time; -+ u8 hop_set; -+ u8 hop_pattern; -+ u8 hop_index; -+} __packed; -+ -+struct ieee_types_ds_param_set { -+ u8 element_id; -+ u8 len; -+ u8 current_chan; -+} __packed; -+ -+union ieee_types_phy_param_set { -+ struct ieee_types_fh_param_set fh_param_set; -+ struct ieee_types_ds_param_set ds_param_set; -+} __packed; -+ -+struct host_cmd_ds_802_11_ad_hoc_start { -+ u8 ssid[IEEE80211_MAX_SSID_LEN]; -+ u8 bss_mode; -+ __le16 beacon_period; -+ u8 dtim_period; -+ union ieee_types_ss_param_set ss_param_set; -+ union ieee_types_phy_param_set phy_param_set; -+ u16 reserved1; -+ __le16 cap_info_bitmap; -+ u8 DataRate[HOSTCMD_SUPPORTED_RATES]; -+} __packed; -+ -+struct host_cmd_ds_802_11_ad_hoc_result { -+ u8 pad[3]; -+ u8 bssid[ETH_ALEN]; -+} __packed; -+ -+struct adhoc_bss_desc { -+ u8 bssid[ETH_ALEN]; -+ u8 ssid[IEEE80211_MAX_SSID_LEN]; -+ u8 bss_mode; -+ __le16 beacon_period; -+ u8 dtim_period; -+ u8 time_stamp[8]; -+ u8 local_time[8]; -+ union ieee_types_phy_param_set phy_param_set; -+ union ieee_types_ss_param_set ss_param_set; -+ __le16 cap_info_bitmap; -+ u8 data_rates[HOSTCMD_SUPPORTED_RATES]; -+ -+ /* -+ * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. -+ * It is used in the Adhoc join command and will cause a -+ * binary layout mismatch with the firmware -+ */ -+} __packed; -+ -+struct host_cmd_ds_802_11_ad_hoc_join { -+ struct adhoc_bss_desc bss_descriptor; -+ u16 reserved1; -+ u16 reserved2; -+} __packed; -+ -+struct host_cmd_ds_802_11_get_log { -+ __le32 mcast_tx_frame; -+ __le32 failed; -+ __le32 retry; -+ __le32 multi_retry; -+ __le32 frame_dup; -+ __le32 rts_success; -+ __le32 rts_failure; -+ __le32 ack_failure; -+ __le32 rx_frag; -+ __le32 mcast_rx_frame; -+ __le32 fcs_error; -+ __le32 tx_frame; -+ __le32 reserved; -+ __le32 wep_icv_err_cnt[4]; -+}; -+ -+struct host_cmd_ds_tx_rate_query { -+ u8 tx_rate; -+ /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 -+ * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 -+ * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ -+ u8 ht_info; -+} __packed; -+ -+enum Host_Sleep_Action { -+ HS_CONFIGURE = 0x0001, -+ HS_ACTIVATE = 0x0002, -+}; -+ -+struct mwifiex_hs_config_param { -+ __le32 conditions; -+ u8 gpio; -+ u8 gap; -+} __packed; -+ -+struct hs_activate_param { -+ u16 resp_ctrl; -+} __packed; -+ -+struct host_cmd_ds_802_11_hs_cfg_enh { -+ __le16 action; -+ -+ union { -+ struct mwifiex_hs_config_param hs_config; -+ struct hs_activate_param hs_activate; -+ } params; -+} __packed; -+ -+enum SNMP_MIB_INDEX { -+ OP_RATE_SET_I = 1, -+ DTIM_PERIOD_I = 3, -+ RTS_THRESH_I = 5, -+ SHORT_RETRY_LIM_I = 6, -+ LONG_RETRY_LIM_I = 7, -+ FRAG_THRESH_I = 8, -+ DOT11D_I = 9, -+}; -+ -+#define MAX_SNMP_BUF_SIZE 128 -+ -+struct host_cmd_ds_802_11_snmp_mib { -+ __le16 query_type; -+ __le16 oid; -+ __le16 buf_size; -+ u8 value[1]; -+} __packed; -+ -+struct mwifiex_rate_scope { -+ __le16 type; -+ __le16 length; -+ __le16 hr_dsss_rate_bitmap; -+ __le16 ofdm_rate_bitmap; -+ __le16 ht_mcs_rate_bitmap[8]; -+} __packed; -+ -+struct mwifiex_rate_drop_pattern { -+ __le16 type; -+ __le16 length; -+ __le32 rate_drop_mode; -+} __packed; -+ -+struct host_cmd_ds_tx_rate_cfg { -+ __le16 action; -+ __le16 cfg_index; -+} __packed; -+ -+struct mwifiex_power_group { -+ u8 modulation_class; -+ u8 first_rate_code; -+ u8 last_rate_code; -+ s8 power_step; -+ s8 power_min; -+ s8 power_max; -+ u8 ht_bandwidth; -+ u8 reserved; -+} __packed; -+ -+struct mwifiex_types_power_group { -+ u16 type; -+ u16 length; -+} __packed; -+ -+struct host_cmd_ds_txpwr_cfg { -+ __le16 action; -+ __le16 cfg_index; -+ __le32 mode; -+} __packed; -+ -+#define MWIFIEX_USER_SCAN_CHAN_MAX 50 -+ -+#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 -+ -+struct mwifiex_scan_cmd_config { -+ /* -+ * BSS Type to be sent in the firmware command -+ * -+ * Field can be used to restrict the types of networks returned in the -+ * scan. Valid settings are: -+ * -+ * - MWIFIEX_SCAN_MODE_BSS (infrastructure) -+ * - MWIFIEX_SCAN_MODE_IBSS (adhoc) -+ * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) -+ */ -+ u8 bss_mode; -+ -+ /* Specific BSSID used to filter scan results in the firmware */ -+ u8 specific_bssid[ETH_ALEN]; -+ -+ /* Length of TLVs sent in command starting at tlvBuffer */ -+ u32 tlv_buf_len; -+ -+ /* -+ * SSID TLV(s) and ChanList TLVs to be sent in the firmware command -+ * -+ * TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set -+ * WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set -+ */ -+ u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored -+ here */ -+} __packed; -+ -+struct mwifiex_user_scan_chan { -+ u8 chan_number; -+ u8 radio_type; -+ u8 scan_type; -+ u8 reserved; -+ u32 scan_time; -+} __packed; -+ -+struct mwifiex_user_scan_ssid { -+ u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; -+ u8 max_len; -+} __packed; -+ -+struct mwifiex_user_scan_cfg { -+ /* -+ * Flag set to keep the previous scan table intact -+ * -+ * If set, the scan results will accumulate, replacing any previous -+ * matched entries for a BSS with the new scan data -+ */ -+ u8 keep_previous_scan; -+ /* -+ * BSS mode to be sent in the firmware command -+ * -+ * Field can be used to restrict the types of networks returned in the -+ * scan. Valid settings are: -+ * -+ * - MWIFIEX_SCAN_MODE_BSS (infrastructure) -+ * - MWIFIEX_SCAN_MODE_IBSS (adhoc) -+ * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) -+ */ -+ u8 bss_mode; -+ /* Configure the number of probe requests for active chan scans */ -+ u8 num_probes; -+ u8 reserved; -+ /* BSSID filter sent in the firmware command to limit the results */ -+ u8 specific_bssid[ETH_ALEN]; -+ /* SSID filter list used in the to limit the scan results */ -+ struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH]; -+ /* Variable number (fixed maximum) of channels to scan up */ -+ struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX]; -+} __packed; -+ -+struct ie_body { -+ u8 grp_key_oui[4]; -+ u8 ptk_cnt[2]; -+ u8 ptk_body[4]; -+} __packed; -+ -+struct host_cmd_ds_802_11_scan { -+ u8 bss_mode; -+ u8 bssid[ETH_ALEN]; -+ u8 tlv_buffer[1]; -+} __packed; -+ -+struct host_cmd_ds_802_11_scan_rsp { -+ __le16 bss_descript_size; -+ u8 number_of_sets; -+ u8 bss_desc_and_tlv_buffer[1]; -+} __packed; -+ -+struct host_cmd_ds_802_11_bg_scan_query { -+ u8 flush; -+} __packed; -+ -+struct host_cmd_ds_802_11_bg_scan_query_rsp { -+ u32 report_condition; -+ struct host_cmd_ds_802_11_scan_rsp scan_resp; -+} __packed; -+ -+struct mwifiex_ietypes_domain_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; -+ struct ieee80211_country_ie_triplet triplet[1]; -+} __packed; -+ -+struct host_cmd_ds_802_11d_domain_info { -+ __le16 action; -+ struct mwifiex_ietypes_domain_param_set domain; -+} __packed; -+ -+struct host_cmd_ds_802_11d_domain_info_rsp { -+ __le16 action; -+ struct mwifiex_ietypes_domain_param_set domain; -+} __packed; -+ -+struct host_cmd_ds_11n_addba_req { -+ u8 add_req_result; -+ u8 peer_mac_addr[ETH_ALEN]; -+ u8 dialog_token; -+ __le16 block_ack_param_set; -+ __le16 block_ack_tmo; -+ __le16 ssn; -+} __packed; -+ -+struct host_cmd_ds_11n_addba_rsp { -+ u8 add_rsp_result; -+ u8 peer_mac_addr[ETH_ALEN]; -+ u8 dialog_token; -+ __le16 status_code; -+ __le16 block_ack_param_set; -+ __le16 block_ack_tmo; -+ __le16 ssn; -+} __packed; -+ -+struct host_cmd_ds_11n_delba { -+ u8 del_result; -+ u8 peer_mac_addr[ETH_ALEN]; -+ __le16 del_ba_param_set; -+ __le16 reason_code; -+ u8 reserved; -+} __packed; -+ -+struct host_cmd_ds_11n_batimeout { -+ u8 tid; -+ u8 peer_mac_addr[ETH_ALEN]; -+ u8 origninator; -+} __packed; -+ -+struct host_cmd_ds_11n_cfg { -+ __le16 action; -+ __le16 ht_tx_cap; -+ __le16 ht_tx_info; -+} __packed; -+ -+struct host_cmd_ds_txbuf_cfg { -+ __le16 action; -+ __le16 buff_size; -+ __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ -+ __le16 reserved3; -+} __packed; -+ -+struct host_cmd_ds_amsdu_aggr_ctrl { -+ __le16 action; -+ __le16 enable; -+ __le16 curr_buf_size; -+} __packed; -+ -+struct mwifiex_ie_types_wmm_param_set { -+ struct mwifiex_ie_types_header header; -+ u8 wmm_ie[1]; -+}; -+ -+struct mwifiex_ie_types_wmm_queue_status { -+ struct mwifiex_ie_types_header header; -+ u8 queue_index; -+ u8 disabled; -+ u16 medium_time; -+ u8 flow_required; -+ u8 flow_created; -+ u32 reserved; -+}; -+ -+struct ieee_types_vendor_header { -+ u8 element_id; -+ u8 len; -+ u8 oui[3]; -+ u8 oui_type; -+ u8 oui_subtype; -+ u8 version; -+} __packed; -+ -+struct ieee_types_wmm_ac_parameters { -+ u8 aci_aifsn_bitmap; -+ u8 ecw_bitmap; -+ __le16 tx_op_limit; -+} __packed; -+ -+struct ieee_types_wmm_parameter { -+ /* -+ * WMM Parameter IE - Vendor Specific Header: -+ * element_id [221/0xdd] -+ * Len [24] -+ * Oui [00:50:f2] -+ * OuiType [2] -+ * OuiSubType [1] -+ * Version [1] -+ */ -+ struct ieee_types_vendor_header vend_hdr; -+ u8 qos_info_bitmap; -+ u8 reserved; -+ struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_MAX_QUEUES]; -+} __packed; -+ -+struct ieee_types_wmm_info { -+ -+ /* -+ * WMM Info IE - Vendor Specific Header: -+ * element_id [221/0xdd] -+ * Len [7] -+ * Oui [00:50:f2] -+ * OuiType [2] -+ * OuiSubType [0] -+ * Version [1] -+ */ -+ struct ieee_types_vendor_header vend_hdr; -+ -+ u8 qos_info_bitmap; -+} __packed; -+ -+struct host_cmd_ds_wmm_get_status { -+ u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * -+ IEEE80211_MAX_QUEUES]; -+ u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; -+} __packed; -+ -+struct mwifiex_wmm_ac_status { -+ u8 disabled; -+ u8 flow_required; -+ u8 flow_created; -+}; -+ -+struct mwifiex_ie_types_htcap { -+ struct mwifiex_ie_types_header header; -+ struct ieee80211_ht_cap ht_cap; -+} __packed; -+ -+struct mwifiex_ie_types_htinfo { -+ struct mwifiex_ie_types_header header; -+ struct ieee80211_ht_info ht_info; -+} __packed; -+ -+struct mwifiex_ie_types_2040bssco { -+ struct mwifiex_ie_types_header header; -+ u8 bss_co_2040; -+} __packed; -+ -+struct mwifiex_ie_types_extcap { -+ struct mwifiex_ie_types_header header; -+ u8 ext_cap; -+} __packed; -+ -+struct host_cmd_ds_mac_reg_access { -+ __le16 action; -+ __le16 offset; -+ __le32 value; -+} __packed; -+ -+struct host_cmd_ds_bbp_reg_access { -+ __le16 action; -+ __le16 offset; -+ u8 value; -+ u8 reserved[3]; -+} __packed; -+ -+struct host_cmd_ds_rf_reg_access { -+ __le16 action; -+ __le16 offset; -+ u8 value; -+ u8 reserved[3]; -+} __packed; -+ -+struct host_cmd_ds_pmic_reg_access { -+ __le16 action; -+ __le16 offset; -+ u8 value; -+ u8 reserved[3]; -+} __packed; -+ -+struct host_cmd_ds_802_11_eeprom_access { -+ __le16 action; -+ -+ __le16 offset; -+ __le16 byte_count; -+ u8 value; -+} __packed; -+ -+struct host_cmd_ds_802_11_rf_channel { -+ __le16 action; -+ __le16 current_channel; -+ __le16 rf_type; -+ __le16 reserved; -+ u8 reserved_1[32]; -+} __packed; -+ -+struct host_cmd_ds_version_ext { -+ u8 version_str_sel; -+ char version_str[128]; -+} __packed; -+ -+struct host_cmd_ds_802_11_ibss_status { -+ __le16 action; -+ __le16 enable; -+ u8 bssid[ETH_ALEN]; -+ __le16 beacon_interval; -+ __le16 atim_window; -+ __le16 use_g_rate_protect; -+} __packed; -+ -+#define CONNECTION_TYPE_INFRA 0 -+#define CONNECTION_TYPE_ADHOC 1 -+ -+struct host_cmd_ds_set_bss_mode { -+ u8 con_type; -+} __packed; -+ -+struct host_cmd_ds_command { -+ __le16 command; -+ __le16 size; -+ __le16 seq_num; -+ __le16 result; -+ union { -+ struct host_cmd_ds_get_hw_spec hw_spec; -+ struct host_cmd_ds_mac_control mac_ctrl; -+ struct host_cmd_ds_802_11_mac_address mac_addr; -+ struct host_cmd_ds_mac_multicast_adr mc_addr; -+ struct host_cmd_ds_802_11_get_log get_log; -+ struct host_cmd_ds_802_11_rssi_info rssi_info; -+ struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp; -+ struct host_cmd_ds_802_11_snmp_mib smib; -+ struct host_cmd_ds_802_11_rf_channel rf_channel; -+ struct host_cmd_ds_tx_rate_query tx_rate; -+ struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; -+ struct host_cmd_ds_txpwr_cfg txp_cfg; -+ struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; -+ struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; -+ struct host_cmd_ds_802_11_scan scan; -+ struct host_cmd_ds_802_11_scan_rsp scan_resp; -+ struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; -+ struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; -+ struct host_cmd_ds_802_11_associate associate; -+ struct host_cmd_ds_802_11_associate_rsp associate_rsp; -+ struct host_cmd_ds_802_11_deauthenticate deauth; -+ struct host_cmd_ds_802_11_ad_hoc_start adhoc_start; -+ struct host_cmd_ds_802_11_ad_hoc_result adhoc_result; -+ struct host_cmd_ds_802_11_ad_hoc_join adhoc_join; -+ struct host_cmd_ds_802_11d_domain_info domain_info; -+ struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp; -+ struct host_cmd_ds_11n_addba_req add_ba_req; -+ struct host_cmd_ds_11n_addba_rsp add_ba_rsp; -+ struct host_cmd_ds_11n_delba del_ba; -+ struct host_cmd_ds_txbuf_cfg tx_buf; -+ struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl; -+ struct host_cmd_ds_11n_cfg htcfg; -+ struct host_cmd_ds_wmm_get_status get_wmm_status; -+ struct host_cmd_ds_802_11_key_material key_material; -+ struct host_cmd_ds_version_ext verext; -+ struct host_cmd_ds_802_11_ibss_status ibss_coalescing; -+ struct host_cmd_ds_mac_reg_access mac_reg; -+ struct host_cmd_ds_bbp_reg_access bbp_reg; -+ struct host_cmd_ds_rf_reg_access rf_reg; -+ struct host_cmd_ds_pmic_reg_access pmic_reg; -+ struct host_cmd_ds_set_bss_mode bss_mode; -+ struct host_cmd_ds_802_11_eeprom_access eeprom; -+ } params; -+} __packed; -+ -+struct mwifiex_opt_sleep_confirm { -+ __le16 command; -+ __le16 size; -+ __le16 seq_num; -+ __le16 result; -+ __le16 action; -+ __le16 resp_ctrl; -+} __packed; -+ -+struct mwifiex_opt_sleep_confirm_buffer { -+ u8 hdr[4]; -+ struct mwifiex_opt_sleep_confirm ps_cfm_sleep; -+} __packed; -+#endif /* !_MWIFIEX_FW_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/init.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/init.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/init.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/init.c 2011-05-05 23:29:45.476441755 +0200 -@@ -0,0 +1,652 @@ -+/* -+ * Marvell Wireless LAN device driver: HW/FW Initialization -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * This function adds a BSS priority table to the table list. -+ * -+ * The function allocates a new BSS priority table node and adds it to -+ * the end of BSS priority table list, kept in driver memory. -+ */ -+static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bss_prio_node *bss_prio; -+ unsigned long flags; -+ -+ bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); -+ if (!bss_prio) { -+ dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", -+ __func__); -+ return -1; -+ } -+ -+ bss_prio->priv = priv; -+ INIT_LIST_HEAD(&bss_prio->list); -+ if (!adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur) -+ adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = -+ bss_prio; -+ -+ spin_lock_irqsave(&adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_lock, flags); -+ list_add_tail(&bss_prio->list, -+ &adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_head); -+ spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_lock, flags); -+ -+ return 0; -+} -+ -+/* -+ * This function initializes the private structure and sets default -+ * values to the members. -+ * -+ * Additionally, it also initializes all the locks and sets up all the -+ * lists. -+ */ -+static int mwifiex_init_priv(struct mwifiex_private *priv) -+{ -+ u32 i; -+ -+ priv->media_connected = false; -+ memset(priv->curr_addr, 0xff, ETH_ALEN); -+ -+ priv->pkt_tx_ctrl = 0; -+ priv->bss_mode = NL80211_IFTYPE_STATION; -+ priv->data_rate = 0; /* Initially indicate the rate as auto */ -+ priv->is_data_rate_auto = true; -+ priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; -+ priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; -+ -+ priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; -+ priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; -+ priv->sec_info.encryption_mode = 0; -+ for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) -+ memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); -+ priv->wep_key_curr_index = 0; -+ priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON | -+ HostCmd_ACT_MAC_ETHERNETII_ENABLE; -+ -+ priv->beacon_period = 100; /* beacon interval */ ; -+ priv->attempted_bss_desc = NULL; -+ memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); -+ priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL; -+ -+ memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); -+ memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); -+ memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); -+ priv->assoc_rsp_size = 0; -+ priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; -+ priv->atim_window = 0; -+ priv->adhoc_state = ADHOC_IDLE; -+ priv->tx_power_level = 0; -+ priv->max_tx_power_level = 0; -+ priv->min_tx_power_level = 0; -+ priv->tx_rate = 0; -+ priv->rxpd_htinfo = 0; -+ priv->rxpd_rate = 0; -+ priv->rate_bitmap = 0; -+ priv->data_rssi_last = 0; -+ priv->data_rssi_avg = 0; -+ priv->data_nf_avg = 0; -+ priv->data_nf_last = 0; -+ priv->bcn_rssi_last = 0; -+ priv->bcn_rssi_avg = 0; -+ priv->bcn_nf_avg = 0; -+ priv->bcn_nf_last = 0; -+ memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); -+ memset(&priv->aes_key, 0, sizeof(priv->aes_key)); -+ priv->wpa_ie_len = 0; -+ priv->wpa_is_gtk_set = false; -+ -+ memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); -+ priv->assoc_tlv_buf_len = 0; -+ memset(&priv->wps, 0, sizeof(priv->wps)); -+ memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); -+ priv->gen_ie_buf_len = 0; -+ memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); -+ -+ priv->wmm_required = true; -+ priv->wmm_enabled = false; -+ priv->wmm_qosinfo = 0; -+ priv->curr_bcn_buf = NULL; -+ priv->curr_bcn_size = 0; -+ -+ priv->scan_block = false; -+ -+ return mwifiex_add_bss_prio_tbl(priv); -+} -+ -+/* -+ * This function allocates buffers for members of the adapter -+ * structure. -+ * -+ * The memory allocated includes scan table, command buffers, and -+ * sleep confirm command buffer. In addition, the queues are -+ * also initialized. -+ */ -+static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ u32 buf_size; -+ struct mwifiex_bssdescriptor *temp_scan_table; -+ -+ /* Allocate buffer to store the BSSID list */ -+ buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP; -+ temp_scan_table = kzalloc(buf_size, GFP_KERNEL); -+ if (!temp_scan_table) { -+ dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", -+ __func__); -+ return -1; -+ } -+ -+ adapter->scan_table = temp_scan_table; -+ -+ /* Allocate command buffer */ -+ ret = mwifiex_alloc_cmd_buffer(adapter); -+ if (ret) { -+ dev_err(adapter->dev, "%s: failed to alloc cmd buffer\n", -+ __func__); -+ return -1; -+ } -+ -+ adapter->sleep_cfm = -+ dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm_buffer) -+ + INTF_HEADER_LEN); -+ -+ if (!adapter->sleep_cfm) { -+ dev_err(adapter->dev, "%s: failed to alloc sleep cfm" -+ " cmd buffer\n", __func__); -+ return -1; -+ } -+ skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); -+ -+ return 0; -+} -+ -+/* -+ * This function initializes the adapter structure and sets default -+ * values to the members of adapter. -+ * -+ * This also initializes the WMM related parameters in the driver private -+ * structures. -+ */ -+static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = NULL; -+ -+ skb_put(adapter->sleep_cfm, sizeof(sleep_cfm_buf->ps_cfm_sleep)); -+ sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) -+ (adapter->sleep_cfm->data); -+ -+ adapter->cmd_sent = false; -+ adapter->data_sent = true; -+ adapter->cmd_resp_received = false; -+ adapter->event_received = false; -+ adapter->data_received = false; -+ -+ adapter->surprise_removed = false; -+ -+ adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; -+ -+ adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; -+ adapter->ps_state = PS_STATE_AWAKE; -+ adapter->need_to_wakeup = false; -+ -+ adapter->scan_mode = HostCmd_BSS_MODE_ANY; -+ adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME; -+ adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; -+ adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; -+ -+ adapter->num_in_scan_table = 0; -+ memset(adapter->scan_table, 0, -+ (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP)); -+ adapter->scan_probes = 1; -+ -+ memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf)); -+ adapter->bcn_buf_end = adapter->bcn_buf; -+ -+ adapter->multiple_dtim = 1; -+ -+ adapter->local_listen_interval = 0; /* default value in firmware -+ will be used */ -+ -+ adapter->is_deep_sleep = false; -+ -+ adapter->delay_null_pkt = false; -+ adapter->delay_to_ps = 1000; -+ adapter->enhanced_ps_mode = PS_MODE_AUTO; -+ -+ adapter->gen_null_pkt = false; /* Disable NULL Pkg generation by -+ default */ -+ adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by -+ default */ -+ adapter->pm_wakeup_card_req = false; -+ -+ adapter->pm_wakeup_fw_try = false; -+ -+ adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; -+ adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; -+ adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; -+ -+ adapter->is_hs_configured = false; -+ adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF); -+ adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF; -+ adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF; -+ adapter->hs_activated = false; -+ -+ memset(adapter->event_body, 0, sizeof(adapter->event_body)); -+ adapter->hw_dot_11n_dev_cap = 0; -+ adapter->hw_dev_mcs_support = 0; -+ adapter->chan_offset = 0; -+ adapter->adhoc_11n_enabled = false; -+ -+ mwifiex_wmm_init(adapter); -+ -+ if (adapter->sleep_cfm) { -+ memset(&sleep_cfm_buf->ps_cfm_sleep, 0, -+ adapter->sleep_cfm->len); -+ sleep_cfm_buf->ps_cfm_sleep.command = -+ cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); -+ sleep_cfm_buf->ps_cfm_sleep.size = -+ cpu_to_le16(adapter->sleep_cfm->len); -+ sleep_cfm_buf->ps_cfm_sleep.result = 0; -+ sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); -+ sleep_cfm_buf->ps_cfm_sleep.resp_ctrl = -+ cpu_to_le16(RESP_NEEDED); -+ } -+ memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); -+ memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); -+ adapter->tx_lock_flag = false; -+ adapter->null_pkt_interval = 0; -+ adapter->fw_bands = 0; -+ adapter->config_bands = 0; -+ adapter->adhoc_start_band = 0; -+ adapter->scan_channels = NULL; -+ adapter->fw_release_number = 0; -+ adapter->fw_cap_info = 0; -+ memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); -+ adapter->event_cause = 0; -+ adapter->region_code = 0; -+ adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; -+ adapter->adhoc_awake_period = 0; -+ memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); -+ adapter->arp_filter_size = 0; -+} -+ -+/* -+ * This function frees the adapter structure. -+ * -+ * The freeing operation is done recursively, by canceling all -+ * pending commands, freeing the member buffers previously -+ * allocated (command buffers, scan table buffer, sleep confirm -+ * command buffer), stopping the timers and calling the cleanup -+ * routines for every interface, before the actual adapter -+ * structure is freed. -+ */ -+static void -+mwifiex_free_adapter(struct mwifiex_adapter *adapter) -+{ -+ if (!adapter) { -+ pr_err("%s: adapter is NULL\n", __func__); -+ return; -+ } -+ -+ mwifiex_cancel_all_pending_cmd(adapter); -+ -+ /* Free lock variables */ -+ mwifiex_free_lock_list(adapter); -+ -+ /* Free command buffer */ -+ dev_dbg(adapter->dev, "info: free cmd buffer\n"); -+ mwifiex_free_cmd_buffer(adapter); -+ -+ del_timer(&adapter->cmd_timer); -+ -+ dev_dbg(adapter->dev, "info: free scan table\n"); -+ kfree(adapter->scan_table); -+ adapter->scan_table = NULL; -+ -+ adapter->if_ops.cleanup_if(adapter); -+ -+ dev_kfree_skb_any(adapter->sleep_cfm); -+} -+ -+/* -+ * This function intializes the lock variables and -+ * the list heads. -+ */ -+int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_private *priv = NULL; -+ s32 i = 0; -+ u32 j = 0; -+ -+ spin_lock_init(&adapter->mwifiex_lock); -+ spin_lock_init(&adapter->int_lock); -+ spin_lock_init(&adapter->main_proc_lock); -+ spin_lock_init(&adapter->mwifiex_cmd_lock); -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ priv = adapter->priv[i]; -+ spin_lock_init(&priv->rx_pkt_lock); -+ spin_lock_init(&priv->wmm.ra_list_spinlock); -+ spin_lock_init(&priv->curr_bcn_buf_lock); -+ } -+ } -+ -+ /* Initialize cmd_free_q */ -+ INIT_LIST_HEAD(&adapter->cmd_free_q); -+ /* Initialize cmd_pending_q */ -+ INIT_LIST_HEAD(&adapter->cmd_pending_q); -+ /* Initialize scan_pending_q */ -+ INIT_LIST_HEAD(&adapter->scan_pending_q); -+ -+ spin_lock_init(&adapter->cmd_free_q_lock); -+ spin_lock_init(&adapter->cmd_pending_q_lock); -+ spin_lock_init(&adapter->scan_pending_q_lock); -+ -+ for (i = 0; i < adapter->priv_num; ++i) { -+ INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); -+ adapter->bss_prio_tbl[i].bss_prio_cur = NULL; -+ spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); -+ } -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (!adapter->priv[i]) -+ continue; -+ priv = adapter->priv[i]; -+ for (j = 0; j < MAX_NUM_TID; ++j) { -+ INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); -+ spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); -+ } -+ INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); -+ INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); -+ -+ spin_lock_init(&priv->tx_ba_stream_tbl_lock); -+ spin_lock_init(&priv->rx_reorder_tbl_lock); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function releases the lock variables and frees the locks and -+ * associated locks. -+ */ -+void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_private *priv = NULL; -+ s32 i = 0; -+ s32 j = 0; -+ -+ /* Free lists */ -+ list_del(&adapter->cmd_free_q); -+ list_del(&adapter->cmd_pending_q); -+ list_del(&adapter->scan_pending_q); -+ -+ for (i = 0; i < adapter->priv_num; i++) -+ list_del(&adapter->bss_prio_tbl[i].bss_prio_head); -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ priv = adapter->priv[i]; -+ for (j = 0; j < MAX_NUM_TID; ++j) -+ list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); -+ list_del(&priv->tx_ba_stream_tbl_ptr); -+ list_del(&priv->rx_reorder_tbl_ptr); -+ } -+ } -+} -+ -+/* -+ * This function initializes the firmware. -+ * -+ * The following operations are performed sequentially - -+ * - Allocate adapter structure -+ * - Initialize the adapter structure -+ * - Initialize the private structure -+ * - Add BSS priority tables to the adapter structure -+ * - For each interface, send the init commands to firmware -+ * - Send the first command in command pending queue, if available -+ */ -+int mwifiex_init_fw(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ struct mwifiex_private *priv = NULL; -+ u8 i = 0; -+ u8 first_sta = true; -+ int is_cmd_pend_q_empty; -+ unsigned long flags; -+ -+ adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; -+ -+ /* Allocate memory for member of adapter structure */ -+ ret = mwifiex_allocate_adapter(adapter); -+ if (ret) -+ return -1; -+ -+ /* Initialize adapter structure */ -+ mwifiex_init_adapter(adapter); -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ priv = adapter->priv[i]; -+ -+ /* Initialize private structure */ -+ ret = mwifiex_init_priv(priv); -+ if (ret) -+ return -1; -+ } -+ } -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); -+ if (ret == -1) -+ return -1; -+ -+ first_sta = false; -+ } -+ } -+ -+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); -+ is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -+ if (!is_cmd_pend_q_empty) { -+ /* Send the first command in queue and return */ -+ if (mwifiex_main_process(adapter) != -1) -+ ret = -EINPROGRESS; -+ } else { -+ adapter->hw_status = MWIFIEX_HW_STATUS_READY; -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function deletes the BSS priority tables. -+ * -+ * The function traverses through all the allocated BSS priority nodes -+ * in every BSS priority table and frees them. -+ */ -+static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) -+{ -+ int i; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bss_prio_node *bssprio_node = NULL, *tmp_node = NULL, -+ **cur = NULL; -+ struct list_head *head; -+ spinlock_t *lock; -+ unsigned long flags; -+ -+ for (i = 0; i < adapter->priv_num; ++i) { -+ head = &adapter->bss_prio_tbl[i].bss_prio_head; -+ cur = &adapter->bss_prio_tbl[i].bss_prio_cur; -+ lock = &adapter->bss_prio_tbl[i].bss_prio_lock; -+ dev_dbg(adapter->dev, "info: delete BSS priority table," -+ " index = %d, i = %d, head = %p, cur = %p\n", -+ priv->bss_index, i, head, *cur); -+ if (*cur) { -+ spin_lock_irqsave(lock, flags); -+ if (list_empty(head)) { -+ spin_unlock_irqrestore(lock, flags); -+ continue; -+ } -+ bssprio_node = list_first_entry(head, -+ struct mwifiex_bss_prio_node, list); -+ spin_unlock_irqrestore(lock, flags); -+ -+ list_for_each_entry_safe(bssprio_node, tmp_node, head, -+ list) { -+ if (bssprio_node->priv == priv) { -+ dev_dbg(adapter->dev, "info: Delete " -+ "node %p, next = %p\n", -+ bssprio_node, tmp_node); -+ spin_lock_irqsave(lock, flags); -+ list_del(&bssprio_node->list); -+ spin_unlock_irqrestore(lock, flags); -+ kfree(bssprio_node); -+ } -+ } -+ *cur = (struct mwifiex_bss_prio_node *)head; -+ } -+ } -+} -+ -+/* -+ * This function is used to shutdown the driver. -+ * -+ * The following operations are performed sequentially - -+ * - Check if already shut down -+ * - Make sure the main process has stopped -+ * - Clean up the Tx and Rx queues -+ * - Delete BSS priority tables -+ * - Free the adapter -+ * - Notify completion -+ */ -+int -+mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) -+{ -+ int ret = -EINPROGRESS; -+ struct mwifiex_private *priv = NULL; -+ s32 i = 0; -+ unsigned long flags; -+ -+ /* mwifiex already shutdown */ -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) -+ return 0; -+ -+ adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING; -+ /* wait for mwifiex_process to complete */ -+ if (adapter->mwifiex_processing) { -+ dev_warn(adapter->dev, "main process is still running\n"); -+ return ret; -+ } -+ -+ /* shut down mwifiex */ -+ dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); -+ -+ /* Clean up Tx/Rx queues and delete BSS priority table */ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ priv = adapter->priv[i]; -+ -+ mwifiex_clean_txrx(priv); -+ mwifiex_delete_bss_prio_tbl(priv); -+ } -+ } -+ -+ spin_lock_irqsave(&adapter->mwifiex_lock, flags); -+ -+ /* Free adapter structure */ -+ mwifiex_free_adapter(adapter); -+ -+ spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); -+ -+ /* Notify completion */ -+ ret = mwifiex_shutdown_fw_complete(adapter); -+ -+ return ret; -+} -+ -+/* -+ * This function downloads the firmware to the card. -+ * -+ * The actual download is preceded by two sanity checks - -+ * - Check if firmware is already running -+ * - Check if the interface is the winner to download the firmware -+ * -+ * ...and followed by another - -+ * - Check if the firmware is downloaded successfully -+ * -+ * After download is successfully completed, the host interrupts are enabled. -+ */ -+int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, -+ struct mwifiex_fw_image *pmfw) -+{ -+ int ret = 0; -+ u32 poll_num = 1; -+ int winner; -+ -+ /* Check if firmware is already running */ -+ ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); -+ if (!ret) { -+ dev_notice(adapter->dev, -+ "WLAN FW already running! Skip FW download\n"); -+ goto done; -+ } -+ poll_num = MAX_FIRMWARE_POLL_TRIES; -+ -+ /* Check if we are the winner for downloading FW */ -+ if (!winner) { -+ dev_notice(adapter->dev, -+ "Other interface already running!" -+ " Skip FW download\n"); -+ poll_num = MAX_MULTI_INTERFACE_POLL_TRIES; -+ goto poll_fw; -+ } -+ if (pmfw) { -+ /* Download firmware with helper */ -+ ret = adapter->if_ops.prog_fw(adapter, pmfw); -+ if (ret) { -+ dev_err(adapter->dev, "prog_fw failed ret=%#x\n", ret); -+ return ret; -+ } -+ } -+ -+poll_fw: -+ /* Check if the firmware is downloaded successfully or not */ -+ ret = adapter->if_ops.check_fw_status(adapter, poll_num, NULL); -+ if (ret) { -+ dev_err(adapter->dev, "FW failed to be active in time\n"); -+ return -1; -+ } -+done: -+ /* re-enable host interrupt for mwifiex after fw dnld is successful */ -+ adapter->if_ops.enable_int(adapter); -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/ioctl.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/ioctl.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/ioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/ioctl.h 2011-05-05 23:29:45.471441695 +0200 -@@ -0,0 +1,410 @@ -+/* -+ * Marvell Wireless LAN device driver: ioctl data structures & APIs -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_IOCTL_H_ -+#define _MWIFIEX_IOCTL_H_ -+ -+#include -+ -+enum { -+ MWIFIEX_SCAN_MODE_UNCHANGED = 0, -+ MWIFIEX_SCAN_MODE_BSS, -+ MWIFIEX_SCAN_MODE_IBSS, -+ MWIFIEX_SCAN_MODE_ANY -+}; -+ -+enum { -+ MWIFIEX_SCAN_TYPE_UNCHANGED = 0, -+ MWIFIEX_SCAN_TYPE_ACTIVE, -+ MWIFIEX_SCAN_TYPE_PASSIVE -+}; -+ -+struct mwifiex_get_scan_table_fixed { -+ u8 bssid[ETH_ALEN]; -+ u8 channel; -+ u8 rssi; -+ long long network_tsf; -+}; -+ -+struct mwifiex_scan_time_params { -+ u32 specific_scan_time; -+ u32 active_scan_time; -+ u32 passive_scan_time; -+}; -+ -+struct mwifiex_user_scan { -+ u32 scan_cfg_len; -+ u8 scan_cfg_buf[1]; -+}; -+ -+struct mwifiex_scan_req { -+ u32 scan_mode; -+ u32 scan_type; -+ struct mwifiex_802_11_ssid scan_ssid; -+ struct mwifiex_scan_time_params scan_time; -+ struct mwifiex_user_scan user_scan; -+}; -+ -+struct mwifiex_scan_resp { -+ u32 num_in_scan_table; -+ u8 *scan_table; -+}; -+ -+#define MWIFIEX_PROMISC_MODE 1 -+#define MWIFIEX_MULTICAST_MODE 2 -+#define MWIFIEX_ALL_MULTI_MODE 4 -+#define MWIFIEX_MAX_MULTICAST_LIST_SIZE 32 -+ -+struct mwifiex_multicast_list { -+ u32 mode; -+ u32 num_multicast_addr; -+ u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -+}; -+ -+#define MWIFIEX_MAX_CHANNEL_NUM 128 -+ -+struct mwifiex_chan_freq { -+ u32 channel; -+ u32 freq; -+}; -+ -+struct mwifiex_chan_list { -+ u32 num_of_chan; -+ struct mwifiex_chan_freq cf[MWIFIEX_MAX_CHANNEL_NUM]; -+}; -+ -+struct mwifiex_ssid_bssid { -+ struct mwifiex_802_11_ssid ssid; -+ u8 bssid[ETH_ALEN]; -+}; -+ -+enum { -+ BAND_B = 1, -+ BAND_G = 2, -+ BAND_A = 4, -+ BAND_GN = 8, -+ BAND_AN = 16, -+}; -+ -+#define NO_SEC_CHANNEL 0 -+#define SEC_CHANNEL_ABOVE 1 -+#define SEC_CHANNEL_BELOW 3 -+ -+struct mwifiex_ds_band_cfg { -+ u32 config_bands; -+ u32 adhoc_start_band; -+ u32 adhoc_channel; -+ u32 sec_chan_offset; -+}; -+ -+enum { -+ ADHOC_IDLE, -+ ADHOC_STARTED, -+ ADHOC_JOINED, -+ ADHOC_COALESCED -+}; -+ -+struct mwifiex_ds_get_stats { -+ u32 mcast_tx_frame; -+ u32 failed; -+ u32 retry; -+ u32 multi_retry; -+ u32 frame_dup; -+ u32 rts_success; -+ u32 rts_failure; -+ u32 ack_failure; -+ u32 rx_frag; -+ u32 mcast_rx_frame; -+ u32 fcs_error; -+ u32 tx_frame; -+ u32 wep_icv_error[4]; -+}; -+ -+#define BCN_RSSI_LAST_MASK 0x00000001 -+#define BCN_RSSI_AVG_MASK 0x00000002 -+#define DATA_RSSI_LAST_MASK 0x00000004 -+#define DATA_RSSI_AVG_MASK 0x00000008 -+#define BCN_SNR_LAST_MASK 0x00000010 -+#define BCN_SNR_AVG_MASK 0x00000020 -+#define DATA_SNR_LAST_MASK 0x00000040 -+#define DATA_SNR_AVG_MASK 0x00000080 -+#define BCN_NF_LAST_MASK 0x00000100 -+#define BCN_NF_AVG_MASK 0x00000200 -+#define DATA_NF_LAST_MASK 0x00000400 -+#define DATA_NF_AVG_MASK 0x00000800 -+#define ALL_RSSI_INFO_MASK 0x00000fff -+ -+struct mwifiex_ds_get_signal { -+ /* -+ * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI, -+ * Bit2: Last Data RSSI, Bit3: Average Data RSSI, -+ * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR, -+ * Bit6: Last Data SNR, Bit7: Average Data SNR, -+ * Bit8: Last Beacon NF, Bit9: Average Beacon NF, -+ * Bit10: Last Data NF, Bit11: Average Data NF -+ */ -+ u16 selector; -+ s16 bcn_rssi_last; -+ s16 bcn_rssi_avg; -+ s16 data_rssi_last; -+ s16 data_rssi_avg; -+ s16 bcn_snr_last; -+ s16 bcn_snr_avg; -+ s16 data_snr_last; -+ s16 data_snr_avg; -+ s16 bcn_nf_last; -+ s16 bcn_nf_avg; -+ s16 data_nf_last; -+ s16 data_nf_avg; -+}; -+ -+struct mwifiex_fw_info { -+ u32 fw_ver; -+ u8 mac_addr[ETH_ALEN]; -+}; -+ -+#define MWIFIEX_MAX_VER_STR_LEN 128 -+ -+struct mwifiex_ver_ext { -+ u32 version_str_sel; -+ char version_str[MWIFIEX_MAX_VER_STR_LEN]; -+}; -+ -+struct mwifiex_bss_info { -+ u32 bss_mode; -+ struct mwifiex_802_11_ssid ssid; -+ u32 scan_table_idx; -+ u32 bss_chan; -+ u32 region_code; -+ u32 media_connected; -+ u32 max_power_level; -+ u32 min_power_level; -+ u32 adhoc_state; -+ signed int bcn_nf_last; -+ u32 wep_status; -+ u32 is_hs_configured; -+ u32 is_deep_sleep; -+ u8 bssid[ETH_ALEN]; -+}; -+ -+#define MAX_NUM_TID 8 -+ -+#define MAX_RX_WINSIZE 64 -+ -+struct mwifiex_ds_rx_reorder_tbl { -+ u16 tid; -+ u8 ta[ETH_ALEN]; -+ u32 start_win; -+ u32 win_size; -+ u32 buffer[MAX_RX_WINSIZE]; -+}; -+ -+struct mwifiex_ds_tx_ba_stream_tbl { -+ u16 tid; -+ u8 ra[ETH_ALEN]; -+}; -+ -+#define DBG_CMD_NUM 5 -+ -+struct mwifiex_debug_info { -+ u32 int_counter; -+ u32 packets_out[MAX_NUM_TID]; -+ u32 max_tx_buf_size; -+ u32 tx_buf_size; -+ u32 curr_tx_buf_size; -+ u32 tx_tbl_num; -+ struct mwifiex_ds_tx_ba_stream_tbl -+ tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED]; -+ u32 rx_tbl_num; -+ struct mwifiex_ds_rx_reorder_tbl rx_tbl -+ [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED]; -+ u16 ps_mode; -+ u32 ps_state; -+ u8 is_deep_sleep; -+ u8 pm_wakeup_card_req; -+ u32 pm_wakeup_fw_try; -+ u8 is_hs_configured; -+ u8 hs_activated; -+ u32 num_cmd_host_to_card_failure; -+ u32 num_cmd_sleep_cfm_host_to_card_failure; -+ u32 num_tx_host_to_card_failure; -+ u32 num_event_deauth; -+ u32 num_event_disassoc; -+ u32 num_event_link_lost; -+ u32 num_cmd_deauth; -+ u32 num_cmd_assoc_success; -+ u32 num_cmd_assoc_failure; -+ u32 num_tx_timeout; -+ u32 num_cmd_timeout; -+ u16 timeout_cmd_id; -+ u16 timeout_cmd_act; -+ u16 last_cmd_id[DBG_CMD_NUM]; -+ u16 last_cmd_act[DBG_CMD_NUM]; -+ u16 last_cmd_index; -+ u16 last_cmd_resp_id[DBG_CMD_NUM]; -+ u16 last_cmd_resp_index; -+ u16 last_event[DBG_CMD_NUM]; -+ u16 last_event_index; -+ u8 data_sent; -+ u8 cmd_sent; -+ u8 cmd_resp_received; -+ u8 event_received; -+}; -+ -+#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 -+#define WAPI_RXPN_LEN 16 -+ -+struct mwifiex_ds_encrypt_key { -+ u32 key_disable; -+ u32 key_index; -+ u32 key_len; -+ u8 key_material[WLAN_MAX_KEY_LEN]; -+ u8 mac_addr[ETH_ALEN]; -+ u32 is_wapi_key; -+ u8 wapi_rxpn[WAPI_RXPN_LEN]; -+}; -+ -+struct mwifiex_rate_cfg { -+ u32 action; -+ u32 is_rate_auto; -+ u32 rate; -+}; -+ -+struct mwifiex_data_rate { -+ u32 tx_data_rate; -+ u32 rx_data_rate; -+}; -+ -+struct mwifiex_power_cfg { -+ u32 is_power_auto; -+ u32 power_level; -+}; -+ -+struct mwifiex_ds_hs_cfg { -+ u32 is_invoke_hostcmd; -+ /* Bit0: non-unicast data -+ * Bit1: unicast data -+ * Bit2: mac events -+ * Bit3: magic packet -+ */ -+ u32 conditions; -+ u32 gpio; -+ u32 gap; -+}; -+ -+#define DEEP_SLEEP_ON 1 -+#define DEEP_SLEEP_OFF 0 -+ -+#define DEEP_SLEEP_IDLE_TIME 100 -+ -+struct mwifiex_ds_auto_ds { -+ u16 auto_ds; -+ u16 idle_time; -+}; -+ -+#define PS_MODE_UNCHANGED 0 -+#define PS_MODE_AUTO 1 -+#define PS_MODE_POLL 2 -+#define PS_MODE_NULL 3 -+ -+ -+struct mwifiex_ds_pm_cfg { -+ union { -+ u32 ps_mode; -+ struct mwifiex_ds_hs_cfg hs_cfg; -+ struct mwifiex_ds_auto_ds auto_deep_sleep; -+ u32 sleep_period; -+ } param; -+}; -+ -+struct mwifiex_ioctl_wmm_queue_status_ac { -+ u8 wmm_acm; -+ u8 flow_required; -+ u8 flow_created; -+ u8 disabled; -+}; -+ -+struct mwifiex_ds_wmm_queue_status { -+ struct mwifiex_ioctl_wmm_queue_status_ac -+ ac_status[IEEE80211_MAX_QUEUES]; -+}; -+ -+struct mwifiex_ds_11n_tx_cfg { -+ u16 tx_htcap; -+ u16 tx_htinfo; -+}; -+ -+struct mwifiex_ds_11n_amsdu_aggr_ctrl { -+ u16 enable; -+ u16 curr_buf_size; -+}; -+ -+#define MWIFIEX_NUM_OF_CMD_BUFFER 20 -+#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 -+ -+enum { -+ MWIFIEX_IE_TYPE_GEN_IE = 0, -+ MWIFIEX_IE_TYPE_ARP_FILTER, -+}; -+ -+enum { -+ MWIFIEX_REG_MAC = 1, -+ MWIFIEX_REG_BBP, -+ MWIFIEX_REG_RF, -+ MWIFIEX_REG_PMIC, -+ MWIFIEX_REG_CAU, -+}; -+ -+struct mwifiex_ds_reg_rw { -+ __le32 type; -+ __le32 offset; -+ __le32 value; -+}; -+ -+#define MAX_EEPROM_DATA 256 -+ -+struct mwifiex_ds_read_eeprom { -+ __le16 offset; -+ __le16 byte_count; -+ u8 value[MAX_EEPROM_DATA]; -+}; -+ -+struct mwifiex_ds_misc_gen_ie { -+ u32 type; -+ u32 len; -+ u8 ie_data[IW_CUSTOM_MAX]; -+}; -+ -+struct mwifiex_ds_misc_cmd { -+ u32 len; -+ u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; -+}; -+ -+#define MWIFIEX_MAX_VSIE_LEN (256) -+#define MWIFIEX_MAX_VSIE_NUM (8) -+#define MWIFIEX_VSIE_MASK_SCAN 0x01 -+#define MWIFIEX_VSIE_MASK_ASSOC 0x02 -+#define MWIFIEX_VSIE_MASK_ADHOC 0x04 -+ -+enum { -+ MWIFIEX_FUNC_INIT = 1, -+ MWIFIEX_FUNC_SHUTDOWN, -+}; -+ -+#endif /* !_MWIFIEX_IOCTL_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/join.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/join.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/join.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/join.c 2011-05-05 23:29:45.491441937 +0200 -@@ -0,0 +1,1424 @@ -+/* -+ * Marvell Wireless LAN device driver: association and ad-hoc start/join -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) -+ -+/* -+ * Append a generic IE as a pass through TLV to a TLV buffer. -+ * -+ * This function is called from the network join command preparation routine. -+ * -+ * If the IE buffer has been setup by the application, this routine appends -+ * the buffer as a pass through TLV type to the request. -+ */ -+static int -+mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) -+{ -+ int ret_len = 0; -+ struct mwifiex_ie_types_header ie_header; -+ -+ /* Null Checks */ -+ if (!buffer) -+ return 0; -+ if (!(*buffer)) -+ return 0; -+ -+ /* -+ * If there is a generic ie buffer setup, append it to the return -+ * parameter buffer pointer. -+ */ -+ if (priv->gen_ie_buf_len) { -+ dev_dbg(priv->adapter->dev, "info: %s: append generic %d to %p\n", -+ __func__, priv->gen_ie_buf_len, *buffer); -+ -+ /* Wrap the generic IE buffer with a pass through TLV type */ -+ ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); -+ ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); -+ memcpy(*buffer, &ie_header, sizeof(ie_header)); -+ -+ /* Increment the return size and the return buffer pointer -+ param */ -+ *buffer += sizeof(ie_header); -+ ret_len += sizeof(ie_header); -+ -+ /* Copy the generic IE buffer to the output buffer, advance -+ pointer */ -+ memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); -+ -+ /* Increment the return size and the return buffer pointer -+ param */ -+ *buffer += priv->gen_ie_buf_len; -+ ret_len += priv->gen_ie_buf_len; -+ -+ /* Reset the generic IE buffer */ -+ priv->gen_ie_buf_len = 0; -+ } -+ -+ /* return the length appended to the buffer */ -+ return ret_len; -+} -+ -+/* -+ * Append TSF tracking info from the scan table for the target AP. -+ * -+ * This function is called from the network join command preparation routine. -+ * -+ * The TSF table TSF sent to the firmware contains two TSF values: -+ * - The TSF of the target AP from its previous beacon/probe response -+ * - The TSF timestamp of our local MAC at the time we observed the -+ * beacon/probe response. -+ * -+ * The firmware uses the timestamp values to set an initial TSF value -+ * in the MAC for the new association after a reassociation attempt. -+ */ -+static int -+mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ struct mwifiex_ie_types_tsf_timestamp tsf_tlv; -+ __le64 tsf_val; -+ -+ /* Null Checks */ -+ if (buffer == NULL) -+ return 0; -+ if (*buffer == NULL) -+ return 0; -+ -+ memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); -+ -+ tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); -+ tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); -+ -+ memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); -+ *buffer += sizeof(tsf_tlv.header); -+ -+ /* TSF at the time when beacon/probe_response was received */ -+ tsf_val = cpu_to_le64(bss_desc->network_tsf); -+ memcpy(*buffer, &tsf_val, sizeof(tsf_val)); -+ *buffer += sizeof(tsf_val); -+ -+ memcpy(&tsf_val, bss_desc->time_stamp, sizeof(tsf_val)); -+ -+ dev_dbg(priv->adapter->dev, "info: %s: TSF offset calc: %016llx - " -+ "%016llx\n", __func__, tsf_val, bss_desc->network_tsf); -+ -+ memcpy(*buffer, &tsf_val, sizeof(tsf_val)); -+ *buffer += sizeof(tsf_val); -+ -+ return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); -+} -+ -+/* -+ * This function finds out the common rates between rate1 and rate2. -+ * -+ * It will fill common rates in rate1 as output if found. -+ * -+ * NOTE: Setting the MSB of the basic rates needs to be taken -+ * care of, either before or after calling this function. -+ */ -+static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, -+ u32 rate1_size, u8 *rate2, u32 rate2_size) -+{ -+ int ret = 0; -+ u8 *ptr = rate1; -+ u8 *tmp = NULL; -+ u32 i, j; -+ -+ tmp = kmalloc(rate1_size, GFP_KERNEL); -+ if (!tmp) { -+ dev_err(priv->adapter->dev, "failed to alloc tmp buf\n"); -+ return -ENOMEM; -+ } -+ -+ memcpy(tmp, rate1, rate1_size); -+ memset(rate1, 0, rate1_size); -+ -+ for (i = 0; rate2[i] && i < rate2_size; i++) { -+ for (j = 0; tmp[j] && j < rate1_size; j++) { -+ /* Check common rate, excluding the bit for -+ basic rate */ -+ if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { -+ *rate1++ = tmp[j]; -+ break; -+ } -+ } -+ } -+ -+ dev_dbg(priv->adapter->dev, "info: Tx data rate set to %#x\n", -+ priv->data_rate); -+ -+ if (!priv->is_data_rate_auto) { -+ while (*ptr) { -+ if ((*ptr & 0x7f) == priv->data_rate) { -+ ret = 0; -+ goto done; -+ } -+ ptr++; -+ } -+ dev_err(priv->adapter->dev, "previously set fixed data rate %#x" -+ " is not compatible with the network\n", -+ priv->data_rate); -+ -+ ret = -1; -+ goto done; -+ } -+ -+ ret = 0; -+done: -+ kfree(tmp); -+ return ret; -+} -+ -+/* -+ * This function creates the intersection of the rates supported by a -+ * target BSS and our adapter settings for use in an assoc/join command. -+ */ -+static int -+mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc, -+ u8 *out_rates, u32 *out_rates_size) -+{ -+ u8 card_rates[MWIFIEX_SUPPORTED_RATES]; -+ u32 card_rates_size = 0; -+ -+ /* Copy AP supported rates */ -+ memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); -+ /* Get the STA supported rates */ -+ card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); -+ /* Get the common rates between AP and STA supported rates */ -+ if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, -+ card_rates, card_rates_size)) { -+ *out_rates_size = 0; -+ dev_err(priv->adapter->dev, "%s: cannot get common rates\n", -+ __func__); -+ return -1; -+ } -+ -+ *out_rates_size = -+ min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); -+ -+ return 0; -+} -+ -+/* -+ * This function updates the scan entry TSF timestamps to reflect -+ * a new association. -+ */ -+static void -+mwifiex_update_tsf_timestamps(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *new_bss_desc) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u32 table_idx; -+ long long new_tsf_base; -+ signed long long tsf_delta; -+ -+ memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base)); -+ -+ tsf_delta = new_tsf_base - new_bss_desc->network_tsf; -+ -+ dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, " -+ "0x%016llx -> 0x%016llx\n", -+ new_bss_desc->network_tsf, new_tsf_base); -+ -+ for (table_idx = 0; table_idx < adapter->num_in_scan_table; -+ table_idx++) -+ adapter->scan_table[table_idx].network_tsf += tsf_delta; -+} -+ -+/* -+ * This function appends a WAPI IE. -+ * -+ * This function is called from the network join command preparation routine. -+ * -+ * If the IE buffer has been setup by the application, this routine appends -+ * the buffer as a WAPI TLV type to the request. -+ */ -+static int -+mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) -+{ -+ int retLen = 0; -+ struct mwifiex_ie_types_header ie_header; -+ -+ /* Null Checks */ -+ if (buffer == NULL) -+ return 0; -+ if (*buffer == NULL) -+ return 0; -+ -+ /* -+ * If there is a wapi ie buffer setup, append it to the return -+ * parameter buffer pointer. -+ */ -+ if (priv->wapi_ie_len) { -+ dev_dbg(priv->adapter->dev, "cmd: append wapi ie %d to %p\n", -+ priv->wapi_ie_len, *buffer); -+ -+ /* Wrap the generic IE buffer with a pass through TLV type */ -+ ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); -+ ie_header.len = cpu_to_le16(priv->wapi_ie_len); -+ memcpy(*buffer, &ie_header, sizeof(ie_header)); -+ -+ /* Increment the return size and the return buffer pointer -+ param */ -+ *buffer += sizeof(ie_header); -+ retLen += sizeof(ie_header); -+ -+ /* Copy the wapi IE buffer to the output buffer, advance -+ pointer */ -+ memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); -+ -+ /* Increment the return size and the return buffer pointer -+ param */ -+ *buffer += priv->wapi_ie_len; -+ retLen += priv->wapi_ie_len; -+ -+ } -+ /* return the length appended to the buffer */ -+ return retLen; -+} -+ -+/* -+ * This function appends rsn ie tlv for wpa/wpa2 security modes. -+ * It is called from the network join command preparation routine. -+ */ -+static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, -+ u8 **buffer) -+{ -+ struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; -+ int rsn_ie_len; -+ -+ if (!buffer || !(*buffer)) -+ return 0; -+ -+ rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); -+ rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); -+ rsn_ie_tlv->header.type = cpu_to_le16( -+ le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); -+ rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); -+ rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) -+ & 0x00FF); -+ if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) -+ memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], -+ le16_to_cpu(rsn_ie_tlv->header.len)); -+ else -+ return -1; -+ -+ rsn_ie_len = sizeof(rsn_ie_tlv->header) + -+ le16_to_cpu(rsn_ie_tlv->header.len); -+ *buffer += rsn_ie_len; -+ -+ return rsn_ie_len; -+} -+ -+/* -+ * This function prepares command for association. -+ * -+ * This sets the following parameters - -+ * - Peer MAC address -+ * - Listen interval -+ * - Beacon interval -+ * - Capability information -+ * -+ * ...and the following TLVs, as required - -+ * - SSID TLV -+ * - PHY TLV -+ * - SS TLV -+ * - Rates TLV -+ * - Authentication TLV -+ * - Channel TLV -+ * - WPA/WPA2 IE -+ * - 11n TLV -+ * - Vendor specific TLV -+ * - WMM TLV -+ * - WAPI IE -+ * - Generic IE -+ * - TSF TLV -+ * -+ * Preparation also includes - -+ * - Setting command ID and proper size -+ * - Ensuring correct endian-ness -+ */ -+int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; -+ struct mwifiex_bssdescriptor *bss_desc; -+ struct mwifiex_ie_types_ssid_param_set *ssid_tlv; -+ struct mwifiex_ie_types_phy_param_set *phy_tlv; -+ struct mwifiex_ie_types_ss_param_set *ss_tlv; -+ struct mwifiex_ie_types_rates_param_set *rates_tlv; -+ struct mwifiex_ie_types_auth_type *auth_tlv; -+ struct mwifiex_ie_types_chan_list_param_set *chan_tlv; -+ u8 rates[MWIFIEX_SUPPORTED_RATES]; -+ u32 rates_size; -+ u16 tmp_cap; -+ u8 *pos; -+ int rsn_ie_len = 0; -+ -+ bss_desc = (struct mwifiex_bssdescriptor *) data_buf; -+ pos = (u8 *) assoc; -+ -+ mwifiex_cfg_tx_buf(priv, bss_desc); -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); -+ -+ /* Save so we know which BSS Desc to use in the response handler */ -+ priv->attempted_bss_desc = bss_desc; -+ -+ memcpy(assoc->peer_sta_addr, -+ bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); -+ pos += sizeof(assoc->peer_sta_addr); -+ -+ /* Set the listen interval */ -+ assoc->listen_interval = cpu_to_le16(priv->listen_interval); -+ /* Set the beacon period */ -+ assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); -+ -+ pos += sizeof(assoc->cap_info_bitmap); -+ pos += sizeof(assoc->listen_interval); -+ pos += sizeof(assoc->beacon_period); -+ pos += sizeof(assoc->dtim_period); -+ -+ ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; -+ ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); -+ ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); -+ memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, -+ le16_to_cpu(ssid_tlv->header.len)); -+ pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); -+ -+ phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; -+ phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); -+ phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); -+ memcpy(&phy_tlv->fh_ds.ds_param_set, -+ &bss_desc->phy_param_set.ds_param_set.current_chan, -+ sizeof(phy_tlv->fh_ds.ds_param_set)); -+ pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); -+ -+ ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; -+ ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); -+ ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); -+ pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); -+ -+ /* Get the common rates supported between the driver and the BSS Desc */ -+ if (mwifiex_setup_rates_from_bssdesc -+ (priv, bss_desc, rates, &rates_size)) -+ return -1; -+ -+ /* Save the data rates into Current BSS state structure */ -+ priv->curr_bss_params.num_of_rates = rates_size; -+ memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); -+ -+ /* Setup the Rates TLV in the association command */ -+ rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; -+ rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); -+ rates_tlv->header.len = cpu_to_le16((u16) rates_size); -+ memcpy(rates_tlv->rates, rates, rates_size); -+ pos += sizeof(rates_tlv->header) + rates_size; -+ dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: rates size = %d\n", -+ rates_size); -+ -+ /* Add the Authentication type to be used for Auth frames */ -+ auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; -+ auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); -+ auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) -+ auth_tlv->auth_type = cpu_to_le16( -+ (u16) priv->sec_info.authentication_mode); -+ else -+ auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); -+ -+ pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); -+ -+ if (IS_SUPPORT_MULTI_BANDS(priv->adapter) -+ && !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) -+ && (!bss_desc->disable_11n) -+ && (priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN) -+ && (bss_desc->bcn_ht_cap) -+ ) -+ ) { -+ /* Append a channel TLV for the channel the attempted AP was -+ found on */ -+ chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; -+ chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); -+ chan_tlv->header.len = -+ cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); -+ -+ memset(chan_tlv->chan_scan_param, 0x00, -+ sizeof(struct mwifiex_chan_scan_param_set)); -+ chan_tlv->chan_scan_param[0].chan_number = -+ (bss_desc->phy_param_set.ds_param_set.current_chan); -+ dev_dbg(priv->adapter->dev, "info: Assoc: TLV Chan = %d\n", -+ chan_tlv->chan_scan_param[0].chan_number); -+ -+ chan_tlv->chan_scan_param[0].radio_type = -+ mwifiex_band_to_radio_type((u8) bss_desc->bss_band); -+ -+ dev_dbg(priv->adapter->dev, "info: Assoc: TLV Band = %d\n", -+ chan_tlv->chan_scan_param[0].radio_type); -+ pos += sizeof(chan_tlv->header) + -+ sizeof(struct mwifiex_chan_scan_param_set); -+ } -+ -+ if (!priv->wps.session_enable) { -+ if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) -+ rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); -+ -+ if (rsn_ie_len == -1) -+ return -1; -+ } -+ -+ if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) -+ && (!bss_desc->disable_11n) -+ && (priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN)) -+ mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); -+ -+ /* Append vendor specific IE TLV */ -+ mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); -+ -+ mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, -+ bss_desc->bcn_ht_cap); -+ if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) -+ mwifiex_cmd_append_wapi_ie(priv, &pos); -+ -+ -+ mwifiex_cmd_append_generic_ie(priv, &pos); -+ -+ mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); -+ -+ cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); -+ -+ /* Set the Capability info at last */ -+ tmp_cap = bss_desc->cap_info_bitmap; -+ -+ if (priv->adapter->config_bands == BAND_B) -+ tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; -+ -+ tmp_cap &= CAPINFO_MASK; -+ dev_dbg(priv->adapter->dev, "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", -+ tmp_cap, CAPINFO_MASK); -+ assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); -+ -+ return 0; -+} -+ -+/* -+ * Association firmware command response handler -+ * -+ * The response buffer for the association command has the following -+ * memory layout. -+ * -+ * For cases where an association response was not received (indicated -+ * by the CapInfo and AId field): -+ * -+ * .------------------------------------------------------------. -+ * | Header(4 * sizeof(t_u16)): Standard command response hdr | -+ * .------------------------------------------------------------. -+ * | cap_info/Error Return(t_u16): | -+ * | 0xFFFF(-1): Internal error | -+ * | 0xFFFE(-2): Authentication unhandled message | -+ * | 0xFFFD(-3): Authentication refused | -+ * | 0xFFFC(-4): Timeout waiting for AP response | -+ * .------------------------------------------------------------. -+ * | status_code(t_u16): | -+ * | If cap_info is -1: | -+ * | An internal firmware failure prevented the | -+ * | command from being processed. The status_code | -+ * | will be set to 1. | -+ * | | -+ * | If cap_info is -2: | -+ * | An authentication frame was received but was | -+ * | not handled by the firmware. IEEE Status | -+ * | code for the failure is returned. | -+ * | | -+ * | If cap_info is -3: | -+ * | An authentication frame was received and the | -+ * | status_code is the IEEE Status reported in the | -+ * | response. | -+ * | | -+ * | If cap_info is -4: | -+ * | (1) Association response timeout | -+ * | (2) Authentication response timeout | -+ * .------------------------------------------------------------. -+ * | a_id(t_u16): 0xFFFF | -+ * .------------------------------------------------------------. -+ * -+ * -+ * For cases where an association response was received, the IEEE -+ * standard association response frame is returned: -+ * -+ * .------------------------------------------------------------. -+ * | Header(4 * sizeof(t_u16)): Standard command response hdr | -+ * .------------------------------------------------------------. -+ * | cap_info(t_u16): IEEE Capability | -+ * .------------------------------------------------------------. -+ * | status_code(t_u16): IEEE Status Code | -+ * .------------------------------------------------------------. -+ * | a_id(t_u16): IEEE Association ID | -+ * .------------------------------------------------------------. -+ * | IEEE IEs(variable): Any received IEs comprising the | -+ * | remaining portion of a received | -+ * | association response frame. | -+ * .------------------------------------------------------------. -+ * -+ * For simplistic handling, the status_code field can be used to determine -+ * an association success (0) or failure (non-zero). -+ */ -+int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int ret = 0; -+ struct ieee_types_assoc_rsp *assoc_rsp; -+ struct mwifiex_bssdescriptor *bss_desc; -+ u8 enable_data = true; -+ -+ assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; -+ -+ priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, -+ sizeof(priv->assoc_rsp_buf)); -+ -+ memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); -+ -+ if (le16_to_cpu(assoc_rsp->status_code)) { -+ priv->adapter->dbg.num_cmd_assoc_failure++; -+ dev_err(priv->adapter->dev, "ASSOC_RESP: association failed, " -+ "status code = %d, error = 0x%x, a_id = 0x%x\n", -+ le16_to_cpu(assoc_rsp->status_code), -+ le16_to_cpu(assoc_rsp->cap_info_bitmap), -+ le16_to_cpu(assoc_rsp->a_id)); -+ -+ ret = -1; -+ goto done; -+ } -+ -+ /* Send a Media Connected event, according to the Spec */ -+ priv->media_connected = true; -+ -+ priv->adapter->ps_state = PS_STATE_AWAKE; -+ priv->adapter->pps_uapsd_mode = false; -+ priv->adapter->tx_lock_flag = false; -+ -+ /* Set the attempted BSSID Index to current */ -+ bss_desc = priv->attempted_bss_desc; -+ -+ dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n", -+ bss_desc->ssid.ssid); -+ -+ /* Make a copy of current BSSID descriptor */ -+ memcpy(&priv->curr_bss_params.bss_descriptor, -+ bss_desc, sizeof(struct mwifiex_bssdescriptor)); -+ -+ /* Update curr_bss_params */ -+ priv->curr_bss_params.bss_descriptor.channel -+ = bss_desc->phy_param_set.ds_param_set.current_chan; -+ -+ priv->curr_bss_params.band = (u8) bss_desc->bss_band; -+ -+ /* -+ * Adjust the timestamps in the scan table to be relative to the newly -+ * associated AP's TSF -+ */ -+ mwifiex_update_tsf_timestamps(priv, bss_desc); -+ -+ if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) -+ priv->curr_bss_params.wmm_enabled = true; -+ else -+ priv->curr_bss_params.wmm_enabled = false; -+ -+ if ((priv->wmm_required || bss_desc->bcn_ht_cap) -+ && priv->curr_bss_params.wmm_enabled) -+ priv->wmm_enabled = true; -+ else -+ priv->wmm_enabled = false; -+ -+ priv->curr_bss_params.wmm_uapsd_enabled = false; -+ -+ if (priv->wmm_enabled) -+ priv->curr_bss_params.wmm_uapsd_enabled -+ = ((bss_desc->wmm_ie.qos_info_bitmap & -+ IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); -+ -+ dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", -+ priv->curr_pkt_filter); -+ if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) -+ priv->wpa_is_gtk_set = false; -+ -+ if (priv->wmm_enabled) { -+ /* Don't re-enable carrier until we get the WMM_GET_STATUS -+ event */ -+ enable_data = false; -+ } else { -+ /* Since WMM is not enabled, setup the queues with the -+ defaults */ -+ mwifiex_wmm_setup_queue_priorities(priv, NULL); -+ mwifiex_wmm_setup_ac_downgrade(priv); -+ } -+ -+ if (enable_data) -+ dev_dbg(priv->adapter->dev, -+ "info: post association, re-enabling data flow\n"); -+ -+ /* Reset SNR/NF/RSSI values */ -+ priv->data_rssi_last = 0; -+ priv->data_nf_last = 0; -+ priv->data_rssi_avg = 0; -+ priv->data_nf_avg = 0; -+ priv->bcn_rssi_last = 0; -+ priv->bcn_nf_last = 0; -+ priv->bcn_rssi_avg = 0; -+ priv->bcn_nf_avg = 0; -+ priv->rxpd_rate = 0; -+ priv->rxpd_htinfo = 0; -+ -+ mwifiex_save_curr_bcn(priv); -+ -+ priv->adapter->dbg.num_cmd_assoc_success++; -+ -+ dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n"); -+ -+ /* Add the ra_list here for infra mode as there will be only 1 ra -+ always */ -+ mwifiex_ralist_add(priv, -+ priv->curr_bss_params.bss_descriptor.mac_address); -+ -+ if (!netif_carrier_ok(priv->netdev)) -+ netif_carrier_on(priv->netdev); -+ if (netif_queue_stopped(priv->netdev)) -+ netif_wake_queue(priv->netdev); -+ -+ if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) -+ priv->scan_block = true; -+ -+done: -+ /* Need to indicate IOCTL complete */ -+ if (adapter->curr_cmd->wait_q_enabled) { -+ if (ret) -+ adapter->cmd_wait_q.status = -1; -+ else -+ adapter->cmd_wait_q.status = 0; -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function prepares command for ad-hoc start. -+ * -+ * Driver will fill up SSID, BSS mode, IBSS parameters, physical -+ * parameters, probe delay, and capability information. Firmware -+ * will fill up beacon period, basic rates and operational rates. -+ * -+ * In addition, the following TLVs are added - -+ * - Channel TLV -+ * - Vendor specific IE -+ * - WPA/WPA2 IE -+ * - HT Capabilities IE -+ * - HT Information IE -+ * -+ * Preparation also includes - -+ * - Setting command ID and proper size -+ * - Ensuring correct endian-ness -+ */ -+int -+mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, void *data_buf) -+{ -+ 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; -+ struct mwifiex_bssdescriptor *bss_desc; -+ u32 cmd_append_size = 0; -+ u32 i; -+ u16 tmp_cap; -+ uint16_t ht_cap_info; -+ struct mwifiex_ie_types_chan_list_param_set *chan_tlv; -+ -+ struct mwifiex_ie_types_htcap *ht_cap; -+ struct mwifiex_ie_types_htinfo *ht_info; -+ u8 *pos = (u8 *) adhoc_start + -+ sizeof(struct host_cmd_ds_802_11_ad_hoc_start); -+ -+ if (!adapter) -+ return -1; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); -+ -+ bss_desc = &priv->curr_bss_params.bss_descriptor; -+ priv->attempted_bss_desc = bss_desc; -+ -+ /* -+ * Fill in the parameters for 2 data structures: -+ * 1. struct host_cmd_ds_802_11_ad_hoc_start command -+ * 2. bss_desc -+ * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, -+ * probe delay, and Cap info. -+ * Firmware will fill up beacon period, Basic rates -+ * and operational rates. -+ */ -+ -+ memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); -+ -+ memcpy(adhoc_start->ssid, -+ ((struct mwifiex_802_11_ssid *) data_buf)->ssid, -+ ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); -+ -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n", -+ adhoc_start->ssid); -+ -+ memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); -+ memcpy(bss_desc->ssid.ssid, -+ ((struct mwifiex_802_11_ssid *) data_buf)->ssid, -+ ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); -+ -+ bss_desc->ssid.ssid_len = -+ ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len; -+ -+ /* Set the BSS mode */ -+ adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; -+ bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; -+ adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); -+ bss_desc->beacon_period = priv->beacon_period; -+ -+ /* Set Physical param set */ -+/* Parameter IE Id */ -+#define DS_PARA_IE_ID 3 -+/* Parameter IE length */ -+#define DS_PARA_IE_LEN 1 -+ -+ adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; -+ adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; -+ -+ if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, adapter->adhoc_start_band, (u16) -+ priv->adhoc_channel)) { -+ struct mwifiex_chan_freq_power *cfp; -+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, -+ adapter->adhoc_start_band, FIRST_VALID_CHANNEL); -+ if (cfp) -+ priv->adhoc_channel = (u8) cfp->channel; -+ } -+ -+ if (!priv->adhoc_channel) { -+ dev_err(adapter->dev, "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); -+ return -1; -+ } -+ -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", -+ priv->adhoc_channel); -+ -+ priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; -+ priv->curr_bss_params.band = adapter->adhoc_start_band; -+ -+ bss_desc->channel = priv->adhoc_channel; -+ adhoc_start->phy_param_set.ds_param_set.current_chan = -+ priv->adhoc_channel; -+ -+ memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, -+ sizeof(union ieee_types_phy_param_set)); -+ -+ /* Set IBSS param set */ -+/* IBSS parameter IE Id */ -+#define IBSS_PARA_IE_ID 6 -+/* IBSS parameter IE length */ -+#define IBSS_PARA_IE_LEN 2 -+ -+ adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; -+ adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; -+ adhoc_start->ss_param_set.ibss_param_set.atim_window -+ = cpu_to_le16(priv->atim_window); -+ memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, -+ sizeof(union ieee_types_ss_param_set)); -+ -+ /* Set Capability info */ -+ bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; -+ tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap); -+ tmp_cap &= ~WLAN_CAPABILITY_ESS; -+ tmp_cap |= WLAN_CAPABILITY_IBSS; -+ -+ /* Set up privacy in bss_desc */ -+ if (priv->sec_info.encryption_mode) { -+ /* Ad-Hoc capability privacy on */ -+ dev_dbg(adapter->dev, -+ "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); -+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; -+ tmp_cap |= WLAN_CAPABILITY_PRIVACY; -+ } else { -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: wep_status NOT set," -+ " setting privacy to ACCEPT ALL\n"); -+ bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; -+ } -+ -+ memset(adhoc_start->DataRate, 0, sizeof(adhoc_start->DataRate)); -+ 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)) { -+ 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; -+ } -+ } -+ /* Find the last non zero */ -+ for (i = 0; i < sizeof(adhoc_start->DataRate) && -+ adhoc_start->DataRate[i]; -+ i++) -+ ; -+ -+ priv->curr_bss_params.num_of_rates = i; -+ -+ /* Copy the ad-hoc creating rates into Current BSS rate structure */ -+ memcpy(&priv->curr_bss_params.data_rates, -+ &adhoc_start->DataRate, priv->curr_bss_params.num_of_rates); -+ -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%02x %02x %02x %02x\n", -+ adhoc_start->DataRate[0], adhoc_start->DataRate[1], -+ adhoc_start->DataRate[2], adhoc_start->DataRate[3]); -+ -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); -+ -+ if (IS_SUPPORT_MULTI_BANDS(adapter)) { -+ /* Append a channel TLV */ -+ chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; -+ chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); -+ chan_tlv->header.len = -+ cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); -+ -+ memset(chan_tlv->chan_scan_param, 0x00, -+ sizeof(struct mwifiex_chan_scan_param_set)); -+ chan_tlv->chan_scan_param[0].chan_number = -+ (u8) priv->curr_bss_params.bss_descriptor.channel; -+ -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Chan = %d\n", -+ chan_tlv->chan_scan_param[0].chan_number); -+ -+ chan_tlv->chan_scan_param[0].radio_type -+ = mwifiex_band_to_radio_type(priv->curr_bss_params.band); -+ if (adapter->adhoc_start_band & BAND_GN -+ || adapter->adhoc_start_band & BAND_AN) { -+ if (adapter->chan_offset == SEC_CHANNEL_ABOVE) -+ chan_tlv->chan_scan_param[0].radio_type |= -+ SECOND_CHANNEL_ABOVE; -+ else if (adapter->chan_offset == SEC_CHANNEL_BELOW) -+ chan_tlv->chan_scan_param[0].radio_type |= -+ SECOND_CHANNEL_BELOW; -+ } -+ dev_dbg(adapter->dev, "info: ADHOC_S_CMD: TLV Band = %d\n", -+ chan_tlv->chan_scan_param[0].radio_type); -+ pos += sizeof(chan_tlv->header) + -+ sizeof(struct mwifiex_chan_scan_param_set); -+ cmd_append_size += -+ sizeof(chan_tlv->header) + -+ sizeof(struct mwifiex_chan_scan_param_set); -+ } -+ -+ /* Append vendor specific IE TLV */ -+ cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, -+ MWIFIEX_VSIE_MASK_ADHOC, &pos); -+ -+ if (priv->sec_info.wpa_enabled) { -+ rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); -+ if (rsn_ie_len == -1) -+ return -1; -+ cmd_append_size += rsn_ie_len; -+ } -+ -+ if (adapter->adhoc_11n_enabled) { -+ { -+ ht_cap = (struct mwifiex_ie_types_htcap *) pos; -+ memset(ht_cap, 0, -+ sizeof(struct mwifiex_ie_types_htcap)); -+ ht_cap->header.type = -+ cpu_to_le16(WLAN_EID_HT_CAPABILITY); -+ ht_cap->header.len = -+ cpu_to_le16(sizeof(struct ieee80211_ht_cap)); -+ ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); -+ -+ ht_cap_info |= IEEE80211_HT_CAP_SGI_20; -+ if (adapter->chan_offset) { -+ ht_cap_info |= IEEE80211_HT_CAP_SGI_40; -+ ht_cap_info |= IEEE80211_HT_CAP_DSSSCCK40; -+ ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); -+ } -+ -+ ht_cap->ht_cap.ampdu_params_info -+ = IEEE80211_HT_MAX_AMPDU_64K; -+ ht_cap->ht_cap.mcs.rx_mask[0] = 0xff; -+ pos += sizeof(struct mwifiex_ie_types_htcap); -+ cmd_append_size += -+ sizeof(struct mwifiex_ie_types_htcap); -+ } -+ { -+ ht_info = (struct mwifiex_ie_types_htinfo *) pos; -+ memset(ht_info, 0, -+ sizeof(struct mwifiex_ie_types_htinfo)); -+ ht_info->header.type = -+ cpu_to_le16(WLAN_EID_HT_INFORMATION); -+ ht_info->header.len = -+ cpu_to_le16(sizeof(struct ieee80211_ht_info)); -+ ht_info->ht_info.control_chan = -+ (u8) priv->curr_bss_params.bss_descriptor. -+ channel; -+ if (adapter->chan_offset) { -+ ht_info->ht_info.ht_param = -+ adapter->chan_offset; -+ ht_info->ht_info.ht_param |= -+ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; -+ } -+ ht_info->ht_info.operation_mode = -+ 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 += -+ sizeof(struct mwifiex_ie_types_htinfo); -+ } -+ } -+ -+ cmd->size = cpu_to_le16((u16) -+ (sizeof(struct host_cmd_ds_802_11_ad_hoc_start) -+ + S_DS_GEN + cmd_append_size)); -+ -+ if (adapter->adhoc_start_band == BAND_B) -+ tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; -+ else -+ tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; -+ -+ adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command for ad-hoc join. -+ * -+ * Most of the parameters are set up by copying from the target BSS descriptor -+ * from the scan response. -+ * -+ * In addition, the following TLVs are added - -+ * - Channel TLV -+ * - Vendor specific IE -+ * - WPA/WPA2 IE -+ * - 11n IE -+ * -+ * Preparation also includes - -+ * - Setting command ID and proper size -+ * - Ensuring correct endian-ness -+ */ -+int -+mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, void *data_buf) -+{ -+ 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 = -+ (struct mwifiex_bssdescriptor *) data_buf; -+ struct mwifiex_ie_types_chan_list_param_set *chan_tlv; -+ u32 cmd_append_size = 0; -+ u16 tmp_cap; -+ u32 i, rates_size = 0; -+ u16 curr_pkt_filter; -+ u8 *pos = -+ (u8 *) adhoc_join + -+ sizeof(struct host_cmd_ds_802_11_ad_hoc_join); -+ -+/* Use G protection */ -+#define USE_G_PROTECTION 0x02 -+ if (bss_desc->erp_flags & USE_G_PROTECTION) { -+ curr_pkt_filter = -+ priv-> -+ curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; -+ -+ 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; -+ } -+ } -+ -+ priv->attempted_bss_desc = bss_desc; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); -+ -+ adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; -+ -+ adhoc_join->bss_descriptor.beacon_period -+ = cpu_to_le16(bss_desc->beacon_period); -+ -+ memcpy(&adhoc_join->bss_descriptor.bssid, -+ &bss_desc->mac_address, ETH_ALEN); -+ -+ memcpy(&adhoc_join->bss_descriptor.ssid, -+ &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); -+ -+ memcpy(&adhoc_join->bss_descriptor.phy_param_set, -+ &bss_desc->phy_param_set, -+ sizeof(union ieee_types_phy_param_set)); -+ -+ memcpy(&adhoc_join->bss_descriptor.ss_param_set, -+ &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); -+ -+ tmp_cap = bss_desc->cap_info_bitmap; -+ -+ tmp_cap &= CAPINFO_MASK; -+ -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: tmp_cap=%4X" -+ " CAPINFO_MASK=%4lX\n", tmp_cap, CAPINFO_MASK); -+ -+ /* Information on BSSID descriptor passed to FW */ -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: BSSID = %pM, SSID = %s\n", -+ adhoc_join->bss_descriptor.bssid, -+ adhoc_join->bss_descriptor.ssid); -+ -+ for (i = 0; bss_desc->supported_rates[i] && -+ i < MWIFIEX_SUPPORTED_RATES; -+ i++) -+ ; -+ rates_size = i; -+ -+ /* Copy Data Rates from the Rates recorded in scan response */ -+ memset(adhoc_join->bss_descriptor.data_rates, 0, -+ sizeof(adhoc_join->bss_descriptor.data_rates)); -+ memcpy(adhoc_join->bss_descriptor.data_rates, -+ bss_desc->supported_rates, rates_size); -+ -+ /* Copy the adhoc join rates into Current BSS state structure */ -+ priv->curr_bss_params.num_of_rates = rates_size; -+ memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, -+ rates_size); -+ -+ /* Copy the channel information */ -+ priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; -+ priv->curr_bss_params.band = (u8) bss_desc->bss_band; -+ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED -+ || priv->sec_info.wpa_enabled) -+ tmp_cap |= WLAN_CAPABILITY_PRIVACY; -+ -+ if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { -+ /* Append a channel TLV */ -+ chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; -+ chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); -+ chan_tlv->header.len = -+ cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); -+ -+ memset(chan_tlv->chan_scan_param, 0x00, -+ sizeof(struct mwifiex_chan_scan_param_set)); -+ chan_tlv->chan_scan_param[0].chan_number = -+ (bss_desc->phy_param_set.ds_param_set.current_chan); -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Chan = %d\n", -+ chan_tlv->chan_scan_param[0].chan_number); -+ -+ chan_tlv->chan_scan_param[0].radio_type = -+ mwifiex_band_to_radio_type((u8) bss_desc->bss_band); -+ -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: TLV Band = %d\n", -+ chan_tlv->chan_scan_param[0].radio_type); -+ pos += sizeof(chan_tlv->header) + -+ sizeof(struct mwifiex_chan_scan_param_set); -+ cmd_append_size += sizeof(chan_tlv->header) + -+ sizeof(struct mwifiex_chan_scan_param_set); -+ } -+ -+ if (priv->sec_info.wpa_enabled) -+ rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); -+ if (rsn_ie_len == -1) -+ return -1; -+ cmd_append_size += rsn_ie_len; -+ -+ if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) -+ cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, -+ bss_desc, &pos); -+ -+ /* Append vendor specific IE TLV */ -+ cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, -+ MWIFIEX_VSIE_MASK_ADHOC, &pos); -+ -+ cmd->size = cpu_to_le16((u16) -+ (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) -+ + S_DS_GEN + cmd_append_size)); -+ -+ adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of ad-hoc start and -+ * ad-hoc join. -+ * -+ * The function generates a device-connected event to notify -+ * the applications, in case of successful ad-hoc start/join, and -+ * saves the beacon buffer. -+ */ -+int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ int ret = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; -+ struct mwifiex_bssdescriptor *bss_desc; -+ -+ adhoc_result = &resp->params.adhoc_result; -+ -+ bss_desc = priv->attempted_bss_desc; -+ -+ /* Join result code 0 --> SUCCESS */ -+ if (le16_to_cpu(resp->result)) { -+ dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n"); -+ if (priv->media_connected) -+ mwifiex_reset_connect_state(priv); -+ -+ memset(&priv->curr_bss_params.bss_descriptor, -+ 0x00, sizeof(struct mwifiex_bssdescriptor)); -+ -+ ret = -1; -+ goto done; -+ } -+ -+ /* Send a Media Connected event, according to the Spec */ -+ priv->media_connected = true; -+ -+ 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); -+ -+ /* Update the created network descriptor with the new BSSID */ -+ memcpy(bss_desc->mac_address, -+ adhoc_result->bssid, ETH_ALEN); -+ -+ priv->adhoc_state = ADHOC_STARTED; -+ } else { -+ /* -+ * Now the join cmd should be successful. -+ * If BSSID has changed use SSID to compare instead of BSSID -+ */ -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n", -+ bss_desc->ssid.ssid); -+ -+ /* -+ * Make a copy of current BSSID descriptor, only needed for -+ * join since the current descriptor is already being used -+ * for adhoc start -+ */ -+ memcpy(&priv->curr_bss_params.bss_descriptor, -+ bss_desc, sizeof(struct mwifiex_bssdescriptor)); -+ -+ priv->adhoc_state = ADHOC_JOINED; -+ } -+ -+ dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n", -+ priv->adhoc_channel); -+ dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n", -+ priv->curr_bss_params.bss_descriptor.mac_address); -+ -+ if (!netif_carrier_ok(priv->netdev)) -+ netif_carrier_on(priv->netdev); -+ if (netif_queue_stopped(priv->netdev)) -+ netif_wake_queue(priv->netdev); -+ -+ mwifiex_save_curr_bcn(priv); -+ -+done: -+ /* Need to indicate IOCTL complete */ -+ if (adapter->curr_cmd->wait_q_enabled) { -+ if (ret) -+ adapter->cmd_wait_q.status = -1; -+ else -+ adapter->cmd_wait_q.status = 0; -+ -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function associates to a specific BSS discovered in a scan. -+ * -+ * It clears any past association response stored for application -+ * retrieval and calls the command preparation routine to send the -+ * command to firmware. -+ */ -+int mwifiex_associate(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ u8 current_bssid[ETH_ALEN]; -+ -+ /* Return error if the adapter or table entry is not marked as infra */ -+ if ((priv->bss_mode != NL80211_IFTYPE_STATION) || -+ (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) -+ return -1; -+ -+ memcpy(¤t_bssid, -+ &priv->curr_bss_params.bss_descriptor.mac_address, -+ sizeof(current_bssid)); -+ -+ /* Clear any past association response stored for application -+ retrieval */ -+ priv->assoc_rsp_size = 0; -+ -+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, -+ HostCmd_ACT_GEN_SET, 0, bss_desc); -+} -+ -+/* -+ * This function starts an ad-hoc network. -+ * -+ * It calls the command preparation routine to send the command to firmware. -+ */ -+int -+mwifiex_adhoc_start(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *adhoc_ssid) -+{ -+ 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", -+ priv->curr_bss_params.bss_descriptor.channel); -+ dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", -+ priv->curr_bss_params.band); -+ -+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, -+ HostCmd_ACT_GEN_SET, 0, adhoc_ssid); -+} -+ -+/* -+ * This function joins an ad-hoc network found in a previous scan. -+ * -+ * It calls the command preparation routine to send the command to firmware, -+ * if already not connected to the requested SSID. -+ */ -+int mwifiex_adhoc_join(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ 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", -+ priv->curr_bss_params.bss_descriptor.ssid.ssid_len); -+ dev_dbg(priv->adapter->dev, "info: adhoc join: ssid =%s\n", -+ bss_desc->ssid.ssid); -+ dev_dbg(priv->adapter->dev, "info: adhoc join: ssid_len =%u\n", -+ bss_desc->ssid.ssid_len); -+ -+ /* Check if the requested SSID is already joined */ -+ if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && -+ !mwifiex_ssid_cmp(&bss_desc->ssid, -+ &priv->curr_bss_params.bss_descriptor.ssid) && -+ (priv->curr_bss_params.bss_descriptor.bss_mode == -+ NL80211_IFTYPE_ADHOC)) { -+ dev_dbg(priv->adapter->dev, "info: ADHOC_J_CMD: new ad-hoc SSID" -+ " is the same as current; not attempting to re-join\n"); -+ return -1; -+ } -+ -+ dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", -+ priv->curr_bss_params.bss_descriptor.channel); -+ dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", -+ priv->curr_bss_params.band); -+ -+ 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, u8 *mac) -+{ -+ u8 mac_address[ETH_ALEN]; -+ int ret = 0; -+ u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -+ -+ if (mac) { -+ if (!memcmp(mac, zero_mac, sizeof(zero_mac))) -+ memcpy((u8 *) &mac_address, -+ (u8 *) &priv->curr_bss_params.bss_descriptor. -+ mac_address, ETH_ALEN); -+ else -+ memcpy((u8 *) &mac_address, (u8 *) mac, ETH_ALEN); -+ } else { -+ memcpy((u8 *) &mac_address, (u8 *) &priv->curr_bss_params. -+ bss_descriptor.mac_address, ETH_ALEN); -+ } -+ -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, -+ HostCmd_ACT_GEN_SET, 0, &mac_address); -+ -+ return ret; -+} -+ -+/* -+ * This function deauthenticates/disconnects from a BSS. -+ * -+ * 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, u8 *mac) -+{ -+ int ret = 0; -+ -+ if (priv->media_connected) { -+ if (priv->bss_mode == NL80211_IFTYPE_STATION) { -+ ret = mwifiex_deauthenticate_infra(priv, mac); -+ } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ 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. -+ */ -+u8 -+mwifiex_band_to_radio_type(u8 band) -+{ -+ switch (band) { -+ case BAND_A: -+ case BAND_AN: -+ case BAND_A | BAND_AN: -+ return HostCmd_SCAN_RADIO_TYPE_A; -+ case BAND_B: -+ case BAND_G: -+ case BAND_B | BAND_G: -+ default: -+ return HostCmd_SCAN_RADIO_TYPE_BG; -+ } -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/Kconfig 2011-05-05 23:29:45.493441961 +0200 -@@ -0,0 +1,21 @@ -+config MWIFIEX -+ tristate "Marvell WiFi-Ex Driver" -+ depends on CFG80211 -+ select LIB80211 -+ ---help--- -+ This adds support for wireless adapters based on Marvell -+ 802.11n chipsets. -+ -+ If you choose to build it as a module, it will be called -+ mwifiex. -+ -+config MWIFIEX_SDIO -+ tristate "Marvell WiFi-Ex Driver for SD8787" -+ depends on MWIFIEX && MMC -+ select FW_LOADER -+ ---help--- -+ This adds support for wireless adapters based on Marvell -+ 8787 chipset with SDIO interface. -+ -+ If you choose to build it as a module, it will be called -+ mwifiex_sdio. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/main.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/main.c 2011-05-05 23:29:45.489441913 +0200 -@@ -0,0 +1,1060 @@ -+/* -+ * Marvell Wireless LAN device driver: major functions -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "main.h" -+#include "wmm.h" -+#include "cfg80211.h" -+#include "11n.h" -+ -+#define VERSION "1.0" -+ -+const char driver_version[] = "mwifiex " VERSION " (%s) "; -+ -+struct mwifiex_adapter *g_adapter; -+EXPORT_SYMBOL_GPL(g_adapter); -+ -+static struct mwifiex_bss_attr mwifiex_bss_sta[] = { -+ {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, -+}; -+ -+static int drv_mode = DRV_MODE_STA; -+ -+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_STA, -+ .intf_num = ARRAY_SIZE(mwifiex_bss_sta), -+ .bss_attr = mwifiex_bss_sta, -+ }, -+}; -+ -+/* -+ * This function registers the device and performs all the necessary -+ * initializations. -+ * -+ * The following initialization operations are performed - -+ * - Allocate adapter structure -+ * - Save interface specific operations table in adapter -+ * - Call interface specific initialization routine -+ * - Allocate private structures -+ * - Set default adapter structure parameters -+ * - Initialize locks -+ * -+ * In case of any errors during inittialization, this function also ensures -+ * proper cleanup before exiting. -+ */ -+static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, -+ struct mwifiex_drv_mode *drv_mode_ptr) -+{ -+ struct mwifiex_adapter *adapter; -+ int i; -+ -+ adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); -+ if (!adapter) -+ return -1; -+ -+ g_adapter = adapter; -+ adapter->card = card; -+ -+ /* Save interface specific operations in adapter */ -+ memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops)); -+ -+ /* card specific initialization has been deferred until now .. */ -+ if (adapter->if_ops.init_if(adapter)) -+ goto error; -+ -+ adapter->priv_num = 0; -+ for (i = 0; i < drv_mode_ptr->intf_num; i++) { -+ adapter->priv[i] = NULL; -+ -+ if (!drv_mode_ptr->bss_attr[i].active) -+ continue; -+ -+ /* Allocate memory for private structure */ -+ adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), -+ GFP_KERNEL); -+ if (!adapter->priv[i]) { -+ dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", -+ __func__, i); -+ goto error; -+ } -+ -+ adapter->priv_num++; -+ adapter->priv[i]->adapter = adapter; -+ /* Save bss_type, frame_type & bss_priority */ -+ adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; -+ adapter->priv[i]->frame_type = -+ drv_mode_ptr->bss_attr[i].frame_type; -+ adapter->priv[i]->bss_priority = -+ 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 (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 = drv_mode_ptr->bss_attr[i].bss_num; -+ } -+ adapter->drv_mode = drv_mode_ptr; -+ -+ if (mwifiex_init_lock_list(adapter)) -+ goto error; -+ -+ init_timer(&adapter->cmd_timer); -+ adapter->cmd_timer.function = mwifiex_cmd_timeout_func; -+ adapter->cmd_timer.data = (unsigned long) adapter; -+ -+ return 0; -+ -+error: -+ dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); -+ -+ mwifiex_free_lock_list(adapter); -+ for (i = 0; i < drv_mode_ptr->intf_num; i++) -+ kfree(adapter->priv[i]); -+ kfree(adapter); -+ -+ return -1; -+} -+ -+/* -+ * This function unregisters the device and performs all the necessary -+ * cleanups. -+ * -+ * The following cleanup operations are performed - -+ * - Free the timers -+ * - Free beacon buffers -+ * - Free private structures -+ * - Free adapter structure -+ */ -+static int mwifiex_unregister(struct mwifiex_adapter *adapter) -+{ -+ s32 i = 0; -+ -+ del_timer(&adapter->cmd_timer); -+ -+ /* Free private structures */ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ mwifiex_free_curr_bcn(adapter->priv[i]); -+ kfree(adapter->priv[i]); -+ } -+ } -+ -+ kfree(adapter); -+ return 0; -+} -+ -+/* -+ * The main process. -+ * -+ * This function is the main procedure of the driver and handles various driver -+ * operations. It runs in a loop and provides the core functionalities. -+ * -+ * The main responsibilities of this function are - -+ * - Ensure concurrency control -+ * - Handle pending interrupts and call interrupt handlers -+ * - Wake up the card if required -+ * - Handle command responses and call response handlers -+ * - Handle events and call event handlers -+ * - Execute pending commands -+ * - Transmit pending data packets -+ */ -+int mwifiex_main_process(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&adapter->main_proc_lock, flags); -+ -+ /* Check if already processing */ -+ if (adapter->mwifiex_processing) { -+ spin_unlock_irqrestore(&adapter->main_proc_lock, flags); -+ goto exit_main_proc; -+ } else { -+ adapter->mwifiex_processing = true; -+ spin_unlock_irqrestore(&adapter->main_proc_lock, flags); -+ } -+process_start: -+ do { -+ if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) || -+ (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) -+ break; -+ -+ /* Handle pending interrupt if any */ -+ if (adapter->int_status) { -+ if (adapter->hs_activated) -+ mwifiex_process_hs_config(adapter); -+ adapter->if_ops.process_int_status(adapter); -+ } -+ -+ /* Need to wake up the card ? */ -+ if ((adapter->ps_state == PS_STATE_SLEEP) && -+ (adapter->pm_wakeup_card_req && -+ !adapter->pm_wakeup_fw_try) && -+ (is_command_pending(adapter) -+ || !mwifiex_wmm_lists_empty(adapter))) { -+ adapter->pm_wakeup_fw_try = true; -+ adapter->if_ops.wakeup(adapter); -+ continue; -+ } -+ if (IS_CARD_RX_RCVD(adapter)) { -+ adapter->pm_wakeup_fw_try = false; -+ if (adapter->ps_state == PS_STATE_SLEEP) -+ adapter->ps_state = PS_STATE_AWAKE; -+ } else { -+ /* We have tried to wakeup the card already */ -+ if (adapter->pm_wakeup_fw_try) -+ break; -+ if (adapter->ps_state != PS_STATE_AWAKE || -+ adapter->tx_lock_flag) -+ break; -+ -+ if (adapter->scan_processing || adapter->data_sent -+ || mwifiex_wmm_lists_empty(adapter)) { -+ if (adapter->cmd_sent || adapter->curr_cmd -+ || (!is_command_pending(adapter))) -+ break; -+ } -+ } -+ -+ /* Check for Cmd Resp */ -+ if (adapter->cmd_resp_received) { -+ adapter->cmd_resp_received = false; -+ mwifiex_process_cmdresp(adapter); -+ -+ /* call mwifiex back when init_fw is done */ -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) { -+ adapter->hw_status = MWIFIEX_HW_STATUS_READY; -+ mwifiex_init_fw_complete(adapter); -+ } -+ } -+ -+ /* Check for event */ -+ if (adapter->event_received) { -+ adapter->event_received = false; -+ mwifiex_process_event(adapter); -+ } -+ -+ /* Check if we need to confirm Sleep Request -+ received previously */ -+ if (adapter->ps_state == PS_STATE_PRE_SLEEP) { -+ if (!adapter->cmd_sent && !adapter->curr_cmd) -+ mwifiex_check_ps_cond(adapter); -+ } -+ -+ /* * The ps_state may have been changed during processing of -+ * Sleep Request event. -+ */ -+ if ((adapter->ps_state == PS_STATE_SLEEP) -+ || (adapter->ps_state == PS_STATE_PRE_SLEEP) -+ || (adapter->ps_state == PS_STATE_SLEEP_CFM) -+ || adapter->tx_lock_flag) -+ continue; -+ -+ if (!adapter->cmd_sent && !adapter->curr_cmd) { -+ if (mwifiex_exec_next_cmd(adapter) == -1) { -+ ret = -1; -+ break; -+ } -+ } -+ -+ if (!adapter->scan_processing && !adapter->data_sent && -+ !mwifiex_wmm_lists_empty(adapter)) { -+ mwifiex_wmm_process_tx(adapter); -+ if (adapter->hs_activated) { -+ adapter->is_hs_configured = false; -+ mwifiex_hs_activated_event -+ (mwifiex_get_priv -+ (adapter, MWIFIEX_BSS_ROLE_ANY), -+ false); -+ } -+ } -+ -+ if (adapter->delay_null_pkt && !adapter->cmd_sent && -+ !adapter->curr_cmd && !is_command_pending(adapter) -+ && mwifiex_wmm_lists_empty(adapter)) { -+ if (!mwifiex_send_null_packet -+ (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), -+ MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | -+ MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) { -+ adapter->delay_null_pkt = false; -+ adapter->ps_state = PS_STATE_SLEEP; -+ } -+ break; -+ } -+ } while (true); -+ -+ if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) -+ goto process_start; -+ -+ spin_lock_irqsave(&adapter->main_proc_lock, flags); -+ adapter->mwifiex_processing = false; -+ spin_unlock_irqrestore(&adapter->main_proc_lock, flags); -+ -+exit_main_proc: -+ if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) -+ mwifiex_shutdown_drv(adapter); -+ return ret; -+} -+ -+/* -+ * This function initializes the software. -+ * -+ * The main work includes allocating and initializing the adapter structure -+ * and initializing the private structures. -+ */ -+static int -+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops) -+{ -+ int i; -+ struct mwifiex_drv_mode *drv_mode_ptr; -+ -+ /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ -+ drv_mode_ptr = NULL; -+ for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { -+ if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { -+ drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; -+ break; -+ } -+ } -+ -+ if (!drv_mode_ptr) { -+ pr_err("invalid drv_mode=%d\n", drv_mode); -+ return -1; -+ } -+ -+ if (mwifiex_register(card, if_ops, drv_mode_ptr)) -+ return -1; -+ -+ return 0; -+} -+ -+/* -+ * This function frees the adapter structure. -+ * -+ * Additionally, this closes the netlink socket, frees the timers -+ * and private structures. -+ */ -+static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) -+{ -+ if (!adapter) { -+ pr_err("%s: adapter is NULL\n", __func__); -+ return; -+ } -+ -+ mwifiex_unregister(adapter); -+ pr_debug("info: %s: free adapter\n", __func__); -+} -+ -+/* -+ * This function initializes the hardware and firmware. -+ * -+ * The main initialization steps followed are - -+ * - Download the correct firmware to card -+ * - Allocate and initialize the adapter structure -+ * - Initialize the private structures -+ * - Issue the init commands to firmware -+ */ -+static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ int err; -+ struct mwifiex_fw_image fw; -+ -+ memset(&fw, 0, sizeof(struct mwifiex_fw_image)); -+ -+ switch (adapter->revision_id) { -+ case SD8787_W0: -+ case SD8787_W1: -+ strcpy(fw_name, SD8787_W1_FW_NAME); -+ break; -+ case SD8787_A0: -+ case SD8787_A1: -+ strcpy(fw_name, SD8787_AX_FW_NAME); -+ break; -+ default: -+ break; -+ } -+ -+ err = request_firmware(&adapter->firmware, fw_name, adapter->dev); -+ if (err < 0) { -+ dev_err(adapter->dev, "request_firmware() returned" -+ " error code %#x\n", err); -+ ret = -1; -+ goto done; -+ } -+ fw.fw_buf = (u8 *) adapter->firmware->data; -+ fw.fw_len = adapter->firmware->size; -+ -+ ret = mwifiex_dnld_fw(adapter, &fw); -+ if (ret == -1) -+ goto done; -+ -+ dev_notice(adapter->dev, "WLAN FW is active\n"); -+ -+ adapter->init_wait_q_woken = false; -+ ret = mwifiex_init_fw(adapter); -+ if (ret == -1) { -+ goto done; -+ } else if (!ret) { -+ adapter->hw_status = MWIFIEX_HW_STATUS_READY; -+ goto done; -+ } -+ /* Wait for mwifiex_init to complete */ -+ wait_event_interruptible(adapter->init_wait_q, -+ adapter->init_wait_q_woken); -+ if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) { -+ ret = -1; -+ goto done; -+ } -+ ret = 0; -+ -+done: -+ if (adapter->firmware) -+ release_firmware(adapter->firmware); -+ if (ret) -+ ret = -1; -+ return ret; -+} -+ -+/* -+ * This function fills a driver buffer. -+ * -+ * The function associates a given SKB with the provided driver buffer -+ * and also updates some of the SKB parameters, including IP header, -+ * priority and timestamp. -+ */ -+static void -+mwifiex_fill_buffer(struct sk_buff *skb) -+{ -+ struct ethhdr *eth = NULL; -+ struct iphdr *iph; -+ struct timeval tv; -+ u8 tid = 0; -+ -+ eth = (struct ethhdr *) skb->data; -+ switch (eth->h_proto) { -+ case __constant_htons(ETH_P_IP): -+ iph = ip_hdr(skb); -+ tid = IPTOS_PREC(iph->tos); -+ pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n", -+ eth->h_proto, tid, skb->priority); -+ break; -+ case __constant_htons(ETH_P_ARP): -+ pr_debug("data: ARP packet: %04x\n", eth->h_proto); -+ default: -+ break; -+ } -+/* Offset for TOS field in the IP header */ -+#define IPTOS_OFFSET 5 -+ tid = (tid >> IPTOS_OFFSET); -+ skb->priority = tid; -+ /* Record the current time the packet was queued; used to -+ determine the amount of time the packet was queued in -+ the driver before it was sent to the firmware. -+ The delay is then sent along with the packet to the -+ firmware for aggregate delay calculation for stats and -+ MSDU lifetime expiry. -+ */ -+ do_gettimeofday(&tv); -+ skb->tstamp = timeval_to_ktime(tv); -+} -+ -+/* -+ * CFG802.11 network device handler for open. -+ * -+ * Starts the data queue. -+ */ -+static int -+mwifiex_open(struct net_device *dev) -+{ -+ netif_start_queue(dev); -+ return 0; -+} -+ -+/* -+ * CFG802.11 network device handler for close. -+ */ -+static int -+mwifiex_close(struct net_device *dev) -+{ -+ return 0; -+} -+ -+/* -+ * CFG802.11 network device handler for data transmission. -+ */ -+static int -+mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ struct sk_buff *new_skb = NULL; -+ struct mwifiex_txinfo *tx_info; -+ -+ dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", -+ jiffies, priv->bss_index); -+ -+ if (priv->adapter->surprise_removed) { -+ kfree(skb); -+ priv->stats.tx_dropped++; -+ return 0; -+ } -+ if (!skb->len || (skb->len > ETH_FRAME_LEN)) { -+ dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); -+ kfree(skb); -+ priv->stats.tx_dropped++; -+ return 0; -+ } -+ if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { -+ dev_dbg(priv->adapter->dev, -+ "data: Tx: insufficient skb headroom %d\n", -+ skb_headroom(skb)); -+ /* Insufficient skb headroom - allocate a new skb */ -+ new_skb = -+ skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); -+ if (unlikely(!new_skb)) { -+ dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); -+ kfree(skb); -+ priv->stats.tx_dropped++; -+ return 0; -+ } -+ kfree_skb(skb); -+ skb = new_skb; -+ dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n", -+ skb_headroom(skb)); -+ } -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ tx_info->bss_index = priv->bss_index; -+ mwifiex_fill_buffer(skb); -+ -+ mwifiex_wmm_add_buf_txqueue(priv->adapter, skb); -+ atomic_inc(&priv->adapter->tx_pending); -+ -+ if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { -+ netif_stop_queue(priv->netdev); -+ dev->trans_start = jiffies; -+ } -+ -+ queue_work(priv->adapter->workqueue, &priv->adapter->main_work); -+ -+ return 0; -+} -+ -+/* -+ * CFG802.11 network device handler for setting MAC address. -+ */ -+static int -+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); -+ -+ /* 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 ret; -+} -+ -+/* -+ * CFG802.11 network device handler for setting multicast list. -+ */ -+static void mwifiex_set_multicast_list(struct net_device *dev) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_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); -+} -+ -+/* -+ * CFG802.11 network device handler for transmission timeout. -+ */ -+static void -+mwifiex_tx_timeout(struct net_device *dev) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ -+ dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n", -+ jiffies, priv->bss_index); -+ dev->trans_start = jiffies; -+ priv->num_tx_timeout++; -+} -+ -+/* -+ * CFG802.11 network device handler for statistics retrieval. -+ */ -+static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) -+{ -+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -+ -+ return &priv->stats; -+} -+ -+/* Network device handlers */ -+static const struct net_device_ops mwifiex_netdev_ops = { -+ .ndo_open = mwifiex_open, -+ .ndo_stop = mwifiex_close, -+ .ndo_start_xmit = mwifiex_hard_start_xmit, -+ .ndo_set_mac_address = mwifiex_set_mac_address, -+ .ndo_tx_timeout = mwifiex_tx_timeout, -+ .ndo_get_stats = mwifiex_get_stats, -+ .ndo_set_multicast_list = mwifiex_set_multicast_list, -+}; -+ -+/* -+ * This function initializes the private structure parameters. -+ * -+ * The following wait queues are initialized - -+ * - IOCTL wait queue -+ * - Command wait queue -+ * - Statistics wait queue -+ * -+ * ...and the following default parameters are set - -+ * - Current key index : Set to 0 -+ * - Rate index : Set to auto -+ * - Media connected : Set to disconnected -+ * - Adhoc link sensed : Set to false -+ * - Nick name : Set to null -+ * - Number of Tx timeout : Set to 0 -+ * - Device address : Set to current address -+ * -+ * In addition, the CFG80211 work queue is also created. -+ */ -+static void -+mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) -+{ -+ dev->netdev_ops = &mwifiex_netdev_ops; -+ /* Initialize private structure */ -+ priv->current_key_index = 0; -+ priv->media_connected = false; -+ memset(&priv->nick_name, 0, sizeof(priv->nick_name)); -+ priv->num_tx_timeout = 0; -+ priv->workqueue = create_singlethread_workqueue("cfg80211_wq"); -+ INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results); -+ memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); -+} -+ -+/* -+ * This function adds a new logical interface. -+ * -+ * It allocates, initializes and registers the interface by performing -+ * the following opearations - -+ * - Allocate a new net device structure -+ * - Assign device name -+ * - Register the new device with CFG80211 subsystem -+ * - Initialize semaphore and private structure -+ * - Register the new device with kernel -+ * - Create the complete debug FS structure if configured -+ */ -+static struct mwifiex_private *mwifiex_add_interface( -+ struct mwifiex_adapter *adapter, -+ u8 bss_index, u8 bss_type) -+{ -+ struct net_device *dev = NULL; -+ struct mwifiex_private *priv = NULL; -+ void *mdev_priv = NULL; -+ -+ dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", -+ ether_setup, 1); -+ if (!dev) { -+ dev_err(adapter->dev, "no memory available for netdevice\n"); -+ goto error; -+ } -+ if (dev_alloc_name(dev, dev->name)) { -+ dev_err(adapter->dev, "unable to alloc name for netdevice\n"); -+ goto error; -+ } -+ -+ if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, -+ adapter->priv[bss_index]) != 0) { -+ dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); -+ goto error; -+ } -+ /* Save the priv pointer in netdev */ -+ priv = adapter->priv[bss_index]; -+ mdev_priv = netdev_priv(dev); -+ *((unsigned long *) mdev_priv) = (unsigned long) priv; -+ -+ priv->netdev = dev; -+ -+ sema_init(&priv->async_sem, 1); -+ priv->scan_pending_on_block = false; -+ -+ mwifiex_init_priv_params(priv, dev); -+ -+ SET_NETDEV_DEV(dev, adapter->dev); -+ -+ /* Register network device */ -+ if (register_netdev(dev)) { -+ dev_err(adapter->dev, "cannot register virtual network device\n"); -+ goto error; -+ } -+ -+ dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); -+#ifdef CONFIG_DEBUG_FS -+ mwifiex_dev_debugfs_init(priv); -+#endif -+ return priv; -+error: -+ if (dev) -+ free_netdev(dev); -+ return NULL; -+} -+ -+/* -+ * This function removes a logical interface. -+ * -+ * It deregisters, resets and frees the interface by performing -+ * the following operations - -+ * - Disconnect the device if connected, send wireless event to -+ * notify applications. -+ * - Remove the debug FS structure if configured -+ * - Unregister the device from kernel -+ * - Free the net device structure -+ * - Cancel all works and destroy work queue -+ * - Unregister and free the wireless device from CFG80211 subsystem -+ */ -+static void -+mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) -+{ -+ struct net_device *dev = NULL; -+ struct mwifiex_private *priv = adapter->priv[bss_index]; -+ -+ if (!priv) -+ return; -+ dev = priv->netdev; -+ -+ if (priv->media_connected) -+ priv->media_connected = false; -+ -+#ifdef CONFIG_DEBUG_FS -+ mwifiex_dev_debugfs_remove(priv); -+#endif -+ /* Last reference is our one */ -+ dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", -+ dev->name, netdev_refcnt_read(dev)); -+ -+ if (dev->reg_state == NETREG_REGISTERED) -+ unregister_netdev(dev); -+ -+ /* Clear the priv in adapter */ -+ priv->netdev = NULL; -+ if (dev) -+ free_netdev(dev); -+ -+ cancel_work_sync(&priv->cfg_workqueue); -+ flush_workqueue(priv->workqueue); -+ destroy_workqueue(priv->workqueue); -+ wiphy_unregister(priv->wdev->wiphy); -+ wiphy_free(priv->wdev->wiphy); -+ kfree(priv->wdev); -+} -+ -+/* -+ * This function check if command is pending. -+ */ -+int is_command_pending(struct mwifiex_adapter *adapter) -+{ -+ unsigned long flags; -+ int is_cmd_pend_q_empty; -+ -+ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); -+ is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); -+ spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -+ -+ return !is_cmd_pend_q_empty; -+} -+ -+/* -+ * This function returns the correct private structure pointer based -+ * upon the BSS number. -+ */ -+struct mwifiex_private * -+mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index) -+{ -+ if (!adapter || (bss_index >= adapter->priv_num)) -+ return NULL; -+ return adapter->priv[bss_index]; -+} -+ -+/* -+ * This is the main work queue function. -+ * -+ * It handles the main process, which in turn handles the complete -+ * driver operations. -+ */ -+static void mwifiex_main_work_queue(struct work_struct *work) -+{ -+ struct mwifiex_adapter *adapter = -+ container_of(work, struct mwifiex_adapter, main_work); -+ -+ if (adapter->surprise_removed) -+ return; -+ mwifiex_main_process(adapter); -+} -+ -+/* -+ * This function cancels all works in the queue and destroys -+ * the main workqueue. -+ */ -+static void -+mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) -+{ -+ flush_workqueue(adapter->workqueue); -+ destroy_workqueue(adapter->workqueue); -+ adapter->workqueue = NULL; -+} -+ -+/* -+ * This function adds the card. -+ * -+ * This function follows the following major steps to set up the device - -+ * - Initialize software. This includes probing the card, registering -+ * the interface operations table, and allocating/initializing the -+ * adapter structure -+ * - Set up the netlink socket -+ * - Create and start the main work queue -+ * - Register the device -+ * - Initialize firmware and hardware -+ * - Add logical interfaces -+ */ -+int -+mwifiex_add_card(void *card, struct semaphore *sem, -+ struct mwifiex_if_ops *if_ops) -+{ -+ int i; -+ struct mwifiex_adapter *adapter; -+ -+ if (down_interruptible(sem)) -+ goto exit_sem_err; -+ -+ if (mwifiex_init_sw(card, if_ops)) { -+ pr_err("%s: software init failed\n", __func__); -+ goto err_init_sw; -+ } -+ -+ adapter = g_adapter; -+ -+ adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; -+ 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; -+ -+ adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); -+ if (!adapter->workqueue) -+ goto err_kmalloc; -+ -+ INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); -+ -+ /* Register the device. Fill up the private data structure with relevant -+ information from the card and request for the required IRQ. */ -+ if (adapter->if_ops.register_dev(adapter)) { -+ pr_err("%s: failed to register mwifiex device\n", __func__); -+ goto err_registerdev; -+ } -+ -+ if (mwifiex_init_hw_fw(adapter)) { -+ pr_err("%s: firmware init failed\n", __func__); -+ goto err_init_fw; -+ } -+ -+ /* Add interfaces */ -+ for (i = 0; i < adapter->drv_mode->intf_num; i++) { -+ if (!mwifiex_add_interface(adapter, i, -+ adapter->drv_mode->bss_attr[i].bss_type)) { -+ goto err_add_intf; -+ } -+ } -+ -+ up(sem); -+ -+ return 0; -+ -+err_add_intf: -+ for (i = 0; i < adapter->priv_num; i++) -+ mwifiex_remove_interface(adapter, i); -+err_init_fw: -+ pr_debug("info: %s: unregister device\n", __func__); -+ adapter->if_ops.unregister_dev(adapter); -+err_registerdev: -+ adapter->surprise_removed = true; -+ mwifiex_terminate_workqueue(adapter); -+err_kmalloc: -+ if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) || -+ (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) { -+ pr_debug("info: %s: shutdown mwifiex\n", __func__); -+ adapter->init_wait_q_woken = false; -+ -+ if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) -+ wait_event_interruptible(adapter->init_wait_q, -+ adapter->init_wait_q_woken); -+ } -+ -+ mwifiex_free_adapter(adapter); -+ -+err_init_sw: -+ up(sem); -+ -+exit_sem_err: -+ return -1; -+} -+EXPORT_SYMBOL_GPL(mwifiex_add_card); -+ -+/* -+ * This function removes the card. -+ * -+ * This function follows the following major steps to remove the device - -+ * - Stop data traffic -+ * - Shutdown firmware -+ * - Remove the logical interfaces -+ * - Terminate the work queue -+ * - Unregister the device -+ * - Free the adapter structure -+ */ -+int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) -+{ -+ struct mwifiex_private *priv = NULL; -+ int i; -+ -+ if (down_interruptible(sem)) -+ goto exit_sem_err; -+ -+ if (!adapter) -+ goto exit_remove; -+ -+ adapter->surprise_removed = true; -+ -+ /* Stop data */ -+ for (i = 0; i < adapter->priv_num; i++) { -+ priv = adapter->priv[i]; -+ if (priv) { -+ if (!netif_queue_stopped(priv->netdev)) -+ netif_stop_queue(priv->netdev); -+ if (netif_carrier_ok(priv->netdev)) -+ netif_carrier_off(priv->netdev); -+ } -+ } -+ -+ dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n"); -+ adapter->init_wait_q_woken = false; -+ -+ 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->cmd_pending)) { -+ dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " -+ "cmd_pending=%d\n", -+ atomic_read(&adapter->rx_pending), -+ atomic_read(&adapter->tx_pending), -+ atomic_read(&adapter->cmd_pending)); -+ } -+ -+ /* Remove interface */ -+ for (i = 0; i < adapter->priv_num; i++) -+ mwifiex_remove_interface(adapter, i); -+ -+ mwifiex_terminate_workqueue(adapter); -+ -+ /* Unregister device */ -+ dev_dbg(adapter->dev, "info: unregister device\n"); -+ adapter->if_ops.unregister_dev(adapter); -+ /* Free adapter structure */ -+ dev_dbg(adapter->dev, "info: free adapter\n"); -+ mwifiex_free_adapter(adapter); -+ -+exit_remove: -+ up(sem); -+exit_sem_err: -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mwifiex_remove_card); -+ -+/* -+ * This function initializes the module. -+ * -+ * The debug FS is also initialized if configured. -+ */ -+static int -+mwifiex_init_module(void) -+{ -+#ifdef CONFIG_DEBUG_FS -+ mwifiex_debugfs_init(); -+#endif -+ return 0; -+} -+ -+/* -+ * This function cleans up the module. -+ * -+ * The debug FS is removed if available. -+ */ -+static void -+mwifiex_cleanup_module(void) -+{ -+#ifdef CONFIG_DEBUG_FS -+ mwifiex_debugfs_remove(); -+#endif -+} -+ -+module_init(mwifiex_init_module); -+module_exit(mwifiex_cleanup_module); -+ -+MODULE_AUTHOR("Marvell International Ltd."); -+MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION); -+MODULE_VERSION(VERSION); -+MODULE_LICENSE("GPL v2"); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/main.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/main.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/main.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/main.h 2011-05-05 23:29:45.466441635 +0200 -@@ -0,0 +1,1008 @@ -+/* -+ * Marvell Wireless LAN device driver: major data structures and prototypes -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_MAIN_H_ -+#define _MWIFIEX_MAIN_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+ -+extern const char driver_version[]; -+extern struct mwifiex_adapter *g_adapter; -+ -+enum { -+ MWIFIEX_ASYNC_CMD, -+ MWIFIEX_SYNC_CMD -+}; -+ -+#define DRV_MODE_STA 0x1 -+ -+#define SD8787_W0 0x30 -+#define SD8787_W1 0x31 -+#define SD8787_A0 0x40 -+#define SD8787_A1 0x41 -+ -+#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" -+#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin" -+#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin" -+ -+struct mwifiex_drv_mode { -+ u16 drv_mode; -+ u16 intf_num; -+ struct mwifiex_bss_attr *bss_attr; -+}; -+ -+ -+#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) -+ -+#define MWIFIEX_TIMER_10S 10000 -+#define MWIFIEX_TIMER_1S 1000 -+ -+#define MAX_TX_PENDING 60 -+ -+#define MWIFIEX_UPLD_SIZE (2312) -+ -+#define MAX_EVENT_SIZE 1024 -+ -+#define ARP_FILTER_MAX_BUF_SIZE 68 -+ -+#define MWIFIEX_KEY_BUFFER_SIZE 16 -+#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10 -+#define MWIFIEX_MAX_REGION_CODE 7 -+ -+#define DEFAULT_BCN_AVG_FACTOR 8 -+#define DEFAULT_DATA_AVG_FACTOR 8 -+ -+#define FIRST_VALID_CHANNEL 0xff -+#define DEFAULT_AD_HOC_CHANNEL 6 -+#define DEFAULT_AD_HOC_CHANNEL_A 36 -+ -+#define DEFAULT_BCN_MISS_TIMEOUT 5 -+ -+#define MAX_SCAN_BEACON_BUFFER 8000 -+ -+#define SCAN_BEACON_ENTRY_PAD 6 -+ -+#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 200 -+#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 200 -+#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 110 -+ -+#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) -+ -+#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) -+ -+#define RSN_GTK_OUI_OFFSET 2 -+ -+#define MWIFIEX_OUI_NOT_PRESENT 0 -+#define MWIFIEX_OUI_PRESENT 1 -+ -+#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ -+ adapter->event_received || \ -+ adapter->data_received) -+ -+#define MWIFIEX_TYPE_CMD 1 -+#define MWIFIEX_TYPE_DATA 0 -+#define MWIFIEX_TYPE_EVENT 3 -+ -+#define DBG_CMD_NUM 5 -+ -+#define MAX_BITMAP_RATES_SIZE 10 -+ -+#define MAX_CHANNEL_BAND_BG 14 -+ -+#define MAX_FREQUENCY_BAND_BG 2484 -+ -+struct mwifiex_dbg { -+ u32 num_cmd_host_to_card_failure; -+ u32 num_cmd_sleep_cfm_host_to_card_failure; -+ u32 num_tx_host_to_card_failure; -+ u32 num_event_deauth; -+ u32 num_event_disassoc; -+ u32 num_event_link_lost; -+ u32 num_cmd_deauth; -+ u32 num_cmd_assoc_success; -+ u32 num_cmd_assoc_failure; -+ u32 num_tx_timeout; -+ u32 num_cmd_timeout; -+ u16 timeout_cmd_id; -+ u16 timeout_cmd_act; -+ u16 last_cmd_id[DBG_CMD_NUM]; -+ u16 last_cmd_act[DBG_CMD_NUM]; -+ u16 last_cmd_index; -+ u16 last_cmd_resp_id[DBG_CMD_NUM]; -+ u16 last_cmd_resp_index; -+ u16 last_event[DBG_CMD_NUM]; -+ u16 last_event_index; -+}; -+ -+enum MWIFIEX_HARDWARE_STATUS { -+ MWIFIEX_HW_STATUS_READY, -+ MWIFIEX_HW_STATUS_INITIALIZING, -+ MWIFIEX_HW_STATUS_FW_READY, -+ MWIFIEX_HW_STATUS_INIT_DONE, -+ MWIFIEX_HW_STATUS_RESET, -+ MWIFIEX_HW_STATUS_CLOSING, -+ MWIFIEX_HW_STATUS_NOT_READY -+}; -+ -+enum MWIFIEX_802_11_POWER_MODE { -+ MWIFIEX_802_11_POWER_MODE_CAM, -+ MWIFIEX_802_11_POWER_MODE_PSP -+}; -+ -+struct mwifiex_tx_param { -+ u32 next_pkt_len; -+}; -+ -+enum MWIFIEX_PS_STATE { -+ PS_STATE_AWAKE, -+ PS_STATE_PRE_SLEEP, -+ PS_STATE_SLEEP_CFM, -+ PS_STATE_SLEEP -+}; -+ -+struct mwifiex_add_ba_param { -+ u32 tx_win_size; -+ u32 rx_win_size; -+ u32 timeout; -+}; -+ -+struct mwifiex_tx_aggr { -+ u8 ampdu_user; -+ u8 ampdu_ap; -+ u8 amsdu; -+}; -+ -+struct mwifiex_ra_list_tbl { -+ struct list_head list; -+ struct sk_buff_head skb_head; -+ u8 ra[ETH_ALEN]; -+ u32 total_pkts_size; -+ u32 is_11n_enabled; -+}; -+ -+struct mwifiex_tid_tbl { -+ struct list_head ra_list; -+ /* spin lock for tid table */ -+ spinlock_t tid_tbl_lock; -+ struct mwifiex_ra_list_tbl *ra_list_curr; -+}; -+ -+#define WMM_HIGHEST_PRIORITY 7 -+#define HIGH_PRIO_TID 7 -+#define LOW_PRIO_TID 0 -+ -+struct mwifiex_wmm_desc { -+ struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; -+ u32 packets_out[MAX_NUM_TID]; -+ /* spin lock to protect ra_list */ -+ spinlock_t ra_list_spinlock; -+ struct mwifiex_wmm_ac_status ac_status[IEEE80211_MAX_QUEUES]; -+ enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_MAX_QUEUES]; -+ u32 drv_pkt_delay_max; -+ u8 queue_priority[IEEE80211_MAX_QUEUES]; -+ u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ -+ -+}; -+ -+struct mwifiex_802_11_security { -+ u8 wpa_enabled; -+ u8 wpa2_enabled; -+ u8 wapi_enabled; -+ u8 wapi_key_on; -+ enum MWIFIEX_802_11_WEP_STATUS wep_status; -+ u32 authentication_mode; -+ u32 encryption_mode; -+}; -+ -+struct ieee_types_header { -+ u8 element_id; -+ u8 len; -+} __packed; -+ -+struct ieee_obss_scan_param { -+ u16 obss_scan_passive_dwell; -+ u16 obss_scan_active_dwell; -+ u16 bss_chan_width_trigger_scan_int; -+ u16 obss_scan_passive_total; -+ u16 obss_scan_active_total; -+ u16 bss_width_chan_trans_delay; -+ u16 obss_scan_active_threshold; -+} __packed; -+ -+struct ieee_types_obss_scan_param { -+ struct ieee_types_header ieee_hdr; -+ struct ieee_obss_scan_param obss_scan; -+} __packed; -+ -+#define MWIFIEX_SUPPORTED_RATES 14 -+ -+#define MWIFIEX_SUPPORTED_RATES_EXT 32 -+ -+#define IEEE_MAX_IE_SIZE 256 -+ -+struct ieee_types_vendor_specific { -+ struct ieee_types_vendor_header vend_hdr; -+ u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; -+} __packed; -+ -+struct ieee_types_generic { -+ struct ieee_types_header ieee_hdr; -+ u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; -+} __packed; -+ -+struct mwifiex_bssdescriptor { -+ u8 mac_address[ETH_ALEN]; -+ struct mwifiex_802_11_ssid ssid; -+ u32 privacy; -+ s32 rssi; -+ u32 channel; -+ u32 freq; -+ u16 beacon_period; -+ u8 erp_flags; -+ u32 bss_mode; -+ u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; -+ u8 data_rates[MWIFIEX_SUPPORTED_RATES]; -+ /* Network band. -+ * BAND_B(0x01): 'b' band -+ * BAND_G(0x02): 'g' band -+ * BAND_A(0X04): 'a' band -+ */ -+ u16 bss_band; -+ u64 network_tsf; -+ u8 time_stamp[8]; -+ union ieee_types_phy_param_set phy_param_set; -+ union ieee_types_ss_param_set ss_param_set; -+ u16 cap_info_bitmap; -+ struct ieee_types_wmm_parameter wmm_ie; -+ u8 disable_11n; -+ struct ieee80211_ht_cap *bcn_ht_cap; -+ u16 ht_cap_offset; -+ struct ieee80211_ht_info *bcn_ht_info; -+ u16 ht_info_offset; -+ u8 *bcn_bss_co_2040; -+ u16 bss_co_2040_offset; -+ u8 *bcn_ext_cap; -+ u16 ext_cap_offset; -+ struct ieee_types_obss_scan_param *bcn_obss_scan; -+ u16 overlap_bss_offset; -+ struct ieee_types_vendor_specific *bcn_wpa_ie; -+ u16 wpa_offset; -+ struct ieee_types_generic *bcn_rsn_ie; -+ u16 rsn_offset; -+ struct ieee_types_generic *bcn_wapi_ie; -+ u16 wapi_offset; -+ u8 *beacon_buf; -+ u32 beacon_buf_size; -+ u32 beacon_buf_size_max; -+ -+}; -+ -+struct mwifiex_current_bss_params { -+ struct mwifiex_bssdescriptor bss_descriptor; -+ u8 wmm_enabled; -+ u8 wmm_uapsd_enabled; -+ u8 band; -+ u32 num_of_rates; -+ u8 data_rates[MWIFIEX_SUPPORTED_RATES]; -+}; -+ -+struct mwifiex_sleep_params { -+ u16 sp_error; -+ u16 sp_offset; -+ u16 sp_stable_time; -+ u8 sp_cal_control; -+ u8 sp_ext_sleep_clk; -+ u16 sp_reserved; -+}; -+ -+struct mwifiex_sleep_period { -+ u16 period; -+ u16 reserved; -+}; -+ -+struct mwifiex_wep_key { -+ u32 length; -+ u32 key_index; -+ u32 key_length; -+ u8 key_material[MWIFIEX_KEY_BUFFER_SIZE]; -+}; -+ -+#define MAX_REGION_CHANNEL_NUM 2 -+ -+struct mwifiex_chan_freq_power { -+ u16 channel; -+ u32 freq; -+ u16 max_tx_power; -+ u8 unsupported; -+}; -+ -+enum state_11d_t { -+ DISABLE_11D = 0, -+ ENABLE_11D = 1, -+}; -+ -+#define MWIFIEX_MAX_TRIPLET_802_11D 83 -+ -+struct mwifiex_802_11d_domain_reg { -+ u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; -+ u8 no_of_triplet; -+ struct ieee80211_country_ie_triplet -+ triplet[MWIFIEX_MAX_TRIPLET_802_11D]; -+}; -+ -+struct mwifiex_vendor_spec_cfg_ie { -+ u16 mask; -+ u16 flag; -+ u8 ie[MWIFIEX_MAX_VSIE_LEN]; -+}; -+ -+struct wps { -+ u8 session_enable; -+}; -+ -+struct mwifiex_adapter; -+struct mwifiex_private; -+ -+struct mwifiex_private { -+ struct mwifiex_adapter *adapter; -+ u8 bss_index; -+ u8 bss_type; -+ u8 bss_role; -+ u8 bss_priority; -+ u8 bss_num; -+ u8 frame_type; -+ u8 curr_addr[ETH_ALEN]; -+ u8 media_connected; -+ u32 num_tx_timeout; -+ struct net_device *netdev; -+ struct net_device_stats stats; -+ u16 curr_pkt_filter; -+ u32 bss_mode; -+ u32 pkt_tx_ctrl; -+ u16 tx_power_level; -+ u8 max_tx_power_level; -+ u8 min_tx_power_level; -+ u8 tx_rate; -+ u8 tx_htinfo; -+ u8 rxpd_htinfo; -+ u8 rxpd_rate; -+ u16 rate_bitmap; -+ u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; -+ u32 data_rate; -+ u8 is_data_rate_auto; -+ u16 bcn_avg_factor; -+ u16 data_avg_factor; -+ s16 data_rssi_last; -+ s16 data_nf_last; -+ s16 data_rssi_avg; -+ s16 data_nf_avg; -+ s16 bcn_rssi_last; -+ s16 bcn_nf_last; -+ s16 bcn_rssi_avg; -+ s16 bcn_nf_avg; -+ struct mwifiex_bssdescriptor *attempted_bss_desc; -+ struct mwifiex_802_11_ssid prev_ssid; -+ u8 prev_bssid[ETH_ALEN]; -+ struct mwifiex_current_bss_params curr_bss_params; -+ u16 beacon_period; -+ u16 listen_interval; -+ u16 atim_window; -+ u8 adhoc_channel; -+ u8 adhoc_is_link_sensed; -+ u8 adhoc_state; -+ struct mwifiex_802_11_security sec_info; -+ struct mwifiex_wep_key wep_key[NUM_WEP_KEYS]; -+ u16 wep_key_curr_index; -+ u8 wpa_ie[256]; -+ u8 wpa_ie_len; -+ u8 wpa_is_gtk_set; -+ struct host_cmd_ds_802_11_key_material aes_key; -+ u8 wapi_ie[256]; -+ u8 wapi_ie_len; -+ u8 wmm_required; -+ u8 wmm_enabled; -+ u8 wmm_qosinfo; -+ struct mwifiex_wmm_desc wmm; -+ struct list_head tx_ba_stream_tbl_ptr; -+ /* spin lock for tx_ba_stream_tbl_ptr queue */ -+ spinlock_t tx_ba_stream_tbl_lock; -+ struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; -+ struct mwifiex_add_ba_param add_ba_param; -+ u16 rx_seq[MAX_NUM_TID]; -+ struct list_head rx_reorder_tbl_ptr; -+ /* spin lock for rx_reorder_tbl_ptr queue */ -+ spinlock_t rx_reorder_tbl_lock; -+ /* spin lock for Rx packets */ -+ spinlock_t rx_pkt_lock; -+ -+#define MWIFIEX_ASSOC_RSP_BUF_SIZE 500 -+ u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE]; -+ u32 assoc_rsp_size; -+ -+#define MWIFIEX_GENIE_BUF_SIZE 256 -+ u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE]; -+ u8 gen_ie_buf_len; -+ -+ struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM]; -+ -+#define MWIFIEX_ASSOC_TLV_BUF_SIZE 256 -+ u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE]; -+ u8 assoc_tlv_buf_len; -+ -+ u8 *curr_bcn_buf; -+ u32 curr_bcn_size; -+ /* spin lock for beacon buffer */ -+ spinlock_t curr_bcn_buf_lock; -+ struct wireless_dev *wdev; -+ struct mwifiex_chan_freq_power cfp; -+ char version_str[128]; -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *dfs_dev_dir; -+#endif -+ u8 nick_name[16]; -+ struct iw_statistics w_stats; -+ u16 current_key_index; -+ struct semaphore async_sem; -+ u8 scan_pending_on_block; -+ u8 report_scan_result; -+ struct cfg80211_scan_request *scan_request; -+ int scan_result_status; -+ bool assoc_request; -+ u16 assoc_result; -+ bool ibss_join_request; -+ u16 ibss_join_result; -+ bool disconnect; -+ u8 cfg_bssid[6]; -+ struct workqueue_struct *workqueue; -+ struct work_struct cfg_workqueue; -+ u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; -+ struct wps wps; -+ u8 scan_block; -+}; -+ -+enum mwifiex_ba_status { -+ BA_STREAM_NOT_SETUP = 0, -+ BA_STREAM_SETUP_INPROGRESS, -+ BA_STREAM_SETUP_COMPLETE -+}; -+ -+struct mwifiex_tx_ba_stream_tbl { -+ struct list_head list; -+ int tid; -+ u8 ra[ETH_ALEN]; -+ enum mwifiex_ba_status ba_status; -+}; -+ -+struct mwifiex_rx_reorder_tbl; -+ -+struct reorder_tmr_cnxt { -+ struct timer_list timer; -+ struct mwifiex_rx_reorder_tbl *ptr; -+ struct mwifiex_private *priv; -+}; -+ -+struct mwifiex_rx_reorder_tbl { -+ struct list_head list; -+ int tid; -+ u8 ta[ETH_ALEN]; -+ int start_win; -+ int win_size; -+ void **rx_reorder_ptr; -+ struct reorder_tmr_cnxt timer_context; -+}; -+ -+struct mwifiex_bss_prio_node { -+ struct list_head list; -+ struct mwifiex_private *priv; -+}; -+ -+struct mwifiex_bss_prio_tbl { -+ struct list_head bss_prio_head; -+ /* spin lock for bss priority */ -+ spinlock_t bss_prio_lock; -+ struct mwifiex_bss_prio_node *bss_prio_cur; -+}; -+ -+struct cmd_ctrl_node { -+ struct list_head list; -+ struct mwifiex_private *priv; -+ u32 cmd_oid; -+ u32 cmd_flag; -+ struct sk_buff *cmd_skb; -+ struct sk_buff *resp_skb; -+ void *data_buf; -+ u32 wait_q_enabled; -+ struct sk_buff *skb; -+}; -+ -+struct mwifiex_if_ops { -+ int (*init_if) (struct mwifiex_adapter *); -+ void (*cleanup_if) (struct mwifiex_adapter *); -+ int (*check_fw_status) (struct mwifiex_adapter *, u32, int *); -+ int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); -+ int (*register_dev) (struct mwifiex_adapter *); -+ void (*unregister_dev) (struct mwifiex_adapter *); -+ int (*enable_int) (struct mwifiex_adapter *); -+ int (*process_int_status) (struct mwifiex_adapter *); -+ int (*host_to_card) (struct mwifiex_adapter *, u8, -+ u8 *payload, u32 pkt_len, -+ struct mwifiex_tx_param *); -+ int (*wakeup) (struct mwifiex_adapter *); -+ int (*wakeup_complete) (struct mwifiex_adapter *); -+ -+ void (*update_mp_end_port) (struct mwifiex_adapter *, u16); -+ void (*cleanup_mpa_buf) (struct mwifiex_adapter *); -+}; -+ -+struct mwifiex_adapter { -+ struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; -+ u8 priv_num; -+ struct mwifiex_drv_mode *drv_mode; -+ const struct firmware *firmware; -+ struct device *dev; -+ bool surprise_removed; -+ u32 fw_release_number; -+ u32 revision_id; -+ u16 init_wait_q_woken; -+ wait_queue_head_t init_wait_q; -+ void *card; -+ struct mwifiex_if_ops if_ops; -+ atomic_t rx_pending; -+ atomic_t tx_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]; -+ /* spin lock for init/shutdown */ -+ spinlock_t mwifiex_lock; -+ /* spin lock for main process */ -+ spinlock_t main_proc_lock; -+ u32 mwifiex_processing; -+ u16 max_tx_buf_size; -+ u16 tx_buf_size; -+ u16 curr_tx_buf_size; -+ u32 ioport; -+ enum MWIFIEX_HARDWARE_STATUS hw_status; -+ u16 number_of_antenna; -+ u32 fw_cap_info; -+ /* spin lock for interrupt handling */ -+ spinlock_t int_lock; -+ u8 int_status; -+ u32 event_cause; -+ struct sk_buff *event_skb; -+ u8 upld_buf[MWIFIEX_UPLD_SIZE]; -+ u8 data_sent; -+ u8 cmd_sent; -+ u8 cmd_resp_received; -+ u8 event_received; -+ u8 data_received; -+ u16 seq_num; -+ struct cmd_ctrl_node *cmd_pool; -+ struct cmd_ctrl_node *curr_cmd; -+ /* spin lock for command */ -+ spinlock_t mwifiex_cmd_lock; -+ u32 num_cmd_timeout; -+ u16 last_init_cmd; -+ struct timer_list cmd_timer; -+ struct list_head cmd_free_q; -+ /* spin lock for cmd_free_q */ -+ spinlock_t cmd_free_q_lock; -+ struct list_head cmd_pending_q; -+ /* spin lock for cmd_pending_q */ -+ spinlock_t cmd_pending_q_lock; -+ struct list_head scan_pending_q; -+ /* spin lock for scan_pending_q */ -+ spinlock_t scan_pending_q_lock; -+ u32 scan_processing; -+ u16 region_code; -+ struct mwifiex_802_11d_domain_reg domain_reg; -+ struct mwifiex_bssdescriptor *scan_table; -+ u32 num_in_scan_table; -+ u16 scan_probes; -+ u32 scan_mode; -+ u16 specific_scan_time; -+ u16 active_scan_time; -+ u16 passive_scan_time; -+ u8 bcn_buf[MAX_SCAN_BEACON_BUFFER]; -+ u8 *bcn_buf_end; -+ u8 fw_bands; -+ u8 adhoc_start_band; -+ u8 config_bands; -+ struct mwifiex_chan_scan_param_set *scan_channels; -+ u8 tx_lock_flag; -+ struct mwifiex_sleep_params sleep_params; -+ struct mwifiex_sleep_period sleep_period; -+ u16 ps_mode; -+ u32 ps_state; -+ u8 need_to_wakeup; -+ u16 multiple_dtim; -+ u16 local_listen_interval; -+ u16 null_pkt_interval; -+ struct sk_buff *sleep_cfm; -+ u16 bcn_miss_time_out; -+ u16 adhoc_awake_period; -+ u8 is_deep_sleep; -+ u8 delay_null_pkt; -+ u16 delay_to_ps; -+ u16 enhanced_ps_mode; -+ u8 pm_wakeup_card_req; -+ u16 gen_null_pkt; -+ u16 pps_uapsd_mode; -+ u32 pm_wakeup_fw_try; -+ u8 is_hs_configured; -+ struct mwifiex_hs_config_param hs_cfg; -+ u8 hs_activated; -+ u16 hs_activate_wait_q_woken; -+ wait_queue_head_t hs_activate_wait_q; -+ bool is_suspended; -+ u8 event_body[MAX_EVENT_SIZE]; -+ u32 hw_dot_11n_dev_cap; -+ u8 hw_dev_mcs_support; -+ u8 adhoc_11n_enabled; -+ u8 chan_offset; -+ 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); -+void mwifiex_free_lock_list(struct mwifiex_adapter *adapter); -+ -+int mwifiex_init_fw(struct mwifiex_adapter *adapter); -+ -+int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); -+ -+int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); -+ -+int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); -+ -+int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); -+ -+int mwifiex_recv_complete(struct mwifiex_adapter *, -+ struct sk_buff *skb, -+ int status); -+ -+int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); -+ -+int mwifiex_process_event(struct mwifiex_adapter *adapter); -+ -+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter); -+ -+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_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); -+ -+void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, -+ struct cmd_ctrl_node *cmd_node); -+ -+void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, -+ struct cmd_ctrl_node *cmd_node, -+ u32 addtail); -+ -+int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter); -+int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter); -+int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb); -+int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, -+ struct mwifiex_tx_param *tx_param); -+int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); -+int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, int status); -+int mwifiex_recv_packet_complete(struct mwifiex_adapter *, -+ struct sk_buff *skb, int status); -+void mwifiex_clean_txrx(struct mwifiex_private *priv); -+u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); -+void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); -+void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *, -+ u32); -+int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, uint16_t ps_bitmap, -+ void *data_buf); -+int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf); -+void mwifiex_process_hs_config(struct mwifiex_adapter *adapter); -+void mwifiex_hs_activated_event(struct mwifiex_private *priv, -+ u8 activated); -+int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp); -+int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb); -+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); -+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, -+ 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); -+s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *ssid, u8 *bssid, -+ u32 mode); -+s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, -+ u32 mode); -+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, -+ 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 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, 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, -+ struct mwifiex_bssdescriptor *bss_desc); -+int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ void *data_buf); -+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); -+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, -+ u8 band, u16 channel); -+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(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_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(u32 rate); -+u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); -+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); -+int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd); -+int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp); -+int is_command_pending(struct mwifiex_adapter *adapter); -+ -+/* -+ * This function checks if the queuing is RA based or not. -+ */ -+static inline u8 -+mwifiex_queuing_ra_based(struct mwifiex_private *priv) -+{ -+ /* -+ * Currently we assume if we are in Infra, then DA=RA. This might not be -+ * true in the future -+ */ -+ if ((priv->bss_mode == NL80211_IFTYPE_STATION) && -+ (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)) -+ return false; -+ -+ return true; -+} -+ -+/* -+ * This function copies rates. -+ */ -+static inline u32 -+mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len && src[i]; i++, pos++) { -+ if (pos >= MWIFIEX_SUPPORTED_RATES) -+ break; -+ dest[pos] = src[i]; -+ } -+ -+ return pos; -+} -+ -+/* -+ * This function returns the correct private structure pointer based -+ * upon the BSS type and BSS number. -+ */ -+static inline struct mwifiex_private * -+mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, -+ u8 bss_num, u8 bss_type) -+{ -+ int i; -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ if ((adapter->priv[i]->bss_num == bss_num) -+ && (adapter->priv[i]->bss_type == bss_type)) -+ break; -+ } -+ } -+ return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -+} -+ -+/* -+ * This function returns the first available private structure pointer -+ * based upon the BSS role. -+ */ -+static inline struct mwifiex_private * -+mwifiex_get_priv(struct mwifiex_adapter *adapter, -+ enum mwifiex_bss_role bss_role) -+{ -+ int i; -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ if (adapter->priv[i]) { -+ if (bss_role == MWIFIEX_BSS_ROLE_ANY || -+ GET_BSS_ROLE(adapter->priv[i]) == bss_role) -+ break; -+ } -+ } -+ -+ return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -+} -+ -+/* -+ * This function returns the driver private structure of a network device. -+ */ -+static inline struct mwifiex_private * -+mwifiex_netdev_get_priv(struct net_device *dev) -+{ -+ return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); -+} -+ -+struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter -+ *adapter, u8 bss_index); -+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_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, -+ struct mwifiex_ssid_bssid *ssid_bssid); -+int mwifiex_set_hs_params(struct mwifiex_private *priv, -+ u16 action, int cmd_type, -+ struct mwifiex_ds_hs_cfg *hscfg); -+int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); -+int mwifiex_enable_hs(struct mwifiex_adapter *adapter); -+int mwifiex_get_signal_info(struct mwifiex_private *priv, -+ struct mwifiex_ds_get_signal *signal); -+int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, -+ struct mwifiex_rate_cfg *rate); -+int mwifiex_find_best_bss(struct mwifiex_private *priv, -+ struct mwifiex_ssid_bssid *ssid_bssid); -+int mwifiex_request_scan(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *req_ssid); -+int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, -+ struct mwifiex_user_scan_cfg *scan_req); -+int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); -+int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); -+ -+int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); -+ -+int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, -+ int key_len, u8 key_index, int disable); -+ -+int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); -+ -+int mwifiex_get_ver_ext(struct mwifiex_private *priv); -+ -+int mwifiex_get_stats_info(struct mwifiex_private *priv, -+ struct mwifiex_ds_get_stats *log); -+ -+int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, -+ u32 reg_offset, u32 reg_value); -+ -+int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, -+ u32 reg_offset, u32 *value); -+ -+int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, -+ u8 *value); -+ -+int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data); -+ -+int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data); -+ -+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, 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, -+ struct mwifiex_power_cfg *power_cfg); -+ -+int mwifiex_main_process(struct mwifiex_adapter *); -+ -+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_ssid_bssid *); -+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 *); -+ -+#ifdef CONFIG_DEBUG_FS -+void mwifiex_debugfs_init(void); -+void mwifiex_debugfs_remove(void); -+ -+void mwifiex_dev_debugfs_init(struct mwifiex_private *priv); -+void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv); -+#endif -+#endif /* !_MWIFIEX_MAIN_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/Makefile 2011-05-05 23:29:45.472441707 +0200 -@@ -0,0 +1,41 @@ -+# -+# Copyright (C) 2011, Marvell International Ltd. -+# -+# This software file (the "File") is distributed by Marvell International -+# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+# (the "License"). You may use, redistribute and/or modify this File in -+# accordance with the terms and conditions of the License, a copy of which -+# is available by writing to the Free Software Foundation, Inc., -+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+# -+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+# this warranty disclaimer. -+ -+ -+mwifiex-y += main.o -+mwifiex-y += init.o -+mwifiex-y += cfp.o -+mwifiex-y += cmdevt.o -+mwifiex-y += util.o -+mwifiex-y += txrx.o -+mwifiex-y += wmm.o -+mwifiex-y += 11n.o -+mwifiex-y += 11n_aggr.o -+mwifiex-y += 11n_rxreorder.o -+mwifiex-y += scan.o -+mwifiex-y += join.o -+mwifiex-y += sta_ioctl.o -+mwifiex-y += sta_cmd.o -+mwifiex-y += sta_cmdresp.o -+mwifiex-y += sta_event.o -+mwifiex-y += sta_tx.o -+mwifiex-y += sta_rx.o -+mwifiex-y += cfg80211.o -+mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o -+obj-$(CONFIG_MWIFIEX) += mwifiex.o -+ -+mwifiex_sdio-y += sdio.o -+obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/README linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/README ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/README 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/README 2011-05-05 23:29:45.491441937 +0200 -@@ -0,0 +1,204 @@ -+# Copyright (C) 2011, Marvell International Ltd. -+# -+# This software file (the "File") is distributed by Marvell International -+# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+# (the "License"). You may use, redistribute and/or modify this File in -+# accordance with the terms and conditions of the License, a copy of which -+# is available by writing to the Free Software Foundation, Inc., -+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+# -+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+# this warranty disclaimer. -+ -+ -+=============================================================================== -+ U S E R M A N U A L -+ -+1) FOR DRIVER INSTALL -+ -+ a) Copy sd8787.bin to /lib/firmware/mrvl/ directory, -+ create the directory if it doesn't exist. -+ b) Install WLAN driver, -+ insmod mwifiex.ko -+ c) Uninstall WLAN driver, -+ ifconfig mlanX down -+ rmmod mwifiex -+ -+ -+2) FOR DRIVER CONFIGURATION AND INFO -+ The configurations can be done either using the 'iw' user space -+ utility or debugfs. -+ -+ a) 'iw' utility commands -+ -+ Following are some useful iw commands:- -+ -+iw dev mlan0 scan -+ -+ This command will trigger a scan. -+ The command will then display the scan table entries -+ -+iw dev mlan0 connect -w [] [] [key 0:abcde d:1123456789a] -+ The above command can be used to connect to an AP with a particular SSID. -+ Ap's operating frequency can be specified or even the bssid. If the AP is using -+ WEP encryption, wep keys can be specified in the command. -+ Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user. -+ -+iw dev mlan0 disconnect -+ This command will be used to disconnect from an AP. -+ -+ -+iw dev mlan0 ibss join [fixed-freq] [fixed-bssid] [key 0:abcde] -+ The command will be used to join or create an ibss. Optionally, operating frequency, -+ bssid and the security related parameters can be specified while joining/creating -+ and ibss. -+ -+iw dev mlan0 ibss leave -+ The command will be used to leave an ibss network. -+ -+iw dev mlan0 link -+ The command will be used to get the connection status. The command will return parameters -+ such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate. -+ -+ Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported. -+ -+ b) Debugfs interface -+ -+ The debugfs interface can be used for configurations and for getting -+ some useful information from the driver. -+ The section below explains the configurations that can be -+ done. -+ -+ Mount debugfs to /debugfs mount point: -+ -+ mkdir /debugfs -+ mount -t debugfs debugfs /debugfs -+ -+ The information is provided in /debugfs/mwifiex/mlanX/: -+ -+iw reg set -+ The command will be used to change the regulatory domain. -+ -+iw reg get -+ The command will be used to get current regulatory domain. -+ -+info -+ This command is used to get driver info. -+ -+ Usage: -+ cat info -+ -+ driver_name = "mwifiex" -+ driver_version = -+ interface_name = "mlanX" -+ bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" -+ media_state = "Disconnected" | "Connected" -+ mac_address = <6-byte adapter MAC address> -+ multicase_count = -+ essid = -+ bssid = -+ channel = -+ region_code = -+ multicasr_address[n] = -+ num_tx_bytes = -+ num_rx_bytes = -+ num_tx_pkts = -+ num_rx_pkts = -+ num_tx_pkts_dropped = -+ num_rx_pkts_dropped = -+ num_tx_pkts_err = -+ num_rx_pkts_err = -+ carrier "on" | "off" -+ tx queue "stopped" | "started" -+ -+ The following debug info are provided in /debugfs/mwifiex/mlanX/debug: -+ -+ int_counter = -+ wmm_ac_vo = -+ wmm_ac_vi = -+ wmm_ac_be = -+ wmm_ac_bk = -+ max_tx_buf_size = -+ tx_buf_size = -+ curr_tx_buf_size = -+ ps_mode = <0/1, CAM mode/PS mode> -+ ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state> -+ is_deep_sleep = <0/1, not deep sleep state/deep sleep state> -+ wakeup_dev_req = <0/1, wakeup device not required/required> -+ wakeup_tries = -+ hs_configured = <0/1, host sleep not configured/configured> -+ hs_activated = <0/1, extended host sleep not activated/activated> -+ num_tx_timeout = -+ num_cmd_timeout = -+ timeout_cmd_id = -+ timeout_cmd_act = -+ last_cmd_id = -+ last_cmd_act = -+ last_cmd_index = <0 based last command index> -+ last_cmd_resp_id = -+ last_cmd_resp_index = <0 based last command response index> -+ last_event = -+ last_event_index = <0 based last event index> -+ num_cmd_h2c_fail = -+ num_cmd_sleep_cfm_fail = -+ num_tx_h2c_fail = -+ num_evt_deauth = -+ num_evt_disassoc = -+ num_evt_link_lost = -+ num_cmd_deauth = -+ num_cmd_assoc_ok = -+ num_cmd_assoc_fail = -+ cmd_sent = <0/1, send command resources available/sending command to device> -+ data_sent = <0/1, send data resources available/sending data to device> -+ mp_rd_bitmap = -+ mp_wr_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> -+ cmd_pending = -+ tx_pending = -+ rx_pending = -+ -+ -+3) FOR DRIVER CONFIGURATION -+ -+regrdwr -+ This command is used to read/write the adapter register. -+ -+ Usage: -+ echo " [value]" > regrdwr -+ cat regrdwr -+ -+ where the parameters are, -+ : 1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU -+ : offset of register -+ [value]: value to be written -+ -+ Examples: -+ echo "1 0xa060" > regrdwr : Read the MAC register -+ echo "1 0xa060 0x12" > regrdwr : Write the MAC register -+ echo "1 0xa794 0x80000000" > regrdwr -+ : Write 0x80000000 to MAC register -+rdeeprom -+ This command is used to read the EEPROM contents of the card. -+ -+ Usage: -+ echo " " > rdeeprom -+ cat rdeeprom -+ -+ where the parameters are, -+ : multiples of 4 -+ : 4-20, multiples of 4 -+ -+ Example: -+ echo "0 20" > rdeeprom : Read 20 bytes of EEPROM data from offset 0 -+ -+getlog -+ This command is used to get the statistics available in the station. -+ Usage: -+ -+ cat getlog -+ -+=============================================================================== -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/scan.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/scan.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/scan.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/scan.c 2011-05-05 23:29:45.445441381 +0200 -@@ -0,0 +1,3025 @@ -+/* -+ * Marvell Wireless LAN device driver: scan ioctl and command handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "11n.h" -+#include "cfg80211.h" -+ -+/* The maximum number of channels the firmware can scan per command */ -+#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 -+ -+#define MWIFIEX_CHANNELS_PER_SCAN_CMD 4 -+ -+/* Memory needed to store a max sized Channel List TLV for a firmware scan */ -+#define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ -+ + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \ -+ *sizeof(struct mwifiex_chan_scan_param_set))) -+ -+/* Memory needed to store supported rate */ -+#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \ -+ + HOSTCMD_SUPPORTED_RATES) -+ -+/* Memory needed to store a max number/size WildCard SSID TLV for a firmware -+ scan */ -+#define WILDCARD_SSID_TLV_MAX_SIZE \ -+ (MWIFIEX_MAX_SSID_LIST_LENGTH * \ -+ (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \ -+ + IEEE80211_MAX_SSID_LEN)) -+ -+/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */ -+#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \ -+ + sizeof(struct mwifiex_ie_types_num_probes) \ -+ + sizeof(struct mwifiex_ie_types_htcap) \ -+ + CHAN_TLV_MAX_SIZE \ -+ + RATE_TLV_MAX_SIZE \ -+ + WILDCARD_SSID_TLV_MAX_SIZE) -+ -+ -+union mwifiex_scan_cmd_config_tlv { -+ /* Scan configuration (variable length) */ -+ struct mwifiex_scan_cmd_config config; -+ /* Max allocated block */ -+ u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC]; -+}; -+ -+enum cipher_suite { -+ CIPHER_SUITE_TKIP, -+ CIPHER_SUITE_CCMP, -+ CIPHER_SUITE_MAX -+}; -+static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = { -+ { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */ -+ { 0x00, 0x50, 0xf2, 0x04 }, /* AES */ -+}; -+static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { -+ { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */ -+ { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ -+}; -+ -+/* -+ * This function parses a given IE for a given OUI. -+ * -+ * This is used to parse a WPA/RSN IE to find if it has -+ * a given oui in PTK. -+ */ -+static u8 -+mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) -+{ -+ u8 count; -+ -+ count = iebody->ptk_cnt[0]; -+ -+ /* There could be multiple OUIs for PTK hence -+ 1) Take the length. -+ 2) Check all the OUIs for AES. -+ 3) If one of them is AES then pass success. */ -+ while (count) { -+ if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body))) -+ return MWIFIEX_OUI_PRESENT; -+ -+ --count; -+ if (count) -+ iebody = (struct ie_body *) ((u8 *) iebody + -+ sizeof(iebody->ptk_body)); -+ } -+ -+ pr_debug("info: %s: OUI is not found in PTK\n", __func__); -+ return MWIFIEX_OUI_NOT_PRESENT; -+} -+ -+/* -+ * This function checks if a given OUI is present in a RSN IE. -+ * -+ * The function first checks if a RSN IE is present or not in the -+ * BSS descriptor. It tries to locate the OUI only if such an IE is -+ * present. -+ */ -+static u8 -+mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -+{ -+ u8 *oui = NULL; -+ struct ie_body *iebody = NULL; -+ u8 ret = MWIFIEX_OUI_NOT_PRESENT; -+ -+ if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). -+ ieee_hdr.element_id == WLAN_EID_RSN))) { -+ iebody = (struct ie_body *) -+ (((u8 *) bss_desc->bcn_rsn_ie->data) + -+ RSN_GTK_OUI_OFFSET); -+ oui = &mwifiex_rsn_oui[cipher][0]; -+ ret = mwifiex_search_oui_in_ie(iebody, oui); -+ if (ret) -+ return ret; -+ } -+ return ret; -+} -+ -+/* -+ * This function checks if a given OUI is present in a WPA IE. -+ * -+ * The function first checks if a WPA IE is present or not in the -+ * BSS descriptor. It tries to locate the OUI only if such an IE is -+ * present. -+ */ -+static u8 -+mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -+{ -+ u8 *oui = NULL; -+ struct ie_body *iebody = NULL; -+ u8 ret = MWIFIEX_OUI_NOT_PRESENT; -+ -+ if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). -+ vend_hdr.element_id == WLAN_EID_WPA))) { -+ iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; -+ oui = &mwifiex_wpa_oui[cipher][0]; -+ ret = mwifiex_search_oui_in_ie(iebody, oui); -+ if (ret) -+ return ret; -+ } -+ return ret; -+} -+ -+/* -+ * This function compares two SSIDs and checks if they match. -+ */ -+s32 -+mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, -+ struct mwifiex_802_11_ssid *ssid2) -+{ -+ if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len)) -+ return -1; -+ return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len); -+} -+ -+/* -+ * Sends IOCTL request to get the best BSS. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int mwifiex_find_best_bss(struct mwifiex_private *priv, -+ struct mwifiex_ssid_bssid *ssid_bssid) -+{ -+ struct mwifiex_ssid_bssid tmp_ssid_bssid; -+ u8 *mac = NULL; -+ -+ if (!ssid_bssid) -+ return -1; -+ -+ memcpy(&tmp_ssid_bssid, ssid_bssid, -+ sizeof(struct mwifiex_ssid_bssid)); -+ -+ 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; -+ } -+ -+ return -1; -+} -+ -+/* -+ * Sends IOCTL request to start a scan with user configurations. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ * -+ * Upon completion, it also generates a wireless event to notify -+ * applications. -+ */ -+int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, -+ struct mwifiex_user_scan_cfg *scan_req) -+{ -+ int status = 0; -+ -+ priv->adapter->cmd_wait_q.condition = false; -+ -+ status = mwifiex_scan_networks(priv, scan_req); -+ if (!status) -+ status = mwifiex_wait_queue_complete(priv->adapter); -+ -+ return status; -+} -+ -+/* -+ * This function checks if wapi is enabled in driver and scanned network is -+ * compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_wapi(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ if (priv->sec_info.wapi_enabled && -+ (bss_desc->bcn_wapi_ie && -+ ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == -+ WLAN_EID_BSS_AC_ACCESS_DELAY))) { -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if driver is configured with no security mode and -+ * scanned network is compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_no_sec(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED -+ && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled -+ && ((!bss_desc->bcn_wpa_ie) || -+ ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != -+ WLAN_EID_WPA)) -+ && ((!bss_desc->bcn_rsn_ie) || -+ ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != -+ WLAN_EID_RSN)) -+ && !priv->sec_info.encryption_mode -+ && !bss_desc->privacy) { -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if static WEP is enabled in driver and scanned network -+ * is compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED -+ && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled -+ && bss_desc->privacy) { -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if wpa is enabled in driver and scanned network is -+ * compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc, -+ int index) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED -+ && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled -+ && ((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)).vend_hdr. -+ element_id == WLAN_EID_WPA)) -+ /* -+ * Privacy bit may NOT be set in some APs like -+ * LinkSys WRT54G && bss_desc->privacy -+ */ -+ ) { -+ dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" -+ " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " -+ "EncMode=%#x privacy=%#x\n", __func__, index, -+ (bss_desc->bcn_wpa_ie) ? -+ (*(bss_desc->bcn_wpa_ie)). -+ vend_hdr.element_id : 0, -+ (bss_desc->bcn_rsn_ie) ? -+ (*(bss_desc->bcn_rsn_ie)). -+ ieee_hdr.element_id : 0, -+ (priv->sec_info.wep_status == -+ MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", -+ (priv->sec_info.wpa_enabled) ? "e" : "d", -+ (priv->sec_info.wpa2_enabled) ? "e" : "d", -+ priv->sec_info.encryption_mode, -+ bss_desc->privacy); -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if wpa2 is enabled in driver and scanned network is -+ * compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc, -+ int index) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED -+ && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled -+ && ((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. -+ element_id == WLAN_EID_RSN)) -+ /* -+ * Privacy bit may NOT be set in some APs like -+ * LinkSys WRT54G && bss_desc->privacy -+ */ -+ ) { -+ dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" -+ " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " -+ "EncMode=%#x privacy=%#x\n", __func__, index, -+ (bss_desc->bcn_wpa_ie) ? -+ (*(bss_desc->bcn_wpa_ie)). -+ vend_hdr.element_id : 0, -+ (bss_desc->bcn_rsn_ie) ? -+ (*(bss_desc->bcn_rsn_ie)). -+ ieee_hdr.element_id : 0, -+ (priv->sec_info.wep_status == -+ MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", -+ (priv->sec_info.wpa_enabled) ? "e" : "d", -+ (priv->sec_info.wpa2_enabled) ? "e" : "d", -+ priv->sec_info.encryption_mode, -+ bss_desc->privacy); -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if adhoc AES is enabled in driver and scanned network is -+ * compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED -+ && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled -+ && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. -+ element_id != WLAN_EID_WPA)) -+ && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. -+ element_id != WLAN_EID_RSN)) -+ && !priv->sec_info.encryption_mode -+ && bss_desc->privacy) { -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if dynamic WEP is enabled in driver and scanned network -+ * is compatible with it. -+ */ -+static bool -+mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, -+ struct mwifiex_bssdescriptor *bss_desc, -+ int index) -+{ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED -+ && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled -+ && ((!bss_desc->bcn_wpa_ie) || ((*(bss_desc->bcn_wpa_ie)).vend_hdr. -+ element_id != WLAN_EID_WPA)) -+ && ((!bss_desc->bcn_rsn_ie) || ((*(bss_desc->bcn_rsn_ie)).ieee_hdr. -+ element_id != WLAN_EID_RSN)) -+ && priv->sec_info.encryption_mode -+ && bss_desc->privacy) { -+ dev_dbg(priv->adapter->dev, "info: %s: dynamic " -+ "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " -+ "EncMode=%#x privacy=%#x\n", -+ __func__, index, -+ (bss_desc->bcn_wpa_ie) ? -+ (*(bss_desc->bcn_wpa_ie)). -+ vend_hdr.element_id : 0, -+ (bss_desc->bcn_rsn_ie) ? -+ (*(bss_desc->bcn_rsn_ie)). -+ ieee_hdr.element_id : 0, -+ priv->sec_info.encryption_mode, -+ bss_desc->privacy); -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * This function checks if a scanned network is compatible with the driver -+ * settings. -+ * -+ * WEP WPA WPA2 ad-hoc encrypt Network -+ * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible -+ * 0 0 0 0 NONE 0 0 0 yes No security -+ * 0 1 0 0 x 1x 1 x yes WPA (disable -+ * HT if no AES) -+ * 0 0 1 0 x 1x x 1 yes WPA2 (disable -+ * HT if no AES) -+ * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES -+ * 1 0 0 0 NONE 1 0 0 yes Static WEP -+ * (disable HT) -+ * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP -+ * -+ * Compatibility is not matched while roaming, except for mode. -+ */ -+static s32 -+mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bssdescriptor *bss_desc; -+ -+ bss_desc = &adapter->scan_table[index]; -+ bss_desc->disable_11n = false; -+ -+ /* Don't check for compatibility if roaming */ -+ if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) -+ && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) -+ return index; -+ -+ if (priv->wps.session_enable) { -+ dev_dbg(adapter->dev, -+ "info: return success directly in WPS period\n"); -+ return index; -+ } -+ -+ if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { -+ dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); -+ return index; -+ } -+ -+ if (bss_desc->bss_mode == mode) { -+ if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { -+ /* No security */ -+ return index; -+ } else if (mwifiex_is_network_compatible_for_static_wep(priv, -+ bss_desc)) { -+ /* Static WEP enabled */ -+ dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); -+ bss_desc->disable_11n = true; -+ return index; -+ } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, -+ index)) { -+ /* WPA enabled */ -+ if (((priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN) -+ && bss_desc->bcn_ht_cap) -+ && !mwifiex_is_wpa_oui_present(bss_desc, -+ CIPHER_SUITE_CCMP)) { -+ -+ if (mwifiex_is_wpa_oui_present(bss_desc, -+ CIPHER_SUITE_TKIP)) { -+ dev_dbg(adapter->dev, -+ "info: Disable 11n if AES " -+ "is not supported by AP\n"); -+ bss_desc->disable_11n = true; -+ } else { -+ return -1; -+ } -+ } -+ return index; -+ } else if (mwifiex_is_network_compatible_for_wpa2(priv, -+ bss_desc, index)) { -+ /* WPA2 enabled */ -+ if (((priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN) -+ && bss_desc->bcn_ht_cap) -+ && !mwifiex_is_rsn_oui_present(bss_desc, -+ CIPHER_SUITE_CCMP)) { -+ -+ if (mwifiex_is_rsn_oui_present(bss_desc, -+ CIPHER_SUITE_TKIP)) { -+ dev_dbg(adapter->dev, -+ "info: Disable 11n if AES " -+ "is not supported by AP\n"); -+ bss_desc->disable_11n = true; -+ } else { -+ return -1; -+ } -+ } -+ return index; -+ } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, -+ bss_desc)) { -+ /* Ad-hoc AES enabled */ -+ return index; -+ } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, -+ bss_desc, index)) { -+ /* Dynamic WEP enabled */ -+ return index; -+ } -+ -+ /* Security doesn't match */ -+ dev_dbg(adapter->dev, "info: %s: failed: index=%d " -+ "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" -+ "=%#x privacy=%#x\n", -+ __func__, index, -+ (bss_desc->bcn_wpa_ie) ? -+ (*(bss_desc->bcn_wpa_ie)).vend_hdr. -+ element_id : 0, -+ (bss_desc->bcn_rsn_ie) ? -+ (*(bss_desc->bcn_rsn_ie)).ieee_hdr. -+ element_id : 0, -+ (priv->sec_info.wep_status == -+ MWIFIEX_802_11_WEP_ENABLED) ? "e" : "d", -+ (priv->sec_info.wpa_enabled) ? "e" : "d", -+ (priv->sec_info.wpa2_enabled) ? "e" : "d", -+ priv->sec_info.encryption_mode, bss_desc->privacy); -+ return -1; -+ } -+ -+ /* Mode doesn't match */ -+ return -1; -+} -+ -+/* -+ * This function finds the best SSID in the scan list. -+ * -+ * It searches the scan table for the best SSID that also matches the current -+ * adapter network preference (mode, security etc.). -+ */ -+static s32 -+mwifiex_find_best_network_in_list(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u32 mode = priv->bss_mode; -+ s32 best_net = -1; -+ s32 best_rssi = 0; -+ u32 i; -+ -+ dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n", -+ adapter->num_in_scan_table); -+ -+ for (i = 0; i < adapter->num_in_scan_table; i++) { -+ switch (mode) { -+ case NL80211_IFTYPE_STATION: -+ case NL80211_IFTYPE_ADHOC: -+ if (mwifiex_is_network_compatible(priv, i, mode) >= 0) { -+ if (SCAN_RSSI(adapter->scan_table[i].rssi) > -+ best_rssi) { -+ best_rssi = SCAN_RSSI(adapter-> -+ scan_table[i].rssi); -+ best_net = i; -+ } -+ } -+ break; -+ case NL80211_IFTYPE_UNSPECIFIED: -+ default: -+ if (SCAN_RSSI(adapter->scan_table[i].rssi) > -+ best_rssi) { -+ best_rssi = SCAN_RSSI(adapter->scan_table[i]. -+ rssi); -+ best_net = i; -+ } -+ break; -+ } -+ } -+ -+ return best_net; -+} -+ -+/* -+ * This function creates a channel list for the driver to scan, based -+ * on region/band information. -+ * -+ * This routine is used for any scan that is not provided with a -+ * specific channel list to scan. -+ */ -+static void -+mwifiex_scan_create_channel_list(struct mwifiex_private *priv, -+ const struct mwifiex_user_scan_cfg -+ *user_scan_in, -+ struct mwifiex_chan_scan_param_set -+ *scan_chan_list, -+ u8 filtered_scan) -+{ -+ enum ieee80211_band band; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_channel *ch; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int chan_idx = 0, i; -+ u8 scan_type; -+ -+ for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { -+ -+ if (!priv->wdev->wiphy->bands[band]) -+ continue; -+ -+ sband = priv->wdev->wiphy->bands[band]; -+ -+ for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) { -+ ch = &sband->channels[i]; -+ if (ch->flags & IEEE80211_CHAN_DISABLED) -+ continue; -+ scan_chan_list[chan_idx].radio_type = band; -+ scan_type = ch->flags & IEEE80211_CHAN_PASSIVE_SCAN; -+ if (user_scan_in && -+ user_scan_in->chan_list[0].scan_time) -+ scan_chan_list[chan_idx].max_scan_time = -+ cpu_to_le16((u16) user_scan_in-> -+ chan_list[0].scan_time); -+ else if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) -+ scan_chan_list[chan_idx].max_scan_time = -+ cpu_to_le16(adapter->passive_scan_time); -+ else -+ scan_chan_list[chan_idx].max_scan_time = -+ cpu_to_le16(adapter->active_scan_time); -+ if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) -+ scan_chan_list[chan_idx].chan_scan_mode_bitmap -+ |= MWIFIEX_PASSIVE_SCAN; -+ else -+ scan_chan_list[chan_idx].chan_scan_mode_bitmap -+ &= ~MWIFIEX_PASSIVE_SCAN; -+ scan_chan_list[chan_idx].chan_number = -+ (u32) ch->hw_value; -+ if (filtered_scan) { -+ scan_chan_list[chan_idx].max_scan_time = -+ cpu_to_le16(adapter->specific_scan_time); -+ scan_chan_list[chan_idx].chan_scan_mode_bitmap -+ |= MWIFIEX_DISABLE_CHAN_FILT; -+ } -+ } -+ -+ } -+} -+ -+/* -+ * This function constructs and sends multiple scan config commands to -+ * the firmware. -+ * -+ * Previous routines in the code flow have created a scan command configuration -+ * with any requested TLVs. This function splits the channel TLV into maximum -+ * channels supported per scan lists and sends the portion of the channel TLV, -+ * along with the other TLVs, to the firmware. -+ */ -+static int -+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 -+ *chan_tlv_out, -+ struct mwifiex_chan_scan_param_set *scan_chan_list) -+{ -+ int ret = 0; -+ struct mwifiex_chan_scan_param_set *tmp_chan_list; -+ struct mwifiex_chan_scan_param_set *start_chan; -+ -+ u32 tlv_idx; -+ u32 total_scan_time; -+ u32 done_early; -+ -+ if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) { -+ dev_dbg(priv->adapter->dev, -+ "info: Scan: Null detect: %p, %p, %p\n", -+ scan_cfg_out, chan_tlv_out, scan_chan_list); -+ return -1; -+ } -+ -+ chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); -+ -+ /* Set the temp channel struct pointer to the start of the desired -+ list */ -+ tmp_chan_list = scan_chan_list; -+ -+ /* Loop through the desired channel list, sending a new firmware scan -+ commands for each max_chan_per_scan channels (or for 1,6,11 -+ individually if configured accordingly) */ -+ while (tmp_chan_list->chan_number) { -+ -+ tlv_idx = 0; -+ total_scan_time = 0; -+ chan_tlv_out->header.len = 0; -+ start_chan = tmp_chan_list; -+ done_early = false; -+ -+ /* -+ * Construct the Channel TLV for the scan command. Continue to -+ * insert channel TLVs until: -+ * - the tlv_idx hits the maximum configured per scan command -+ * - the next channel to insert is 0 (end of desired channel -+ * list) -+ * - done_early is set (controlling individual scanning of -+ * 1,6,11) -+ */ -+ while (tlv_idx < max_chan_per_scan -+ && tmp_chan_list->chan_number && !done_early) { -+ -+ dev_dbg(priv->adapter->dev, -+ "info: Scan: Chan(%3d), Radio(%d)," -+ " Mode(%d, %d), Dur(%d)\n", -+ tmp_chan_list->chan_number, -+ tmp_chan_list->radio_type, -+ tmp_chan_list->chan_scan_mode_bitmap -+ & MWIFIEX_PASSIVE_SCAN, -+ (tmp_chan_list->chan_scan_mode_bitmap -+ & MWIFIEX_DISABLE_CHAN_FILT) >> 1, -+ le16_to_cpu(tmp_chan_list->max_scan_time)); -+ -+ /* Copy the current channel TLV to the command being -+ prepared */ -+ memcpy(chan_tlv_out->chan_scan_param + tlv_idx, -+ tmp_chan_list, -+ sizeof(chan_tlv_out->chan_scan_param)); -+ -+ /* Increment the TLV header length by the size -+ appended */ -+ chan_tlv_out->header.len = -+ cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) + -+ (sizeof(chan_tlv_out->chan_scan_param))); -+ -+ /* -+ * The tlv buffer length is set to the number of bytes -+ * of the between the channel tlv pointer and the start -+ * of the tlv buffer. This compensates for any TLVs -+ * that were appended before the channel list. -+ */ -+ scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out - -+ scan_cfg_out->tlv_buf); -+ -+ /* Add the size of the channel tlv header and the data -+ length */ -+ scan_cfg_out->tlv_buf_len += -+ (sizeof(chan_tlv_out->header) -+ + le16_to_cpu(chan_tlv_out->header.len)); -+ -+ /* Increment the index to the channel tlv we are -+ constructing */ -+ tlv_idx++; -+ -+ /* Count the total scan time per command */ -+ total_scan_time += -+ le16_to_cpu(tmp_chan_list->max_scan_time); -+ -+ done_early = false; -+ -+ /* Stop the loop if the *current* channel is in the -+ 1,6,11 set and we are not filtering on a BSSID -+ or SSID. */ -+ if (!filtered_scan && (tmp_chan_list->chan_number == 1 -+ || tmp_chan_list->chan_number == 6 -+ || tmp_chan_list->chan_number == 11)) -+ done_early = true; -+ -+ /* Increment the tmp pointer to the next channel to -+ be scanned */ -+ tmp_chan_list++; -+ -+ /* Stop the loop if the *next* channel is in the 1,6,11 -+ set. This will cause it to be the only channel -+ scanned on the next interation */ -+ if (!filtered_scan && (tmp_chan_list->chan_number == 1 -+ || tmp_chan_list->chan_number == 6 -+ || tmp_chan_list->chan_number == 11)) -+ done_early = true; -+ } -+ -+ /* The total scan time should be less than scan command timeout -+ value */ -+ if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) { -+ dev_err(priv->adapter->dev, "total scan time %dms" -+ " is over limit (%dms), scan skipped\n", -+ total_scan_time, MWIFIEX_MAX_TOTAL_SCAN_TIME); -+ ret = -1; -+ break; -+ } -+ -+ priv->adapter->scan_channels = start_chan; -+ -+ /* Send the scan command to the firmware with the specified -+ cfg */ -+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, -+ HostCmd_ACT_GEN_SET, 0, -+ scan_cfg_out); -+ if (ret) -+ break; -+ } -+ -+ if (ret) -+ return -1; -+ -+ return 0; -+} -+ -+/* -+ * This function constructs a scan command configuration structure to use -+ * in scan commands. -+ * -+ * Application layer or other functions can invoke network scanning -+ * with a scan configuration supplied in a user scan configuration structure. -+ * This structure is used as the basis of one or many scan command configuration -+ * commands that are sent to the command processing module and eventually to the -+ * firmware. -+ * -+ * This function creates a scan command configuration structure based on the -+ * following user supplied parameters (if present): -+ * - SSID filter -+ * - BSSID filter -+ * - Number of Probes to be sent -+ * - Channel list -+ * -+ * If the SSID or BSSID filter is not present, the filter is disabled/cleared. -+ * If the number of probes is not set, adapter default setting is used. -+ */ -+static void -+mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, -+ const struct mwifiex_user_scan_cfg *user_scan_in, -+ struct mwifiex_scan_cmd_config *scan_cfg_out, -+ struct mwifiex_ie_types_chan_list_param_set -+ **chan_list_out, -+ struct mwifiex_chan_scan_param_set -+ *scan_chan_list, -+ u8 *max_chan_per_scan, u8 *filtered_scan, -+ u8 *scan_current_only) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_ie_types_num_probes *num_probes_tlv; -+ struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; -+ struct mwifiex_ie_types_rates_param_set *rates_tlv; -+ const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -+ u8 *tlv_pos; -+ u32 num_probes; -+ u32 ssid_len; -+ u32 chan_idx; -+ u32 scan_type; -+ u16 scan_dur; -+ u8 channel; -+ u8 radio_type; -+ u32 ssid_idx; -+ u8 ssid_filter; -+ u8 rates[MWIFIEX_SUPPORTED_RATES]; -+ u32 rates_size; -+ struct mwifiex_ie_types_htcap *ht_cap; -+ -+ /* The tlv_buf_len is calculated for each scan command. The TLVs added -+ in this routine will be preserved since the routine that sends the -+ command will append channelTLVs at *chan_list_out. The difference -+ between the *chan_list_out and the tlv_buf start will be used to -+ calculate the size of anything we add in this routine. */ -+ scan_cfg_out->tlv_buf_len = 0; -+ -+ /* Running tlv pointer. Assigned to chan_list_out at end of function -+ so later routines know where channels can be added to the command -+ buf */ -+ tlv_pos = scan_cfg_out->tlv_buf; -+ -+ /* Initialize the scan as un-filtered; the flag is later set to TRUE -+ below if a SSID or BSSID filter is sent in the command */ -+ *filtered_scan = false; -+ -+ /* Initialize the scan as not being only on the current channel. If -+ the channel list is customized, only contains one channel, and is -+ the active channel, this is set true and data flow is not halted. */ -+ *scan_current_only = false; -+ -+ if (user_scan_in) { -+ -+ /* Default the ssid_filter flag to TRUE, set false under -+ certain wildcard conditions and qualified by the existence -+ of an SSID list before marking the scan as filtered */ -+ ssid_filter = true; -+ -+ /* Set the BSS type scan filter, use Adapter setting if -+ unset */ -+ scan_cfg_out->bss_mode = -+ (user_scan_in->bss_mode ? (u8) user_scan_in-> -+ bss_mode : (u8) adapter->scan_mode); -+ -+ /* Set the number of probes to send, use Adapter setting -+ if unset */ -+ num_probes = -+ (user_scan_in->num_probes ? user_scan_in-> -+ num_probes : adapter->scan_probes); -+ -+ /* -+ * Set the BSSID filter to the incoming configuration, -+ * if non-zero. If not set, it will remain disabled -+ * (all zeros). -+ */ -+ memcpy(scan_cfg_out->specific_bssid, -+ user_scan_in->specific_bssid, -+ sizeof(scan_cfg_out->specific_bssid)); -+ -+ for (ssid_idx = 0; -+ ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list)) -+ && (*user_scan_in->ssid_list[ssid_idx].ssid -+ || user_scan_in->ssid_list[ssid_idx].max_len)); -+ ssid_idx++) { -+ -+ ssid_len = strlen(user_scan_in->ssid_list[ssid_idx]. -+ ssid) + 1; -+ -+ wildcard_ssid_tlv = -+ (struct mwifiex_ie_types_wildcard_ssid_params *) -+ tlv_pos; -+ wildcard_ssid_tlv->header.type = -+ cpu_to_le16(TLV_TYPE_WILDCARDSSID); -+ wildcard_ssid_tlv->header.len = cpu_to_le16( -+ (u16) (ssid_len + sizeof(wildcard_ssid_tlv-> -+ max_ssid_length))); -+ wildcard_ssid_tlv->max_ssid_length = -+ user_scan_in->ssid_list[ssid_idx].max_len; -+ -+ memcpy(wildcard_ssid_tlv->ssid, -+ user_scan_in->ssid_list[ssid_idx].ssid, -+ ssid_len); -+ -+ tlv_pos += (sizeof(wildcard_ssid_tlv->header) -+ + le16_to_cpu(wildcard_ssid_tlv->header.len)); -+ -+ dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n", -+ ssid_idx, wildcard_ssid_tlv->ssid, -+ wildcard_ssid_tlv->max_ssid_length); -+ -+ /* Empty wildcard ssid with a maxlen will match many or -+ potentially all SSIDs (maxlen == 32), therefore do -+ not treat the scan as -+ filtered. */ -+ if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) -+ ssid_filter = false; -+ -+ } -+ -+ /* -+ * The default number of channels sent in the command is low to -+ * ensure the response buffer from the firmware does not -+ * truncate scan results. That is not an issue with an SSID -+ * or BSSID filter applied to the scan results in the firmware. -+ */ -+ if ((ssid_idx && ssid_filter) -+ || memcmp(scan_cfg_out->specific_bssid, &zero_mac, -+ sizeof(zero_mac))) -+ *filtered_scan = true; -+ } else { -+ scan_cfg_out->bss_mode = (u8) adapter->scan_mode; -+ num_probes = adapter->scan_probes; -+ } -+ -+ /* -+ * If a specific BSSID or SSID is used, the number of channels in the -+ * scan command will be increased to the absolute maximum. -+ */ -+ if (*filtered_scan) -+ *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; -+ else -+ *max_chan_per_scan = MWIFIEX_CHANNELS_PER_SCAN_CMD; -+ -+ /* If the input config or adapter has the number of Probes set, -+ add tlv */ -+ if (num_probes) { -+ -+ dev_dbg(adapter->dev, "info: scan: num_probes = %d\n", -+ num_probes); -+ -+ num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos; -+ num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); -+ num_probes_tlv->header.len = -+ cpu_to_le16(sizeof(num_probes_tlv->num_probes)); -+ num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes); -+ -+ tlv_pos += sizeof(num_probes_tlv->header) + -+ le16_to_cpu(num_probes_tlv->header.len); -+ -+ } -+ -+ /* Append rates tlv */ -+ memset(rates, 0, sizeof(rates)); -+ -+ rates_size = mwifiex_get_supported_rates(priv, rates); -+ -+ rates_tlv = (struct mwifiex_ie_types_rates_param_set *) tlv_pos; -+ rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); -+ rates_tlv->header.len = cpu_to_le16((u16) rates_size); -+ memcpy(rates_tlv->rates, rates, rates_size); -+ tlv_pos += sizeof(rates_tlv->header) + rates_size; -+ -+ dev_dbg(adapter->dev, "info: SCAN_CMD: Rates size = %d\n", rates_size); -+ -+ if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) -+ && (priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN)) { -+ ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos; -+ memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); -+ ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); -+ ht_cap->header.len = -+ cpu_to_le16(sizeof(struct ieee80211_ht_cap)); -+ radio_type = -+ mwifiex_band_to_radio_type(priv->adapter->config_bands); -+ mwifiex_fill_cap_info(priv, radio_type, ht_cap); -+ tlv_pos += sizeof(struct mwifiex_ie_types_htcap); -+ } -+ -+ /* Append vendor specific IE TLV */ -+ mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos); -+ -+ /* -+ * Set the output for the channel TLV to the address in the tlv buffer -+ * past any TLVs that were added in this function (SSID, num_probes). -+ * Channel TLVs will be added past this for each scan command, -+ * preserving the TLVs that were previously added. -+ */ -+ *chan_list_out = -+ (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos; -+ -+ if (user_scan_in && user_scan_in->chan_list[0].chan_number) { -+ -+ dev_dbg(adapter->dev, "info: Scan: Using supplied channel list\n"); -+ -+ for (chan_idx = 0; -+ chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX -+ && user_scan_in->chan_list[chan_idx].chan_number; -+ chan_idx++) { -+ -+ channel = user_scan_in->chan_list[chan_idx].chan_number; -+ (scan_chan_list + chan_idx)->chan_number = channel; -+ -+ radio_type = -+ user_scan_in->chan_list[chan_idx].radio_type; -+ (scan_chan_list + chan_idx)->radio_type = radio_type; -+ -+ scan_type = user_scan_in->chan_list[chan_idx].scan_type; -+ -+ if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) -+ (scan_chan_list + -+ chan_idx)->chan_scan_mode_bitmap -+ |= MWIFIEX_PASSIVE_SCAN; -+ else -+ (scan_chan_list + -+ chan_idx)->chan_scan_mode_bitmap -+ &= ~MWIFIEX_PASSIVE_SCAN; -+ -+ if (user_scan_in->chan_list[chan_idx].scan_time) { -+ scan_dur = (u16) user_scan_in-> -+ chan_list[chan_idx].scan_time; -+ } else { -+ if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) -+ scan_dur = adapter->passive_scan_time; -+ else if (*filtered_scan) -+ scan_dur = adapter->specific_scan_time; -+ else -+ scan_dur = adapter->active_scan_time; -+ } -+ -+ (scan_chan_list + chan_idx)->min_scan_time = -+ cpu_to_le16(scan_dur); -+ (scan_chan_list + chan_idx)->max_scan_time = -+ cpu_to_le16(scan_dur); -+ } -+ -+ /* Check if we are only scanning the current channel */ -+ if ((chan_idx == 1) -+ && (user_scan_in->chan_list[0].chan_number -+ == priv->curr_bss_params.bss_descriptor.channel)) { -+ *scan_current_only = true; -+ dev_dbg(adapter->dev, -+ "info: Scan: Scanning current channel only\n"); -+ } -+ -+ } else { -+ dev_dbg(adapter->dev, -+ "info: Scan: Creating full region channel list\n"); -+ mwifiex_scan_create_channel_list(priv, user_scan_in, -+ scan_chan_list, -+ *filtered_scan); -+ } -+} -+ -+/* -+ * This function inspects the scan response buffer for pointers to -+ * expected TLVs. -+ * -+ * TLVs can be included at the end of the scan response BSS information. -+ * -+ * Data in the buffer is parsed pointers to TLVs that can potentially -+ * be passed back in the response. -+ */ -+static void -+mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, -+ struct mwifiex_ie_types_data *tlv, -+ u32 tlv_buf_size, u32 req_tlv_type, -+ struct mwifiex_ie_types_data **tlv_data) -+{ -+ struct mwifiex_ie_types_data *current_tlv; -+ u32 tlv_buf_left; -+ u32 tlv_type; -+ u32 tlv_len; -+ -+ current_tlv = tlv; -+ tlv_buf_left = tlv_buf_size; -+ *tlv_data = NULL; -+ -+ dev_dbg(adapter->dev, "info: SCAN_RESP: tlv_buf_size = %d\n", -+ tlv_buf_size); -+ -+ while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) { -+ -+ tlv_type = le16_to_cpu(current_tlv->header.type); -+ tlv_len = le16_to_cpu(current_tlv->header.len); -+ -+ if (sizeof(tlv->header) + tlv_len > tlv_buf_left) { -+ dev_err(adapter->dev, "SCAN_RESP: TLV buffer corrupt\n"); -+ break; -+ } -+ -+ if (req_tlv_type == tlv_type) { -+ switch (tlv_type) { -+ case TLV_TYPE_TSFTIMESTAMP: -+ dev_dbg(adapter->dev, "info: SCAN_RESP: TSF " -+ "timestamp TLV, len = %d\n", tlv_len); -+ *tlv_data = (struct mwifiex_ie_types_data *) -+ current_tlv; -+ break; -+ case TLV_TYPE_CHANNELBANDLIST: -+ dev_dbg(adapter->dev, "info: SCAN_RESP: channel" -+ " band list TLV, len = %d\n", tlv_len); -+ *tlv_data = (struct mwifiex_ie_types_data *) -+ current_tlv; -+ break; -+ default: -+ dev_err(adapter->dev, -+ "SCAN_RESP: unhandled TLV = %d\n", -+ tlv_type); -+ /* Give up, this seems corrupted */ -+ return; -+ } -+ } -+ -+ if (*tlv_data) -+ break; -+ -+ -+ tlv_buf_left -= (sizeof(tlv->header) + tlv_len); -+ current_tlv = -+ (struct mwifiex_ie_types_data *) (current_tlv->data + -+ tlv_len); -+ -+ } /* while */ -+} -+ -+/* -+ * This function interprets a BSS scan response returned from the firmware. -+ * -+ * The various fixed fields and IEs are parsed and passed back for a BSS -+ * probe response or beacon from scan command. Information is recorded as -+ * needed in the scan table for that entry. -+ * -+ * The following IE types are recognized and parsed - -+ * - SSID -+ * - Supported rates -+ * - FH parameters set -+ * - DS parameters set -+ * - CF parameters set -+ * - IBSS parameters set -+ * - ERP information -+ * - Extended supported rates -+ * - Vendor specific (221) -+ * - RSN IE -+ * - WAPI IE -+ * - HT capability -+ * - HT operation -+ * - BSS Coexistence 20/40 -+ * - Extended capability -+ * - Overlapping BSS scan parameters -+ */ -+static int -+mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, -+ struct mwifiex_bssdescriptor *bss_entry, -+ u8 **beacon_info, u32 *bytes_left) -+{ -+ int ret = 0; -+ u8 element_id; -+ struct ieee_types_fh_param_set *fh_param_set; -+ struct ieee_types_ds_param_set *ds_param_set; -+ struct ieee_types_cf_param_set *cf_param_set; -+ struct ieee_types_ibss_param_set *ibss_param_set; -+ __le16 beacon_interval; -+ __le16 capabilities; -+ u8 *current_ptr; -+ u8 *rate; -+ u8 element_len; -+ u16 total_ie_len; -+ u8 bytes_to_copy; -+ u8 rate_size; -+ u16 beacon_size; -+ u8 found_data_rate_ie; -+ u32 bytes_left_for_current_beacon; -+ struct ieee_types_vendor_specific *vendor_ie; -+ const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; -+ const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; -+ -+ found_data_rate_ie = false; -+ rate_size = 0; -+ beacon_size = 0; -+ -+ if (*bytes_left >= sizeof(beacon_size)) { -+ /* Extract & convert beacon size from the command buffer */ -+ memcpy(&beacon_size, *beacon_info, sizeof(beacon_size)); -+ *bytes_left -= sizeof(beacon_size); -+ *beacon_info += sizeof(beacon_size); -+ } -+ -+ if (!beacon_size || beacon_size > *bytes_left) { -+ *beacon_info += *bytes_left; -+ *bytes_left = 0; -+ return -1; -+ } -+ -+ /* Initialize the current working beacon pointer for this BSS -+ iteration */ -+ current_ptr = *beacon_info; -+ -+ /* Advance the return beacon pointer past the current beacon */ -+ *beacon_info += beacon_size; -+ *bytes_left -= beacon_size; -+ -+ bytes_left_for_current_beacon = beacon_size; -+ -+ memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN); -+ dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n", -+ bss_entry->mac_address); -+ -+ current_ptr += ETH_ALEN; -+ bytes_left_for_current_beacon -= ETH_ALEN; -+ -+ if (bytes_left_for_current_beacon < 12) { -+ dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); -+ return -1; -+ } -+ -+ /* -+ * Next 4 fields are RSSI, time stamp, beacon interval, -+ * and capability information -+ */ -+ -+ /* RSSI is 1 byte long */ -+ bss_entry->rssi = (s32) (*current_ptr); -+ dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr); -+ current_ptr += 1; -+ bytes_left_for_current_beacon -= 1; -+ -+ /* -+ * The RSSI is not part of the beacon/probe response. After we have -+ * advanced current_ptr past the RSSI field, save the remaining -+ * data for use at the application layer -+ */ -+ bss_entry->beacon_buf = current_ptr; -+ bss_entry->beacon_buf_size = bytes_left_for_current_beacon; -+ -+ /* Time stamp is 8 bytes long */ -+ memcpy(bss_entry->time_stamp, current_ptr, 8); -+ current_ptr += 8; -+ bytes_left_for_current_beacon -= 8; -+ -+ /* Beacon interval is 2 bytes long */ -+ memcpy(&beacon_interval, current_ptr, 2); -+ bss_entry->beacon_period = le16_to_cpu(beacon_interval); -+ current_ptr += 2; -+ bytes_left_for_current_beacon -= 2; -+ -+ /* Capability information is 2 bytes long */ -+ memcpy(&capabilities, current_ptr, 2); -+ dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", -+ capabilities); -+ bss_entry->cap_info_bitmap = le16_to_cpu(capabilities); -+ current_ptr += 2; -+ bytes_left_for_current_beacon -= 2; -+ -+ /* Rest of the current buffer are IE's */ -+ dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", -+ bytes_left_for_current_beacon); -+ -+ if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { -+ dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n"); -+ bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; -+ } else { -+ bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; -+ } -+ -+ if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS) -+ bss_entry->bss_mode = NL80211_IFTYPE_ADHOC; -+ else -+ bss_entry->bss_mode = NL80211_IFTYPE_STATION; -+ -+ -+ /* Process variable IE */ -+ while (bytes_left_for_current_beacon >= 2) { -+ element_id = *current_ptr; -+ element_len = *(current_ptr + 1); -+ total_ie_len = element_len + sizeof(struct ieee_types_header); -+ -+ if (bytes_left_for_current_beacon < total_ie_len) { -+ dev_err(adapter->dev, "err: InterpretIE: in processing" -+ " IE, bytes left < IE length\n"); -+ bytes_left_for_current_beacon = 0; -+ ret = -1; -+ continue; -+ } -+ switch (element_id) { -+ case WLAN_EID_SSID: -+ bss_entry->ssid.ssid_len = element_len; -+ memcpy(bss_entry->ssid.ssid, (current_ptr + 2), -+ element_len); -+ dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", -+ bss_entry->ssid.ssid); -+ break; -+ -+ case WLAN_EID_SUPP_RATES: -+ memcpy(bss_entry->data_rates, current_ptr + 2, -+ element_len); -+ memcpy(bss_entry->supported_rates, current_ptr + 2, -+ element_len); -+ rate_size = element_len; -+ found_data_rate_ie = true; -+ break; -+ -+ case WLAN_EID_FH_PARAMS: -+ fh_param_set = -+ (struct ieee_types_fh_param_set *) current_ptr; -+ memcpy(&bss_entry->phy_param_set.fh_param_set, -+ fh_param_set, -+ sizeof(struct ieee_types_fh_param_set)); -+ break; -+ -+ case WLAN_EID_DS_PARAMS: -+ ds_param_set = -+ (struct ieee_types_ds_param_set *) current_ptr; -+ -+ bss_entry->channel = ds_param_set->current_chan; -+ -+ memcpy(&bss_entry->phy_param_set.ds_param_set, -+ ds_param_set, -+ sizeof(struct ieee_types_ds_param_set)); -+ break; -+ -+ case WLAN_EID_CF_PARAMS: -+ cf_param_set = -+ (struct ieee_types_cf_param_set *) current_ptr; -+ memcpy(&bss_entry->ss_param_set.cf_param_set, -+ cf_param_set, -+ sizeof(struct ieee_types_cf_param_set)); -+ break; -+ -+ case WLAN_EID_IBSS_PARAMS: -+ ibss_param_set = -+ (struct ieee_types_ibss_param_set *) -+ current_ptr; -+ memcpy(&bss_entry->ss_param_set.ibss_param_set, -+ ibss_param_set, -+ sizeof(struct ieee_types_ibss_param_set)); -+ break; -+ -+ case WLAN_EID_ERP_INFO: -+ bss_entry->erp_flags = *(current_ptr + 2); -+ break; -+ -+ case WLAN_EID_EXT_SUPP_RATES: -+ /* -+ * Only process extended supported rate -+ * if data rate is already found. -+ * Data rate IE should come before -+ * extended supported rate IE -+ */ -+ if (found_data_rate_ie) { -+ if ((element_len + rate_size) > -+ MWIFIEX_SUPPORTED_RATES) -+ bytes_to_copy = -+ (MWIFIEX_SUPPORTED_RATES - -+ rate_size); -+ else -+ bytes_to_copy = element_len; -+ -+ rate = (u8 *) bss_entry->data_rates; -+ rate += rate_size; -+ memcpy(rate, current_ptr + 2, bytes_to_copy); -+ -+ rate = (u8 *) bss_entry->supported_rates; -+ rate += rate_size; -+ memcpy(rate, current_ptr + 2, bytes_to_copy); -+ } -+ break; -+ -+ case WLAN_EID_VENDOR_SPECIFIC: -+ vendor_ie = (struct ieee_types_vendor_specific *) -+ current_ptr; -+ -+ if (!memcmp -+ (vendor_ie->vend_hdr.oui, wpa_oui, -+ sizeof(wpa_oui))) { -+ bss_entry->bcn_wpa_ie = -+ (struct ieee_types_vendor_specific *) -+ current_ptr; -+ bss_entry->wpa_offset = (u16) (current_ptr - -+ bss_entry->beacon_buf); -+ } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, -+ sizeof(wmm_oui))) { -+ if (total_ie_len == -+ sizeof(struct ieee_types_wmm_parameter) -+ || total_ie_len == -+ sizeof(struct ieee_types_wmm_info)) -+ /* -+ * Only accept and copy the WMM IE if -+ * it matches the size expected for the -+ * WMM Info IE or the WMM Parameter IE. -+ */ -+ memcpy((u8 *) &bss_entry->wmm_ie, -+ current_ptr, total_ie_len); -+ } -+ break; -+ case WLAN_EID_RSN: -+ bss_entry->bcn_rsn_ie = -+ (struct ieee_types_generic *) current_ptr; -+ bss_entry->rsn_offset = (u16) (current_ptr - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_BSS_AC_ACCESS_DELAY: -+ bss_entry->bcn_wapi_ie = -+ (struct ieee_types_generic *) current_ptr; -+ bss_entry->wapi_offset = (u16) (current_ptr - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_HT_CAPABILITY: -+ bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *) -+ (current_ptr + -+ sizeof(struct ieee_types_header)); -+ bss_entry->ht_cap_offset = (u16) (current_ptr + -+ sizeof(struct ieee_types_header) - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_HT_INFORMATION: -+ bss_entry->bcn_ht_info = (struct ieee80211_ht_info *) -+ (current_ptr + -+ sizeof(struct ieee_types_header)); -+ bss_entry->ht_info_offset = (u16) (current_ptr + -+ sizeof(struct ieee_types_header) - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_BSS_COEX_2040: -+ bss_entry->bcn_bss_co_2040 = (u8 *) (current_ptr + -+ sizeof(struct ieee_types_header)); -+ bss_entry->bss_co_2040_offset = (u16) (current_ptr + -+ sizeof(struct ieee_types_header) - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_EXT_CAPABILITY: -+ bss_entry->bcn_ext_cap = (u8 *) (current_ptr + -+ sizeof(struct ieee_types_header)); -+ bss_entry->ext_cap_offset = (u16) (current_ptr + -+ sizeof(struct ieee_types_header) - -+ bss_entry->beacon_buf); -+ break; -+ case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: -+ bss_entry->bcn_obss_scan = -+ (struct ieee_types_obss_scan_param *) -+ current_ptr; -+ bss_entry->overlap_bss_offset = (u16) (current_ptr - -+ bss_entry->beacon_buf); -+ break; -+ default: -+ break; -+ } -+ -+ current_ptr += element_len + 2; -+ -+ /* Need to account for IE ID and IE Len */ -+ bytes_left_for_current_beacon -= (element_len + 2); -+ -+ } /* while (bytes_left_for_current_beacon > 2) */ -+ return ret; -+} -+ -+/* -+ * This function adjusts the pointers used in beacon buffers to reflect -+ * shifts. -+ * -+ * The memory allocated for beacon buffers is of fixed sizes where all the -+ * saved beacons must be stored. New beacons are added in the free portion -+ * of this memory, space permitting; while duplicate beacon buffers are -+ * placed at the same start location. However, since duplicate beacon -+ * buffers may not match the size of the old one, all the following buffers -+ * in the memory must be shifted to either make space, or to fill up freed -+ * up space. -+ * -+ * This function is used to update the beacon buffer pointers that are past -+ * an existing beacon buffer that is updated with a new one of different -+ * size. The pointers are shifted by a fixed amount, either forward or -+ * backward. -+ * -+ * the following pointers in every affected beacon buffers are changed, if -+ * present - -+ * - WPA IE pointer -+ * - RSN IE pointer -+ * - WAPI IE pointer -+ * - HT capability IE pointer -+ * - HT information IE pointer -+ * - BSS coexistence 20/40 IE pointer -+ * - Extended capability IE pointer -+ * - Overlapping BSS scan parameter IE pointer -+ */ -+static void -+mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance, -+ u8 *bcn_store, u32 rem_bcn_size, -+ u32 num_of_ent) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u32 adj_idx; -+ for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) { -+ if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) { -+ -+ if (advance) -+ adapter->scan_table[adj_idx].beacon_buf += -+ rem_bcn_size; -+ else -+ adapter->scan_table[adj_idx].beacon_buf -= -+ rem_bcn_size; -+ -+ if (adapter->scan_table[adj_idx].bcn_wpa_ie) -+ adapter->scan_table[adj_idx].bcn_wpa_ie = -+ (struct ieee_types_vendor_specific *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].wpa_offset); -+ if (adapter->scan_table[adj_idx].bcn_rsn_ie) -+ adapter->scan_table[adj_idx].bcn_rsn_ie = -+ (struct ieee_types_generic *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].rsn_offset); -+ if (adapter->scan_table[adj_idx].bcn_wapi_ie) -+ adapter->scan_table[adj_idx].bcn_wapi_ie = -+ (struct ieee_types_generic *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].wapi_offset); -+ if (adapter->scan_table[adj_idx].bcn_ht_cap) -+ adapter->scan_table[adj_idx].bcn_ht_cap = -+ (struct ieee80211_ht_cap *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].ht_cap_offset); -+ -+ if (adapter->scan_table[adj_idx].bcn_ht_info) -+ adapter->scan_table[adj_idx].bcn_ht_info = -+ (struct ieee80211_ht_info *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].ht_info_offset); -+ if (adapter->scan_table[adj_idx].bcn_bss_co_2040) -+ adapter->scan_table[adj_idx].bcn_bss_co_2040 = -+ (u8 *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].bss_co_2040_offset); -+ if (adapter->scan_table[adj_idx].bcn_ext_cap) -+ adapter->scan_table[adj_idx].bcn_ext_cap = -+ (u8 *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].ext_cap_offset); -+ if (adapter->scan_table[adj_idx].bcn_obss_scan) -+ adapter->scan_table[adj_idx].bcn_obss_scan = -+ (struct ieee_types_obss_scan_param *) -+ (adapter->scan_table[adj_idx].beacon_buf + -+ adapter->scan_table[adj_idx].overlap_bss_offset); -+ } -+ } -+} -+ -+/* -+ * This function updates the pointers used in beacon buffer for given bss -+ * descriptor to reflect shifts -+ * -+ * Following pointers are updated -+ * - WPA IE pointer -+ * - RSN IE pointer -+ * - WAPI IE pointer -+ * - HT capability IE pointer -+ * - HT information IE pointer -+ * - BSS coexistence 20/40 IE pointer -+ * - Extended capability IE pointer -+ * - Overlapping BSS scan parameter IE pointer -+ */ -+static void -+mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon) -+{ -+ if (beacon->bcn_wpa_ie) -+ beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *) -+ (beacon->beacon_buf + beacon->wpa_offset); -+ if (beacon->bcn_rsn_ie) -+ beacon->bcn_rsn_ie = (struct ieee_types_generic *) -+ (beacon->beacon_buf + beacon->rsn_offset); -+ if (beacon->bcn_wapi_ie) -+ beacon->bcn_wapi_ie = (struct ieee_types_generic *) -+ (beacon->beacon_buf + beacon->wapi_offset); -+ if (beacon->bcn_ht_cap) -+ beacon->bcn_ht_cap = (struct ieee80211_ht_cap *) -+ (beacon->beacon_buf + beacon->ht_cap_offset); -+ if (beacon->bcn_ht_info) -+ beacon->bcn_ht_info = (struct ieee80211_ht_info *) -+ (beacon->beacon_buf + beacon->ht_info_offset); -+ if (beacon->bcn_bss_co_2040) -+ beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf + -+ beacon->bss_co_2040_offset); -+ if (beacon->bcn_ext_cap) -+ beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf + -+ beacon->ext_cap_offset); -+ if (beacon->bcn_obss_scan) -+ beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *) -+ (beacon->beacon_buf + beacon->overlap_bss_offset); -+} -+ -+/* -+ * This function stores a beacon or probe response for a BSS returned -+ * in the scan. -+ * -+ * This stores a new scan response or an update for a previous scan response. -+ * New entries need to verify that they do not exceed the total amount of -+ * memory allocated for the table. -+ * -+ * Replacement entries need to take into consideration the amount of space -+ * currently allocated for the beacon/probe response and adjust the entry -+ * as needed. -+ * -+ * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved -+ * for an entry in case it is a beacon since a probe response for the -+ * network will by larger per the standard. This helps to reduce the -+ * amount of memory copying to fit a new probe response into an entry -+ * already occupied by a network's previously stored beacon. -+ */ -+static void -+mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv, -+ u32 beacon_idx, u32 num_of_ent, -+ struct mwifiex_bssdescriptor *new_beacon) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u8 *bcn_store; -+ u32 new_bcn_size; -+ u32 old_bcn_size; -+ u32 bcn_space; -+ -+ if (adapter->scan_table[beacon_idx].beacon_buf) { -+ -+ new_bcn_size = new_beacon->beacon_buf_size; -+ old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size; -+ bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max; -+ bcn_store = adapter->scan_table[beacon_idx].beacon_buf; -+ -+ /* Set the max to be the same as current entry unless changed -+ below */ -+ new_beacon->beacon_buf_size_max = bcn_space; -+ if (new_bcn_size == old_bcn_size) { -+ /* -+ * Beacon is the same size as the previous entry. -+ * Replace the previous contents with the scan result -+ */ -+ memcpy(bcn_store, new_beacon->beacon_buf, -+ new_beacon->beacon_buf_size); -+ -+ } else if (new_bcn_size <= bcn_space) { -+ /* -+ * New beacon size will fit in the amount of space -+ * we have previously allocated for it -+ */ -+ -+ /* Copy the new beacon buffer entry over the old one */ -+ memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); -+ -+ /* -+ * If the old beacon size was less than the maximum -+ * we had alloted for the entry, and the new entry -+ * is even smaller, reset the max size to the old -+ * beacon entry and compress the storage space -+ * (leaving a new pad space of (old_bcn_size - -+ * new_bcn_size). -+ */ -+ if (old_bcn_size < bcn_space -+ && new_bcn_size <= old_bcn_size) { -+ /* -+ * Old Beacon size is smaller than the alloted -+ * storage size. Shrink the alloted storage -+ * space. -+ */ -+ dev_dbg(adapter->dev, "info: AppControl:" -+ " smaller duplicate beacon " -+ "(%d), old = %d, new = %d, space = %d," -+ "left = %d\n", -+ beacon_idx, old_bcn_size, new_bcn_size, -+ bcn_space, -+ (int)(sizeof(adapter->bcn_buf) - -+ (adapter->bcn_buf_end - -+ adapter->bcn_buf))); -+ -+ /* -+ * memmove (since the memory overlaps) the -+ * data after the beacon we just stored to the -+ * end of the current beacon. This cleans up -+ * any unused space the old larger beacon was -+ * using in the buffer -+ */ -+ memmove(bcn_store + old_bcn_size, -+ bcn_store + bcn_space, -+ adapter->bcn_buf_end - (bcn_store + -+ bcn_space)); -+ -+ /* -+ * Decrement the end pointer by the difference -+ * between the old larger size and the new -+ * smaller size since we are using less space -+ * due to the new beacon being smaller -+ */ -+ adapter->bcn_buf_end -= -+ (bcn_space - old_bcn_size); -+ -+ /* Set the maximum storage size to the old -+ beacon size */ -+ new_beacon->beacon_buf_size_max = old_bcn_size; -+ -+ /* Adjust beacon buffer pointers that are past -+ the current */ -+ mwifiex_adjust_beacon_buffer_ptrs(priv, 0, -+ bcn_store, (bcn_space - old_bcn_size), -+ num_of_ent); -+ } -+ } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space) -+ < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) { -+ /* -+ * Beacon is larger than space previously allocated -+ * (bcn_space) and there is enough space left in the -+ * beaconBuffer to store the additional data -+ */ -+ dev_dbg(adapter->dev, "info: AppControl:" -+ " larger duplicate beacon (%d), " -+ "old = %d, new = %d, space = %d, left = %d\n", -+ beacon_idx, old_bcn_size, new_bcn_size, -+ bcn_space, -+ (int)(sizeof(adapter->bcn_buf) - -+ (adapter->bcn_buf_end - -+ adapter->bcn_buf))); -+ -+ /* -+ * memmove (since the memory overlaps) the data -+ * after the beacon we just stored to the end of -+ * the current beacon. This moves the data for -+ * the beacons after this further in memory to -+ * make space for the new larger beacon we are -+ * about to copy in. -+ */ -+ memmove(bcn_store + new_bcn_size, -+ bcn_store + bcn_space, -+ adapter->bcn_buf_end - (bcn_store + bcn_space)); -+ -+ /* Copy the new beacon buffer entry over the old one */ -+ memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size); -+ -+ /* Move the beacon end pointer by the amount of new -+ beacon data we are adding */ -+ adapter->bcn_buf_end += (new_bcn_size - bcn_space); -+ -+ /* -+ * This entry is bigger than the alloted max space -+ * previously reserved. Increase the max space to -+ * be equal to the new beacon size -+ */ -+ new_beacon->beacon_buf_size_max = new_bcn_size; -+ -+ /* Adjust beacon buffer pointers that are past the -+ current */ -+ mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store, -+ (new_bcn_size - bcn_space), -+ num_of_ent); -+ } else { -+ /* -+ * Beacon is larger than the previously allocated space, -+ * but there is not enough free space to store the -+ * additional data. -+ */ -+ dev_err(adapter->dev, "AppControl: larger duplicate " -+ " beacon (%d), old = %d new = %d, space = %d," -+ " left = %d\n", beacon_idx, old_bcn_size, -+ new_bcn_size, bcn_space, -+ (int)(sizeof(adapter->bcn_buf) - -+ (adapter->bcn_buf_end - adapter->bcn_buf))); -+ -+ /* Storage failure, keep old beacon intact */ -+ new_beacon->beacon_buf_size = old_bcn_size; -+ if (new_beacon->bcn_wpa_ie) -+ new_beacon->wpa_offset = -+ adapter->scan_table[beacon_idx]. -+ wpa_offset; -+ if (new_beacon->bcn_rsn_ie) -+ new_beacon->rsn_offset = -+ adapter->scan_table[beacon_idx]. -+ rsn_offset; -+ if (new_beacon->bcn_wapi_ie) -+ new_beacon->wapi_offset = -+ adapter->scan_table[beacon_idx]. -+ wapi_offset; -+ if (new_beacon->bcn_ht_cap) -+ new_beacon->ht_cap_offset = -+ adapter->scan_table[beacon_idx]. -+ ht_cap_offset; -+ if (new_beacon->bcn_ht_info) -+ new_beacon->ht_info_offset = -+ adapter->scan_table[beacon_idx]. -+ ht_info_offset; -+ if (new_beacon->bcn_bss_co_2040) -+ new_beacon->bss_co_2040_offset = -+ adapter->scan_table[beacon_idx]. -+ bss_co_2040_offset; -+ if (new_beacon->bcn_ext_cap) -+ new_beacon->ext_cap_offset = -+ adapter->scan_table[beacon_idx]. -+ ext_cap_offset; -+ if (new_beacon->bcn_obss_scan) -+ new_beacon->overlap_bss_offset = -+ adapter->scan_table[beacon_idx]. -+ overlap_bss_offset; -+ } -+ /* Point the new entry to its permanent storage space */ -+ new_beacon->beacon_buf = bcn_store; -+ mwifiex_update_beacon_buffer_ptrs(new_beacon); -+ } else { -+ /* -+ * No existing beacon data exists for this entry, check to see -+ * if we can fit it in the remaining space -+ */ -+ if (adapter->bcn_buf_end + new_beacon->beacon_buf_size + -+ SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf + -+ sizeof(adapter->bcn_buf))) { -+ -+ /* -+ * Copy the beacon buffer data from the local entry to -+ * the adapter dev struct buffer space used to store -+ * the raw beacon data for each entry in the scan table -+ */ -+ memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf, -+ new_beacon->beacon_buf_size); -+ -+ /* Update the beacon ptr to point to the table save -+ area */ -+ new_beacon->beacon_buf = adapter->bcn_buf_end; -+ new_beacon->beacon_buf_size_max = -+ (new_beacon->beacon_buf_size + -+ SCAN_BEACON_ENTRY_PAD); -+ -+ mwifiex_update_beacon_buffer_ptrs(new_beacon); -+ -+ /* Increment the end pointer by the size reserved */ -+ adapter->bcn_buf_end += new_beacon->beacon_buf_size_max; -+ -+ dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]" -+ " sz=%03d, used = %04d, left = %04d\n", -+ beacon_idx, -+ new_beacon->beacon_buf_size, -+ (int)(adapter->bcn_buf_end - adapter->bcn_buf), -+ (int)(sizeof(adapter->bcn_buf) - -+ (adapter->bcn_buf_end - -+ adapter->bcn_buf))); -+ } else { -+ /* No space for new beacon */ -+ dev_dbg(adapter->dev, "info: AppControl: no space for" -+ " beacon (%d): %pM sz=%03d, left=%03d\n", -+ beacon_idx, new_beacon->mac_address, -+ new_beacon->beacon_buf_size, -+ (int)(sizeof(adapter->bcn_buf) - -+ (adapter->bcn_buf_end - -+ adapter->bcn_buf))); -+ -+ /* Storage failure; clear storage records for this -+ bcn */ -+ new_beacon->beacon_buf = NULL; -+ new_beacon->beacon_buf_size = 0; -+ new_beacon->beacon_buf_size_max = 0; -+ new_beacon->bcn_wpa_ie = NULL; -+ new_beacon->wpa_offset = 0; -+ new_beacon->bcn_rsn_ie = NULL; -+ new_beacon->rsn_offset = 0; -+ new_beacon->bcn_wapi_ie = NULL; -+ new_beacon->wapi_offset = 0; -+ new_beacon->bcn_ht_cap = NULL; -+ new_beacon->ht_cap_offset = 0; -+ new_beacon->bcn_ht_info = NULL; -+ new_beacon->ht_info_offset = 0; -+ new_beacon->bcn_bss_co_2040 = NULL; -+ new_beacon->bss_co_2040_offset = 0; -+ new_beacon->bcn_ext_cap = NULL; -+ new_beacon->ext_cap_offset = 0; -+ new_beacon->bcn_obss_scan = NULL; -+ new_beacon->overlap_bss_offset = 0; -+ } -+ } -+} -+ -+/* -+ * This function restores a beacon buffer of the current BSS descriptor. -+ */ -+static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bssdescriptor *curr_bss = -+ &priv->curr_bss_params.bss_descriptor; -+ unsigned long flags; -+ -+ if (priv->curr_bcn_buf && -+ ((adapter->bcn_buf_end + priv->curr_bcn_size) < -+ (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) { -+ spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); -+ -+ /* restore the current beacon buffer */ -+ memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf, -+ priv->curr_bcn_size); -+ curr_bss->beacon_buf = adapter->bcn_buf_end; -+ curr_bss->beacon_buf_size = priv->curr_bcn_size; -+ adapter->bcn_buf_end += priv->curr_bcn_size; -+ -+ /* adjust the pointers in the current BSS descriptor */ -+ if (curr_bss->bcn_wpa_ie) -+ curr_bss->bcn_wpa_ie = -+ (struct ieee_types_vendor_specific *) -+ (curr_bss->beacon_buf + -+ curr_bss->wpa_offset); -+ -+ if (curr_bss->bcn_rsn_ie) -+ curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) -+ (curr_bss->beacon_buf + -+ curr_bss->rsn_offset); -+ -+ if (curr_bss->bcn_ht_cap) -+ curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) -+ (curr_bss->beacon_buf + -+ curr_bss->ht_cap_offset); -+ -+ if (curr_bss->bcn_ht_info) -+ curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) -+ (curr_bss->beacon_buf + -+ curr_bss->ht_info_offset); -+ -+ if (curr_bss->bcn_bss_co_2040) -+ curr_bss->bcn_bss_co_2040 = -+ (u8 *) (curr_bss->beacon_buf + -+ curr_bss->bss_co_2040_offset); -+ -+ if (curr_bss->bcn_ext_cap) -+ curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf + -+ curr_bss->ext_cap_offset); -+ -+ if (curr_bss->bcn_obss_scan) -+ curr_bss->bcn_obss_scan = -+ (struct ieee_types_obss_scan_param *) -+ (curr_bss->beacon_buf + -+ curr_bss->overlap_bss_offset); -+ -+ spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); -+ -+ dev_dbg(adapter->dev, "info: current beacon restored %d\n", -+ priv->curr_bcn_size); -+ } else { -+ dev_warn(adapter->dev, -+ "curr_bcn_buf not saved or bcn_buf has no space\n"); -+ } -+} -+ -+/* -+ * This function post processes the scan table after a new scan command has -+ * completed. -+ * -+ * It inspects each entry of the scan table and tries to find an entry that -+ * matches with our current associated/joined network from the scan. If -+ * one is found, the stored copy of the BSS descriptor of our current network -+ * is updated. -+ * -+ * It also debug dumps the current scan table contents after processing is over. -+ */ -+static void -+mwifiex_process_scan_results(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ s32 j; -+ u32 i; -+ unsigned long flags; -+ -+ if (priv->media_connected) { -+ -+ j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params. -+ bss_descriptor.ssid, -+ priv->curr_bss_params. -+ bss_descriptor.mac_address, -+ priv->bss_mode); -+ -+ if (j >= 0) { -+ spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); -+ priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL; -+ priv->curr_bss_params.bss_descriptor.wpa_offset = 0; -+ priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL; -+ priv->curr_bss_params.bss_descriptor.rsn_offset = 0; -+ priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; -+ priv->curr_bss_params.bss_descriptor.wapi_offset = 0; -+ priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; -+ priv->curr_bss_params.bss_descriptor.ht_cap_offset = -+ 0; -+ priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; -+ priv->curr_bss_params.bss_descriptor.ht_info_offset = -+ 0; -+ priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = -+ NULL; -+ priv->curr_bss_params.bss_descriptor. -+ bss_co_2040_offset = 0; -+ priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; -+ priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; -+ priv->curr_bss_params.bss_descriptor. -+ bcn_obss_scan = NULL; -+ priv->curr_bss_params.bss_descriptor. -+ overlap_bss_offset = 0; -+ priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; -+ priv->curr_bss_params.bss_descriptor.beacon_buf_size = -+ 0; -+ priv->curr_bss_params.bss_descriptor. -+ beacon_buf_size_max = 0; -+ -+ dev_dbg(adapter->dev, "info: Found current ssid/bssid" -+ " in list @ index #%d\n", j); -+ /* Make a copy of current BSSID descriptor */ -+ memcpy(&priv->curr_bss_params.bss_descriptor, -+ &adapter->scan_table[j], -+ sizeof(priv->curr_bss_params.bss_descriptor)); -+ -+ mwifiex_save_curr_bcn(priv); -+ spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); -+ -+ } else { -+ mwifiex_restore_curr_bcn(priv); -+ } -+ } -+ -+ for (i = 0; i < adapter->num_in_scan_table; i++) -+ dev_dbg(adapter->dev, "info: scan:(%02d) %pM " -+ "RSSI[%03d], SSID[%s]\n", -+ i, adapter->scan_table[i].mac_address, -+ (s32) adapter->scan_table[i].rssi, -+ adapter->scan_table[i].ssid.ssid); -+} -+ -+/* -+ * This function converts radio type scan parameter to a band configuration -+ * to be used in join command. -+ */ -+static u8 -+mwifiex_radio_type_to_band(u8 radio_type) -+{ -+ switch (radio_type) { -+ case HostCmd_SCAN_RADIO_TYPE_A: -+ return BAND_A; -+ case HostCmd_SCAN_RADIO_TYPE_BG: -+ default: -+ return BAND_G; -+ } -+} -+ -+/* -+ * This function deletes a specific indexed entry from the scan table. -+ * -+ * This also compacts the remaining entries and adjusts any buffering -+ * of beacon/probe response data if needed. -+ */ -+static void -+mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u32 del_idx; -+ u32 beacon_buf_adj; -+ u8 *beacon_buf; -+ -+ /* -+ * Shift the saved beacon buffer data for the scan table back over the -+ * entry being removed. Update the end of buffer pointer. Save the -+ * deleted buffer allocation size for pointer adjustments for entries -+ * compacted after the deleted index. -+ */ -+ beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max; -+ -+ dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer " -+ "removal = %d bytes\n", table_idx, beacon_buf_adj); -+ -+ /* Check if the table entry had storage allocated for its beacon */ -+ if (beacon_buf_adj) { -+ beacon_buf = adapter->scan_table[table_idx].beacon_buf; -+ -+ /* -+ * Remove the entry's buffer space, decrement the table end -+ * pointer by the amount we are removing -+ */ -+ adapter->bcn_buf_end -= beacon_buf_adj; -+ -+ dev_dbg(adapter->dev, "info: scan: delete entry %d," -+ " compact data: %p <- %p (sz = %d)\n", -+ table_idx, beacon_buf, -+ beacon_buf + beacon_buf_adj, -+ (int)(adapter->bcn_buf_end - beacon_buf)); -+ -+ /* -+ * Compact data storage. Copy all data after the deleted -+ * entry's end address (beacon_buf + beacon_buf_adj) back -+ * to the original start address (beacon_buf). -+ * -+ * Scan table entries affected by the move will have their -+ * entry pointer adjusted below. -+ * -+ * Use memmove since the dest/src memory regions overlap. -+ */ -+ memmove(beacon_buf, beacon_buf + beacon_buf_adj, -+ adapter->bcn_buf_end - beacon_buf); -+ } -+ -+ dev_dbg(adapter->dev, -+ "info: Scan: Delete Entry %d, num_in_scan_table = %d\n", -+ table_idx, adapter->num_in_scan_table); -+ -+ /* Shift all of the entries after the table_idx back by one, compacting -+ the table and removing the requested entry */ -+ for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table; -+ del_idx++) { -+ /* Copy the next entry over this one */ -+ memcpy(adapter->scan_table + del_idx, -+ adapter->scan_table + del_idx + 1, -+ sizeof(struct mwifiex_bssdescriptor)); -+ -+ /* -+ * Adjust this entry's pointer to its beacon buffer based on -+ * the removed/compacted entry from the deleted index. Don't -+ * decrement if the buffer pointer is NULL (no data stored for -+ * this entry). -+ */ -+ if (adapter->scan_table[del_idx].beacon_buf) { -+ adapter->scan_table[del_idx].beacon_buf -= -+ beacon_buf_adj; -+ if (adapter->scan_table[del_idx].bcn_wpa_ie) -+ adapter->scan_table[del_idx].bcn_wpa_ie = -+ (struct ieee_types_vendor_specific *) -+ (adapter->scan_table[del_idx]. -+ beacon_buf + -+ adapter->scan_table[del_idx]. -+ wpa_offset); -+ if (adapter->scan_table[del_idx].bcn_rsn_ie) -+ adapter->scan_table[del_idx].bcn_rsn_ie = -+ (struct ieee_types_generic *) -+ (adapter->scan_table[del_idx]. -+ beacon_buf + -+ adapter->scan_table[del_idx]. -+ rsn_offset); -+ if (adapter->scan_table[del_idx].bcn_wapi_ie) -+ adapter->scan_table[del_idx].bcn_wapi_ie = -+ (struct ieee_types_generic *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ wapi_offset); -+ if (adapter->scan_table[del_idx].bcn_ht_cap) -+ adapter->scan_table[del_idx].bcn_ht_cap = -+ (struct ieee80211_ht_cap *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ ht_cap_offset); -+ -+ if (adapter->scan_table[del_idx].bcn_ht_info) -+ adapter->scan_table[del_idx].bcn_ht_info = -+ (struct ieee80211_ht_info *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ ht_info_offset); -+ if (adapter->scan_table[del_idx].bcn_bss_co_2040) -+ adapter->scan_table[del_idx].bcn_bss_co_2040 = -+ (u8 *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ bss_co_2040_offset); -+ if (adapter->scan_table[del_idx].bcn_ext_cap) -+ adapter->scan_table[del_idx].bcn_ext_cap = -+ (u8 *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ ext_cap_offset); -+ if (adapter->scan_table[del_idx].bcn_obss_scan) -+ adapter->scan_table[del_idx]. -+ bcn_obss_scan = -+ (struct ieee_types_obss_scan_param *) -+ (adapter->scan_table[del_idx].beacon_buf -+ + adapter->scan_table[del_idx]. -+ overlap_bss_offset); -+ } -+ } -+ -+ /* The last entry is invalid now that it has been deleted or moved -+ back */ -+ memset(adapter->scan_table + adapter->num_in_scan_table - 1, -+ 0x00, sizeof(struct mwifiex_bssdescriptor)); -+ -+ adapter->num_in_scan_table--; -+} -+ -+/* -+ * This function deletes all occurrences of a given SSID from the scan table. -+ * -+ * This iterates through the scan table and deletes all entries that match -+ * the given SSID. It also compacts the remaining scan table entries. -+ */ -+static int -+mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *del_ssid) -+{ -+ s32 table_idx = -1; -+ -+ dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n", -+ del_ssid->ssid); -+ -+ /* If the requested SSID is found in the table, delete it. Then keep -+ searching the table for multiple entires for the SSID until no -+ more are found */ -+ while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL, -+ NL80211_IFTYPE_UNSPECIFIED)) >= 0) { -+ dev_dbg(priv->adapter->dev, -+ "info: Scan: Delete SSID Entry: Found Idx = %d\n", -+ table_idx); -+ mwifiex_scan_delete_table_entry(priv, table_idx); -+ } -+ -+ return table_idx == -1 ? -1 : 0; -+} -+ -+/* -+ * This is an internal function used to start a scan based on an input -+ * configuration. -+ * -+ * This uses the input user scan configuration information when provided in -+ * order to send the appropriate scan commands to firmware to populate or -+ * update the internal driver scan table. -+ */ -+int mwifiex_scan_networks(struct mwifiex_private *priv, -+ const struct mwifiex_user_scan_cfg *user_scan_in) -+{ -+ int ret = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct cmd_ctrl_node *cmd_node = NULL; -+ union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL; -+ struct mwifiex_ie_types_chan_list_param_set *chan_list_out; -+ u32 buf_size; -+ struct mwifiex_chan_scan_param_set *scan_chan_list; -+ u8 keep_previous_scan; -+ u8 filtered_scan; -+ u8 scan_current_chan_only; -+ u8 max_chan_per_scan; -+ unsigned long flags; -+ -+ if (adapter->scan_processing) { -+ dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); -+ return ret; -+ } -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->scan_processing = true; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ -+ if (priv->scan_block) { -+ dev_dbg(adapter->dev, -+ "cmd: Scan is blocked during association...\n"); -+ return ret; -+ } -+ -+ scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv), -+ GFP_KERNEL); -+ if (!scan_cfg_out) { -+ dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); -+ return -1; -+ } -+ -+ buf_size = sizeof(struct mwifiex_chan_scan_param_set) * -+ MWIFIEX_USER_SCAN_CHAN_MAX; -+ scan_chan_list = kzalloc(buf_size, GFP_KERNEL); -+ if (!scan_chan_list) { -+ dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); -+ kfree(scan_cfg_out); -+ return -1; -+ } -+ -+ keep_previous_scan = false; -+ -+ mwifiex_scan_setup_scan_config(priv, user_scan_in, -+ &scan_cfg_out->config, &chan_list_out, -+ scan_chan_list, &max_chan_per_scan, -+ &filtered_scan, &scan_current_chan_only); -+ -+ if (user_scan_in) -+ keep_previous_scan = user_scan_in->keep_previous_scan; -+ -+ -+ if (!keep_previous_scan) { -+ memset(adapter->scan_table, 0x00, -+ sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); -+ adapter->num_in_scan_table = 0; -+ adapter->bcn_buf_end = adapter->bcn_buf; -+ } -+ -+ 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) { -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ if (!list_empty(&adapter->scan_pending_q)) { -+ cmd_node = list_first_entry(&adapter->scan_pending_q, -+ struct cmd_ctrl_node, list); -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, -+ flags); -+ mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, -+ true); -+ } else { -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, -+ flags); -+ } -+ } else { -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->scan_processing = true; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ } -+ -+ kfree(scan_cfg_out); -+ kfree(scan_chan_list); -+ return ret; -+} -+ -+/* -+ * This function prepares a scan command to be sent to the firmware. -+ * -+ * This uses the scan command configuration sent to the command processing -+ * module in command preparation stage to configure a scan command structure -+ * to send to firmware. -+ * -+ * The fixed fields specifying the BSS type and BSSID filters as well as a -+ * variable number/length of TLVs are sent in the command to firmware. -+ * -+ * Preparation also includes - -+ * - Setting command ID, and proper size -+ * - Ensuring correct endian-ness -+ */ -+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; -+ -+ scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf; -+ -+ /* Set fixed field variables in scan command */ -+ scan_cmd->bss_mode = scan_cfg->bss_mode; -+ memcpy(scan_cmd->bssid, scan_cfg->specific_bssid, -+ sizeof(scan_cmd->bssid)); -+ memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN); -+ -+ /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ -+ cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode) -+ + sizeof(scan_cmd->bssid) -+ + scan_cfg->tlv_buf_len + S_DS_GEN)); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of scan. -+ * -+ * The response buffer for the scan command has the following -+ * memory layout: -+ * -+ * .-------------------------------------------------------------. -+ * | Header (4 * sizeof(t_u16)): Standard command response hdr | -+ * .-------------------------------------------------------------. -+ * | BufSize (t_u16) : sizeof the BSS Description data | -+ * .-------------------------------------------------------------. -+ * | NumOfSet (t_u8) : Number of BSS Descs returned | -+ * .-------------------------------------------------------------. -+ * | BSSDescription data (variable, size given in BufSize) | -+ * .-------------------------------------------------------------. -+ * | TLV data (variable, size calculated using Header->Size, | -+ * | BufSize and sizeof the fixed fields above) | -+ * .-------------------------------------------------------------. -+ */ -+int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ int ret = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ 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; -+ struct mwifiex_ie_types_data *tlv_data; -+ struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; -+ u8 *bss_info; -+ u32 scan_resp_size; -+ u32 bytes_left; -+ u32 num_in_table; -+ u32 bss_idx; -+ u32 idx; -+ u32 tlv_buf_size; -+ long long tsf_val; -+ struct mwifiex_chan_freq_power *cfp; -+ struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; -+ struct chan_band_param_set *chan_band; -+ u8 band; -+ u8 is_bgscan_resp; -+ unsigned long flags; -+ -+ is_bgscan_resp = (le16_to_cpu(resp->command) -+ == HostCmd_CMD_802_11_BG_SCAN_QUERY); -+ if (is_bgscan_resp) -+ scan_rsp = &resp->params.bg_scan_query_resp.scan_resp; -+ else -+ scan_rsp = &resp->params.scan_resp; -+ -+ -+ if (scan_rsp->number_of_sets > IW_MAX_AP) { -+ dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", -+ scan_rsp->number_of_sets); -+ ret = -1; -+ goto done; -+ } -+ -+ bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); -+ dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", -+ bytes_left); -+ -+ scan_resp_size = le16_to_cpu(resp->size); -+ -+ dev_dbg(adapter->dev, -+ "info: SCAN_RESP: returned %d APs before parsing\n", -+ scan_rsp->number_of_sets); -+ -+ num_in_table = adapter->num_in_scan_table; -+ bss_info = scan_rsp->bss_desc_and_tlv_buffer; -+ -+ /* -+ * The size of the TLV buffer is equal to the entire command response -+ * size (scan_resp_size) minus the fixed fields (sizeof()'s), the -+ * BSS Descriptions (bss_descript_size as bytesLef) and the command -+ * response header (S_DS_GEN) -+ */ -+ tlv_buf_size = scan_resp_size - (bytes_left -+ + sizeof(scan_rsp->bss_descript_size) -+ + sizeof(scan_rsp->number_of_sets) -+ + S_DS_GEN); -+ -+ tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp-> -+ bss_desc_and_tlv_buffer + -+ bytes_left); -+ -+ /* Search the TLV buffer space in the scan response for any valid -+ TLVs */ -+ mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, -+ TLV_TYPE_TSFTIMESTAMP, -+ (struct mwifiex_ie_types_data **) -+ &tsf_tlv); -+ -+ /* Search the TLV buffer space in the scan response for any valid -+ TLVs */ -+ mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, -+ TLV_TYPE_CHANNELBANDLIST, -+ (struct mwifiex_ie_types_data **) -+ &chan_band_tlv); -+ -+ /* -+ * Process each scan response returned (scan_rsp->number_of_sets). -+ * Save the information in the bss_new_entry and then insert into the -+ * driver scan table either as an update to an existing entry -+ * or as an addition at the end of the table -+ */ -+ bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor), -+ GFP_KERNEL); -+ if (!bss_new_entry) { -+ dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); -+ return -1; -+ } -+ -+ for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { -+ /* Zero out the bss_new_entry we are about to store info in */ -+ memset(bss_new_entry, 0x00, -+ sizeof(struct mwifiex_bssdescriptor)); -+ -+ if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, -+ &bss_info, -+ &bytes_left)) { -+ /* Error parsing/interpreting scan response, skipped */ -+ dev_err(adapter->dev, "SCAN_RESP: " -+ "mwifiex_interpret_bss_desc_with_ie " -+ "returned ERROR\n"); -+ continue; -+ } -+ -+ /* Process the data fields and IEs returned for this BSS */ -+ dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", -+ bss_new_entry->mac_address); -+ -+ /* Search the scan table for the same bssid */ -+ for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { -+ if (memcmp(bss_new_entry->mac_address, -+ adapter->scan_table[bss_idx].mac_address, -+ sizeof(bss_new_entry->mac_address))) { -+ continue; -+ } -+ /* -+ * If the SSID matches as well, it is a -+ * duplicate of this entry. Keep the bss_idx -+ * set to this entry so we replace the old -+ * contents in the table -+ */ -+ if ((bss_new_entry->ssid.ssid_len -+ == adapter->scan_table[bss_idx]. ssid.ssid_len) -+ && (!memcmp(bss_new_entry->ssid.ssid, -+ adapter->scan_table[bss_idx].ssid.ssid, -+ bss_new_entry->ssid.ssid_len))) { -+ dev_dbg(adapter->dev, "info: SCAN_RESP:" -+ " duplicate of index: %d\n", bss_idx); -+ break; -+ } -+ } -+ /* -+ * If the bss_idx is equal to the number of entries in -+ * the table, the new entry was not a duplicate; append -+ * it to the scan table -+ */ -+ if (bss_idx == num_in_table) { -+ /* Range check the bss_idx, keep it limited to -+ the last entry */ -+ if (bss_idx == IW_MAX_AP) -+ bss_idx--; -+ else -+ num_in_table++; -+ } -+ -+ /* -+ * Save the beacon/probe response returned for later application -+ * retrieval. Duplicate beacon/probe responses are updated if -+ * possible -+ */ -+ mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx, -+ num_in_table, bss_new_entry); -+ /* -+ * If the TSF TLV was appended to the scan results, save this -+ * entry's TSF value in the networkTSF field.The networkTSF is -+ * the firmware's TSF value at the time the beacon or probe -+ * response was received. -+ */ -+ if (tsf_tlv) { -+ memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] -+ , sizeof(tsf_val)); -+ memcpy(&bss_new_entry->network_tsf, &tsf_val, -+ sizeof(bss_new_entry->network_tsf)); -+ } -+ band = BAND_G; -+ if (chan_band_tlv) { -+ chan_band = &chan_band_tlv->chan_band_param[idx]; -+ band = mwifiex_radio_type_to_band(chan_band->radio_type -+ & (BIT(0) | BIT(1))); -+ } -+ -+ /* Save the band designation for this entry for use in join */ -+ bss_new_entry->bss_band = band; -+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, -+ (u8) bss_new_entry->bss_band, -+ (u16)bss_new_entry->channel); -+ -+ if (cfp) -+ bss_new_entry->freq = cfp->freq; -+ else -+ bss_new_entry->freq = 0; -+ -+ /* Copy the locally created bss_new_entry to the scan table */ -+ memcpy(&adapter->scan_table[bss_idx], bss_new_entry, -+ sizeof(adapter->scan_table[bss_idx])); -+ -+ } -+ -+ dev_dbg(adapter->dev, -+ "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", -+ scan_rsp->number_of_sets, -+ num_in_table - adapter->num_in_scan_table, num_in_table); -+ -+ /* Update the total number of BSSIDs in the scan table */ -+ adapter->num_in_scan_table = num_in_table; -+ -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ if (list_empty(&adapter->scan_pending_q)) { -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->scan_processing = false; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ /* -+ * Process the resulting scan table: -+ * - Remove any bad ssids -+ * - Update our current BSS information from scan data -+ */ -+ mwifiex_process_scan_results(priv); -+ -+ /* Need to indicate IOCTL complete */ -+ 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; -+ if (priv->scan_pending_on_block) { -+ priv->scan_pending_on_block = false; -+ up(&priv->async_sem); -+ } -+ -+ } else { -+ /* Get scan command from scan_pending_q and put to -+ cmd_pending_q */ -+ cmd_node = list_first_entry(&adapter->scan_pending_q, -+ struct cmd_ctrl_node, list); -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -+ -+ mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); -+ } -+ -+done: -+ kfree((u8 *) bss_new_entry); -+ return ret; -+} -+ -+/* -+ * This function prepares command for background scan query. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting background scan flush parameter -+ * - Ensuring correct endian-ness -+ */ -+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; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query) -+ + S_DS_GEN); -+ -+ bg_query->flush = 1; -+ -+ return 0; -+} -+ -+/* -+ * This function finds a SSID in the scan table. -+ * -+ * A BSSID may optionally be provided to qualify the SSID. -+ * For non-Auto mode, further check is made to make sure the -+ * BSS found in the scan table is compatible with the current -+ * settings of the driver. -+ */ -+s32 -+mwifiex_find_ssid_in_list(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *ssid, u8 *bssid, -+ u32 mode) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ s32 net = -1, j; -+ u8 best_rssi = 0; -+ u32 i; -+ -+ dev_dbg(adapter->dev, "info: num of entries in table = %d\n", -+ adapter->num_in_scan_table); -+ -+ /* -+ * Loop through the table until the maximum is reached or until a match -+ * is found based on the bssid field comparison -+ */ -+ for (i = 0; -+ i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0)); -+ i++) { -+ if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) && -+ (!bssid -+ || !memcmp(adapter->scan_table[i].mac_address, bssid, -+ ETH_ALEN)) -+ && -+ (mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, (u8) adapter->scan_table[i].bss_band, -+ (u16) adapter->scan_table[i].channel))) { -+ switch (mode) { -+ case NL80211_IFTYPE_STATION: -+ case NL80211_IFTYPE_ADHOC: -+ j = mwifiex_is_network_compatible(priv, i, -+ mode); -+ -+ if (j >= 0) { -+ if (SCAN_RSSI -+ (adapter->scan_table[i].rssi) > -+ best_rssi) { -+ best_rssi = SCAN_RSSI(adapter-> -+ scan_table -+ [i].rssi); -+ net = i; -+ } -+ } else { -+ if (net == -1) -+ net = j; -+ } -+ break; -+ case NL80211_IFTYPE_UNSPECIFIED: -+ default: -+ /* -+ * Do not check compatibility if the mode -+ * requested is Auto/Unknown. Allows generic -+ * find to work without verifying against the -+ * Adapter security settings -+ */ -+ if (SCAN_RSSI(adapter->scan_table[i].rssi) > -+ best_rssi) { -+ best_rssi = SCAN_RSSI(adapter-> -+ scan_table[i].rssi); -+ net = i; -+ } -+ break; -+ } -+ } -+ } -+ -+ return net; -+} -+ -+/* -+ * This function finds a specific compatible BSSID in the scan list. -+ * -+ * This function loops through the scan table looking for a compatible -+ * match. If a BSSID matches, but the BSS is found to be not compatible -+ * the function ignores it and continues to search through the rest of -+ * the entries in case there is an AP with multiple SSIDs assigned to -+ * the same BSSID. -+ */ -+s32 -+mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid, -+ u32 mode) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ s32 net = -1; -+ u32 i; -+ -+ if (!bssid) -+ return -1; -+ -+ dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n", -+ adapter->num_in_scan_table); -+ -+ /* -+ * Look through the scan table for a compatible match. The ret return -+ * variable will be equal to the index in the scan table (greater -+ * than zero) if the network is compatible. The loop will continue -+ * past a matched bssid that is not compatible in case there is an -+ * AP with multiple SSIDs assigned to the same BSSID -+ */ -+ for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) { -+ if (!memcmp -+ (adapter->scan_table[i].mac_address, bssid, ETH_ALEN) -+ && mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, -+ (u8) adapter-> -+ scan_table[i]. -+ bss_band, -+ (u16) adapter-> -+ scan_table[i]. -+ channel)) { -+ switch (mode) { -+ case NL80211_IFTYPE_STATION: -+ case NL80211_IFTYPE_ADHOC: -+ net = mwifiex_is_network_compatible(priv, i, -+ mode); -+ break; -+ default: -+ net = i; -+ break; -+ } -+ } -+ } -+ -+ return net; -+} -+ -+/* -+ * This function inserts scan command node to the scan pending queue. -+ */ -+void -+mwifiex_queue_scan_cmd(struct mwifiex_private *priv, -+ struct cmd_ctrl_node *cmd_node) -+{ -+ 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); -+} -+ -+/* -+ * This function finds an AP with specific ssid in the scan list. -+ */ -+int mwifiex_find_best_network(struct mwifiex_private *priv, -+ struct mwifiex_ssid_bssid *req_ssid_bssid) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bssdescriptor *req_bss; -+ s32 i; -+ -+ memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); -+ -+ i = mwifiex_find_best_network_in_list(priv); -+ -+ if (i >= 0) { -+ req_bss = &adapter->scan_table[i]; -+ memcpy(&req_ssid_bssid->ssid, &req_bss->ssid, -+ sizeof(struct mwifiex_802_11_ssid)); -+ memcpy((u8 *) &req_ssid_bssid->bssid, -+ (u8 *) &req_bss->mac_address, ETH_ALEN); -+ -+ /* Make sure we are in the right mode */ -+ if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED) -+ priv->bss_mode = req_bss->bss_mode; -+ } -+ -+ if (!req_ssid_bssid->ssid.ssid_len) -+ return -1; -+ -+ dev_dbg(adapter->dev, "info: Best network found = [%s], " -+ "[%pM]\n", req_ssid_bssid->ssid.ssid, -+ req_ssid_bssid->bssid); -+ -+ return 0; -+} -+ -+/* -+ * This function sends a scan command for all available channels to the -+ * firmware, filtered on a specific SSID. -+ */ -+static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, -+ struct mwifiex_802_11_ssid *req_ssid) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int ret = 0; -+ struct mwifiex_user_scan_cfg *scan_cfg; -+ -+ if (!req_ssid) -+ return -1; -+ -+ if (adapter->scan_processing) { -+ dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); -+ return ret; -+ } -+ -+ if (priv->scan_block) { -+ dev_dbg(adapter->dev, -+ "cmd: Scan is blocked during association...\n"); -+ return ret; -+ } -+ -+ mwifiex_scan_delete_ssid_table_entry(priv, req_ssid); -+ -+ scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); -+ if (!scan_cfg) { -+ dev_err(adapter->dev, "failed to alloc scan_cfg\n"); -+ return -1; -+ } -+ -+ memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, -+ req_ssid->ssid_len); -+ scan_cfg->keep_previous_scan = true; -+ -+ ret = mwifiex_scan_networks(priv, scan_cfg); -+ -+ kfree(scan_cfg); -+ return ret; -+} -+ -+/* -+ * Sends IOCTL request to start a scan. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ * -+ * 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, -+ struct mwifiex_802_11_ssid *req_ssid) -+{ -+ int ret = 0; -+ -+ if (down_interruptible(&priv->async_sem)) { -+ dev_err(priv->adapter->dev, "%s: acquire semaphore\n", -+ __func__); -+ return -1; -+ } -+ priv->scan_pending_on_block = true; -+ -+ priv->adapter->cmd_wait_q.condition = false; -+ -+ if (req_ssid && req_ssid->ssid_len != 0) -+ /* Specific SSID scan */ -+ ret = mwifiex_scan_specific_ssid(priv, req_ssid); -+ else -+ /* Normal scan */ -+ 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; -+} -+ -+/* -+ * This function appends the vendor specific IE TLV to a buffer. -+ */ -+int -+mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, -+ u16 vsie_mask, u8 **buffer) -+{ -+ int id, ret_len = 0; -+ struct mwifiex_ie_types_vendor_param_set *vs_param_set; -+ -+ if (!buffer) -+ return 0; -+ if (!(*buffer)) -+ return 0; -+ -+ /* -+ * Traverse through the saved vendor specific IE array and append -+ * the selected(scan/assoc/adhoc) IE as TLV to the command -+ */ -+ for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) { -+ if (priv->vs_ie[id].mask & vsie_mask) { -+ vs_param_set = -+ (struct mwifiex_ie_types_vendor_param_set *) -+ *buffer; -+ vs_param_set->header.type = -+ cpu_to_le16(TLV_TYPE_PASSTHROUGH); -+ vs_param_set->header.len = -+ cpu_to_le16((((u16) priv->vs_ie[id].ie[1]) -+ & 0x00FF) + 2); -+ memcpy(vs_param_set->ie, priv->vs_ie[id].ie, -+ le16_to_cpu(vs_param_set->header.len)); -+ *buffer += le16_to_cpu(vs_param_set->header.len) + -+ sizeof(struct mwifiex_ie_types_header); -+ ret_len += le16_to_cpu(vs_param_set->header.len) + -+ sizeof(struct mwifiex_ie_types_header); -+ } -+ } -+ return ret_len; -+} -+ -+/* -+ * This function saves a beacon buffer of the current BSS descriptor. -+ * -+ * The current beacon buffer is saved so that it can be restored in the -+ * following cases that makes the beacon buffer not to contain the current -+ * ssid's beacon buffer. -+ * - The current ssid was not found somehow in the last scan. -+ * - The current ssid was the last entry of the scan table and overloaded. -+ */ -+void -+mwifiex_save_curr_bcn(struct mwifiex_private *priv) -+{ -+ struct mwifiex_bssdescriptor *curr_bss = -+ &priv->curr_bss_params.bss_descriptor; -+ -+ if (!curr_bss->beacon_buf_size) -+ return; -+ -+ /* allocate beacon buffer at 1st time; or if it's size has changed */ -+ if (!priv->curr_bcn_buf || -+ priv->curr_bcn_size != curr_bss->beacon_buf_size) { -+ priv->curr_bcn_size = curr_bss->beacon_buf_size; -+ -+ kfree(priv->curr_bcn_buf); -+ priv->curr_bcn_buf = kzalloc(curr_bss->beacon_buf_size, -+ GFP_KERNEL); -+ if (!priv->curr_bcn_buf) { -+ dev_err(priv->adapter->dev, -+ "failed to alloc curr_bcn_buf\n"); -+ return; -+ } -+ } -+ -+ memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, -+ curr_bss->beacon_buf_size); -+ dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", -+ priv->curr_bcn_size); -+} -+ -+/* -+ * This function frees the current BSS descriptor beacon buffer. -+ */ -+void -+mwifiex_free_curr_bcn(struct mwifiex_private *priv) -+{ -+ kfree(priv->curr_bcn_buf); -+ priv->curr_bcn_buf = NULL; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sdio.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sdio.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sdio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sdio.c 2011-05-05 23:29:45.493441961 +0200 -@@ -0,0 +1,1753 @@ -+/* -+ * Marvell Wireless LAN device driver: SDIO specific handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+#include "sdio.h" -+ -+ -+#define SDIO_VERSION "1.0" -+ -+static struct mwifiex_if_ops sdio_ops; -+ -+static struct semaphore add_remove_card_sem; -+ -+/* -+ * SDIO probe. -+ * -+ * This function probes an mwifiex device and registers it. It allocates -+ * the card structure, enables SDIO function number and initiates the -+ * device registration and initialization procedure by adding a logical -+ * interface. -+ */ -+static int -+mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) -+{ -+ int ret = 0; -+ struct sdio_mmc_card *card = NULL; -+ -+ pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", -+ func->vendor, func->device, func->class, func->num); -+ -+ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); -+ if (!card) { -+ pr_err("%s: failed to alloc memory\n", __func__); -+ return -ENOMEM; -+ } -+ -+ card->func = func; -+ -+ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; -+ -+ sdio_claim_host(func); -+ ret = sdio_enable_func(func); -+ sdio_release_host(func); -+ -+ if (ret) { -+ pr_err("%s: failed to enable function\n", __func__); -+ return -EIO; -+ } -+ -+ if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops)) { -+ pr_err("%s: add card failed\n", __func__); -+ kfree(card); -+ sdio_claim_host(func); -+ ret = sdio_disable_func(func); -+ sdio_release_host(func); -+ ret = -1; -+ } -+ -+ return ret; -+} -+ -+/* -+ * SDIO remove. -+ * -+ * This function removes the interface and frees up the card structure. -+ */ -+static void -+mwifiex_sdio_remove(struct sdio_func *func) -+{ -+ struct sdio_mmc_card *card; -+ -+ pr_debug("info: SDIO func num=%d\n", func->num); -+ -+ if (func) { -+ card = sdio_get_drvdata(func); -+ if (card) { -+ mwifiex_remove_card(card->adapter, -+ &add_remove_card_sem); -+ kfree(card); -+ } -+ } -+} -+ -+/* -+ * SDIO suspend. -+ * -+ * Kernel needs to suspend all functions separately. Therefore all -+ * registered functions must have drivers with suspend and resume -+ * methods. Failing that the kernel simply removes the whole card. -+ * -+ * If already not suspended, this function allocates and sends a host -+ * sleep activate request to the firmware and turns off the traffic. -+ */ -+static int mwifiex_sdio_suspend(struct device *dev) -+{ -+ struct sdio_func *func = dev_to_sdio_func(dev); -+ struct sdio_mmc_card *card; -+ struct mwifiex_adapter *adapter = NULL; -+ mmc_pm_flag_t pm_flag = 0; -+ int hs_actived = 0; -+ int i; -+ int ret = 0; -+ -+ if (func) { -+ pm_flag = sdio_get_host_pm_caps(func); -+ pr_debug("cmd: %s: suspend: PM flag = 0x%x\n", -+ sdio_func_id(func), pm_flag); -+ if (!(pm_flag & MMC_PM_KEEP_POWER)) { -+ pr_err("%s: cannot remain alive while host is" -+ " suspended\n", sdio_func_id(func)); -+ return -ENOSYS; -+ } -+ -+ card = sdio_get_drvdata(func); -+ if (!card || !card->adapter) { -+ pr_err("suspend: invalid card or adapter\n"); -+ return 0; -+ } -+ } else { -+ pr_err("suspend: sdio_func is not specified\n"); -+ return 0; -+ } -+ -+ adapter = card->adapter; -+ -+ /* Enable the Host Sleep */ -+ hs_actived = mwifiex_enable_hs(adapter); -+ if (hs_actived) { -+ pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); -+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); -+ } -+ -+ /* Indicate device suspended */ -+ adapter->is_suspended = true; -+ -+ for (i = 0; i < adapter->priv_num; i++) -+ netif_carrier_off(adapter->priv[i]->netdev); -+ -+ return ret; -+} -+ -+/* -+ * SDIO resume. -+ * -+ * Kernel needs to suspend all functions separately. Therefore all -+ * registered functions must have drivers with suspend and resume -+ * methods. Failing that the kernel simply removes the whole card. -+ * -+ * If already not resumed, this function turns on the traffic and -+ * sends a host sleep cancel request to the firmware. -+ */ -+static int mwifiex_sdio_resume(struct device *dev) -+{ -+ struct sdio_func *func = dev_to_sdio_func(dev); -+ struct sdio_mmc_card *card; -+ struct mwifiex_adapter *adapter = NULL; -+ mmc_pm_flag_t pm_flag = 0; -+ int i; -+ -+ if (func) { -+ pm_flag = sdio_get_host_pm_caps(func); -+ card = sdio_get_drvdata(func); -+ if (!card || !card->adapter) { -+ pr_err("resume: invalid card or adapter\n"); -+ return 0; -+ } -+ } else { -+ pr_err("resume: sdio_func is not specified\n"); -+ return 0; -+ } -+ -+ adapter = card->adapter; -+ -+ if (!adapter->is_suspended) { -+ dev_warn(adapter->dev, "device already resumed\n"); -+ return 0; -+ } -+ -+ adapter->is_suspended = false; -+ -+ for (i = 0; i < adapter->priv_num; i++) -+ if (adapter->priv[i]->media_connected) -+ netif_carrier_on(adapter->priv[i]->netdev); -+ -+ /* Disable Host Sleep */ -+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), -+ MWIFIEX_ASYNC_CMD); -+ -+ return 0; -+} -+ -+/* Device ID for SD8787 */ -+#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) -+ -+/* WLAN IDs */ -+static const struct sdio_device_id mwifiex_ids[] = { -+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(sdio, mwifiex_ids); -+ -+static const struct dev_pm_ops mwifiex_sdio_pm_ops = { -+ .suspend = mwifiex_sdio_suspend, -+ .resume = mwifiex_sdio_resume, -+}; -+ -+static struct sdio_driver mwifiex_sdio = { -+ .name = "mwifiex_sdio", -+ .id_table = mwifiex_ids, -+ .probe = mwifiex_sdio_probe, -+ .remove = mwifiex_sdio_remove, -+ .drv = { -+ .owner = THIS_MODULE, -+ .pm = &mwifiex_sdio_pm_ops, -+ } -+}; -+ -+/* -+ * This function writes data into SDIO card register. -+ */ -+static int -+mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u32 data) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = -1; -+ -+ sdio_claim_host(card->func); -+ sdio_writeb(card->func, (u8) data, reg, &ret); -+ sdio_release_host(card->func); -+ -+ return ret; -+} -+ -+/* -+ * This function reads data from SDIO card register. -+ */ -+static int -+mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = -1; -+ u8 val; -+ -+ sdio_claim_host(card->func); -+ val = sdio_readb(card->func, reg, &ret); -+ sdio_release_host(card->func); -+ -+ *data = val; -+ -+ return ret; -+} -+ -+/* -+ * This function writes multiple data into SDIO card memory. -+ * -+ * This does not work in suspended mode. -+ */ -+static int -+mwifiex_write_data_sync(struct mwifiex_adapter *adapter, -+ u8 *buffer, u32 pkt_len, u32 port) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = -1; -+ u8 blk_mode = -+ (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; -+ u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; -+ u32 blk_cnt = -+ (blk_mode == -+ BLOCK_MODE) ? (pkt_len / -+ MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; -+ u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); -+ -+ if (adapter->is_suspended) { -+ dev_err(adapter->dev, -+ "%s: not allowed while suspended\n", __func__); -+ return -1; -+ } -+ -+ sdio_claim_host(card->func); -+ -+ if (!sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size)) -+ ret = 0; -+ -+ sdio_release_host(card->func); -+ -+ return ret; -+} -+ -+/* -+ * 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, u8 claim) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = -1; -+ u8 blk_mode = -+ (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; -+ u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; -+ u32 blk_cnt = -+ (blk_mode == -+ BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) : len; -+ u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); -+ -+ if (claim) -+ sdio_claim_host(card->func); -+ -+ if (!sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size)) -+ ret = 0; -+ -+ if (claim) -+ sdio_release_host(card->func); -+ -+ return ret; -+} -+ -+/* -+ * This function wakes up the card. -+ * -+ * A host power up command is written to the card configuration -+ * register to wake up the card. -+ */ -+static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) -+{ -+ dev_dbg(adapter->dev, "event: wakeup device...\n"); -+ -+ return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); -+} -+ -+/* -+ * This function is called after the card has woken up. -+ * -+ * The card configuration register is reset. -+ */ -+static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) -+{ -+ dev_dbg(adapter->dev, "cmd: wakeup device completed\n"); -+ -+ return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); -+} -+ -+/* -+ * This function initializes the IO ports. -+ * -+ * The following operations are performed - -+ * - Read the IO ports (0, 1 and 2) -+ * - Set host interrupt Reset-To-Read to clear -+ * - Set auto re-enable interrupt -+ */ -+static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) -+{ -+ u32 reg; -+ -+ adapter->ioport = 0; -+ -+ /* Read the IO port */ -+ if (!mwifiex_read_reg(adapter, IO_PORT_0_REG, ®)) -+ adapter->ioport |= (reg & 0xff); -+ else -+ return -1; -+ -+ if (!mwifiex_read_reg(adapter, IO_PORT_1_REG, ®)) -+ adapter->ioport |= ((reg & 0xff) << 8); -+ else -+ return -1; -+ -+ if (!mwifiex_read_reg(adapter, IO_PORT_2_REG, ®)) -+ adapter->ioport |= ((reg & 0xff) << 16); -+ else -+ return -1; -+ -+ pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); -+ -+ /* Set Host interrupt reset to read to clear */ -+ if (!mwifiex_read_reg(adapter, HOST_INT_RSR_REG, ®)) -+ mwifiex_write_reg(adapter, HOST_INT_RSR_REG, -+ reg | SDIO_INT_MASK); -+ else -+ return -1; -+ -+ /* Dnld/Upld ready set to auto reset */ -+ if (!mwifiex_read_reg(adapter, CARD_MISC_CFG_REG, ®)) -+ mwifiex_write_reg(adapter, CARD_MISC_CFG_REG, -+ reg | AUTO_RE_ENABLE_INT); -+ else -+ return -1; -+ -+ return 0; -+} -+ -+/* -+ * This function sends data to the card. -+ */ -+static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, -+ u8 *payload, u32 pkt_len, u32 port) -+{ -+ u32 i = 0; -+ int ret = 0; -+ -+ do { -+ ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); -+ if (ret) { -+ i++; -+ dev_err(adapter->dev, "host_to_card, write iomem" -+ " (%d) failed: %d\n", i, ret); -+ if (mwifiex_write_reg(adapter, -+ CONFIGURATION_REG, 0x04)) -+ dev_err(adapter->dev, "write CFG reg failed\n"); -+ -+ ret = -1; -+ if (i > MAX_WRITE_IOMEM_RETRY) -+ return ret; -+ } -+ } while (ret == -1); -+ -+ return ret; -+} -+ -+/* -+ * This function gets the read port. -+ * -+ * If control port bit is set in MP read bitmap, the control port -+ * is returned, otherwise the current read port is returned and -+ * the value is increased (provided it does not reach the maximum -+ * limit, in which case it is reset to 1) -+ */ -+static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ u16 rd_bitmap = card->mp_rd_bitmap; -+ -+ dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%04x\n", rd_bitmap); -+ -+ if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK))) -+ return -1; -+ -+ if (card->mp_rd_bitmap & CTRL_PORT_MASK) { -+ card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK); -+ *port = CTRL_PORT; -+ dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n", -+ *port, card->mp_rd_bitmap); -+ } else { -+ if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) { -+ card->mp_rd_bitmap &= -+ (u16) (~(1 << card->curr_rd_port)); -+ *port = card->curr_rd_port; -+ -+ if (++card->curr_rd_port == MAX_PORT) -+ card->curr_rd_port = 1; -+ } else { -+ return -1; -+ } -+ -+ dev_dbg(adapter->dev, -+ "data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n", -+ *port, rd_bitmap, card->mp_rd_bitmap); -+ } -+ return 0; -+} -+ -+/* -+ * This function gets the write port for data. -+ * -+ * The current write port is returned if available and the value is -+ * increased (provided it does not reach the maximum limit, in which -+ * case it is reset to 1) -+ */ -+static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ u16 wr_bitmap = card->mp_wr_bitmap; -+ -+ dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%04x\n", wr_bitmap); -+ -+ if (!(wr_bitmap & card->mp_data_port_mask)) -+ return -1; -+ -+ if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { -+ card->mp_wr_bitmap &= (u16) (~(1 << card->curr_wr_port)); -+ *port = card->curr_wr_port; -+ if (++card->curr_wr_port == card->mp_end_port) -+ card->curr_wr_port = 1; -+ } else { -+ adapter->data_sent = true; -+ return -EBUSY; -+ } -+ -+ if (*port == CTRL_PORT) { -+ dev_err(adapter->dev, "invalid data port=%d cur port=%d" -+ " mp_wr_bitmap=0x%04x -> 0x%04x\n", -+ *port, card->curr_wr_port, wr_bitmap, -+ card->mp_wr_bitmap); -+ return -1; -+ } -+ -+ dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n", -+ *port, wr_bitmap, card->mp_wr_bitmap); -+ -+ return 0; -+} -+ -+/* -+ * This function polls the card status. -+ */ -+static int -+mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) -+{ -+ u32 tries; -+ u32 cs = 0; -+ -+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { -+ if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) -+ break; -+ else if ((cs & bits) == bits) -+ return 0; -+ -+ udelay(10); -+ } -+ -+ dev_err(adapter->dev, "poll card status failed, tries = %d\n", -+ tries); -+ return -1; -+} -+ -+/* -+ * This function reads the firmware status. -+ */ -+static int -+mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) -+{ -+ u32 fws0 = 0, fws1 = 0; -+ -+ if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) -+ return -1; -+ -+ if (mwifiex_read_reg(adapter, CARD_FW_STATUS1_REG, &fws1)) -+ return -1; -+ -+ *dat = (u16) ((fws1 << 8) | fws0); -+ -+ return 0; -+} -+ -+/* -+ * This function disables the host interrupt. -+ * -+ * The host interrupt mask is read, the disable bit is reset and -+ * written back to the card host interrupt mask register. -+ */ -+static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) -+{ -+ u32 host_int_mask = 0; -+ -+ /* Read back the host_int_mask register */ -+ if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) -+ return -1; -+ -+ /* Update with the mask and write back to the register */ -+ host_int_mask &= ~HOST_INT_DISABLE; -+ -+ if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) { -+ dev_err(adapter->dev, "disable host interrupt failed\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function enables the host interrupt. -+ * -+ * The host interrupt enable mask is written to the card -+ * host interrupt mask register. -+ */ -+static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) -+{ -+ /* Simply write the mask to the register */ -+ if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, HOST_INT_ENABLE)) { -+ dev_err(adapter->dev, "enable host interrupt failed\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+/* -+ * This function sends a data buffer to the card. -+ */ -+static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, -+ u32 *type, u8 *buffer, -+ u32 npayload, u32 ioport) -+{ -+ int ret = 0; -+ u32 nb; -+ -+ if (!buffer) { -+ dev_err(adapter->dev, "%s: buffer is NULL\n", __func__); -+ return -1; -+ } -+ -+ ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1); -+ -+ if (ret) { -+ dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__, -+ ret); -+ return -1; -+ } -+ -+ nb = le16_to_cpu(*(__le16 *) (buffer)); -+ if (nb > npayload) { -+ dev_err(adapter->dev, "%s: invalid packet, nb=%d, npayload=%d\n", -+ __func__, nb, npayload); -+ return -1; -+ } -+ -+ *type = le16_to_cpu(*(__le16 *) (buffer + 2)); -+ -+ return ret; -+} -+ -+/* -+ * This function downloads the firmware to the card. -+ * -+ * Firmware is downloaded to the card in blocks. Every block download -+ * is tested for CRC errors, and retried a number of times before -+ * returning failure. -+ */ -+static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, -+ struct mwifiex_fw_image *fw) -+{ -+ int ret = 0; -+ u8 *firmware = fw->fw_buf; -+ u32 firmware_len = fw->fw_len; -+ u32 offset = 0; -+ u32 base0, base1; -+ u8 *fwbuf; -+ u16 len = 0; -+ u32 txlen = 0, tx_blocks = 0, tries = 0; -+ u32 i = 0; -+ -+ if (!firmware_len) { -+ dev_err(adapter->dev, "firmware image not found!" -+ " Terminating download\n"); -+ return -1; -+ } -+ -+ dev_dbg(adapter->dev, "info: downloading FW image (%d bytes)\n", -+ firmware_len); -+ -+ /* Assume that the allocated buffer is 8-byte aligned */ -+ fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL); -+ if (!fwbuf) { -+ dev_err(adapter->dev, "unable to alloc buffer for firmware." -+ " Terminating download\n"); -+ return -1; -+ } -+ -+ /* Perform firmware data transfer */ -+ do { -+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY -+ bits */ -+ ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY | -+ DN_LD_CARD_RDY); -+ if (ret) { -+ dev_err(adapter->dev, "FW download with helper:" -+ " poll status timeout @ %d\n", offset); -+ goto done; -+ } -+ -+ /* More data? */ -+ if (offset >= firmware_len) -+ break; -+ -+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { -+ ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0, -+ &base0); -+ if (ret) { -+ dev_err(adapter->dev, "dev BASE0 register read" -+ " failed: base0=0x%04X(%d). Terminating " -+ "download\n", base0, base0); -+ goto done; -+ } -+ ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1, -+ &base1); -+ if (ret) { -+ dev_err(adapter->dev, "dev BASE1 register read" -+ " failed: base1=0x%04X(%d). Terminating " -+ "download\n", base1, base1); -+ goto done; -+ } -+ len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff)); -+ -+ if (len) -+ break; -+ -+ udelay(10); -+ } -+ -+ if (!len) { -+ break; -+ } else if (len > MWIFIEX_UPLD_SIZE) { -+ dev_err(adapter->dev, "FW download failed @ %d," -+ " invalid length %d\n", offset, len); -+ ret = -1; -+ goto done; -+ } -+ -+ txlen = len; -+ -+ if (len & BIT(0)) { -+ i++; -+ if (i > MAX_WRITE_IOMEM_RETRY) { -+ dev_err(adapter->dev, "FW download failed @" -+ " %d, over max retry count\n", offset); -+ ret = -1; -+ goto done; -+ } -+ dev_err(adapter->dev, "CRC indicated by the helper:" -+ " len = 0x%04X, txlen = %d\n", len, txlen); -+ len &= ~BIT(0); -+ /* Setting this to 0 to resend from same offset */ -+ txlen = 0; -+ } else { -+ i = 0; -+ -+ /* Set blocksize to transfer - checking for last -+ block */ -+ if (firmware_len - offset < txlen) -+ txlen = firmware_len - offset; -+ -+ tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - -+ 1) / MWIFIEX_SDIO_BLOCK_SIZE; -+ -+ /* Copy payload to buffer */ -+ memmove(fwbuf, &firmware[offset], txlen); -+ } -+ -+ ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks * -+ MWIFIEX_SDIO_BLOCK_SIZE, -+ adapter->ioport); -+ if (ret) { -+ dev_err(adapter->dev, "FW download, write iomem (%d)" -+ " failed @ %d\n", i, offset); -+ if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04)) -+ dev_err(adapter->dev, "write CFG reg failed\n"); -+ -+ ret = -1; -+ goto done; -+ } -+ -+ offset += txlen; -+ } while (true); -+ -+ dev_dbg(adapter->dev, "info: FW download over, size %d bytes\n", -+ offset); -+ -+ ret = 0; -+done: -+ kfree(fwbuf); -+ return ret; -+} -+ -+/* -+ * This function checks the firmware status in card. -+ * -+ * The winner interface is also determined by this function. -+ */ -+static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, -+ u32 poll_num, int *winner) -+{ -+ int ret = 0; -+ u16 firmware_stat; -+ u32 tries; -+ u32 winner_status; -+ -+ /* Wait for firmware initialization event */ -+ for (tries = 0; tries < poll_num; tries++) { -+ ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); -+ if (ret) -+ continue; -+ if (firmware_stat == FIRMWARE_READY) { -+ ret = 0; -+ break; -+ } else { -+ mdelay(100); -+ ret = -1; -+ } -+ } -+ -+ if (winner && ret) { -+ if (mwifiex_read_reg -+ (adapter, CARD_FW_STATUS0_REG, &winner_status)) -+ winner_status = 0; -+ -+ if (winner_status) -+ *winner = 0; -+ else -+ *winner = 1; -+ } -+ return ret; -+} -+ -+/* -+ * This function reads the interrupt status from card. -+ */ -+static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ u32 sdio_ireg = 0; -+ unsigned long flags; -+ -+ if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, -+ REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, -+ 0)) { -+ dev_err(adapter->dev, "read mp_regs failed\n"); -+ return; -+ } -+ -+ sdio_ireg = card->mp_regs[HOST_INTSTATUS_REG]; -+ if (sdio_ireg) { -+ /* -+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS -+ * Clear the interrupt status register -+ */ -+ dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg); -+ spin_lock_irqsave(&adapter->int_lock, flags); -+ adapter->int_status |= sdio_ireg; -+ spin_unlock_irqrestore(&adapter->int_lock, flags); -+ } -+} -+ -+/* -+ * SDIO interrupt handler. -+ * -+ * This function reads the interrupt status from firmware and assigns -+ * the main process in workqueue which will handle the interrupt. -+ */ -+static void -+mwifiex_sdio_interrupt(struct sdio_func *func) -+{ -+ struct mwifiex_adapter *adapter; -+ struct sdio_mmc_card *card; -+ -+ card = sdio_get_drvdata(func); -+ if (!card || !card->adapter) { -+ pr_debug("int: func=%p card=%p adapter=%p\n", -+ func, card, card ? card->adapter : NULL); -+ return; -+ } -+ adapter = card->adapter; -+ -+ if (adapter->surprise_removed) -+ return; -+ -+ if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) -+ adapter->ps_state = PS_STATE_AWAKE; -+ -+ mwifiex_interrupt_status(adapter); -+ queue_work(adapter->workqueue, &adapter->main_work); -+} -+ -+/* -+ * This function decodes a received packet. -+ * -+ * Based on the type, the packet is treated as either a data, or -+ * a command response, or an event, and the correct handler -+ * function is invoked. -+ */ -+static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, u32 upld_typ) -+{ -+ u8 *cmd_buf; -+ -+ skb_pull(skb, INTF_HEADER_LEN); -+ -+ switch (upld_typ) { -+ case MWIFIEX_TYPE_DATA: -+ dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); -+ mwifiex_handle_rx_packet(adapter, skb); -+ break; -+ -+ case MWIFIEX_TYPE_CMD: -+ dev_dbg(adapter->dev, "info: --- Rx: Cmd Response ---\n"); -+ /* take care of curr_cmd = NULL case */ -+ if (!adapter->curr_cmd) { -+ cmd_buf = adapter->upld_buf; -+ -+ if (adapter->ps_state == PS_STATE_SLEEP_CFM) -+ mwifiex_process_sleep_confirm_resp(adapter, -+ skb->data, skb->len); -+ -+ memcpy(cmd_buf, skb->data, min_t(u32, -+ MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); -+ -+ dev_kfree_skb_any(skb); -+ } else { -+ adapter->cmd_resp_received = true; -+ adapter->curr_cmd->resp_skb = skb; -+ } -+ break; -+ -+ case MWIFIEX_TYPE_EVENT: -+ dev_dbg(adapter->dev, "info: --- Rx: Event ---\n"); -+ adapter->event_cause = *(u32 *) skb->data; -+ -+ skb_pull(skb, MWIFIEX_EVENT_HEADER_LEN); -+ -+ if ((skb->len > 0) && (skb->len < MAX_EVENT_SIZE)) -+ memcpy(adapter->event_body, skb->data, skb->len); -+ -+ /* event cause has been saved to adapter->event_cause */ -+ adapter->event_received = true; -+ adapter->event_skb = skb; -+ -+ break; -+ -+ default: -+ dev_err(adapter->dev, "unknown upload type %#x\n", upld_typ); -+ dev_kfree_skb_any(skb); -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function transfers received packets from card to driver, performing -+ * aggregation if required. -+ * -+ * For data received on control port, or if aggregation is disabled, the -+ * received buffers are uploaded as separate packets. However, if aggregation -+ * is enabled and required, the buffers are copied onto an aggregation buffer, -+ * provided there is space left, processed and finally uploaded. -+ */ -+static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, u8 port) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ s32 f_do_rx_aggr = 0; -+ s32 f_do_rx_cur = 0; -+ s32 f_aggr_cur = 0; -+ struct sk_buff *skb_deaggr; -+ u32 pind = 0; -+ u32 pkt_len, pkt_type = 0; -+ u8 *curr_ptr; -+ u32 rx_len = skb->len; -+ -+ if (port == CTRL_PORT) { -+ /* Read the command Resp without aggr */ -+ dev_dbg(adapter->dev, "info: %s: no aggregation for cmd " -+ "response\n", __func__); -+ -+ f_do_rx_cur = 1; -+ goto rx_curr_single; -+ } -+ -+ if (!card->mpa_rx.enabled) { -+ dev_dbg(adapter->dev, "info: %s: rx aggregation disabled\n", -+ __func__); -+ -+ f_do_rx_cur = 1; -+ goto rx_curr_single; -+ } -+ -+ if (card->mp_rd_bitmap & (~((u16) CTRL_PORT_MASK))) { -+ /* Some more data RX pending */ -+ dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); -+ -+ if (MP_RX_AGGR_IN_PROGRESS(card)) { -+ if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) { -+ f_aggr_cur = 1; -+ } else { -+ /* No room in Aggr buf, do rx aggr now */ -+ f_do_rx_aggr = 1; -+ f_do_rx_cur = 1; -+ } -+ } else { -+ /* Rx aggr not in progress */ -+ f_aggr_cur = 1; -+ } -+ -+ } else { -+ /* No more data RX pending */ -+ dev_dbg(adapter->dev, "info: %s: last packet\n", __func__); -+ -+ if (MP_RX_AGGR_IN_PROGRESS(card)) { -+ f_do_rx_aggr = 1; -+ if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) -+ f_aggr_cur = 1; -+ else -+ /* No room in Aggr buf, do rx aggr now */ -+ f_do_rx_cur = 1; -+ } else { -+ f_do_rx_cur = 1; -+ } -+ } -+ -+ if (f_aggr_cur) { -+ dev_dbg(adapter->dev, "info: current packet aggregation\n"); -+ /* Curr pkt can be aggregated */ -+ MP_RX_AGGR_SETUP(card, skb, port); -+ -+ if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || -+ MP_RX_AGGR_PORT_LIMIT_REACHED(card)) { -+ dev_dbg(adapter->dev, "info: %s: aggregated packet " -+ "limit reached\n", __func__); -+ /* No more pkts allowed in Aggr buf, rx it */ -+ f_do_rx_aggr = 1; -+ } -+ } -+ -+ if (f_do_rx_aggr) { -+ /* do aggr RX now */ -+ dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", -+ card->mpa_rx.pkt_cnt); -+ -+ if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, -+ card->mpa_rx.buf_len, -+ (adapter->ioport | 0x1000 | -+ (card->mpa_rx.ports << 4)) + -+ card->mpa_rx.start_port, 1)) -+ return -1; -+ -+ curr_ptr = card->mpa_rx.buf; -+ -+ for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { -+ -+ /* get curr PKT len & type */ -+ pkt_len = *(u16 *) &curr_ptr[0]; -+ pkt_type = *(u16 *) &curr_ptr[2]; -+ -+ /* copy pkt to deaggr buf */ -+ skb_deaggr = card->mpa_rx.skb_arr[pind]; -+ -+ if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= -+ card->mpa_rx.len_arr[pind])) { -+ -+ memcpy(skb_deaggr->data, curr_ptr, pkt_len); -+ -+ skb_trim(skb_deaggr, pkt_len); -+ -+ /* Process de-aggr packet */ -+ mwifiex_decode_rx_packet(adapter, skb_deaggr, -+ pkt_type); -+ } else { -+ dev_err(adapter->dev, "wrong aggr pkt:" -+ " type=%d len=%d max_len=%d\n", -+ pkt_type, pkt_len, -+ card->mpa_rx.len_arr[pind]); -+ dev_kfree_skb_any(skb_deaggr); -+ } -+ curr_ptr += card->mpa_rx.len_arr[pind]; -+ } -+ MP_RX_AGGR_BUF_RESET(card); -+ } -+ -+rx_curr_single: -+ if (f_do_rx_cur) { -+ dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", -+ port, rx_len); -+ -+ if (mwifiex_sdio_card_to_host(adapter, &pkt_type, -+ skb->data, skb->len, -+ adapter->ioport + port)) -+ return -1; -+ -+ mwifiex_decode_rx_packet(adapter, skb, pkt_type); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function checks the current interrupt status. -+ * -+ * The following interrupts are checked and handled by this function - -+ * - Data sent -+ * - Command sent -+ * - Packets received -+ * -+ * Since the firmware does not generate download ready interrupt if the -+ * port updated is command port only, command sent interrupt checking -+ * should be done manually, and for every SDIO interrupt. -+ * -+ * In case of Rx packets received, the packets are uploaded from card to -+ * host and processed accordingly. -+ */ -+static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = 0; -+ u8 sdio_ireg; -+ struct sk_buff *skb = NULL; -+ u8 port = CTRL_PORT; -+ u32 len_reg_l, len_reg_u; -+ u32 rx_blocks; -+ u16 rx_len; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&adapter->int_lock, flags); -+ sdio_ireg = adapter->int_status; -+ adapter->int_status = 0; -+ spin_unlock_irqrestore(&adapter->int_lock, flags); -+ -+ if (!sdio_ireg) -+ return ret; -+ -+ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { -+ card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8; -+ card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L]; -+ dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n", -+ card->mp_wr_bitmap); -+ if (adapter->data_sent && -+ (card->mp_wr_bitmap & card->mp_data_port_mask)) { -+ dev_dbg(adapter->dev, -+ "info: <--- Tx DONE Interrupt --->\n"); -+ adapter->data_sent = false; -+ } -+ } -+ -+ /* As firmware will not generate download ready interrupt if the port -+ updated is command port only, cmd_sent should be done for any SDIO -+ interrupt. */ -+ if (adapter->cmd_sent) { -+ /* Check if firmware has attach buffer at command port and -+ update just that in wr_bit_map. */ -+ card->mp_wr_bitmap |= -+ (u16) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; -+ if (card->mp_wr_bitmap & CTRL_PORT_MASK) -+ adapter->cmd_sent = false; -+ } -+ -+ dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", -+ adapter->cmd_sent, adapter->data_sent); -+ if (sdio_ireg & UP_LD_HOST_INT_STATUS) { -+ card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8; -+ card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L]; -+ dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n", -+ card->mp_rd_bitmap); -+ -+ while (true) { -+ ret = mwifiex_get_rd_port(adapter, &port); -+ if (ret) { -+ dev_dbg(adapter->dev, -+ "info: no more rd_port available\n"); -+ break; -+ } -+ len_reg_l = RD_LEN_P0_L + (port << 1); -+ len_reg_u = RD_LEN_P0_U + (port << 1); -+ rx_len = ((u16) card->mp_regs[len_reg_u]) << 8; -+ rx_len |= (u16) card->mp_regs[len_reg_l]; -+ dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n", -+ port, rx_len); -+ rx_blocks = -+ (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - -+ 1) / MWIFIEX_SDIO_BLOCK_SIZE; -+ if (rx_len <= INTF_HEADER_LEN -+ || (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > -+ MWIFIEX_RX_DATA_BUF_SIZE) { -+ dev_err(adapter->dev, "invalid rx_len=%d\n", -+ rx_len); -+ return -1; -+ } -+ rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); -+ -+ skb = dev_alloc_skb(rx_len); -+ -+ if (!skb) { -+ dev_err(adapter->dev, "%s: failed to alloc skb", -+ __func__); -+ return -1; -+ } -+ -+ skb_put(skb, rx_len); -+ -+ dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n", -+ rx_len, skb->len); -+ -+ if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, -+ port)) { -+ u32 cr = 0; -+ -+ dev_err(adapter->dev, "card_to_host_mpa failed:" -+ " int status=%#x\n", sdio_ireg); -+ if (mwifiex_read_reg(adapter, -+ CONFIGURATION_REG, &cr)) -+ dev_err(adapter->dev, -+ "read CFG reg failed\n"); -+ -+ dev_dbg(adapter->dev, -+ "info: CFG reg val = %d\n", cr); -+ if (mwifiex_write_reg(adapter, -+ CONFIGURATION_REG, -+ (cr | 0x04))) -+ dev_err(adapter->dev, -+ "write CFG reg failed\n"); -+ -+ dev_dbg(adapter->dev, "info: write success\n"); -+ if (mwifiex_read_reg(adapter, -+ CONFIGURATION_REG, &cr)) -+ dev_err(adapter->dev, -+ "read CFG reg failed\n"); -+ -+ dev_dbg(adapter->dev, -+ "info: CFG reg val =%x\n", cr); -+ dev_kfree_skb_any(skb); -+ return -1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function aggregates transmission buffers in driver and downloads -+ * the aggregated packet to card. -+ * -+ * The individual packets are aggregated by copying into an aggregation -+ * buffer and then downloaded to the card. Previous unsent packets in the -+ * aggregation buffer are pre-copied first before new packets are added. -+ * Aggregation is done till there is space left in the aggregation buffer, -+ * or till new packets are available. -+ * -+ * The function will only download the packet to the card when aggregation -+ * stops, otherwise it will just aggregate the packet in aggregation buffer -+ * and return. -+ */ -+static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, -+ u8 *payload, u32 pkt_len, u8 port, -+ u32 next_pkt_len) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = 0; -+ s32 f_send_aggr_buf = 0; -+ s32 f_send_cur_buf = 0; -+ s32 f_precopy_cur_buf = 0; -+ s32 f_postcopy_cur_buf = 0; -+ -+ if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) { -+ dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n", -+ __func__); -+ -+ f_send_cur_buf = 1; -+ goto tx_curr_single; -+ } -+ -+ if (next_pkt_len) { -+ /* More pkt in TX queue */ -+ dev_dbg(adapter->dev, "info: %s: more packets in queue.\n", -+ __func__); -+ -+ if (MP_TX_AGGR_IN_PROGRESS(card)) { -+ if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) && -+ MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { -+ f_precopy_cur_buf = 1; -+ -+ if (!(card->mp_wr_bitmap & -+ (1 << card->curr_wr_port)) -+ || !MP_TX_AGGR_BUF_HAS_ROOM( -+ card, next_pkt_len)) -+ f_send_aggr_buf = 1; -+ } else { -+ /* No room in Aggr buf, send it */ -+ f_send_aggr_buf = 1; -+ -+ if (MP_TX_AGGR_PORT_LIMIT_REACHED(card) || -+ !(card->mp_wr_bitmap & -+ (1 << card->curr_wr_port))) -+ f_send_cur_buf = 1; -+ else -+ f_postcopy_cur_buf = 1; -+ } -+ } else { -+ if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) -+ && (card->mp_wr_bitmap & (1 << card->curr_wr_port))) -+ f_precopy_cur_buf = 1; -+ else -+ f_send_cur_buf = 1; -+ } -+ } else { -+ /* Last pkt in TX queue */ -+ dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n", -+ __func__); -+ -+ if (MP_TX_AGGR_IN_PROGRESS(card)) { -+ /* some packs in Aggr buf already */ -+ f_send_aggr_buf = 1; -+ -+ if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) -+ f_precopy_cur_buf = 1; -+ else -+ /* No room in Aggr buf, send it */ -+ f_send_cur_buf = 1; -+ } else { -+ f_send_cur_buf = 1; -+ } -+ } -+ -+ if (f_precopy_cur_buf) { -+ dev_dbg(adapter->dev, "data: %s: precopy current buffer\n", -+ __func__); -+ MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); -+ -+ if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || -+ MP_TX_AGGR_PORT_LIMIT_REACHED(card)) -+ /* No more pkts allowed in Aggr buf, send it */ -+ f_send_aggr_buf = 1; -+ } -+ -+ if (f_send_aggr_buf) { -+ dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", -+ __func__, -+ card->mpa_tx.start_port, card->mpa_tx.ports); -+ ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, -+ card->mpa_tx.buf_len, -+ (adapter->ioport | 0x1000 | -+ (card->mpa_tx.ports << 4)) + -+ card->mpa_tx.start_port); -+ -+ MP_TX_AGGR_BUF_RESET(card); -+ } -+ -+tx_curr_single: -+ if (f_send_cur_buf) { -+ dev_dbg(adapter->dev, "data: %s: send current buffer %d\n", -+ __func__, port); -+ ret = mwifiex_write_data_to_card(adapter, payload, pkt_len, -+ adapter->ioport + port); -+ } -+ -+ if (f_postcopy_cur_buf) { -+ dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n", -+ __func__); -+ MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function downloads data from driver to card. -+ * -+ * Both commands and data packets are transferred to the card by this -+ * function. -+ * -+ * This function adds the SDIO specific header to the front of the buffer -+ * before transferring. The header contains the length of the packet and -+ * the type. The firmware handles the packets based upon this set type. -+ */ -+static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, -+ u8 type, u8 *payload, u32 pkt_len, -+ struct mwifiex_tx_param *tx_param) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = 0; -+ u32 buf_block_len; -+ u32 blk_size; -+ u8 port = CTRL_PORT; -+ -+ /* Allocate buffer and copy payload */ -+ blk_size = MWIFIEX_SDIO_BLOCK_SIZE; -+ buf_block_len = (pkt_len + blk_size - 1) / blk_size; -+ *(u16 *) &payload[0] = (u16) pkt_len; -+ *(u16 *) &payload[2] = type; -+ -+ /* -+ * This is SDIO specific header -+ * u16 length, -+ * u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1, -+ * MWIFIEX_TYPE_EVENT = 3) -+ */ -+ if (type == MWIFIEX_TYPE_DATA) { -+ ret = mwifiex_get_wr_port_data(adapter, &port); -+ if (ret) { -+ dev_err(adapter->dev, "%s: no wr_port available\n", -+ __func__); -+ return ret; -+ } -+ } else { -+ adapter->cmd_sent = true; -+ /* Type must be MWIFIEX_TYPE_CMD */ -+ -+ if (pkt_len <= INTF_HEADER_LEN || -+ pkt_len > MWIFIEX_UPLD_SIZE) -+ dev_err(adapter->dev, "%s: payload=%p, nb=%d\n", -+ __func__, payload, pkt_len); -+ } -+ -+ /* Transfer data to card */ -+ pkt_len = buf_block_len * blk_size; -+ -+ if (tx_param) -+ ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, -+ port, tx_param->next_pkt_len); -+ else -+ ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, -+ port, 0); -+ -+ if (ret) { -+ if (type == MWIFIEX_TYPE_CMD) -+ adapter->cmd_sent = false; -+ if (type == MWIFIEX_TYPE_DATA) -+ adapter->data_sent = false; -+ } else { -+ if (type == MWIFIEX_TYPE_DATA) { -+ if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) -+ adapter->data_sent = true; -+ else -+ adapter->data_sent = false; -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function allocates the MPA Tx and Rx buffers. -+ */ -+static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, -+ u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret = 0; -+ -+ card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); -+ if (!card->mpa_tx.buf) { -+ dev_err(adapter->dev, "could not alloc buffer for MP-A TX\n"); -+ ret = -1; -+ goto error; -+ } -+ -+ card->mpa_tx.buf_size = mpa_tx_buf_size; -+ -+ card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); -+ if (!card->mpa_rx.buf) { -+ dev_err(adapter->dev, "could not alloc buffer for MP-A RX\n"); -+ ret = -1; -+ goto error; -+ } -+ -+ card->mpa_rx.buf_size = mpa_rx_buf_size; -+ -+error: -+ if (ret) { -+ kfree(card->mpa_tx.buf); -+ kfree(card->mpa_rx.buf); -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function unregisters the SDIO device. -+ * -+ * The SDIO IRQ is released, the function is disabled and driver -+ * data is set to null. -+ */ -+static void -+mwifiex_unregister_dev(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ -+ if (adapter->card) { -+ /* Release the SDIO IRQ */ -+ sdio_claim_host(card->func); -+ sdio_release_irq(card->func); -+ sdio_disable_func(card->func); -+ sdio_release_host(card->func); -+ sdio_set_drvdata(card->func, NULL); -+ } -+} -+ -+/* -+ * This function registers the SDIO device. -+ * -+ * SDIO IRQ is claimed, block size is set and driver data is initialized. -+ */ -+static int mwifiex_register_dev(struct mwifiex_adapter *adapter) -+{ -+ int ret = 0; -+ struct sdio_mmc_card *card = adapter->card; -+ struct sdio_func *func = card->func; -+ -+ /* save adapter pointer in card */ -+ card->adapter = adapter; -+ -+ sdio_claim_host(func); -+ -+ /* Request the SDIO IRQ */ -+ ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); -+ if (ret) { -+ pr_err("claim irq failed: ret=%d\n", ret); -+ goto disable_func; -+ } -+ -+ /* Set block size */ -+ ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); -+ if (ret) { -+ pr_err("cannot set SDIO block size\n"); -+ ret = -1; -+ goto release_irq; -+ } -+ -+ sdio_release_host(func); -+ sdio_set_drvdata(func, card); -+ -+ adapter->dev = &func->dev; -+ -+ return 0; -+ -+release_irq: -+ sdio_release_irq(func); -+disable_func: -+ sdio_disable_func(func); -+ sdio_release_host(func); -+ adapter->card = NULL; -+ -+ return -1; -+} -+ -+/* -+ * This function initializes the SDIO driver. -+ * -+ * The following initializations steps are followed - -+ * - Read the Host interrupt status register to acknowledge -+ * the first interrupt got from bootloader -+ * - Disable host interrupt mask register -+ * - Get SDIO port -+ * - Get revision ID -+ * - Initialize SDIO variables in card -+ * - Allocate MP registers -+ * - Allocate MPA Tx and Rx buffers -+ */ -+static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int ret; -+ u32 sdio_ireg = 0; -+ -+ /* -+ * Read the HOST_INT_STATUS_REG for ACK the first interrupt got -+ * from the bootloader. If we don't do this we get a interrupt -+ * as soon as we register the irq. -+ */ -+ mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); -+ -+ /* Disable host interrupt mask register for SDIO */ -+ mwifiex_sdio_disable_host_int(adapter); -+ -+ /* Get SDIO ioport */ -+ mwifiex_init_sdio_ioport(adapter); -+ -+ /* Get revision ID */ -+#define REV_ID_REG 0x5c -+ mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id); -+ -+ /* Initialize SDIO variables in card */ -+ card->mp_rd_bitmap = 0; -+ card->mp_wr_bitmap = 0; -+ card->curr_rd_port = 1; -+ card->curr_wr_port = 1; -+ -+ card->mp_data_port_mask = DATA_PORT_MASK; -+ -+ card->mpa_tx.buf_len = 0; -+ card->mpa_tx.pkt_cnt = 0; -+ card->mpa_tx.start_port = 0; -+ -+ card->mpa_tx.enabled = 0; -+ card->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; -+ -+ card->mpa_rx.buf_len = 0; -+ card->mpa_rx.pkt_cnt = 0; -+ card->mpa_rx.start_port = 0; -+ -+ card->mpa_rx.enabled = 0; -+ card->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; -+ -+ /* Allocate buffers for SDIO MP-A */ -+ card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); -+ if (!card->mp_regs) { -+ dev_err(adapter->dev, "failed to alloc mp_regs\n"); -+ return -1; -+ } -+ -+ ret = mwifiex_alloc_sdio_mpa_buffers(adapter, -+ SDIO_MP_TX_AGGR_DEF_BUF_SIZE, -+ SDIO_MP_RX_AGGR_DEF_BUF_SIZE); -+ if (ret) { -+ dev_err(adapter->dev, "failed to alloc sdio mp-a buffers\n"); -+ kfree(card->mp_regs); -+ return -1; -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function resets the MPA Tx and Rx buffers. -+ */ -+static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ -+ MP_TX_AGGR_BUF_RESET(card); -+ MP_RX_AGGR_BUF_RESET(card); -+} -+ -+/* -+ * This function cleans up the allocated card buffers. -+ * -+ * The following are freed by this function - -+ * - MP registers -+ * - MPA Tx buffer -+ * - MPA Rx buffer -+ */ -+static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ -+ kfree(card->mp_regs); -+ kfree(card->mpa_tx.buf); -+ kfree(card->mpa_rx.buf); -+} -+ -+/* -+ * This function updates the MP end port in card. -+ */ -+static void -+mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) -+{ -+ struct sdio_mmc_card *card = adapter->card; -+ int i; -+ -+ card->mp_end_port = port; -+ -+ card->mp_data_port_mask = DATA_PORT_MASK; -+ -+ for (i = 1; i <= MAX_PORT - card->mp_end_port; i++) -+ card->mp_data_port_mask &= ~(1 << (MAX_PORT - i)); -+ -+ card->curr_wr_port = 1; -+ -+ dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n", -+ port, card->mp_data_port_mask); -+} -+ -+static struct mwifiex_if_ops sdio_ops = { -+ .init_if = mwifiex_init_sdio, -+ .cleanup_if = mwifiex_cleanup_sdio, -+ .check_fw_status = mwifiex_check_fw_status, -+ .prog_fw = mwifiex_prog_fw_w_helper, -+ .register_dev = mwifiex_register_dev, -+ .unregister_dev = mwifiex_unregister_dev, -+ .enable_int = mwifiex_sdio_enable_host_int, -+ .process_int_status = mwifiex_process_int_status, -+ .host_to_card = mwifiex_sdio_host_to_card, -+ .wakeup = mwifiex_pm_wakeup_card, -+ .wakeup_complete = mwifiex_pm_wakeup_card_complete, -+ -+ /* SDIO specific */ -+ .update_mp_end_port = mwifiex_update_mp_end_port, -+ .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, -+}; -+ -+/* -+ * This function initializes the SDIO driver. -+ * -+ * This initiates the semaphore and registers the device with -+ * SDIO bus. -+ */ -+static int -+mwifiex_sdio_init_module(void) -+{ -+ sema_init(&add_remove_card_sem, 1); -+ -+ return sdio_register_driver(&mwifiex_sdio); -+} -+ -+/* -+ * This function cleans up the SDIO driver. -+ * -+ * The following major steps are followed for cleanup - -+ * - Resume the device if its suspended -+ * - Disconnect the device if connected -+ * - Shutdown the firmware -+ * - Unregister the device from SDIO bus. -+ */ -+static void -+mwifiex_sdio_cleanup_module(void) -+{ -+ struct mwifiex_adapter *adapter = g_adapter; -+ int i; -+ -+ if (down_interruptible(&add_remove_card_sem)) -+ goto exit_sem_err; -+ -+ if (!adapter || !adapter->priv_num) -+ goto exit; -+ -+ if (adapter->is_suspended) -+ mwifiex_sdio_resume(adapter->dev); -+ -+ 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_deauthenticate(adapter->priv[i], NULL); -+ -+ if (!adapter->surprise_removed) -+ mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, -+ MWIFIEX_BSS_ROLE_ANY), -+ MWIFIEX_FUNC_SHUTDOWN); -+ -+exit: -+ up(&add_remove_card_sem); -+ -+exit_sem_err: -+ sdio_unregister_driver(&mwifiex_sdio); -+} -+ -+module_init(mwifiex_sdio_init_module); -+module_exit(mwifiex_sdio_cleanup_module); -+ -+MODULE_AUTHOR("Marvell International Ltd."); -+MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); -+MODULE_VERSION(SDIO_VERSION); -+MODULE_LICENSE("GPL v2"); -+MODULE_FIRMWARE("sd8787.bin"); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sdio.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sdio.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sdio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sdio.h 2011-05-05 23:29:45.494441973 +0200 -@@ -0,0 +1,305 @@ -+/* -+ * Marvell Wireless LAN device driver: SDIO specific definitions -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_SDIO_H -+#define _MWIFIEX_SDIO_H -+ -+ -+#include -+#include -+#include -+#include -+ -+#include "main.h" -+ -+#define BLOCK_MODE 1 -+#define BYTE_MODE 0 -+ -+#define REG_PORT 0 -+#define RD_BITMAP_L 0x04 -+#define RD_BITMAP_U 0x05 -+#define WR_BITMAP_L 0x06 -+#define WR_BITMAP_U 0x07 -+#define RD_LEN_P0_L 0x08 -+#define RD_LEN_P0_U 0x09 -+ -+#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff -+ -+#define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000 -+ -+#define CTRL_PORT 0 -+#define CTRL_PORT_MASK 0x0001 -+#define DATA_PORT_MASK 0xfffe -+ -+#define MAX_MP_REGS 64 -+#define MAX_PORT 16 -+ -+#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 -+ -+#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ -+ -+/* Multi port RX aggregation buffer size */ -+#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE (4096) /* 4K */ -+ -+/* Misc. Config Register : Auto Re-enable interrupts */ -+#define AUTO_RE_ENABLE_INT BIT(4) -+ -+/* Host Control Registers */ -+/* Host Control Registers : I/O port 0 */ -+#define IO_PORT_0_REG 0x78 -+/* Host Control Registers : I/O port 1 */ -+#define IO_PORT_1_REG 0x79 -+/* Host Control Registers : I/O port 2 */ -+#define IO_PORT_2_REG 0x7A -+ -+/* Host Control Registers : Configuration */ -+#define CONFIGURATION_REG 0x00 -+/* Host Control Registers : Host without Command 53 finish host*/ -+#define HOST_TO_CARD_EVENT (0x1U << 3) -+/* Host Control Registers : Host without Command 53 finish host */ -+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) -+/* Host Control Registers : Host power up */ -+#define HOST_POWER_UP (0x1U << 1) -+/* Host Control Registers : Host power down */ -+#define HOST_POWER_DOWN (0x1U << 0) -+ -+/* Host Control Registers : Host interrupt mask */ -+#define HOST_INT_MASK_REG 0x02 -+/* Host Control Registers : Upload host interrupt mask */ -+#define UP_LD_HOST_INT_MASK (0x1U) -+/* Host Control Registers : Download host interrupt mask */ -+#define DN_LD_HOST_INT_MASK (0x2U) -+/* Enable Host interrupt mask */ -+#define HOST_INT_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) -+/* Disable Host interrupt mask */ -+#define HOST_INT_DISABLE 0xff -+ -+/* Host Control Registers : Host interrupt status */ -+#define HOST_INTSTATUS_REG 0x03 -+/* Host Control Registers : Upload host interrupt status */ -+#define UP_LD_HOST_INT_STATUS (0x1U) -+/* Host Control Registers : Download host interrupt status */ -+#define DN_LD_HOST_INT_STATUS (0x2U) -+ -+/* Host Control Registers : Host interrupt RSR */ -+#define HOST_INT_RSR_REG 0x01 -+/* Host Control Registers : Upload host interrupt RSR */ -+#define UP_LD_HOST_INT_RSR (0x1U) -+#define SDIO_INT_MASK 0x3F -+ -+/* Host Control Registers : Host interrupt status */ -+#define HOST_INT_STATUS_REG 0x28 -+/* Host Control Registers : Upload CRC error */ -+#define UP_LD_CRC_ERR (0x1U << 2) -+/* Host Control Registers : Upload restart */ -+#define UP_LD_RESTART (0x1U << 1) -+/* Host Control Registers : Download restart */ -+#define DN_LD_RESTART (0x1U << 0) -+ -+/* Card Control Registers : Card status register */ -+#define CARD_STATUS_REG 0x30 -+/* Card Control Registers : Card I/O ready */ -+#define CARD_IO_READY (0x1U << 3) -+/* Card Control Registers : CIS card ready */ -+#define CIS_CARD_RDY (0x1U << 2) -+/* Card Control Registers : Upload card ready */ -+#define UP_LD_CARD_RDY (0x1U << 1) -+/* Card Control Registers : Download card ready */ -+#define DN_LD_CARD_RDY (0x1U << 0) -+ -+/* Card Control Registers : Host interrupt mask register */ -+#define HOST_INTERRUPT_MASK_REG 0x34 -+/* Card Control Registers : Host power interrupt mask */ -+#define HOST_POWER_INT_MASK (0x1U << 3) -+/* Card Control Registers : Abort card interrupt mask */ -+#define ABORT_CARD_INT_MASK (0x1U << 2) -+/* Card Control Registers : Upload card interrupt mask */ -+#define UP_LD_CARD_INT_MASK (0x1U << 1) -+/* Card Control Registers : Download card interrupt mask */ -+#define DN_LD_CARD_INT_MASK (0x1U << 0) -+ -+/* Card Control Registers : Card interrupt status register */ -+#define CARD_INTERRUPT_STATUS_REG 0x38 -+/* Card Control Registers : Power up interrupt */ -+#define POWER_UP_INT (0x1U << 4) -+/* Card Control Registers : Power down interrupt */ -+#define POWER_DOWN_INT (0x1U << 3) -+ -+/* Card Control Registers : Card interrupt RSR register */ -+#define CARD_INTERRUPT_RSR_REG 0x3c -+/* Card Control Registers : Power up RSR */ -+#define POWER_UP_RSR (0x1U << 4) -+/* Card Control Registers : Power down RSR */ -+#define POWER_DOWN_RSR (0x1U << 3) -+ -+/* Card Control Registers : Miscellaneous Configuration Register */ -+#define CARD_MISC_CFG_REG 0x6C -+ -+/* Host F1 read base 0 */ -+#define HOST_F1_RD_BASE_0 0x0040 -+/* Host F1 read base 1 */ -+#define HOST_F1_RD_BASE_1 0x0041 -+/* Host F1 card ready */ -+#define HOST_F1_CARD_RDY 0x0020 -+ -+/* Firmware status 0 register */ -+#define CARD_FW_STATUS0_REG 0x60 -+/* Firmware status 1 register */ -+#define CARD_FW_STATUS1_REG 0x61 -+/* Rx length register */ -+#define CARD_RX_LEN_REG 0x62 -+/* Rx unit register */ -+#define CARD_RX_UNIT_REG 0x63 -+ -+/* Event header Len*/ -+#define MWIFIEX_EVENT_HEADER_LEN 8 -+ -+/* Max retry number of CMD53 write */ -+#define MAX_WRITE_IOMEM_RETRY 2 -+ -+/* SDIO Tx aggregation in progress ? */ -+#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0) -+ -+/* SDIO Tx aggregation buffer room for next packet ? */ -+#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len) \ -+ <= a->mpa_tx.buf_size) -+ -+/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */ -+#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do { \ -+ memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len], \ -+ payload, pkt_len); \ -+ a->mpa_tx.buf_len += pkt_len; \ -+ if (!a->mpa_tx.pkt_cnt) \ -+ a->mpa_tx.start_port = port; \ -+ if (a->mpa_tx.start_port <= port) \ -+ a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \ -+ else \ -+ a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ -+ a->mp_end_port))); \ -+ a->mpa_tx.pkt_cnt++; \ -+} while (0); -+ -+/* SDIO Tx aggregation limit ? */ -+#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ -+ (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit) -+ -+/* SDIO Tx aggregation port limit ? */ -+#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \ -+ a->mpa_tx.start_port) && (((MAX_PORT - \ -+ a->mpa_tx.start_port) + a->curr_wr_port) >= \ -+ SDIO_MP_AGGR_DEF_PKT_LIMIT)) -+ -+/* Reset SDIO Tx aggregation buffer parameters */ -+#define MP_TX_AGGR_BUF_RESET(a) do { \ -+ a->mpa_tx.pkt_cnt = 0; \ -+ a->mpa_tx.buf_len = 0; \ -+ a->mpa_tx.ports = 0; \ -+ a->mpa_tx.start_port = 0; \ -+} while (0); -+ -+/* SDIO Rx aggregation limit ? */ -+#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ -+ (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit) -+ -+/* SDIO Tx aggregation port limit ? */ -+#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \ -+ a->mpa_rx.start_port) && (((MAX_PORT - \ -+ a->mpa_rx.start_port) + a->curr_rd_port) >= \ -+ SDIO_MP_AGGR_DEF_PKT_LIMIT)) -+ -+/* SDIO Rx aggregation in progress ? */ -+#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) -+ -+/* SDIO Rx aggregation buffer room for next packet ? */ -+#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \ -+ ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size) -+ -+/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ -+#define MP_RX_AGGR_SETUP(a, skb, port) do { \ -+ a->mpa_rx.buf_len += skb->len; \ -+ if (!a->mpa_rx.pkt_cnt) \ -+ a->mpa_rx.start_port = port; \ -+ if (a->mpa_rx.start_port <= port) \ -+ a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt)); \ -+ else \ -+ a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt+1)); \ -+ a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ -+ a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ -+ a->mpa_rx.pkt_cnt++; \ -+} while (0); -+ -+/* Reset SDIO Rx aggregation buffer parameters */ -+#define MP_RX_AGGR_BUF_RESET(a) do { \ -+ a->mpa_rx.pkt_cnt = 0; \ -+ a->mpa_rx.buf_len = 0; \ -+ a->mpa_rx.ports = 0; \ -+ a->mpa_rx.start_port = 0; \ -+} while (0); -+ -+ -+/* data structure for SDIO MPA TX */ -+struct mwifiex_sdio_mpa_tx { -+ /* multiport tx aggregation buffer pointer */ -+ u8 *buf; -+ u32 buf_len; -+ u32 pkt_cnt; -+ u16 ports; -+ u16 start_port; -+ u8 enabled; -+ u32 buf_size; -+ u32 pkt_aggr_limit; -+}; -+ -+struct mwifiex_sdio_mpa_rx { -+ u8 *buf; -+ u32 buf_len; -+ u32 pkt_cnt; -+ u16 ports; -+ u16 start_port; -+ -+ struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; -+ u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; -+ -+ u8 enabled; -+ u32 buf_size; -+ u32 pkt_aggr_limit; -+}; -+ -+int mwifiex_bus_register(void); -+void mwifiex_bus_unregister(void); -+ -+struct sdio_mmc_card { -+ struct sdio_func *func; -+ struct mwifiex_adapter *adapter; -+ -+ u16 mp_rd_bitmap; -+ u16 mp_wr_bitmap; -+ -+ u16 mp_end_port; -+ u16 mp_data_port_mask; -+ -+ u8 curr_rd_port; -+ u8 curr_wr_port; -+ -+ u8 *mp_regs; -+ -+ struct mwifiex_sdio_mpa_tx mpa_tx; -+ struct mwifiex_sdio_mpa_rx mpa_rx; -+}; -+#endif /* _MWIFIEX_SDIO_H */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_cmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_cmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_cmd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_cmd.c 2011-05-05 23:29:45.492441949 +0200 -@@ -0,0 +1,1219 @@ -+/* -+ * Marvell Wireless LAN device driver: station command handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * This function prepares command to set/get RSSI information. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting data/beacon average factors -+ * - Resetting SNR/NF/RSSI values in private structure -+ * - Ensuring correct endian-ness -+ */ -+static int -+mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, u16 cmd_action) -+{ -+ cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + -+ S_DS_GEN); -+ cmd->params.rssi_info.action = cpu_to_le16(cmd_action); -+ cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); -+ cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); -+ -+ /* Reset SNR/NF/RSSI values in private structure */ -+ priv->data_rssi_last = 0; -+ priv->data_nf_last = 0; -+ priv->data_rssi_avg = 0; -+ priv->data_nf_avg = 0; -+ priv->bcn_rssi_last = 0; -+ priv->bcn_nf_last = 0; -+ priv->bcn_rssi_avg = 0; -+ priv->bcn_nf_avg = 0; -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set MAC control. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, void *data_buf) -+{ -+ struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; -+ u16 action = *((u16 *) data_buf); -+ -+ if (cmd_action != HostCmd_ACT_GEN_SET) { -+ dev_err(priv->adapter->dev, -+ "mac_control: only support set cmd\n"); -+ return -1; -+ } -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL); -+ cmd->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); -+ mac_ctrl->action = cpu_to_le16(action); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get SNMP MIB. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting SNMP MIB OID number and value -+ * (as required) -+ * - Ensuring correct endian-ness -+ * -+ * The following SNMP MIB OIDs are supported - -+ * - FRAG_THRESH_I : Fragmentation threshold -+ * - RTS_THRESH_I : RTS threshold -+ * - SHORT_RETRY_LIM_I : Short retry limit -+ * - DOT11D_I : 11d support -+ */ -+static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, u32 cmd_oid, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; -+ u32 ul_temp; -+ -+ dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) -+ - 1 + S_DS_GEN); -+ -+ if (cmd_action == HostCmd_ACT_GEN_GET) { -+ snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); -+ snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) -+ + MAX_SNMP_BUF_SIZE); -+ } -+ -+ switch (cmd_oid) { -+ case FRAG_THRESH_I: -+ snmp_mib->oid = cpu_to_le16((u16) FRAG_THRESH_I); -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); -+ snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -+ ul_temp = *((u32 *) data_buf); -+ *((__le16 *) (snmp_mib->value)) = -+ cpu_to_le16((u16) ul_temp); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) -+ + sizeof(u16)); -+ } -+ break; -+ case RTS_THRESH_I: -+ snmp_mib->oid = cpu_to_le16((u16) RTS_THRESH_I); -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); -+ snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -+ ul_temp = *((u32 *) data_buf); -+ *(__le16 *) (snmp_mib->value) = -+ cpu_to_le16((u16) ul_temp); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) -+ + sizeof(u16)); -+ } -+ break; -+ -+ case SHORT_RETRY_LIM_I: -+ snmp_mib->oid = cpu_to_le16((u16) SHORT_RETRY_LIM_I); -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); -+ snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -+ ul_temp = (*(u32 *) data_buf); -+ *((__le16 *) (snmp_mib->value)) = -+ cpu_to_le16((u16) ul_temp); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) -+ + sizeof(u16)); -+ } -+ break; -+ case DOT11D_I: -+ snmp_mib->oid = cpu_to_le16((u16) DOT11D_I); -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); -+ snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -+ ul_temp = *(u32 *) data_buf; -+ *((__le16 *) (snmp_mib->value)) = -+ cpu_to_le16((u16) ul_temp); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) -+ + sizeof(u16)); -+ } -+ break; -+ default: -+ break; -+ } -+ dev_dbg(priv->adapter->dev, -+ "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," -+ " Value=0x%x\n", -+ cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size), -+ le16_to_cpu(*(__le16 *) snmp_mib->value)); -+ return 0; -+} -+ -+/* -+ * This function prepares command to get log. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Ensuring correct endian-ness -+ */ -+static int -+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) + -+ S_DS_GEN); -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get Tx data rate configuration. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting configuration index, rate scope and rate drop pattern -+ * parameters (as required) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, void *data_buf) -+{ -+ struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; -+ struct mwifiex_rate_scope *rate_scope; -+ struct mwifiex_rate_drop_pattern *rate_drop; -+ u16 *pbitmap_rates = (u16 *) data_buf; -+ -+ u32 i; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); -+ -+ rate_cfg->action = cpu_to_le16(cmd_action); -+ rate_cfg->cfg_index = 0; -+ -+ rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg + -+ sizeof(struct host_cmd_ds_tx_rate_cfg)); -+ rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); -+ rate_scope->length = cpu_to_le16(sizeof(struct mwifiex_rate_scope) - -+ sizeof(struct mwifiex_ie_types_header)); -+ if (pbitmap_rates != NULL) { -+ rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); -+ rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); -+ for (i = 0; -+ i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); -+ i++) -+ rate_scope->ht_mcs_rate_bitmap[i] = -+ cpu_to_le16(pbitmap_rates[2 + i]); -+ } else { -+ rate_scope->hr_dsss_rate_bitmap = -+ cpu_to_le16(priv->bitmap_rates[0]); -+ rate_scope->ofdm_rate_bitmap = -+ cpu_to_le16(priv->bitmap_rates[1]); -+ for (i = 0; -+ i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); -+ i++) -+ rate_scope->ht_mcs_rate_bitmap[i] = -+ cpu_to_le16(priv->bitmap_rates[2 + i]); -+ } -+ -+ rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + -+ sizeof(struct mwifiex_rate_scope)); -+ rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); -+ rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); -+ rate_drop->rate_drop_mode = 0; -+ -+ cmd->size = -+ cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + -+ sizeof(struct mwifiex_rate_scope) + -+ sizeof(struct mwifiex_rate_drop_pattern)); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get Tx power configuration. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting Tx power mode, power group TLV -+ * (as required) -+ * - Ensuring correct endian-ness -+ */ -+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; -+ struct host_cmd_ds_txpwr_cfg *txp = NULL; -+ struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); -+ cmd->size = -+ cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); -+ switch (cmd_action) { -+ case HostCmd_ACT_GEN_SET: -+ txp = (struct host_cmd_ds_txpwr_cfg *) data_buf; -+ if (txp->mode) { -+ pg_tlv = (struct mwifiex_types_power_group -+ *) ((unsigned long) data_buf + -+ sizeof(struct host_cmd_ds_txpwr_cfg)); -+ memmove(cmd_txp_cfg, data_buf, -+ sizeof(struct host_cmd_ds_txpwr_cfg) + -+ sizeof(struct mwifiex_types_power_group) + -+ pg_tlv->length); -+ -+ pg_tlv = (struct mwifiex_types_power_group *) ((u8 *) -+ cmd_txp_cfg + -+ sizeof(struct host_cmd_ds_txpwr_cfg)); -+ cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + -+ sizeof(struct mwifiex_types_power_group) + -+ pg_tlv->length); -+ } else { -+ memmove(cmd_txp_cfg, data_buf, -+ sizeof(struct host_cmd_ds_txpwr_cfg)); -+ } -+ cmd_txp_cfg->action = cpu_to_le16(cmd_action); -+ break; -+ case HostCmd_ACT_GEN_GET: -+ cmd_txp_cfg->action = cpu_to_le16(cmd_action); -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set Host Sleep configuration. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting Host Sleep action, conditions, ARP filters -+ * (as required) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, -+ struct mwifiex_hs_config_param *data_buf) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; -+ u16 hs_activate = false; -+ -+ if (data_buf == NULL) -+ /* New Activate command */ -+ hs_activate = true; -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); -+ -+ if (!hs_activate && -+ (data_buf->conditions -+ != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) -+ && ((adapter->arp_filter_size > 0) -+ && (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { -+ dev_dbg(adapter->dev, -+ "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", -+ adapter->arp_filter_size); -+ memcpy(((u8 *) hs_cfg) + -+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), -+ adapter->arp_filter, adapter->arp_filter_size); -+ cmd->size = cpu_to_le16(adapter->arp_filter_size + -+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) -+ + S_DS_GEN); -+ } else { -+ cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct -+ host_cmd_ds_802_11_hs_cfg_enh)); -+ } -+ if (hs_activate) { -+ hs_cfg->action = cpu_to_le16(HS_ACTIVATE); -+ hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED; -+ } else { -+ hs_cfg->action = cpu_to_le16(HS_CONFIGURE); -+ hs_cfg->params.hs_config.conditions = data_buf->conditions; -+ hs_cfg->params.hs_config.gpio = data_buf->gpio; -+ hs_cfg->params.hs_config.gap = data_buf->gap; -+ dev_dbg(adapter->dev, -+ "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", -+ hs_cfg->params.hs_config.conditions, -+ hs_cfg->params.hs_config.gpio, -+ hs_cfg->params.hs_config.gap); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get MAC address. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting MAC address (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action) -+{ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + -+ S_DS_GEN); -+ cmd->result = 0; -+ -+ cmd->params.mac_addr.action = cpu_to_le16(cmd_action); -+ -+ if (cmd_action == HostCmd_ACT_GEN_SET) -+ memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, -+ ETH_ALEN); -+ return 0; -+} -+ -+/* -+ * This function prepares command to set MAC multicast address. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting MAC multicast address -+ * - Ensuring correct endian-ness -+ */ -+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 = -+ (struct mwifiex_multicast_list *) data_buf; -+ struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; -+ -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + -+ S_DS_GEN); -+ cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); -+ -+ mcast_addr->action = cpu_to_le16(cmd_action); -+ mcast_addr->num_of_adrs = -+ cpu_to_le16((u16) mcast_list->num_multicast_addr); -+ memcpy(mcast_addr->mac_list, mcast_list->mac_list, -+ mcast_list->num_multicast_addr * ETH_ALEN); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to deauthenticate. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Setting AP MAC address and reason code -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) -+ + S_DS_GEN); -+ -+ /* Set AP MAC address */ -+ memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN); -+ -+ dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr); -+ -+ deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to stop Ad-Hoc network. -+ * -+ * Preparation includes - -+ * - Setting command ID and proper size -+ * - Ensuring correct endian-ness -+ */ -+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); -+ return 0; -+} -+ -+/* -+ * This function sets WEP key(s) to key parameter TLV(s). -+ * -+ * Multi-key parameter TLVs are supported, so we can send multiple -+ * WEP keys in a single buffer. -+ */ -+static int -+mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, -+ struct mwifiex_ie_type_key_param_set *key_param_set, -+ u16 *key_param_len) -+{ -+ int cur_key_param_len = 0; -+ u8 i; -+ -+ /* Multi-key_param_set TLV is supported */ -+ for (i = 0; i < NUM_WEP_KEYS; i++) { -+ if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) || -+ (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) { -+ key_param_set->type = -+ cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -+/* Key_param_set WEP fixed length */ -+#define KEYPARAMSET_WEP_FIXED_LEN 8 -+ key_param_set->length = cpu_to_le16((u16) -+ (priv->wep_key[i]. -+ key_length + -+ KEYPARAMSET_WEP_FIXED_LEN)); -+ key_param_set->key_type_id = -+ cpu_to_le16(KEY_TYPE_ID_WEP); -+ key_param_set->key_info = -+ 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 */ -+ key_param_set->key[0] = i; -+ /* Set default Tx key flag */ -+ if (i == -+ (priv-> -+ wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) -+ key_param_set->key[1] = 1; -+ else -+ key_param_set->key[1] = 0; -+ memmove(&key_param_set->key[2], -+ priv->wep_key[i].key_material, -+ priv->wep_key[i].key_length); -+ -+ cur_key_param_len = priv->wep_key[i].key_length + -+ KEYPARAMSET_WEP_FIXED_LEN + -+ sizeof(struct mwifiex_ie_types_header); -+ *key_param_len += (u16) cur_key_param_len; -+ key_param_set = -+ (struct mwifiex_ie_type_key_param_set *) -+ ((u8 *)key_param_set + -+ cur_key_param_len); -+ } else if (!priv->wep_key[i].key_length) { -+ continue; -+ } else { -+ dev_err(priv->adapter->dev, -+ "key%d Length = %d is incorrect\n", -+ (i + 1), priv->wep_key[i].key_length); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get/reset network key(s). -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting WEP keys, WAPI keys or WPA keys along with required -+ * encryption (TKIP, AES) (as required) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, -+ u32 cmd_oid, void *data_buf) -+{ -+ struct host_cmd_ds_802_11_key_material *key_material = -+ &cmd->params.key_material; -+ struct mwifiex_ds_encrypt_key *enc_key = -+ (struct mwifiex_ds_encrypt_key *) data_buf; -+ u16 key_param_len = 0; -+ int ret = 0; -+ const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); -+ key_material->action = cpu_to_le16(cmd_action); -+ -+ if (cmd_action == HostCmd_ACT_GEN_GET) { -+ cmd->size = -+ cpu_to_le16(sizeof(key_material->action) + S_DS_GEN); -+ return ret; -+ } -+ -+ if (!enc_key) { -+ memset(&key_material->key_param_set, 0, -+ (NUM_WEP_KEYS * -+ sizeof(struct mwifiex_ie_type_key_param_set))); -+ ret = mwifiex_set_keyparamset_wep(priv, -+ &key_material->key_param_set, -+ &key_param_len); -+ cmd->size = cpu_to_le16(key_param_len + -+ sizeof(key_material->action) + S_DS_GEN); -+ return ret; -+ } else -+ memset(&key_material->key_param_set, 0, -+ sizeof(struct mwifiex_ie_type_key_param_set)); -+ if (enc_key->is_wapi_key) { -+ dev_dbg(priv->adapter->dev, "info: Set WAPI Key\n"); -+ key_material->key_param_set.key_type_id = -+ cpu_to_le16(KEY_TYPE_ID_WAPI); -+ if (cmd_oid == KEY_INFO_ENABLED) -+ key_material->key_param_set.key_info = -+ cpu_to_le16(KEY_ENABLED); -+ else -+ key_material->key_param_set.key_info = -+ cpu_to_le16(!KEY_ENABLED); -+ -+ key_material->key_param_set.key[0] = enc_key->key_index; -+ if (!priv->sec_info.wapi_key_on) -+ key_material->key_param_set.key[1] = 1; -+ else -+ /* set 0 when re-key */ -+ key_material->key_param_set.key[1] = 0; -+ -+ 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_UNICAST); -+ } else { /* WAPI group key: multicast */ -+ key_material->key_param_set.key_info |= -+ cpu_to_le16(KEY_MCAST); -+ priv->sec_info.wapi_key_on = true; -+ } -+ -+ key_material->key_param_set.type = -+ cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -+ key_material->key_param_set.key_len = -+ cpu_to_le16(WAPI_KEY_LEN); -+ memcpy(&key_material->key_param_set.key[2], -+ enc_key->key_material, enc_key->key_len); -+ memcpy(&key_material->key_param_set.key[2 + enc_key->key_len], -+ enc_key->wapi_rxpn, WAPI_RXPN_LEN); -+ key_material->key_param_set.length = -+ cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); -+ -+ key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + -+ sizeof(struct mwifiex_ie_types_header); -+ cmd->size = cpu_to_le16(key_param_len + -+ sizeof(key_material->action) + S_DS_GEN); -+ return ret; -+ } -+ if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { -+ dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n"); -+ key_material->key_param_set.key_type_id = -+ cpu_to_le16(KEY_TYPE_ID_AES); -+ if (cmd_oid == KEY_INFO_ENABLED) -+ key_material->key_param_set.key_info = -+ cpu_to_le16(KEY_ENABLED); -+ else -+ key_material->key_param_set.key_info = -+ 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_UNICAST); -+ else /* AES group key: multicast */ -+ key_material->key_param_set.key_info |= -+ 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_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_UNICAST); -+ else /* TKIP group key: multicast */ -+ key_material->key_param_set.key_info |= -+ cpu_to_le16(KEY_MCAST); -+ } -+ -+ if (key_material->key_param_set.key_type_id) { -+ key_material->key_param_set.type = -+ cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -+ key_material->key_param_set.key_len = -+ cpu_to_le16((u16) enc_key->key_len); -+ memcpy(key_material->key_param_set.key, enc_key->key_material, -+ enc_key->key_len); -+ key_material->key_param_set.length = -+ cpu_to_le16((u16) enc_key->key_len + -+ KEYPARAMSET_FIXED_LEN); -+ -+ key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN) -+ + sizeof(struct mwifiex_ie_types_header); -+ -+ cmd->size = cpu_to_le16(key_param_len + -+ sizeof(key_material->action) + S_DS_GEN); -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function prepares command to set/get 11d domain information. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting domain information fields (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11d_domain_info *domain_info = -+ &cmd->params.domain_info; -+ struct mwifiex_ietypes_domain_param_set *domain = -+ &domain_info->domain; -+ u8 no_of_triplet = adapter->domain_reg.no_of_triplet; -+ -+ dev_dbg(adapter->dev, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); -+ domain_info->action = cpu_to_le16(cmd_action); -+ if (cmd_action == HostCmd_ACT_GEN_GET) { -+ cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); -+ return 0; -+ } -+ -+ /* Set domain info fields */ -+ domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); -+ memcpy(domain->country_code, adapter->domain_reg.country_code, -+ sizeof(domain->country_code)); -+ -+ domain->header.len = cpu_to_le16((no_of_triplet * -+ sizeof(struct ieee80211_country_ie_triplet)) + -+ sizeof(domain->country_code)); -+ -+ if (no_of_triplet) { -+ memcpy(domain->triplet, adapter->domain_reg.triplet, -+ no_of_triplet * -+ sizeof(struct ieee80211_country_ie_triplet)); -+ -+ cmd->size = cpu_to_le16(sizeof(domain_info->action) + -+ le16_to_cpu(domain->header.len) + -+ sizeof(struct mwifiex_ie_types_header) -+ + S_DS_GEN); -+ } else { -+ cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get RF channel. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting RF type and current RF channel (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *cmd, -+ u16 cmd_action, void *data_buf) -+{ -+ struct host_cmd_ds_802_11_rf_channel *rf_chan = -+ &cmd->params.rf_channel; -+ uint16_t rf_type = le16_to_cpu(rf_chan->rf_type); -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rf_channel) -+ + S_DS_GEN); -+ -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ if ((priv->adapter->adhoc_start_band & BAND_A) -+ || (priv->adapter->adhoc_start_band & BAND_AN)) -+ rf_chan->rf_type = -+ cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A); -+ -+ rf_type = le16_to_cpu(rf_chan->rf_type); -+ SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset); -+ rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf)); -+ } -+ rf_chan->action = cpu_to_le16(cmd_action); -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get IBSS coalescing status. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting status to enable or disable (for SET only) -+ * - Ensuring correct endian-ness -+ */ -+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 = -+ &(cmd->params.ibss_coalescing); -+ u16 enable = 0; -+ -+ cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); -+ cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + -+ S_DS_GEN); -+ cmd->result = 0; -+ ibss_coal->action = cpu_to_le16(cmd_action); -+ -+ switch (cmd_action) { -+ case HostCmd_ACT_GEN_SET: -+ if (data_buf != NULL) -+ enable = *(u16 *) data_buf; -+ ibss_coal->enable = cpu_to_le16(enable); -+ break; -+ -+ /* In other case.. Nothing to do */ -+ case HostCmd_ACT_GEN_GET: -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares command to set/get register value. -+ * -+ * Preparation includes - -+ * - Setting command ID, action and proper size -+ * - Setting register offset (for both GET and SET) and -+ * register value (for SET only) -+ * - Ensuring correct endian-ness -+ * -+ * The following type of registers can be accessed with this function - -+ * - MAC register -+ * - BBP register -+ * - RF register -+ * - PMIC register -+ * - CAU register -+ * - EEPROM -+ */ -+static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, -+ u16 cmd_action, void *data_buf) -+{ -+ struct mwifiex_ds_reg_rw *reg_rw; -+ -+ reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; -+ switch (le16_to_cpu(cmd->command)) { -+ case HostCmd_CMD_MAC_REG_ACCESS: -+ { -+ struct host_cmd_ds_mac_reg_access *mac_reg; -+ -+ cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); -+ mac_reg = (struct host_cmd_ds_mac_reg_access *) &cmd-> -+ params.mac_reg; -+ mac_reg->action = cpu_to_le16(cmd_action); -+ mac_reg->offset = -+ cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); -+ mac_reg->value = reg_rw->value; -+ break; -+ } -+ case HostCmd_CMD_BBP_REG_ACCESS: -+ { -+ struct host_cmd_ds_bbp_reg_access *bbp_reg; -+ -+ cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); -+ bbp_reg = (struct host_cmd_ds_bbp_reg_access *) &cmd-> -+ params.bbp_reg; -+ bbp_reg->action = cpu_to_le16(cmd_action); -+ bbp_reg->offset = -+ cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); -+ bbp_reg->value = (u8) le32_to_cpu(reg_rw->value); -+ break; -+ } -+ case HostCmd_CMD_RF_REG_ACCESS: -+ { -+ struct host_cmd_ds_rf_reg_access *rf_reg; -+ -+ cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); -+ rf_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> -+ params.rf_reg; -+ rf_reg->action = cpu_to_le16(cmd_action); -+ rf_reg->offset = -+ cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); -+ rf_reg->value = (u8) le32_to_cpu(reg_rw->value); -+ break; -+ } -+ case HostCmd_CMD_PMIC_REG_ACCESS: -+ { -+ struct host_cmd_ds_pmic_reg_access *pmic_reg; -+ -+ cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); -+ pmic_reg = (struct host_cmd_ds_pmic_reg_access *) &cmd-> -+ params.pmic_reg; -+ pmic_reg->action = cpu_to_le16(cmd_action); -+ pmic_reg->offset = -+ cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); -+ pmic_reg->value = (u8) le32_to_cpu(reg_rw->value); -+ break; -+ } -+ case HostCmd_CMD_CAU_REG_ACCESS: -+ { -+ struct host_cmd_ds_rf_reg_access *cau_reg; -+ -+ cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); -+ cau_reg = (struct host_cmd_ds_rf_reg_access *) &cmd-> -+ params.rf_reg; -+ cau_reg->action = cpu_to_le16(cmd_action); -+ cau_reg->offset = -+ cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); -+ cau_reg->value = (u8) le32_to_cpu(reg_rw->value); -+ break; -+ } -+ case HostCmd_CMD_802_11_EEPROM_ACCESS: -+ { -+ struct mwifiex_ds_read_eeprom *rd_eeprom = -+ (struct mwifiex_ds_read_eeprom *) data_buf; -+ struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = -+ (struct host_cmd_ds_802_11_eeprom_access *) -+ &cmd->params.eeprom; -+ -+ cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); -+ cmd_eeprom->action = cpu_to_le16(cmd_action); -+ cmd_eeprom->offset = rd_eeprom->offset; -+ cmd_eeprom->byte_count = rd_eeprom->byte_count; -+ cmd_eeprom->value = 0; -+ break; -+ } -+ default: -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function prepares the commands before sending them to the firmware. -+ * -+ * This is a generic function which calls specific command preparation -+ * routines based upon the command number. -+ */ -+int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, -+ u16 cmd_action, u32 cmd_oid, -+ void *data_buf, void *cmd_buf) -+{ -+ struct host_cmd_ds_command *cmd_ptr = -+ (struct host_cmd_ds_command *) cmd_buf; -+ int ret = 0; -+ -+ /* Prepare command */ -+ switch (cmd_no) { -+ case HostCmd_CMD_GET_HW_SPEC: -+ ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); -+ break; -+ case HostCmd_CMD_MAC_CONTROL: -+ ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_802_11_MAC_ADDRESS: -+ ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr, -+ cmd_action); -+ break; -+ case HostCmd_CMD_MAC_MULTICAST_ADR: -+ ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_TX_RATE_CFG: -+ ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_TXPWR_CFG: -+ ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_802_11_PS_MODE_ENH: -+ ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, -+ (uint16_t)cmd_oid, data_buf); -+ break; -+ case HostCmd_CMD_802_11_HS_CFG_ENH: -+ ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action, -+ (struct mwifiex_hs_config_param *) data_buf); -+ break; -+ case HostCmd_CMD_802_11_SCAN: -+ 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(cmd_ptr); -+ break; -+ case HostCmd_CMD_802_11_ASSOCIATE: -+ ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); -+ break; -+ case HostCmd_CMD_802_11_DEAUTHENTICATE: -+ ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr, -+ data_buf); -+ break; -+ case HostCmd_CMD_802_11_AD_HOC_START: -+ ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr, -+ data_buf); -+ break; -+ case HostCmd_CMD_802_11_GET_LOG: -+ 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(cmd_ptr); -+ break; -+ case HostCmd_CMD_RSSI_INFO: -+ ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); -+ break; -+ case HostCmd_CMD_802_11_SNMP_MIB: -+ ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action, -+ cmd_oid, data_buf); -+ break; -+ case HostCmd_CMD_802_11_TX_RATE_QUERY: -+ cmd_ptr->command = -+ cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); -+ cmd_ptr->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + -+ S_DS_GEN); -+ priv->tx_rate = 0; -+ ret = 0; -+ break; -+ case HostCmd_CMD_VERSION_EXT: -+ cmd_ptr->command = cpu_to_le16(cmd_no); -+ cmd_ptr->params.verext.version_str_sel = -+ (u8) (*((u32 *) data_buf)); -+ memcpy(&cmd_ptr->params, data_buf, -+ sizeof(struct host_cmd_ds_version_ext)); -+ cmd_ptr->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + -+ S_DS_GEN); -+ ret = 0; -+ break; -+ case HostCmd_CMD_802_11_RF_CHANNEL: -+ ret = mwifiex_cmd_802_11_rf_channel(priv, cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_FUNC_INIT: -+ if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) -+ priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; -+ cmd_ptr->command = cpu_to_le16(cmd_no); -+ cmd_ptr->size = cpu_to_le16(S_DS_GEN); -+ break; -+ case HostCmd_CMD_FUNC_SHUTDOWN: -+ priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET; -+ cmd_ptr->command = cpu_to_le16(cmd_no); -+ cmd_ptr->size = cpu_to_le16(S_DS_GEN); -+ break; -+ case HostCmd_CMD_11N_ADDBA_REQ: -+ ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf); -+ break; -+ case HostCmd_CMD_11N_DELBA: -+ 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); -+ break; -+ case HostCmd_CMD_802_11_KEY_MATERIAL: -+ ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr, -+ cmd_action, cmd_oid, -+ data_buf); -+ break; -+ case HostCmd_CMD_802_11D_DOMAIN_INFO: -+ ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr, -+ cmd_action); -+ break; -+ case HostCmd_CMD_RECONFIGURE_TX_BUFF: -+ ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_AMSDU_AGGR_CTRL: -+ ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_11N_CFG: -+ ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, -+ data_buf); -+ break; -+ case HostCmd_CMD_WMM_GET_STATUS: -+ dev_dbg(priv->adapter->dev, -+ "cmd: WMM: WMM_GET_STATUS cmd sent\n"); -+ cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); -+ cmd_ptr->size = -+ cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + -+ S_DS_GEN); -+ ret = 0; -+ break; -+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: -+ 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: -+ case HostCmd_CMD_RF_REG_ACCESS: -+ case HostCmd_CMD_PMIC_REG_ACCESS: -+ case HostCmd_CMD_CAU_REG_ACCESS: -+ case HostCmd_CMD_802_11_EEPROM_ACCESS: -+ ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf); -+ break; -+ case HostCmd_CMD_SET_BSS_MODE: -+ cmd_ptr->command = cpu_to_le16(cmd_no); -+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC) -+ cmd_ptr->params.bss_mode.con_type = -+ CONNECTION_TYPE_ADHOC; -+ else if (priv->bss_mode == NL80211_IFTYPE_STATION) -+ cmd_ptr->params.bss_mode.con_type = -+ CONNECTION_TYPE_INFRA; -+ cmd_ptr->size = cpu_to_le16(sizeof(struct -+ host_cmd_ds_set_bss_mode) + S_DS_GEN); -+ ret = 0; -+ break; -+ default: -+ dev_err(priv->adapter->dev, -+ "PREP_CMD: unknown cmd- %#x\n", cmd_no); -+ ret = -1; -+ break; -+ } -+ return ret; -+} -+ -+/* -+ * This function issues commands to initialize firmware. -+ * -+ * This is called after firmware download to bring the card to -+ * working state. -+ * -+ * The following commands are issued sequentially - -+ * - Function init (for first interface only) -+ * - Read MAC address (for first interface only) -+ * - Reconfigure Tx buffer size (for first interface only) -+ * - Enable auto deep sleep (for first interface only) -+ * - Get Tx rate -+ * - Get Tx power -+ * - Set IBSS coalescing status -+ * - Set AMSDU aggregation control -+ * - Set 11d control -+ * - Set MAC control (this must be the last command to initialize firmware) -+ */ -+int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) -+{ -+ int ret = 0; -+ u16 enable = true; -+ struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; -+ struct mwifiex_ds_auto_ds auto_ds; -+ enum state_11d_t state_11d; -+ -+ if (first_sta) { -+ -+ 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_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_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_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_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_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG, -+ HostCmd_ACT_GEN_GET, 0, NULL); -+ if (ret) -+ return -1; -+ -+ /* set ibss coalescing_status */ -+ 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_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_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, -+ HostCmd_ACT_GEN_SET, 0, -+ &priv->curr_pkt_filter); -+ if (ret) -+ return -1; -+ -+ if (first_sta) { -+ /* Enable auto deep sleep */ -+ auto_ds.auto_ds = DEEP_SLEEP_ON; -+ auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; -+ 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_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"); -+ -+ /* set last_init_cmd */ -+ priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB; -+ ret = -EINPROGRESS; -+ -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_cmdresp.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_cmdresp.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_cmdresp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_cmdresp.c 2011-05-05 23:29:45.475441743 +0200 -@@ -0,0 +1,972 @@ -+/* -+ * Marvell Wireless LAN device driver: station command response handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+ -+/* -+ * This function handles the command response error case. -+ * -+ * For scan response error, the function cancels all the pending -+ * scan commands and generates an event to inform the applications -+ * of the scan completion. -+ * -+ * For Power Save command failure, we do not retry enter PS -+ * command in case of Ad-hoc mode. -+ * -+ * For all other response errors, the current command buffer is freed -+ * and returned to the free command queue. -+ */ -+static void -+mwifiex_process_cmdresp_error(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_802_11_ps_mode_enh *pm; -+ unsigned long flags; -+ -+ dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n", -+ resp->command, resp->result); -+ -+ 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: -+ pm = &resp->params.psmode_enh; -+ dev_err(adapter->dev, "PS_MODE_ENH cmd failed: " -+ "result=0x%x action=0x%X\n", -+ resp->result, le16_to_cpu(pm->action)); -+ /* We do not re-try enter-ps command in ad-hoc mode. */ -+ if (le16_to_cpu(pm->action) == EN_AUTO_PS && -+ (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) && -+ priv->bss_mode == NL80211_IFTYPE_ADHOC) -+ adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; -+ -+ break; -+ case HostCmd_CMD_802_11_SCAN: -+ /* Cancel all pending scan command */ -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ list_for_each_entry_safe(cmd_node, tmp_node, -+ &adapter->scan_pending_q, list) { -+ list_del(&cmd_node->list); -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, -+ flags); -+ mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -+ spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); -+ } -+ spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->scan_processing = false; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+ if (priv->report_scan_result) -+ priv->report_scan_result = false; -+ if (priv->scan_pending_on_block) { -+ priv->scan_pending_on_block = false; -+ up(&priv->async_sem); -+ } -+ break; -+ -+ case HostCmd_CMD_MAC_CONTROL: -+ break; -+ -+ default: -+ break; -+ } -+ /* Handling errors here */ -+ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); -+ -+ spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -+ adapter->curr_cmd = NULL; -+ spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -+} -+ -+/* -+ * This function handles the command response of get RSSI info. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the following parameters in driver - -+ * - Last data and beacon RSSI value -+ * - Average data and beacon RSSI value -+ * - Last data and beacon NF value -+ * - Average data and beacon NF value -+ * -+ * The parameters are send to the application as well, along with -+ * calculated SNR values. -+ */ -+static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = -+ &resp->params.rssi_info_rsp; -+ struct mwifiex_ds_get_signal *signal = NULL; -+ -+ priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); -+ priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); -+ -+ priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); -+ priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); -+ -+ priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); -+ priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); -+ -+ priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); -+ priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); -+ -+ /* Need to indicate IOCTL complete */ -+ if (data_buf) { -+ signal = (struct mwifiex_ds_get_signal *) data_buf; -+ memset(signal, 0, sizeof(struct mwifiex_ds_get_signal)); -+ -+ signal->selector = ALL_RSSI_INFO_MASK; -+ -+ /* RSSI */ -+ signal->bcn_rssi_last = priv->bcn_rssi_last; -+ signal->bcn_rssi_avg = priv->bcn_rssi_avg; -+ signal->data_rssi_last = priv->data_rssi_last; -+ signal->data_rssi_avg = priv->data_rssi_avg; -+ -+ /* SNR */ -+ signal->bcn_snr_last = -+ CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last); -+ signal->bcn_snr_avg = -+ CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg); -+ signal->data_snr_last = -+ CAL_SNR(priv->data_rssi_last, priv->data_nf_last); -+ signal->data_snr_avg = -+ CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg); -+ -+ /* NF */ -+ signal->bcn_nf_last = priv->bcn_nf_last; -+ signal->bcn_nf_avg = priv->bcn_nf_avg; -+ signal->data_nf_last = priv->data_nf_last; -+ signal->data_nf_avg = priv->data_nf_avg; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get SNMP -+ * MIB parameters. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the parameter in driver. -+ * -+ * The following parameters are supported - -+ * - Fragmentation threshold -+ * - RTS threshold -+ * - Short retry limit -+ */ -+static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; -+ u16 oid = le16_to_cpu(smib->oid); -+ u16 query_type = le16_to_cpu(smib->query_type); -+ u32 ul_temp; -+ -+ dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x," -+ " query_type = %#x, buf size = %#x\n", -+ oid, query_type, le16_to_cpu(smib->buf_size)); -+ if (query_type == HostCmd_ACT_GEN_GET) { -+ ul_temp = le16_to_cpu(*((__le16 *) (smib->value))); -+ if (data_buf) -+ *(u32 *)data_buf = ul_temp; -+ switch (oid) { -+ case FRAG_THRESH_I: -+ dev_dbg(priv->adapter->dev, -+ "info: SNMP_RESP: FragThsd =%u\n", ul_temp); -+ break; -+ case RTS_THRESH_I: -+ dev_dbg(priv->adapter->dev, -+ "info: SNMP_RESP: RTSThsd =%u\n", ul_temp); -+ break; -+ case SHORT_RETRY_LIM_I: -+ dev_dbg(priv->adapter->dev, -+ "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get log request -+ * -+ * Handling includes changing the header fields into CPU format -+ * and sending the received parameters to application. -+ */ -+static int mwifiex_ret_get_log(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_get_log *get_log = -+ (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; -+ struct mwifiex_ds_get_stats *stats = NULL; -+ -+ if (data_buf) { -+ stats = (struct mwifiex_ds_get_stats *) data_buf; -+ stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); -+ stats->failed = le32_to_cpu(get_log->failed); -+ stats->retry = le32_to_cpu(get_log->retry); -+ stats->multi_retry = le32_to_cpu(get_log->multi_retry); -+ stats->frame_dup = le32_to_cpu(get_log->frame_dup); -+ stats->rts_success = le32_to_cpu(get_log->rts_success); -+ stats->rts_failure = le32_to_cpu(get_log->rts_failure); -+ stats->ack_failure = le32_to_cpu(get_log->ack_failure); -+ stats->rx_frag = le32_to_cpu(get_log->rx_frag); -+ stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); -+ stats->fcs_error = le32_to_cpu(get_log->fcs_error); -+ stats->tx_frame = le32_to_cpu(get_log->tx_frame); -+ stats->wep_icv_error[0] = -+ le32_to_cpu(get_log->wep_icv_err_cnt[0]); -+ stats->wep_icv_error[1] = -+ le32_to_cpu(get_log->wep_icv_err_cnt[1]); -+ stats->wep_icv_error[2] = -+ le32_to_cpu(get_log->wep_icv_err_cnt[2]); -+ stats->wep_icv_error[3] = -+ le32_to_cpu(get_log->wep_icv_err_cnt[3]); -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get Tx rate -+ * configurations. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the following parameters in driver - -+ * - DSSS rate bitmap -+ * - OFDM rate bitmap -+ * - HT MCS rate bitmaps -+ * -+ * Based on the new rate bitmaps, the function re-evaluates if -+ * auto data rate has been activated. If not, it sends another -+ * query to the firmware to get the current Tx data rate and updates -+ * the driver value. -+ */ -+static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ 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; -+ struct mwifiex_ie_types_header *head = NULL; -+ u16 tlv, tlv_buf_len; -+ u8 *tlv_buf; -+ u32 i; -+ int ret = 0; -+ -+ tlv_buf = (u8 *) ((u8 *) rate_cfg) + -+ sizeof(struct host_cmd_ds_tx_rate_cfg); -+ tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16)); -+ -+ while (tlv_buf && tlv_buf_len > 0) { -+ tlv = (*tlv_buf); -+ tlv = tlv | (*(tlv_buf + 1) << 8); -+ -+ switch (tlv) { -+ case TLV_TYPE_RATE_SCOPE: -+ rate_scope = (struct mwifiex_rate_scope *) tlv_buf; -+ priv->bitmap_rates[0] = -+ le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); -+ priv->bitmap_rates[1] = -+ le16_to_cpu(rate_scope->ofdm_rate_bitmap); -+ for (i = 0; -+ i < -+ sizeof(rate_scope->ht_mcs_rate_bitmap) / -+ sizeof(u16); i++) -+ priv->bitmap_rates[2 + i] = -+ le16_to_cpu(rate_scope-> -+ ht_mcs_rate_bitmap[i]); -+ break; -+ /* Add RATE_DROP tlv here */ -+ } -+ -+ head = (struct mwifiex_ie_types_header *) tlv_buf; -+ tlv_buf += le16_to_cpu(head->len) + sizeof(*head); -+ tlv_buf_len -= le16_to_cpu(head->len); -+ } -+ -+ priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); -+ -+ if (priv->is_data_rate_auto) -+ priv->data_rate = 0; -+ else -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_802_11_TX_RATE_QUERY, -+ HostCmd_ACT_GEN_GET, 0, NULL); -+ -+ if (data_buf) { -+ ds_rate = (struct mwifiex_rate_cfg *) data_buf; -+ if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) { -+ if (priv->is_data_rate_auto) { -+ ds_rate->is_rate_auto = 1; -+ } else { -+ ds_rate->rate = mwifiex_get_rate_index(priv-> -+ bitmap_rates, -+ sizeof(priv-> -+ bitmap_rates)); -+ if (ds_rate->rate >= -+ MWIFIEX_RATE_BITMAP_OFDM0 -+ && ds_rate->rate <= -+ MWIFIEX_RATE_BITMAP_OFDM7) -+ ds_rate->rate -= -+ (MWIFIEX_RATE_BITMAP_OFDM0 - -+ MWIFIEX_RATE_INDEX_OFDM0); -+ if (ds_rate->rate >= -+ MWIFIEX_RATE_BITMAP_MCS0 -+ && ds_rate->rate <= -+ MWIFIEX_RATE_BITMAP_MCS127) -+ ds_rate->rate -= -+ (MWIFIEX_RATE_BITMAP_MCS0 - -+ MWIFIEX_RATE_INDEX_MCS0); -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function handles the command response of get Tx power level. -+ * -+ * Handling includes saving the maximum and minimum Tx power levels -+ * in driver, as well as sending the values to user. -+ */ -+static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) -+{ -+ int length = -1, max_power = -1, min_power = -1; -+ struct mwifiex_types_power_group *pg_tlv_hdr = NULL; -+ struct mwifiex_power_group *pg = NULL; -+ -+ if (data_buf) { -+ pg_tlv_hdr = -+ (struct mwifiex_types_power_group *) ((u8 *) data_buf -+ + sizeof(struct host_cmd_ds_txpwr_cfg)); -+ pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr + -+ sizeof(struct mwifiex_types_power_group)); -+ length = pg_tlv_hdr->length; -+ if (length > 0) { -+ max_power = pg->power_max; -+ min_power = pg->power_min; -+ length -= sizeof(struct mwifiex_power_group); -+ } -+ while (length) { -+ pg++; -+ if (max_power < pg->power_max) -+ max_power = pg->power_max; -+ -+ if (min_power > pg->power_min) -+ min_power = pg->power_min; -+ -+ length -= sizeof(struct mwifiex_power_group); -+ } -+ if (pg_tlv_hdr->length > 0) { -+ priv->min_tx_power_level = (u8) min_power; -+ priv->max_tx_power_level = (u8) max_power; -+ } -+ } else { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get Tx power -+ * configurations. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the current Tx power level in driver. -+ */ -+static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; -+ struct mwifiex_types_power_group *pg_tlv_hdr = NULL; -+ struct mwifiex_power_group *pg = NULL; -+ u16 action = le16_to_cpu(txp_cfg->action); -+ -+ switch (action) { -+ case HostCmd_ACT_GEN_GET: -+ { -+ pg_tlv_hdr = -+ (struct mwifiex_types_power_group *) ((u8 *) -+ txp_cfg + -+ sizeof -+ (struct -+ host_cmd_ds_txpwr_cfg)); -+ pg = (struct mwifiex_power_group *) ((u8 *) -+ pg_tlv_hdr + -+ sizeof(struct -+ mwifiex_types_power_group)); -+ if (adapter->hw_status == -+ MWIFIEX_HW_STATUS_INITIALIZING) -+ mwifiex_get_power_level(priv, txp_cfg); -+ priv->tx_power_level = (u16) pg->power_min; -+ break; -+ } -+ case HostCmd_ACT_GEN_SET: -+ if (le32_to_cpu(txp_cfg->mode)) { -+ pg_tlv_hdr = -+ (struct mwifiex_types_power_group *) ((u8 *) -+ txp_cfg + -+ sizeof -+ (struct -+ host_cmd_ds_txpwr_cfg)); -+ pg = (struct mwifiex_power_group *) ((u8 *) pg_tlv_hdr -+ + -+ sizeof(struct -+ mwifiex_types_power_group)); -+ if (pg->power_max == pg->power_min) -+ priv->tx_power_level = (u16) pg->power_min; -+ } -+ break; -+ default: -+ dev_err(adapter->dev, "CMD_RESP: unknown cmd action %d\n", -+ action); -+ return 0; -+ } -+ dev_dbg(adapter->dev, -+ "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", -+ priv->tx_power_level, priv->max_tx_power_level, -+ priv->min_tx_power_level); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get MAC address. -+ * -+ * Handling includes saving the MAC address in driver. -+ */ -+static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = -+ &resp->params.mac_addr; -+ -+ memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); -+ -+ dev_dbg(priv->adapter->dev, -+ "info: set mac address: %pM\n", priv->curr_addr); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get MAC multicast -+ * address. -+ */ -+static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get Tx rate query. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the Tx rate and HT information parameters in driver. -+ * -+ * Both rate configuration and current data rate can be retrieved -+ * with this request. -+ */ -+static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ 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(priv->tx_rate, -+ priv->tx_htinfo); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of a deauthenticate -+ * command. -+ * -+ * If the deauthenticated MAC matches the current BSS MAC, the connection -+ * state is reset. -+ */ -+static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ adapter->dbg.num_cmd_deauth++; -+ if (!memcmp(resp->params.deauth.mac_addr, -+ &priv->curr_bss_params.bss_descriptor.mac_address, -+ sizeof(resp->params.deauth.mac_addr))) -+ mwifiex_reset_connect_state(priv); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of ad-hoc stop. -+ * -+ * The function resets the connection state in driver. -+ */ -+static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ mwifiex_reset_connect_state(priv); -+ return 0; -+} -+ -+/* -+ * This function handles the command response of set/get key material. -+ * -+ * Handling includes updating the driver parameters to reflect the -+ * changes. -+ */ -+static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_802_11_key_material *key = -+ &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_MCAST)) { -+ dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); -+ priv->wpa_is_gtk_set = true; -+ priv->scan_block = false; -+ } -+ } -+ -+ memset(priv->aes_key.key_param_set.key, 0, -+ sizeof(key->key_param_set.key)); -+ priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; -+ memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, -+ le16_to_cpu(priv->aes_key.key_param_set.key_len)); -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get 11d domain information. -+ */ -+static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = -+ &resp->params.domain_info_resp; -+ struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; -+ u16 action = le16_to_cpu(domain_info->action); -+ u8 no_of_triplet = 0; -+ -+ no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - -+ IEEE80211_COUNTRY_STRING_LEN) / -+ sizeof(struct ieee80211_country_ie_triplet)); -+ -+ dev_dbg(priv->adapter->dev, "info: 11D Domain Info Resp:" -+ " no_of_triplet=%d\n", no_of_triplet); -+ -+ if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { -+ dev_warn(priv->adapter->dev, -+ "11D: invalid number of triplets %d " -+ "returned!!\n", no_of_triplet); -+ return -1; -+ } -+ -+ switch (action) { -+ case HostCmd_ACT_GEN_SET: /* Proc Set Action */ -+ break; -+ case HostCmd_ACT_GEN_GET: -+ break; -+ default: -+ dev_err(priv->adapter->dev, -+ "11D: invalid action:%d\n", domain_info->action); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get RF channel. -+ * -+ * Handling includes changing the header fields into CPU format -+ * and saving the new channel in driver. -+ */ -+static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct host_cmd_ds_802_11_rf_channel *rf_channel = -+ &resp->params.rf_channel; -+ u16 new_channel = le16_to_cpu(rf_channel->current_channel); -+ -+ if (priv->curr_bss_params.bss_descriptor.channel != new_channel) { -+ dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n", -+ priv->curr_bss_params.bss_descriptor.channel, -+ new_channel); -+ /* Update the channel again */ -+ priv->curr_bss_params.bss_descriptor.channel = new_channel; -+ } -+ if (data_buf) -+ *((u16 *)data_buf) = new_channel; -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get extended version. -+ * -+ * Handling includes forming the extended version string and sending it -+ * to application. -+ */ -+static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; -+ struct host_cmd_ds_version_ext *version_ext = NULL; -+ -+ if (data_buf) { -+ version_ext = (struct host_cmd_ds_version_ext *)data_buf; -+ version_ext->version_str_sel = ver_ext->version_str_sel; -+ memcpy(version_ext->version_str, ver_ext->version_str, -+ sizeof(char) * 128); -+ memcpy(priv->version_str, ver_ext->version_str, 128); -+ } -+ return 0; -+} -+ -+/* -+ * This function handles the command response of register access. -+ * -+ * The register value and offset are returned to the user. For EEPROM -+ * access, the byte count is also returned. -+ */ -+static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, -+ void *data_buf) -+{ -+ struct mwifiex_ds_reg_rw *reg_rw = NULL; -+ struct mwifiex_ds_read_eeprom *eeprom = NULL; -+ -+ if (data_buf) { -+ reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; -+ eeprom = (struct mwifiex_ds_read_eeprom *) data_buf; -+ switch (type) { -+ case HostCmd_CMD_MAC_REG_ACCESS: -+ { -+ struct host_cmd_ds_mac_reg_access *reg; -+ reg = (struct host_cmd_ds_mac_reg_access *) -+ &resp->params.mac_reg; -+ reg_rw->offset = cpu_to_le32( -+ (u32) le16_to_cpu(reg->offset)); -+ reg_rw->value = reg->value; -+ break; -+ } -+ case HostCmd_CMD_BBP_REG_ACCESS: -+ { -+ struct host_cmd_ds_bbp_reg_access *reg; -+ reg = (struct host_cmd_ds_bbp_reg_access *) -+ &resp->params.bbp_reg; -+ reg_rw->offset = cpu_to_le32( -+ (u32) le16_to_cpu(reg->offset)); -+ reg_rw->value = cpu_to_le32((u32) reg->value); -+ break; -+ } -+ -+ case HostCmd_CMD_RF_REG_ACCESS: -+ { -+ struct host_cmd_ds_rf_reg_access *reg; -+ reg = (struct host_cmd_ds_rf_reg_access *) -+ &resp->params.rf_reg; -+ reg_rw->offset = cpu_to_le32( -+ (u32) le16_to_cpu(reg->offset)); -+ reg_rw->value = cpu_to_le32((u32) reg->value); -+ break; -+ } -+ case HostCmd_CMD_PMIC_REG_ACCESS: -+ { -+ struct host_cmd_ds_pmic_reg_access *reg; -+ reg = (struct host_cmd_ds_pmic_reg_access *) -+ &resp->params.pmic_reg; -+ reg_rw->offset = cpu_to_le32( -+ (u32) le16_to_cpu(reg->offset)); -+ reg_rw->value = cpu_to_le32((u32) reg->value); -+ break; -+ } -+ case HostCmd_CMD_CAU_REG_ACCESS: -+ { -+ struct host_cmd_ds_rf_reg_access *reg; -+ reg = (struct host_cmd_ds_rf_reg_access *) -+ &resp->params.rf_reg; -+ reg_rw->offset = cpu_to_le32( -+ (u32) le16_to_cpu(reg->offset)); -+ reg_rw->value = cpu_to_le32((u32) reg->value); -+ break; -+ } -+ case HostCmd_CMD_802_11_EEPROM_ACCESS: -+ { -+ struct host_cmd_ds_802_11_eeprom_access -+ *cmd_eeprom = -+ (struct host_cmd_ds_802_11_eeprom_access -+ *) &resp->params.eeprom; -+ pr_debug("info: EEPROM read len=%x\n", -+ cmd_eeprom->byte_count); -+ if (le16_to_cpu(eeprom->byte_count) < -+ le16_to_cpu( -+ cmd_eeprom->byte_count)) { -+ eeprom->byte_count = cpu_to_le16(0); -+ pr_debug("info: EEPROM read " -+ "length is too big\n"); -+ return -1; -+ } -+ eeprom->offset = cmd_eeprom->offset; -+ eeprom->byte_count = cmd_eeprom->byte_count; -+ if (le16_to_cpu(eeprom->byte_count) > 0) -+ memcpy(&eeprom->value, -+ &cmd_eeprom->value, -+ le16_to_cpu(eeprom->byte_count)); -+ -+ break; -+ } -+ default: -+ return -1; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * This function handles the command response of get IBSS coalescing status. -+ * -+ * If the received BSSID is different than the current one, the current BSSID, -+ * beacon interval, ATIM window and ERP information are updated, along with -+ * changing the ad-hoc state accordingly. -+ */ -+static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, -+ struct host_cmd_ds_command *resp) -+{ -+ struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = -+ &(resp->params.ibss_coalescing); -+ u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -+ -+ if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) -+ return 0; -+ -+ dev_dbg(priv->adapter->dev, -+ "info: new BSSID %pM\n", ibss_coal_resp->bssid); -+ -+ /* If rsp has NULL BSSID, Just return..... No Action */ -+ if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { -+ dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); -+ return 0; -+ } -+ -+ /* If BSSID is diff, modify current BSS parameters */ -+ if (memcmp(priv->curr_bss_params.bss_descriptor.mac_address, -+ ibss_coal_resp->bssid, ETH_ALEN)) { -+ /* BSSID */ -+ memcpy(priv->curr_bss_params.bss_descriptor.mac_address, -+ ibss_coal_resp->bssid, ETH_ALEN); -+ -+ /* Beacon Interval */ -+ priv->curr_bss_params.bss_descriptor.beacon_period -+ = le16_to_cpu(ibss_coal_resp->beacon_interval); -+ -+ /* ERP Information */ -+ priv->curr_bss_params.bss_descriptor.erp_flags = -+ (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); -+ -+ priv->adhoc_state = ADHOC_COALESCED; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function handles the command responses. -+ * -+ * This is a generic function, which calls command specific -+ * response handlers based on the command ID. -+ */ -+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, -+ 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; -+ 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); -+ return -1; -+ } -+ /* Command successful, handle response */ -+ switch (cmdresp_no) { -+ case HostCmd_CMD_GET_HW_SPEC: -+ ret = mwifiex_ret_get_hw_spec(priv, resp); -+ break; -+ case HostCmd_CMD_MAC_CONTROL: -+ break; -+ case HostCmd_CMD_802_11_MAC_ADDRESS: -+ ret = mwifiex_ret_802_11_mac_address(priv, resp); -+ break; -+ case HostCmd_CMD_MAC_MULTICAST_ADR: -+ ret = mwifiex_ret_mac_multicast_adr(priv, resp); -+ break; -+ case HostCmd_CMD_TX_RATE_CFG: -+ 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); -+ adapter->curr_cmd->wait_q_enabled = false; -+ break; -+ case HostCmd_CMD_802_11_BG_SCAN_QUERY: -+ ret = mwifiex_ret_802_11_scan(priv, resp); -+ dev_dbg(adapter->dev, -+ "info: CMD_RESP: BG_SCAN result is ready!\n"); -+ break; -+ case HostCmd_CMD_TXPWR_CFG: -+ ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_802_11_PS_MODE_ENH: -+ ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_802_11_HS_CFG_ENH: -+ ret = mwifiex_ret_802_11_hs_cfg(priv, resp); -+ break; -+ case HostCmd_CMD_802_11_ASSOCIATE: -+ 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); -+ break; -+ case HostCmd_CMD_802_11_AD_HOC_STOP: -+ ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); -+ break; -+ case HostCmd_CMD_802_11_GET_LOG: -+ ret = mwifiex_ret_get_log(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_RSSI_INFO: -+ ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_802_11_SNMP_MIB: -+ ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_802_11_TX_RATE_QUERY: -+ ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); -+ break; -+ case HostCmd_CMD_802_11_RF_CHANNEL: -+ ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_VERSION_EXT: -+ ret = mwifiex_ret_ver_ext(priv, resp, data_buf); -+ break; -+ case HostCmd_CMD_FUNC_INIT: -+ case HostCmd_CMD_FUNC_SHUTDOWN: -+ break; -+ case HostCmd_CMD_802_11_KEY_MATERIAL: -+ ret = mwifiex_ret_802_11_key_material(priv, resp); -+ break; -+ case HostCmd_CMD_802_11D_DOMAIN_INFO: -+ ret = mwifiex_ret_802_11d_domain_info(priv, resp); -+ break; -+ case HostCmd_CMD_11N_ADDBA_REQ: -+ ret = mwifiex_ret_11n_addba_req(priv, resp); -+ break; -+ case HostCmd_CMD_11N_DELBA: -+ ret = mwifiex_ret_11n_delba(priv, resp); -+ break; -+ case HostCmd_CMD_11N_ADDBA_RSP: -+ ret = mwifiex_ret_11n_addba_resp(priv, resp); -+ break; -+ case HostCmd_CMD_RECONFIGURE_TX_BUFF: -+ adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. -+ tx_buf.buff_size); -+ adapter->tx_buf_size = (adapter->tx_buf_size / -+ MWIFIEX_SDIO_BLOCK_SIZE) * -+ MWIFIEX_SDIO_BLOCK_SIZE; -+ adapter->curr_tx_buf_size = adapter->tx_buf_size; -+ dev_dbg(adapter->dev, -+ "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n", -+ adapter->max_tx_buf_size, adapter->tx_buf_size); -+ -+ if (adapter->if_ops.update_mp_end_port) -+ adapter->if_ops.update_mp_end_port(adapter, -+ le16_to_cpu(resp-> -+ params. -+ tx_buf. -+ mp_end_port)); -+ break; -+ case HostCmd_CMD_AMSDU_AGGR_CTRL: -+ ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf); -+ break; -+ case HostCmd_CMD_WMM_GET_STATUS: -+ ret = mwifiex_ret_wmm_get_status(priv, resp); -+ break; -+ case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: -+ ret = mwifiex_ret_ibss_coalescing_status(priv, resp); -+ break; -+ case HostCmd_CMD_MAC_REG_ACCESS: -+ case HostCmd_CMD_BBP_REG_ACCESS: -+ case HostCmd_CMD_RF_REG_ACCESS: -+ case HostCmd_CMD_PMIC_REG_ACCESS: -+ case HostCmd_CMD_CAU_REG_ACCESS: -+ case HostCmd_CMD_802_11_EEPROM_ACCESS: -+ ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); -+ break; -+ case HostCmd_CMD_SET_BSS_MODE: -+ break; -+ case HostCmd_CMD_11N_CFG: -+ ret = mwifiex_ret_11n_cfg(resp, data_buf); -+ break; -+ default: -+ dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", -+ resp->command); -+ break; -+ } -+ -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_event.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_event.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_event.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_event.c 2011-05-05 23:29:45.489441913 +0200 -@@ -0,0 +1,406 @@ -+/* -+ * Marvell Wireless LAN device driver: station event handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * This function resets the connection state. -+ * -+ * The function is invoked after receiving a disconnect event from firmware, -+ * and performs the following actions - -+ * - Set media status to disconnected -+ * - Clean up Tx and Rx packets -+ * - Resets SNR/NF/RSSI value in driver -+ * - Resets security configurations in driver -+ * - Enables auto data rate -+ * - Saves the previous SSID and BSSID so that they can -+ * be used for re-association, if required -+ * - Erases current SSID and BSSID information -+ * - Sends a disconnect event to upper layers/applications. -+ */ -+void -+mwifiex_reset_connect_state(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ if (!priv->media_connected) -+ return; -+ -+ dev_dbg(adapter->dev, "info: handles disconnect event\n"); -+ -+ priv->media_connected = false; -+ -+ priv->scan_block = false; -+ -+ /* Free Tx and Rx packets, report disconnect to upper layer */ -+ mwifiex_clean_txrx(priv); -+ -+ /* Reset SNR/NF/RSSI values */ -+ priv->data_rssi_last = 0; -+ priv->data_nf_last = 0; -+ priv->data_rssi_avg = 0; -+ priv->data_nf_avg = 0; -+ priv->bcn_rssi_last = 0; -+ priv->bcn_nf_last = 0; -+ priv->bcn_rssi_avg = 0; -+ priv->bcn_nf_avg = 0; -+ priv->rxpd_rate = 0; -+ priv->rxpd_htinfo = 0; -+ priv->sec_info.wpa_enabled = false; -+ priv->sec_info.wpa2_enabled = false; -+ priv->wpa_ie_len = 0; -+ -+ priv->sec_info.wapi_enabled = false; -+ priv->wapi_ie_len = 0; -+ priv->sec_info.wapi_key_on = false; -+ -+ priv->sec_info.encryption_mode = 0; -+ -+ /* Enable auto data rate */ -+ priv->is_data_rate_auto = true; -+ priv->data_rate = 0; -+ -+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ priv->adhoc_state = ADHOC_IDLE; -+ priv->adhoc_is_link_sensed = false; -+ } -+ -+ /* -+ * Memorize the previous SSID and BSSID so -+ * it could be used for re-assoc -+ */ -+ -+ dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n", -+ priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); -+ -+ dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n", -+ priv->curr_bss_params.bss_descriptor.ssid.ssid, -+ priv->curr_bss_params.bss_descriptor.ssid.ssid_len); -+ -+ memcpy(&priv->prev_ssid, -+ &priv->curr_bss_params.bss_descriptor.ssid, -+ sizeof(struct mwifiex_802_11_ssid)); -+ -+ memcpy(priv->prev_bssid, -+ priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); -+ -+ /* Need to erase the current SSID and BSSID info */ -+ memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); -+ -+ adapter->tx_lock_flag = false; -+ adapter->pps_uapsd_mode = false; -+ -+ if (adapter->num_cmd_timeout && adapter->curr_cmd) -+ return; -+ priv->media_connected = false; -+ if (!priv->disconnect) { -+ priv->disconnect = 1; -+ dev_dbg(adapter->dev, "info: successfully disconnected from" -+ " %pM: reason code %d\n", priv->cfg_bssid, -+ WLAN_REASON_DEAUTH_LEAVING); -+ cfg80211_disconnected(priv->netdev, -+ WLAN_REASON_DEAUTH_LEAVING, NULL, 0, -+ GFP_KERNEL); -+ queue_work(priv->workqueue, &priv->cfg_workqueue); -+ } -+ if (!netif_queue_stopped(priv->netdev)) -+ netif_stop_queue(priv->netdev); -+ if (netif_carrier_ok(priv->netdev)) -+ netif_carrier_off(priv->netdev); -+ /* Reset wireless stats signal info */ -+ priv->w_stats.qual.level = 0; -+ priv->w_stats.qual.noise = 0; -+} -+ -+/* -+ * This function handles events generated by firmware. -+ * -+ * This is a generic function and handles all events. -+ * -+ * Event specific routines are called by this function based -+ * upon the generated event cause. -+ * -+ * For the following events, the function just forwards them to upper -+ * layers, optionally recording the change - -+ * - EVENT_LINK_SENSED -+ * - EVENT_MIC_ERR_UNICAST -+ * - EVENT_MIC_ERR_MULTICAST -+ * - EVENT_PORT_RELEASE -+ * - EVENT_RSSI_LOW -+ * - EVENT_SNR_LOW -+ * - EVENT_MAX_FAIL -+ * - EVENT_RSSI_HIGH -+ * - EVENT_SNR_HIGH -+ * - EVENT_DATA_RSSI_LOW -+ * - EVENT_DATA_SNR_LOW -+ * - EVENT_DATA_RSSI_HIGH -+ * - EVENT_DATA_SNR_HIGH -+ * - EVENT_LINK_QUALITY -+ * - EVENT_PRE_BEACON_LOST -+ * - EVENT_IBSS_COALESCED -+ * - EVENT_WEP_ICV_ERR -+ * - EVENT_BW_CHANGE -+ * - EVENT_HOSTWAKE_STAIE -+ * -+ * For the following events, no action is taken - -+ * - EVENT_MIB_CHANGED -+ * - EVENT_INIT_DONE -+ * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL -+ * -+ * Rest of the supported events requires driver handling - -+ * - EVENT_DEAUTHENTICATED -+ * - EVENT_DISASSOCIATED -+ * - EVENT_LINK_LOST -+ * - EVENT_PS_SLEEP -+ * - EVENT_PS_AWAKE -+ * - EVENT_DEEP_SLEEP_AWAKE -+ * - EVENT_HS_ACT_REQ -+ * - EVENT_ADHOC_BCN_LOST -+ * - EVENT_BG_SCAN_REPORT -+ * - EVENT_WMM_STATUS_CHANGE -+ * - EVENT_ADDBA -+ * - EVENT_DELBA -+ * - EVENT_BA_STREAM_TIEMOUT -+ * - EVENT_AMSDU_AGGR_CTRL -+ */ -+int mwifiex_process_sta_event(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int ret = 0; -+ u32 eventcause = adapter->event_cause; -+ -+ switch (eventcause) { -+ case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: -+ dev_err(adapter->dev, "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL," -+ " ignoring it\n"); -+ break; -+ case EVENT_LINK_SENSED: -+ dev_dbg(adapter->dev, "event: LINK_SENSED\n"); -+ if (!netif_carrier_ok(priv->netdev)) -+ netif_carrier_on(priv->netdev); -+ if (netif_queue_stopped(priv->netdev)) -+ netif_wake_queue(priv->netdev); -+ break; -+ -+ case EVENT_DEAUTHENTICATED: -+ dev_dbg(adapter->dev, "event: Deauthenticated\n"); -+ adapter->dbg.num_event_deauth++; -+ if (priv->media_connected) -+ mwifiex_reset_connect_state(priv); -+ break; -+ -+ case EVENT_DISASSOCIATED: -+ dev_dbg(adapter->dev, "event: Disassociated\n"); -+ adapter->dbg.num_event_disassoc++; -+ if (priv->media_connected) -+ mwifiex_reset_connect_state(priv); -+ break; -+ -+ case EVENT_LINK_LOST: -+ dev_dbg(adapter->dev, "event: Link lost\n"); -+ adapter->dbg.num_event_link_lost++; -+ if (priv->media_connected) -+ mwifiex_reset_connect_state(priv); -+ break; -+ -+ case EVENT_PS_SLEEP: -+ dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); -+ -+ adapter->ps_state = PS_STATE_PRE_SLEEP; -+ -+ mwifiex_check_ps_cond(adapter); -+ break; -+ -+ case EVENT_PS_AWAKE: -+ dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); -+ if (!adapter->pps_uapsd_mode && -+ priv->media_connected && -+ adapter->sleep_period.period) { -+ adapter->pps_uapsd_mode = true; -+ dev_dbg(adapter->dev, -+ "event: PPS/UAPSD mode activated\n"); -+ } -+ adapter->tx_lock_flag = false; -+ if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { -+ if (mwifiex_check_last_packet_indication(priv)) { -+ if (!adapter->data_sent) { -+ if (!mwifiex_send_null_packet(priv, -+ MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET -+ | -+ MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) -+ adapter->ps_state = -+ PS_STATE_SLEEP; -+ return 0; -+ } -+ } -+ } -+ adapter->ps_state = PS_STATE_AWAKE; -+ adapter->pm_wakeup_card_req = false; -+ adapter->pm_wakeup_fw_try = false; -+ -+ break; -+ -+ case EVENT_DEEP_SLEEP_AWAKE: -+ adapter->if_ops.wakeup_complete(adapter); -+ dev_dbg(adapter->dev, "event: DS_AWAKE\n"); -+ if (adapter->is_deep_sleep) -+ adapter->is_deep_sleep = false; -+ break; -+ -+ case EVENT_HS_ACT_REQ: -+ dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_802_11_HS_CFG_ENH, -+ 0, 0, NULL); -+ break; -+ -+ case EVENT_MIC_ERR_UNICAST: -+ dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n"); -+ break; -+ -+ case EVENT_MIC_ERR_MULTICAST: -+ dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n"); -+ break; -+ case EVENT_MIB_CHANGED: -+ case EVENT_INIT_DONE: -+ break; -+ -+ case EVENT_ADHOC_BCN_LOST: -+ dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n"); -+ priv->adhoc_is_link_sensed = false; -+ mwifiex_clean_txrx(priv); -+ if (!netif_queue_stopped(priv->netdev)) -+ netif_stop_queue(priv->netdev); -+ if (netif_carrier_ok(priv->netdev)) -+ netif_carrier_off(priv->netdev); -+ break; -+ -+ case EVENT_BG_SCAN_REPORT: -+ dev_dbg(adapter->dev, "event: BGS_REPORT\n"); -+ /* Clear the previous scan result */ -+ memset(adapter->scan_table, 0x00, -+ sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP); -+ adapter->num_in_scan_table = 0; -+ adapter->bcn_buf_end = adapter->bcn_buf; -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_802_11_BG_SCAN_QUERY, -+ HostCmd_ACT_GEN_GET, 0, NULL); -+ break; -+ -+ case EVENT_PORT_RELEASE: -+ dev_dbg(adapter->dev, "event: PORT RELEASE\n"); -+ break; -+ -+ case EVENT_WMM_STATUS_CHANGE: -+ dev_dbg(adapter->dev, "event: WMM status changed\n"); -+ ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, -+ 0, 0, NULL); -+ break; -+ -+ case EVENT_RSSI_LOW: -+ dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); -+ break; -+ case EVENT_SNR_LOW: -+ dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n"); -+ break; -+ case EVENT_MAX_FAIL: -+ dev_dbg(adapter->dev, "event: MAX_FAIL\n"); -+ break; -+ case EVENT_RSSI_HIGH: -+ dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); -+ break; -+ case EVENT_SNR_HIGH: -+ dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n"); -+ break; -+ case EVENT_DATA_RSSI_LOW: -+ dev_dbg(adapter->dev, "event: Data RSSI_LOW\n"); -+ break; -+ case EVENT_DATA_SNR_LOW: -+ dev_dbg(adapter->dev, "event: Data SNR_LOW\n"); -+ break; -+ case EVENT_DATA_RSSI_HIGH: -+ dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n"); -+ break; -+ case EVENT_DATA_SNR_HIGH: -+ dev_dbg(adapter->dev, "event: Data SNR_HIGH\n"); -+ break; -+ case EVENT_LINK_QUALITY: -+ dev_dbg(adapter->dev, "event: Link Quality\n"); -+ break; -+ case EVENT_PRE_BEACON_LOST: -+ dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n"); -+ break; -+ case EVENT_IBSS_COALESCED: -+ dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, -+ HostCmd_ACT_GEN_GET, 0, NULL); -+ break; -+ case EVENT_ADDBA: -+ dev_dbg(adapter->dev, "event: ADDBA Request\n"); -+ 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"); -+ mwifiex_11n_delete_ba_stream(priv, adapter->event_body); -+ break; -+ case EVENT_BA_STREAM_TIEMOUT: -+ dev_dbg(adapter->dev, "event: BA Stream timeout\n"); -+ mwifiex_11n_ba_stream_timeout(priv, -+ (struct host_cmd_ds_11n_batimeout -+ *) -+ adapter->event_body); -+ break; -+ case EVENT_AMSDU_AGGR_CTRL: -+ dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", -+ *(u16 *) adapter->event_body); -+ adapter->tx_buf_size = -+ min(adapter->curr_tx_buf_size, -+ le16_to_cpu(*(__le16 *) adapter->event_body)); -+ dev_dbg(adapter->dev, "event: tx_buf_size %d\n", -+ adapter->tx_buf_size); -+ break; -+ -+ case EVENT_WEP_ICV_ERR: -+ dev_dbg(adapter->dev, "event: WEP ICV error\n"); -+ break; -+ -+ case EVENT_BW_CHANGE: -+ dev_dbg(adapter->dev, "event: BW Change\n"); -+ break; -+ -+ case EVENT_HOSTWAKE_STAIE: -+ dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); -+ break; -+ default: -+ dev_dbg(adapter->dev, "event: unknown event id: %#x\n", -+ eventcause); -+ break; -+ } -+ -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_ioctl.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_ioctl.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_ioctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_ioctl.c 2011-05-05 23:29:45.490441925 +0200 -@@ -0,0 +1,1605 @@ -+/* -+ * Marvell Wireless LAN device driver: functions for station ioctl -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+#include "cfg80211.h" -+ -+/* -+ * Copies the multicast address list from device to driver. -+ * -+ * This function does not validate the destination memory for -+ * size, and the calling function must ensure enough memory is -+ * available. -+ */ -+int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, -+ struct net_device *dev) -+{ -+ int i = 0; -+ struct netdev_hw_addr *ha; -+ -+ netdev_for_each_mc_addr(ha, dev) -+ memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN); -+ -+ return i; -+} -+ -+/* -+ * Wait queue completion handler. -+ * -+ * This function waits on a cmd wait queue. It also cancels the pending -+ * request after waking up, in case of errors. -+ */ -+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) -+{ -+ bool cancel_flag = false; -+ int status = adapter->cmd_wait_q.status; -+ -+ dev_dbg(adapter->dev, "cmd pending\n"); -+ atomic_inc(&adapter->cmd_pending); -+ -+ /* Status pending, wake up main process */ -+ queue_work(adapter->workqueue, &adapter->main_work); -+ -+ /* 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 (cancel_flag) { -+ mwifiex_cancel_pending_ioctl(adapter); -+ dev_dbg(adapter->dev, "cmd cancel\n"); -+ } -+ adapter->cmd_wait_q.status = 0; -+ -+ return status; -+} -+ -+/* -+ * 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. -+ */ -+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 (mcast_list->mode == MWIFIEX_PROMISC_MODE) { -+ dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n"); -+ priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; -+ priv->curr_pkt_filter &= -+ ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; -+ } else { -+ /* Multicast */ -+ priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; -+ if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { -+ dev_dbg(priv->adapter->dev, -+ "info: Enabling All Multicast!\n"); -+ priv->curr_pkt_filter |= -+ HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; -+ } else { -+ priv->curr_pkt_filter &= -+ ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; -+ if (mcast_list->num_multicast_addr) { -+ dev_dbg(priv->adapter->dev, -+ "info: Set multicast list=%d\n", -+ mcast_list->num_multicast_addr); -+ /* Set multicast addresses to firmware */ -+ if (old_pkt_filter == priv->curr_pkt_filter) { -+ /* Send request to firmware */ -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_MAC_MULTICAST_ADR, -+ HostCmd_ACT_GEN_SET, 0, -+ mcast_list); -+ } else { -+ /* Send request to firmware */ -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_MAC_MULTICAST_ADR, -+ HostCmd_ACT_GEN_SET, 0, -+ mcast_list); -+ } -+ } -+ } -+ } -+ dev_dbg(priv->adapter->dev, -+ "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_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, -+ HostCmd_ACT_GEN_SET, -+ 0, &priv->curr_pkt_filter); -+ } -+ -+ return ret; -+} -+ -+/* -+ * 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. -+ */ -+int mwifiex_bss_start(struct mwifiex_private *priv, -+ struct mwifiex_ssid_bssid *ssid_bssid) -+{ -+ int ret = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ s32 i = -1; -+ -+ priv->scan_block = false; -+ if (!ssid_bssid) -+ return -1; -+ -+ if (priv->bss_mode == NL80211_IFTYPE_STATION) { -+ /* Infra mode */ -+ ret = mwifiex_deauthenticate(priv, NULL); -+ if (ret) -+ return ret; -+ -+ /* Search for the requested SSID in the scan table */ -+ if (ssid_bssid->ssid.ssid_len) -+ i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, -+ NULL, NL80211_IFTYPE_STATION); -+ else -+ i = mwifiex_find_bssid_in_list(priv, -+ (u8 *) &ssid_bssid->bssid, -+ NL80211_IFTYPE_STATION); -+ if (i < 0) -+ return -1; -+ -+ dev_dbg(adapter->dev, -+ "info: SSID found in scan list ... associating...\n"); -+ -+ /* Clear any past association response stored for -+ * application retrieval */ -+ priv->assoc_rsp_size = 0; -+ ret = mwifiex_associate(priv, &adapter->scan_table[i]); -+ if (ret) -+ return ret; -+ } else { -+ /* Adhoc mode */ -+ /* If the requested SSID matches current SSID, return */ -+ if (ssid_bssid->ssid.ssid_len && -+ (!mwifiex_ssid_cmp -+ (&priv->curr_bss_params.bss_descriptor.ssid, -+ &ssid_bssid->ssid))) -+ return 0; -+ -+ /* Exit Adhoc mode first */ -+ dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); -+ ret = mwifiex_deauthenticate(priv, NULL); -+ if (ret) -+ return ret; -+ -+ priv->adhoc_is_link_sensed = false; -+ -+ /* Search for the requested network in the scan table */ -+ if (ssid_bssid->ssid.ssid_len) -+ i = mwifiex_find_ssid_in_list(priv, -+ &ssid_bssid->ssid, NULL, -+ NL80211_IFTYPE_ADHOC); -+ else -+ i = mwifiex_find_bssid_in_list(priv, -+ (u8 *)&ssid_bssid->bssid, -+ NL80211_IFTYPE_ADHOC); -+ -+ if (i >= 0) { -+ dev_dbg(adapter->dev, "info: network found in scan" -+ " list. Joining...\n"); -+ ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); -+ if (ret) -+ return ret; -+ } 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, &ssid_bssid->ssid); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set host sleep configuration. -+ * -+ * This function prepares the correct firmware command and -+ * issues it. -+ */ -+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) { -+ dev_dbg(adapter->dev, "info: Host Sleep IOCTL" -+ " is blocked in UAPSD/PPS mode\n"); -+ status = -1; -+ break; -+ } -+ if (hs_cfg->is_invoke_hostcmd) { -+ if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) { -+ if (!adapter->is_hs_configured) -+ /* Already cancelled */ -+ break; -+ /* Save previous condition */ -+ prev_cond = le32_to_cpu(adapter->hs_cfg -+ .conditions); -+ adapter->hs_cfg.conditions = -+ cpu_to_le32(hs_cfg->conditions); -+ } else if (hs_cfg->conditions) { -+ adapter->hs_cfg.conditions = -+ cpu_to_le32(hs_cfg->conditions); -+ adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; -+ if (hs_cfg->gap) -+ adapter->hs_cfg.gap = (u8)hs_cfg->gap; -+ } else if (adapter->hs_cfg.conditions == -+ cpu_to_le32( -+ HOST_SLEEP_CFG_CANCEL)) { -+ /* Return failure if no parameters for HS -+ enable */ -+ status = -1; -+ break; -+ } -+ 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 = -+ cpu_to_le32(prev_cond); -+ } else { -+ adapter->hs_cfg.conditions = -+ cpu_to_le32(hs_cfg->conditions); -+ adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; -+ adapter->hs_cfg.gap = (u8)hs_cfg->gap; -+ } -+ break; -+ case HostCmd_ACT_GEN_GET: -+ hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions); -+ hs_cfg->gpio = adapter->hs_cfg.gpio; -+ hs_cfg->gap = adapter->hs_cfg.gap; -+ break; -+ default: -+ status = -1; -+ break; -+ } -+ -+ return status; -+} -+ -+/* -+ * 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, int cmd_type) -+{ -+ struct mwifiex_ds_hs_cfg hscfg; -+ -+ hscfg.conditions = HOST_SLEEP_CFG_CANCEL; -+ hscfg.is_invoke_hostcmd = true; -+ -+ return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, -+ cmd_type, &hscfg); -+} -+EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); -+ -+/* -+ * 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_enable_hs(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_ds_hs_cfg hscfg; -+ -+ if (adapter->hs_activated) { -+ dev_dbg(adapter->dev, "cmd: HS Already actived\n"); -+ return true; -+ } -+ -+ adapter->hs_activate_wait_q_woken = false; -+ -+ memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param)); -+ hscfg.is_invoke_hostcmd = true; -+ -+ if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, -+ MWIFIEX_BSS_ROLE_STA), -+ HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, -+ &hscfg)) { -+ dev_err(adapter->dev, "IOCTL request HS enable failed\n"); -+ return false; -+ } -+ -+ wait_event_interruptible(adapter->hs_activate_wait_q, -+ adapter->hs_activate_wait_q_woken); -+ -+ return true; -+} -+EXPORT_SYMBOL_GPL(mwifiex_enable_hs); -+ -+/* -+ * IOCTL request handler to get BSS information. -+ * -+ * This function collates the information from different driver structures -+ * to send to the user. -+ */ -+int mwifiex_get_bss_info(struct mwifiex_private *priv, -+ struct mwifiex_bss_info *info) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bssdescriptor *bss_desc; -+ s32 tbl_idx = 0; -+ -+ if (!info) -+ return -1; -+ -+ bss_desc = &priv->curr_bss_params.bss_descriptor; -+ -+ info->bss_mode = priv->bss_mode; -+ -+ memcpy(&info->ssid, &bss_desc->ssid, -+ sizeof(struct mwifiex_802_11_ssid)); -+ -+ memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); -+ -+ info->bss_chan = bss_desc->channel; -+ -+ info->region_code = adapter->region_code; -+ -+ /* Scan table index if connected */ -+ info->scan_table_idx = 0; -+ if (priv->media_connected) { -+ tbl_idx = -+ mwifiex_find_ssid_in_list(priv, &bss_desc->ssid, -+ bss_desc->mac_address, -+ priv->bss_mode); -+ if (tbl_idx >= 0) -+ info->scan_table_idx = tbl_idx; -+ } -+ -+ info->media_connected = priv->media_connected; -+ -+ info->max_power_level = priv->max_tx_power_level; -+ info->min_power_level = priv->min_tx_power_level; -+ -+ info->adhoc_state = priv->adhoc_state; -+ -+ info->bcn_nf_last = priv->bcn_nf_last; -+ -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) -+ info->wep_status = true; -+ else -+ info->wep_status = false; -+ -+ info->is_hs_configured = adapter->is_hs_configured; -+ info->is_deep_sleep = adapter->is_deep_sleep; -+ -+ return 0; -+} -+ -+/* -+ * The function sets band configurations. -+ * -+ * it performs extra checks to make sure the Ad-Hoc -+ * band and channel are compatible. Otherwise it returns an error. -+ * -+ */ -+int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, -+ struct mwifiex_ds_band_cfg *radio_cfg) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u8 infra_band = 0; -+ u8 adhoc_band = 0; -+ u32 adhoc_channel = 0; -+ -+ infra_band = (u8) radio_cfg->config_bands; -+ adhoc_band = (u8) radio_cfg->adhoc_start_band; -+ adhoc_channel = radio_cfg->adhoc_channel; -+ -+ /* SET Infra band */ -+ if ((infra_band | adapter->fw_bands) & ~adapter->fw_bands) -+ return -1; -+ -+ adapter->config_bands = infra_band; -+ -+ /* SET Ad-hoc Band */ -+ if ((adhoc_band | adapter->fw_bands) & ~adapter->fw_bands) -+ return -1; -+ -+ if (adhoc_band) -+ adapter->adhoc_start_band = adhoc_band; -+ adapter->chan_offset = (u8) radio_cfg->sec_chan_offset; -+ /* -+ * If no adhoc_channel is supplied verify if the existing adhoc -+ * channel compiles with new adhoc_band -+ */ -+ if (!adhoc_channel) { -+ if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, adapter->adhoc_start_band, -+ priv->adhoc_channel)) { -+ /* Pass back the default channel */ -+ radio_cfg->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; -+ if ((adapter->adhoc_start_band & BAND_A) -+ || (adapter->adhoc_start_band & BAND_AN)) -+ radio_cfg->adhoc_channel = -+ DEFAULT_AD_HOC_CHANNEL_A; -+ } -+ } else { /* Retrurn error if adhoc_band and -+ adhoc_channel combination is invalid */ -+ if (!mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, adapter->adhoc_start_band, (u16) adhoc_channel)) -+ return -1; -+ priv->adhoc_channel = (u8) adhoc_channel; -+ } -+ if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN)) -+ adapter->adhoc_11n_enabled = true; -+ else -+ adapter->adhoc_11n_enabled = false; -+ -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to set/get active channel. -+ * -+ * This function performs validity checking on channel/frequency -+ * compatibility and returns failure if not valid. -+ */ -+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; -+ -+ if (!chan) -+ return -1; -+ -+ if (!chan->channel && !chan->freq) -+ return -1; -+ if (adapter->adhoc_start_band & BAND_AN) -+ adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; -+ else if (adapter->adhoc_start_band & BAND_A) -+ adapter->adhoc_start_band = BAND_G | BAND_B; -+ if (chan->channel) { -+ if (chan->channel <= MAX_CHANNEL_BAND_BG) -+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, 0, (u16) chan->channel); -+ if (!cfp) { -+ cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211 -+ (priv, BAND_A, (u16) chan->channel); -+ if (cfp) { -+ if (adapter->adhoc_11n_enabled) -+ adapter->adhoc_start_band = BAND_A -+ | BAND_AN; -+ else -+ adapter->adhoc_start_band = BAND_A; -+ } -+ } -+ } else { -+ if (chan->freq <= MAX_FREQUENCY_BAND_BG) -+ cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211( -+ priv, 0, chan->freq); -+ if (!cfp) { -+ cfp = mwifiex_get_cfp_by_band_and_freq_from_cfg80211 -+ (priv, BAND_A, chan->freq); -+ if (cfp) { -+ if (adapter->adhoc_11n_enabled) -+ adapter->adhoc_start_band = BAND_A -+ | BAND_AN; -+ else -+ adapter->adhoc_start_band = BAND_A; -+ } -+ } -+ } -+ if (!cfp || !cfp->channel) { -+ dev_err(adapter->dev, "invalid channel/freq\n"); -+ return -1; -+ } -+ priv->adhoc_channel = (u8) cfp->channel; -+ chan->channel = cfp->channel; -+ chan->freq = cfp->freq; -+ -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to set/get Ad-Hoc channel. -+ * -+ * This function prepares the correct firmware command and -+ * issues it to set or get the ad-hoc channel. -+ */ -+static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, -+ u16 action, u16 *channel) -+{ -+ if (action == HostCmd_ACT_GEN_GET) { -+ if (!priv->media_connected) { -+ *channel = priv->adhoc_channel; -+ return 0; -+ } -+ } else { -+ priv->adhoc_channel = (u8) *channel; -+ } -+ -+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, -+ action, 0, channel); -+} -+ -+/* -+ * IOCTL request handler to find a particular BSS. -+ * -+ * The BSS can be searched with either a BSSID or a SSID. If none of -+ * these are provided, just the best BSS (best RSSI) is returned. -+ */ -+int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, -+ struct mwifiex_ssid_bssid *ssid_bssid) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_bssdescriptor *bss_desc; -+ u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -+ u8 mac[ETH_ALEN]; -+ int i = 0; -+ -+ if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) { -+ i = mwifiex_find_bssid_in_list(priv, -+ (u8 *) ssid_bssid->bssid, -+ priv->bss_mode); -+ if (i < 0) { -+ memcpy(mac, ssid_bssid->bssid, sizeof(mac)); -+ dev_err(adapter->dev, "cannot find bssid %pM\n", mac); -+ return -1; -+ } -+ bss_desc = &adapter->scan_table[i]; -+ memcpy(&ssid_bssid->ssid, &bss_desc->ssid, -+ sizeof(struct mwifiex_802_11_ssid)); -+ } else if (ssid_bssid->ssid.ssid_len) { -+ i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL, -+ priv->bss_mode); -+ if (i < 0) { -+ dev_err(adapter->dev, "cannot find ssid %s\n", -+ ssid_bssid->ssid.ssid); -+ return -1; -+ } -+ bss_desc = &adapter->scan_table[i]; -+ memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN); -+ } else { -+ return mwifiex_find_best_network(priv, ssid_bssid); -+ } -+ -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to change Ad-Hoc channel. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ * -+ * The function follows the following steps to perform the change - -+ * - Get current IBSS information -+ * - Get current channel -+ * - If no change is required, return -+ * - If not connected, change channel and return -+ * - If connected, -+ * - Disconnect -+ * - Change channel -+ * - Perform specific SSID scan with same SSID -+ * - Start/Join the IBSS -+ */ -+int -+mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) -+{ -+ int ret = 0; -+ struct mwifiex_bss_info bss_info; -+ struct mwifiex_ssid_bssid ssid_bssid; -+ u16 curr_chan = 0; -+ -+ memset(&bss_info, 0, sizeof(bss_info)); -+ -+ /* Get BSS information */ -+ if (mwifiex_get_bss_info(priv, &bss_info)) -+ return -1; -+ -+ /* Get current channel */ -+ ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, -+ &curr_chan); -+ -+ if (curr_chan == channel) { -+ ret = 0; -+ goto done; -+ } -+ dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", -+ curr_chan, channel); -+ -+ if (!bss_info.media_connected) { -+ ret = 0; -+ goto done; -+ } -+ -+ /* Do disonnect */ -+ memset(&ssid_bssid, 0, ETH_ALEN); -+ ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); -+ -+ ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, -+ (u16 *) &channel); -+ -+ /* Do specific SSID scanning */ -+ if (mwifiex_request_scan(priv, &bss_info.ssid)) { -+ ret = -1; -+ goto done; -+ } -+ /* Start/Join Adhoc network */ -+ memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); -+ memcpy(&ssid_bssid.ssid, &bss_info.ssid, -+ sizeof(struct mwifiex_802_11_ssid)); -+ -+ ret = mwifiex_bss_start(priv, &ssid_bssid); -+done: -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to get rate. -+ * -+ * This function prepares the correct firmware command and -+ * issues it to get the current rate if it is connected, -+ * otherwise, the function returns the lowest supported rate -+ * for the band. -+ */ -+static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, -+ struct mwifiex_rate_cfg *rate_cfg) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ rate_cfg->is_rate_auto = priv->is_data_rate_auto; -+ if (!priv->media_connected) { -+ switch (adapter->config_bands) { -+ case BAND_B: -+ /* Return the lowest supported rate for B band */ -+ rate_cfg->rate = supported_rates_b[0] & 0x7f; -+ break; -+ case BAND_G: -+ case BAND_G | BAND_GN: -+ /* Return the lowest supported rate for G band */ -+ rate_cfg->rate = supported_rates_g[0] & 0x7f; -+ break; -+ case BAND_B | BAND_G: -+ case BAND_A | BAND_B | BAND_G: -+ case BAND_A | BAND_B: -+ case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: -+ case BAND_B | BAND_G | BAND_GN: -+ /* Return the lowest supported rate for BG band */ -+ rate_cfg->rate = supported_rates_bg[0] & 0x7f; -+ break; -+ case BAND_A: -+ case BAND_A | BAND_G: -+ case BAND_A | BAND_G | BAND_AN | BAND_GN: -+ case BAND_A | BAND_AN: -+ /* Return the lowest supported rate for A band */ -+ rate_cfg->rate = supported_rates_a[0] & 0x7f; -+ break; -+ case BAND_GN: -+ /* Return the lowest supported rate for N band */ -+ rate_cfg->rate = supported_rates_n[0] & 0x7f; -+ break; -+ default: -+ dev_warn(adapter->dev, "invalid band %#x\n", -+ adapter->config_bands); -+ break; -+ } -+ } else { -+ return mwifiex_send_cmd_sync(priv, -+ HostCmd_CMD_802_11_TX_RATE_QUERY, -+ HostCmd_ACT_GEN_GET, 0, NULL); -+ } -+ -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to set rate. -+ * -+ * This function prepares the correct firmware command and -+ * issues it to set the current rate. -+ * -+ * The function also performs validation checking on the supplied value. -+ */ -+static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, -+ struct mwifiex_rate_cfg *rate_cfg) -+{ -+ u8 rates[MWIFIEX_SUPPORTED_RATES]; -+ u8 *rate = NULL; -+ int rate_index = 0; -+ u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; -+ u32 i = 0; -+ int ret = 0; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ if (rate_cfg->is_rate_auto) { -+ memset(bitmap_rates, 0, sizeof(bitmap_rates)); -+ /* Support all HR/DSSS rates */ -+ bitmap_rates[0] = 0x000F; -+ /* Support all OFDM rates */ -+ bitmap_rates[1] = 0x00FF; -+ /* Support all HT-MCSs rate */ -+ for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates) - 3; i++) -+ bitmap_rates[i + 2] = 0xFFFF; -+ bitmap_rates[9] = 0x3FFF; -+ } else { -+ memset(rates, 0, sizeof(rates)); -+ mwifiex_get_active_data_rates(priv, rates); -+ rate = rates; -+ for (i = 0; (rate[i] && i < MWIFIEX_SUPPORTED_RATES); i++) { -+ dev_dbg(adapter->dev, "info: rate=%#x wanted=%#x\n", -+ rate[i], rate_cfg->rate); -+ if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f)) -+ break; -+ } -+ if (!rate[i] || (i == MWIFIEX_SUPPORTED_RATES)) { -+ dev_err(adapter->dev, "fixed data rate %#x is out " -+ "of range\n", rate_cfg->rate); -+ return -1; -+ } -+ memset(bitmap_rates, 0, sizeof(bitmap_rates)); -+ -+ 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 && -+ rate_index <= MWIFIEX_RATE_INDEX_HRDSSS3) { -+ bitmap_rates[0] = 1 << rate_index; -+ } else { -+ rate_index -= 1; /* There is a 0x00 in the table */ -+ if (rate_index >= MWIFIEX_RATE_INDEX_OFDM0 && -+ rate_index <= MWIFIEX_RATE_INDEX_OFDM7) -+ bitmap_rates[1] = 1 << (rate_index - -+ MWIFIEX_RATE_INDEX_OFDM0); -+ } -+ } -+ -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, -+ HostCmd_ACT_GEN_SET, 0, bitmap_rates); -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set/get rate. -+ * -+ * This function can be used to set/get either the rate value or the -+ * rate index. -+ */ -+static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, -+ struct mwifiex_rate_cfg *rate_cfg) -+{ -+ int status = 0; -+ -+ if (!rate_cfg) -+ return -1; -+ -+ if (rate_cfg->action == HostCmd_ACT_GEN_GET) -+ status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg); -+ else -+ status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg); -+ -+ return status; -+} -+ -+/* -+ * Sends IOCTL request to get the data rate. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, -+ struct mwifiex_rate_cfg *rate) -+{ -+ int ret = 0; -+ -+ memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); -+ rate->action = HostCmd_ACT_GEN_GET; -+ ret = mwifiex_rate_ioctl_cfg(priv, rate); -+ -+ if (!ret) { -+ if (rate && rate->is_rate_auto) -+ rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, -+ priv->tx_htinfo); -+ else if (rate) -+ rate->rate = priv->data_rate; -+ } else { -+ ret = -1; -+ } -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set tx power configuration. -+ * -+ * This function prepares the correct firmware command and -+ * issues it. -+ * -+ * For non-auto power mode, all the following power groups are set - -+ * - Modulation class HR/DSSS -+ * - Modulation class OFDM -+ * - Modulation class HTBW20 -+ * - Modulation class HTBW40 -+ */ -+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; -+ struct mwifiex_types_power_group *pg_tlv = NULL; -+ struct mwifiex_power_group *pg = NULL; -+ u8 *buf = NULL; -+ u16 dbm = 0; -+ -+ if (!power_cfg->is_power_auto) { -+ dbm = (u16) power_cfg->power_level; -+ if ((dbm < priv->min_tx_power_level) || -+ (dbm > priv->max_tx_power_level)) { -+ dev_err(priv->adapter->dev, "txpower value %d dBm" -+ " is out of range (%d dBm-%d dBm)\n", -+ dbm, priv->min_tx_power_level, -+ priv->max_tx_power_level); -+ return -1; -+ } -+ } -+ buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); -+ if (!buf) { -+ dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", -+ __func__); -+ return -1; -+ } -+ -+ txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; -+ txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); -+ if (!power_cfg->is_power_auto) { -+ txp_cfg->mode = cpu_to_le32(1); -+ pg_tlv = (struct mwifiex_types_power_group *) (buf + -+ sizeof(struct host_cmd_ds_txpwr_cfg)); -+ pg_tlv->type = TLV_TYPE_POWER_GROUP; -+ pg_tlv->length = 4 * sizeof(struct mwifiex_power_group); -+ pg = (struct mwifiex_power_group *) (buf + -+ sizeof(struct host_cmd_ds_txpwr_cfg) + -+ sizeof(struct mwifiex_types_power_group)); -+ /* Power group for modulation class HR/DSSS */ -+ pg->first_rate_code = 0x00; -+ pg->last_rate_code = 0x03; -+ pg->modulation_class = MOD_CLASS_HR_DSSS; -+ pg->power_step = 0; -+ pg->power_min = (s8) dbm; -+ pg->power_max = (s8) dbm; -+ pg++; -+ /* Power group for modulation class OFDM */ -+ pg->first_rate_code = 0x00; -+ pg->last_rate_code = 0x07; -+ pg->modulation_class = MOD_CLASS_OFDM; -+ pg->power_step = 0; -+ pg->power_min = (s8) dbm; -+ pg->power_max = (s8) dbm; -+ pg++; -+ /* Power group for modulation class HTBW20 */ -+ pg->first_rate_code = 0x00; -+ pg->last_rate_code = 0x20; -+ pg->modulation_class = MOD_CLASS_HT; -+ pg->power_step = 0; -+ pg->power_min = (s8) dbm; -+ pg->power_max = (s8) dbm; -+ pg->ht_bandwidth = HT_BW_20; -+ pg++; -+ /* Power group for modulation class HTBW40 */ -+ pg->first_rate_code = 0x00; -+ pg->last_rate_code = 0x20; -+ pg->modulation_class = MOD_CLASS_HT; -+ pg->power_step = 0; -+ pg->power_min = (s8) dbm; -+ pg->power_max = (s8) dbm; -+ pg->ht_bandwidth = HT_BW_40; -+ } -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, -+ HostCmd_ACT_GEN_SET, 0, buf); -+ -+ kfree(buf); -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to get power save mode. -+ * -+ * This function prepares the correct firmware command and -+ * issues it. -+ */ -+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 (*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; -+} -+ -+/* -+ * IOCTL request handler to set/reset WPA IE. -+ * -+ * The supplied WPA IE is treated as a opaque buffer. Only the first field -+ * is checked to determine WPA version. If buffer length is zero, the existing -+ * WPA IE is reset. -+ */ -+static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv, -+ u8 *ie_data_ptr, u16 ie_len) -+{ -+ if (ie_len) { -+ if (ie_len > sizeof(priv->wpa_ie)) { -+ dev_err(priv->adapter->dev, -+ "failed to copy WPA IE, too big\n"); -+ return -1; -+ } -+ memcpy(priv->wpa_ie, ie_data_ptr, ie_len); -+ priv->wpa_ie_len = (u8) ie_len; -+ dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n", -+ priv->wpa_ie_len, priv->wpa_ie[0]); -+ -+ if (priv->wpa_ie[0] == WLAN_EID_WPA) { -+ priv->sec_info.wpa_enabled = true; -+ } else if (priv->wpa_ie[0] == WLAN_EID_RSN) { -+ priv->sec_info.wpa2_enabled = true; -+ } else { -+ priv->sec_info.wpa_enabled = false; -+ priv->sec_info.wpa2_enabled = false; -+ } -+ } else { -+ memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie)); -+ priv->wpa_ie_len = 0; -+ dev_dbg(priv->adapter->dev, "info: reset wpa_ie_len=%d IE=%#x\n", -+ priv->wpa_ie_len, priv->wpa_ie[0]); -+ priv->sec_info.wpa_enabled = false; -+ priv->sec_info.wpa2_enabled = false; -+ } -+ -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to set/reset WAPI IE. -+ * -+ * The supplied WAPI IE is treated as a opaque buffer. Only the first field -+ * is checked to internally enable WAPI. If buffer length is zero, the existing -+ * WAPI IE is reset. -+ */ -+static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, -+ u8 *ie_data_ptr, u16 ie_len) -+{ -+ if (ie_len) { -+ if (ie_len > sizeof(priv->wapi_ie)) { -+ dev_dbg(priv->adapter->dev, -+ "info: failed to copy WAPI IE, too big\n"); -+ return -1; -+ } -+ memcpy(priv->wapi_ie, ie_data_ptr, ie_len); -+ priv->wapi_ie_len = ie_len; -+ dev_dbg(priv->adapter->dev, "cmd: Set wapi_ie_len=%d IE=%#x\n", -+ priv->wapi_ie_len, priv->wapi_ie[0]); -+ -+ if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY) -+ priv->sec_info.wapi_enabled = true; -+ } else { -+ memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie)); -+ priv->wapi_ie_len = ie_len; -+ dev_dbg(priv->adapter->dev, -+ "info: Reset wapi_ie_len=%d IE=%#x\n", -+ priv->wapi_ie_len, priv->wapi_ie[0]); -+ priv->sec_info.wapi_enabled = false; -+ } -+ return 0; -+} -+ -+/* -+ * IOCTL request handler to set WAPI key. -+ * -+ * This function prepares the correct firmware command and -+ * issues it. -+ */ -+static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, -+ struct mwifiex_ds_encrypt_key *encrypt_key) -+{ -+ -+ return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -+ HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, -+ encrypt_key); -+} -+ -+/* -+ * IOCTL request handler to set WEP network key. -+ * -+ * This function prepares the correct firmware command and -+ * issues it, after validation checks. -+ */ -+static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, -+ struct mwifiex_ds_encrypt_key *encrypt_key) -+{ -+ int ret = 0; -+ struct mwifiex_wep_key *wep_key = NULL; -+ int index; -+ -+ if (priv->wep_key_curr_index >= NUM_WEP_KEYS) -+ priv->wep_key_curr_index = 0; -+ wep_key = &priv->wep_key[priv->wep_key_curr_index]; -+ index = encrypt_key->key_index; -+ if (encrypt_key->key_disable) { -+ priv->sec_info.wep_status = MWIFIEX_802_11_WEP_DISABLED; -+ } else if (!encrypt_key->key_len) { -+ /* Copy the required key as the current key */ -+ wep_key = &priv->wep_key[index]; -+ if (!wep_key->key_length) { -+ dev_err(priv->adapter->dev, -+ "key not set, so cannot enable it\n"); -+ return -1; -+ } -+ priv->wep_key_curr_index = (u16) index; -+ priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; -+ } else { -+ wep_key = &priv->wep_key[index]; -+ memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); -+ /* Copy the key in the driver */ -+ memcpy(wep_key->key_material, -+ encrypt_key->key_material, -+ encrypt_key->key_len); -+ wep_key->key_index = index; -+ wep_key->key_length = encrypt_key->key_len; -+ priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED; -+ } -+ if (wep_key->key_length) { -+ /* Send request to firmware */ -+ ret = mwifiex_send_cmd_async(priv, -+ HostCmd_CMD_802_11_KEY_MATERIAL, -+ HostCmd_ACT_GEN_SET, 0, NULL); -+ if (ret) -+ return ret; -+ } -+ if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED) -+ priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; -+ else -+ priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; -+ -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, -+ HostCmd_ACT_GEN_SET, 0, -+ &priv->curr_pkt_filter); -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set WPA key. -+ * -+ * This function prepares the correct firmware command and -+ * issues it, after validation checks. -+ * -+ * Current driver only supports key length of up to 32 bytes. -+ * -+ * This function can also be used to disable a currently set key. -+ */ -+static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, -+ struct mwifiex_ds_encrypt_key *encrypt_key) -+{ -+ int ret = 0; -+ 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 > WLAN_MAX_KEY_LEN) { -+ dev_err(priv->adapter->dev, "key length too long\n"); -+ return -1; -+ } -+ -+ if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -+ /* -+ * IBSS/WPA-None uses only one key (Group) for both receiving -+ * and sending unicast and multicast packets. -+ */ -+ /* Send the key as PTK to firmware */ -+ encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; -+ 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; -+ -+ ibss_key = &priv->aes_key; -+ memset(ibss_key, 0, -+ sizeof(struct host_cmd_ds_802_11_key_material)); -+ /* Copy the key in the driver */ -+ memcpy(ibss_key->key_param_set.key, encrypt_key->key_material, -+ encrypt_key->key_len); -+ memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len, -+ 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_ENABLED); -+ -+ /* Send the key as GTK to firmware */ -+ encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; -+ } -+ -+ if (!encrypt_key->key_index) -+ encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; -+ -+ if (remove_key) -+ ret = mwifiex_send_cmd_sync(priv, -+ HostCmd_CMD_802_11_KEY_MATERIAL, -+ HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED), -+ encrypt_key); -+ else -+ ret = mwifiex_send_cmd_sync(priv, -+ HostCmd_CMD_802_11_KEY_MATERIAL, -+ HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, -+ encrypt_key); -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set/get network keys. -+ * -+ * This is a generic key handling function which supports WEP, WPA -+ * and WAPI. -+ */ -+static int -+mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, -+ struct mwifiex_ds_encrypt_key *encrypt_key) -+{ -+ int status = 0; -+ -+ if (encrypt_key->is_wapi_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(priv, encrypt_key); -+ else -+ status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key); -+ return status; -+} -+ -+/* -+ * This function returns the driver version. -+ */ -+int -+mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, -+ int max_len) -+{ -+ union { -+ u32 l; -+ u8 c[4]; -+ } ver; -+ char fw_ver[32]; -+ -+ ver.l = adapter->fw_release_number; -+ sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); -+ -+ snprintf(version, max_len, driver_version, fw_ver); -+ -+ dev_dbg(adapter->dev, "info: MWIFIEX VERSION: %s\n", version); -+ -+ return 0; -+} -+ -+/* -+ * 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, -+ struct mwifiex_ds_get_signal *signal) -+{ -+ struct mwifiex_ds_get_signal info; -+ int status = 0; -+ -+ memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); -+ info.selector = ALL_RSSI_INFO_MASK; -+ -+ /* 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); -+ -+ if (!status) { -+ if (signal) -+ memcpy(signal, &info, -+ sizeof(struct mwifiex_ds_get_signal)); -+ if (info.selector & BCN_RSSI_AVG_MASK) -+ priv->w_stats.qual.level = info.bcn_rssi_avg; -+ if (info.selector & BCN_NF_AVG_MASK) -+ priv->w_stats.qual.noise = info.bcn_nf_avg; -+ } -+ -+ return status; -+} -+ -+/* -+ * Sends IOCTL request to set encoding parameters. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, -+ int key_len, u8 key_index, int disable) -+{ -+ struct mwifiex_ds_encrypt_key encrypt_key; -+ -+ memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); -+ encrypt_key.key_len = key_len; -+ if (!disable) { -+ encrypt_key.key_index = key_index; -+ if (key_len) -+ memcpy(encrypt_key.key_material, key, key_len); -+ } else { -+ encrypt_key.key_disable = true; -+ } -+ -+ return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); -+} -+ -+/* -+ * Sends IOCTL request to get extended version. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_get_ver_ext(struct mwifiex_private *priv) -+{ -+ struct mwifiex_ver_ext ver_ext; -+ -+ memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); -+ if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, -+ HostCmd_ACT_GEN_GET, 0, &ver_ext)) -+ return -1; -+ -+ return 0; -+} -+ -+/* -+ * Sends IOCTL request to get statistics information. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_get_stats_info(struct mwifiex_private *priv, -+ struct mwifiex_ds_get_stats *log) -+{ -+ int ret = 0; -+ struct mwifiex_ds_get_stats get_log; -+ -+ memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, -+ HostCmd_ACT_GEN_GET, 0, &get_log); -+ -+ if (!ret) { -+ if (log) -+ memcpy(log, &get_log, sizeof(struct -+ mwifiex_ds_get_stats)); -+ priv->w_stats.discard.fragment = get_log.fcs_error; -+ priv->w_stats.discard.retries = get_log.retry; -+ priv->w_stats.discard.misc = get_log.ack_failure; -+ } -+ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to read/write register. -+ * -+ * This function prepares the correct firmware command and -+ * issues it. -+ * -+ * Access to the following registers are supported - -+ * - MAC -+ * - BBP -+ * - RF -+ * - PMIC -+ * - CAU -+ */ -+static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, -+ struct mwifiex_ds_reg_rw *reg_rw, -+ u16 action) -+{ -+ u16 cmd_no; -+ -+ switch (le32_to_cpu(reg_rw->type)) { -+ case MWIFIEX_REG_MAC: -+ cmd_no = HostCmd_CMD_MAC_REG_ACCESS; -+ break; -+ case MWIFIEX_REG_BBP: -+ cmd_no = HostCmd_CMD_BBP_REG_ACCESS; -+ break; -+ case MWIFIEX_REG_RF: -+ cmd_no = HostCmd_CMD_RF_REG_ACCESS; -+ break; -+ case MWIFIEX_REG_PMIC: -+ cmd_no = HostCmd_CMD_PMIC_REG_ACCESS; -+ break; -+ case MWIFIEX_REG_CAU: -+ cmd_no = HostCmd_CMD_CAU_REG_ACCESS; -+ break; -+ default: -+ return -1; -+ } -+ -+ return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); -+ -+} -+ -+/* -+ * Sends IOCTL request to write to a register. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, -+ u32 reg_offset, u32 reg_value) -+{ -+ struct mwifiex_ds_reg_rw reg_rw; -+ -+ reg_rw.type = cpu_to_le32(reg_type); -+ reg_rw.offset = cpu_to_le32(reg_offset); -+ reg_rw.value = cpu_to_le32(reg_value); -+ -+ return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); -+} -+ -+/* -+ * Sends IOCTL request to read from a register. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, -+ u32 reg_offset, u32 *value) -+{ -+ int ret = 0; -+ struct mwifiex_ds_reg_rw reg_rw; -+ -+ reg_rw.type = cpu_to_le32(reg_type); -+ reg_rw.offset = cpu_to_le32(reg_offset); -+ ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET); -+ -+ if (ret) -+ goto done; -+ -+ *value = le32_to_cpu(reg_rw.value); -+ -+done: -+ return ret; -+} -+ -+/* -+ * Sends IOCTL request to read from EEPROM. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, -+ u8 *value) -+{ -+ int ret = 0; -+ struct mwifiex_ds_read_eeprom rd_eeprom; -+ -+ rd_eeprom.offset = cpu_to_le16((u16) offset); -+ rd_eeprom.byte_count = cpu_to_le16((u16) bytes); -+ -+ /* Send request to firmware */ -+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, -+ HostCmd_ACT_GEN_GET, 0, &rd_eeprom); -+ -+ if (!ret) -+ memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); -+ return ret; -+} -+ -+/* -+ * This function sets a generic IE. In addition to generic IE, it can -+ * also handle WPA, WPA2 and WAPI IEs. -+ */ -+static int -+mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, -+ u16 ie_len) -+{ -+ int ret = 0; -+ struct ieee_types_vendor_header *pvendor_ie; -+ const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; -+ const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 }; -+ -+ /* If the passed length is zero, reset the buffer */ -+ if (!ie_len) { -+ priv->gen_ie_buf_len = 0; -+ priv->wps.session_enable = false; -+ -+ return 0; -+ } else if (!ie_data_ptr) { -+ return -1; -+ } -+ pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; -+ /* Test to see if it is a WPA IE, if not, then it is a gen IE */ -+ if (((pvendor_ie->element_id == WLAN_EID_WPA) -+ && (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) -+ || (pvendor_ie->element_id == WLAN_EID_RSN)) { -+ -+ /* IE is a WPA/WPA2 IE so call set_wpa function */ -+ ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len); -+ priv->wps.session_enable = false; -+ -+ return ret; -+ } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) { -+ /* IE is a WAPI IE so call set_wapi function */ -+ ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len); -+ -+ return ret; -+ } -+ /* -+ * Verify that the passed length is not larger than the -+ * available space remaining in the buffer -+ */ -+ if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { -+ -+ /* Test to see if it is a WPS IE, if so, enable -+ * wps session flag -+ */ -+ pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; -+ if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) -+ && (!memcmp(pvendor_ie->oui, wps_oui, -+ sizeof(wps_oui)))) { -+ priv->wps.session_enable = true; -+ dev_dbg(priv->adapter->dev, -+ "info: WPS Session Enabled.\n"); -+ } -+ -+ /* Append the passed data to the end of the -+ genIeBuffer */ -+ memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr, -+ ie_len); -+ /* Increment the stored buffer length by the -+ size passed */ -+ priv->gen_ie_buf_len += ie_len; -+ } else { -+ /* Passed data does not fit in the remaining -+ buffer space */ -+ ret = -1; -+ } -+ -+ /* Return 0, or -1 for error case */ -+ return ret; -+} -+ -+/* -+ * IOCTL request handler to set/get generic IE. -+ * -+ * In addition to various generic IEs, this function can also be -+ * used to set the ARP filter. -+ */ -+static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, -+ struct mwifiex_ds_misc_gen_ie *gen_ie, -+ u16 action) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ switch (gen_ie->type) { -+ case MWIFIEX_IE_TYPE_GEN_IE: -+ if (action == HostCmd_ACT_GEN_GET) { -+ gen_ie->len = priv->wpa_ie_len; -+ memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len); -+ } else { -+ mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data, -+ (u16) gen_ie->len); -+ } -+ break; -+ case MWIFIEX_IE_TYPE_ARP_FILTER: -+ memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter)); -+ if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) { -+ adapter->arp_filter_size = 0; -+ dev_err(adapter->dev, "invalid ARP filter size\n"); -+ return -1; -+ } else { -+ memcpy(adapter->arp_filter, gen_ie->ie_data, -+ gen_ie->len); -+ adapter->arp_filter_size = gen_ie->len; -+ } -+ break; -+ default: -+ dev_err(adapter->dev, "invalid IE type\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+/* -+ * Sends IOCTL request to set a generic IE. -+ * -+ * This function allocates the IOCTL request buffer, fills it -+ * with requisite parameters and calls the IOCTL handler. -+ */ -+int -+mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) -+{ -+ struct mwifiex_ds_misc_gen_ie gen_ie; -+ -+ if (ie_len > IW_CUSTOM_MAX) -+ return -EFAULT; -+ -+ gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; -+ gen_ie.len = ie_len; -+ memcpy(gen_ie.ie_data, ie, ie_len); -+ if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET)) -+ return -EFAULT; -+ -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_rx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_rx.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_rx.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_rx.c 2011-05-05 23:29:45.492441949 +0200 -@@ -0,0 +1,182 @@ -+/* -+ * Marvell Wireless LAN device driver: station RX data handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "11n_aggr.h" -+#include "11n_rxreorder.h" -+ -+/* -+ * This function processes the received packet and forwards it -+ * to kernel/upper layer. -+ * -+ * This function parses through the received packet and determines -+ * if it is a debug packet or normal packet. -+ * -+ * For non-debug packets, the function chops off unnecessary leading -+ * header bytes, reconstructs the packet as an ethernet frame or -+ * 802.2/llc/snap frame as required, and sends it to kernel/upper layer. -+ * -+ * The completion callback is called after processing in complete. -+ */ -+int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb) -+{ -+ int ret = 0; -+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); -+ struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; -+ struct rx_packet_hdr *rx_pkt_hdr; -+ struct rxpd *local_rx_pd; -+ int hdr_chop; -+ struct ethhdr *eth_hdr; -+ u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -+ -+ local_rx_pd = (struct rxpd *) (skb->data); -+ -+ rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + -+ local_rx_pd->rx_pkt_offset); -+ -+ if (!memcmp(&rx_pkt_hdr->rfc1042_hdr, -+ rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) { -+ /* -+ * Replace the 803 header and rfc1042 header (llc/snap) with an -+ * EthernetII header, keep the src/dst and snap_type -+ * (ethertype). -+ * The firmware only passes up SNAP frames converting -+ * all RX Data from 802.11 to 802.2/LLC/SNAP frames. -+ * To create the Ethernet II, just move the src, dst address -+ * right before the snap_type. -+ */ -+ eth_hdr = (struct ethhdr *) -+ ((u8 *) &rx_pkt_hdr->eth803_hdr -+ + sizeof(rx_pkt_hdr->eth803_hdr) + -+ sizeof(rx_pkt_hdr->rfc1042_hdr) -+ - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) -+ - sizeof(rx_pkt_hdr->eth803_hdr.h_source) -+ - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); -+ -+ memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, -+ sizeof(eth_hdr->h_source)); -+ memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, -+ sizeof(eth_hdr->h_dest)); -+ -+ /* Chop off the rxpd + the excess memory from the 802.2/llc/snap -+ header that was removed. */ -+ hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd; -+ } else { -+ /* Chop off the rxpd */ -+ hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr - -+ (u8 *) local_rx_pd; -+ } -+ -+ /* Chop off the leading header bytes so the it points to the start of -+ either the reconstructed EthII frame or the 802.2/llc/snap frame */ -+ skb_pull(skb, hdr_chop); -+ -+ priv->rxpd_rate = local_rx_pd->rx_rate; -+ -+ priv->rxpd_htinfo = local_rx_pd->ht_info; -+ -+ ret = mwifiex_recv_packet(adapter, skb); -+ if (ret == -1) -+ dev_err(adapter->dev, "recv packet failed\n"); -+ -+ return ret; -+} -+ -+/* -+ * This function processes the received buffer. -+ * -+ * The function looks into the RxPD and performs sanity tests on the -+ * received buffer to ensure its a valid packet, before processing it -+ * further. If the packet is determined to be aggregated, it is -+ * de-aggregated accordingly. Non-unicast packets are sent directly to -+ * the kernel/upper layers. Unicast packets are handed over to the -+ * Rx reordering routine if 11n is enabled. -+ * -+ * The completion callback is called after processing in complete. -+ */ -+int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb) -+{ -+ int ret = 0; -+ struct rxpd *local_rx_pd; -+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); -+ struct rx_packet_hdr *rx_pkt_hdr; -+ u8 ta[ETH_ALEN]; -+ u16 rx_pkt_type = 0; -+ struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; -+ -+ local_rx_pd = (struct rxpd *) (skb->data); -+ rx_pkt_type = local_rx_pd->rx_pkt_type; -+ -+ rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd + -+ local_rx_pd->rx_pkt_offset); -+ -+ if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) > -+ (u16) skb->len) { -+ dev_err(adapter->dev, "wrong rx packet: len=%d," -+ " rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, -+ local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length); -+ priv->stats.rx_dropped++; -+ dev_kfree_skb_any(skb); -+ return ret; -+ } -+ if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { -+ mwifiex_11n_deaggregate_pkt(priv, skb); -+ return ret; -+ } -+ /* -+ * If the packet is not an unicast packet then send the packet -+ * directly to os. Don't pass thru rx reordering -+ */ -+ if (!IS_11N_ENABLED(priv) || -+ memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { -+ mwifiex_process_rx_packet(adapter, skb); -+ return ret; -+ } -+ -+ if (mwifiex_queuing_ra_based(priv)) { -+ memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); -+ } else { -+ if (rx_pkt_type != PKT_TYPE_BAR) -+ priv->rx_seq[local_rx_pd->priority] = -+ local_rx_pd->seq_num; -+ memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, -+ ETH_ALEN); -+ } -+ -+ /* Reorder and send to OS */ -+ ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num, -+ local_rx_pd->priority, ta, -+ (u8) local_rx_pd->rx_pkt_type, -+ (void *) skb); -+ -+ if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { -+ if (priv && (ret == -1)) -+ priv->stats.rx_dropped++; -+ -+ dev_kfree_skb_any(skb); -+ } -+ -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/sta_tx.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/sta_tx.c 2011-05-05 23:29:45.471441695 +0200 -@@ -0,0 +1,198 @@ -+/* -+ * Marvell Wireless LAN device driver: station TX data handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+ -+/* -+ * This function fills the TxPD for tx packets. -+ * -+ * The Tx buffer received by this function should already have the -+ * header space allocated for TxPD. -+ * -+ * This function inserts the TxPD in between interface header and actual -+ * data and adjusts the buffer pointers accordingly. -+ * -+ * The following TxPD fields are set by this function, as required - -+ * - BSS number -+ * - Tx packet length and offset -+ * - Priority -+ * - Packet delay -+ * - Priority specific Tx control -+ * - Flags -+ */ -+void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, -+ struct sk_buff *skb) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct txpd *local_tx_pd; -+ struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); -+ -+ if (!skb->len) { -+ dev_err(adapter->dev, "Tx: bad packet length: %d\n", -+ skb->len); -+ tx_info->status_code = -1; -+ return skb->data; -+ } -+ -+ BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN)); -+ skb_push(skb, sizeof(*local_tx_pd)); -+ -+ local_tx_pd = (struct txpd *) skb->data; -+ memset(local_tx_pd, 0, sizeof(struct txpd)); -+ local_tx_pd->bss_num = priv->bss_num; -+ local_tx_pd->bss_type = priv->bss_type; -+ local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len - -+ sizeof(struct txpd))); -+ -+ local_tx_pd->priority = (u8) skb->priority; -+ local_tx_pd->pkt_delay_2ms = -+ mwifiex_wmm_compute_drv_pkt_delay(priv, skb); -+ -+ if (local_tx_pd->priority < -+ ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) -+ /* -+ * Set the priority specific tx_control field, setting of 0 will -+ * cause the default value to be used later in this function -+ */ -+ local_tx_pd->tx_control = -+ cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd-> -+ priority]); -+ -+ if (adapter->pps_uapsd_mode) { -+ if (mwifiex_check_last_packet_indication(priv)) { -+ adapter->tx_lock_flag = true; -+ local_tx_pd->flags = -+ MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; -+ } -+ } -+ -+ /* Offset of actual data */ -+ local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); -+ -+ /* make space for INTF_HEADER_LEN */ -+ skb_push(skb, INTF_HEADER_LEN); -+ -+ if (!local_tx_pd->tx_control) -+ /* TxCtrl set by user or default */ -+ local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); -+ -+ return skb->data; -+} -+ -+/* -+ * This function tells firmware to send a NULL data packet. -+ * -+ * The function creates a NULL data packet with TxPD and sends to the -+ * firmware for transmission, with highest priority setting. -+ */ -+int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct txpd *local_tx_pd; -+/* sizeof(struct txpd) + Interface specific header */ -+#define NULL_PACKET_HDR 64 -+ u32 data_len = NULL_PACKET_HDR; -+ struct sk_buff *skb = NULL; -+ int ret = 0; -+ struct mwifiex_txinfo *tx_info = NULL; -+ -+ if (adapter->surprise_removed) -+ return -1; -+ -+ if (!priv->media_connected) -+ return -1; -+ -+ if (adapter->data_sent) -+ return -1; -+ -+ skb = dev_alloc_skb(data_len); -+ if (!skb) -+ return -1; -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ tx_info->bss_index = priv->bss_index; -+ skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN); -+ skb_push(skb, sizeof(struct txpd)); -+ -+ local_tx_pd = (struct txpd *) skb->data; -+ local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); -+ local_tx_pd->flags = flags; -+ local_tx_pd->priority = WMM_HIGHEST_PRIORITY; -+ local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); -+ local_tx_pd->bss_num = priv->bss_num; -+ local_tx_pd->bss_type = priv->bss_type; -+ -+ skb_push(skb, INTF_HEADER_LEN); -+ -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, -+ skb->data, skb->len, NULL); -+ switch (ret) { -+ case -EBUSY: -+ adapter->data_sent = true; -+ /* Fall through FAILURE handling */ -+ case -1: -+ dev_kfree_skb_any(skb); -+ dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", -+ __func__, ret); -+ adapter->dbg.num_tx_host_to_card_failure++; -+ break; -+ case 0: -+ dev_kfree_skb_any(skb); -+ dev_dbg(adapter->dev, "data: %s: host_to_card succeeded\n", -+ __func__); -+ adapter->tx_lock_flag = true; -+ break; -+ case -EINPROGRESS: -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+/* -+ * This function checks if we need to send last packet indication. -+ */ -+u8 -+mwifiex_check_last_packet_indication(struct mwifiex_private *priv) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u8 ret = false; -+ -+ if (!adapter->sleep_period.period) -+ return ret; -+ if (mwifiex_wmm_lists_empty(adapter)) -+ ret = true; -+ -+ if (ret && !adapter->cmd_sent && !adapter->curr_cmd -+ && !is_command_pending(adapter)) { -+ adapter->delay_null_pkt = false; -+ ret = true; -+ } else { -+ ret = false; -+ adapter->delay_null_pkt = true; -+ } -+ return ret; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/txrx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/txrx.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/txrx.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/txrx.c 2011-05-05 23:29:45.439441309 +0200 -@@ -0,0 +1,200 @@ -+/* -+ * Marvell Wireless LAN device driver: generic TX/RX data handling -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+ -+/* -+ * This function processes the received buffer. -+ * -+ * Main responsibility of this function is to parse the RxPD to -+ * identify the correct interface this packet is headed for and -+ * forwarding it to the associated handling function, where the -+ * packet will be further processed and sent to kernel/upper layer -+ * if required. -+ */ -+int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb) -+{ -+ struct mwifiex_private *priv = -+ mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ struct rxpd *local_rx_pd; -+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); -+ -+ local_rx_pd = (struct rxpd *) (skb->data); -+ /* Get the BSS number from rxpd, get corresponding priv */ -+ priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num & -+ BSS_NUM_MASK, local_rx_pd->bss_type); -+ if (!priv) -+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); -+ -+ rx_info->bss_index = priv->bss_index; -+ -+ return mwifiex_process_sta_rx_packet(adapter, skb); -+} -+EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); -+ -+/* -+ * This function sends a packet to device. -+ * -+ * It processes the packet to add the TxPD, checks condition and -+ * sends the processed packet to firmware for transmission. -+ * -+ * On successful completion, the function calls the completion callback -+ * and logs the time. -+ */ -+int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, -+ struct mwifiex_tx_param *tx_param) -+{ -+ int ret = -1; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ u8 *head_ptr = NULL; -+ struct txpd *local_tx_pd = NULL; -+ -+ head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); -+ if (head_ptr) { -+ if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) -+ local_tx_pd = -+ (struct txpd *) (head_ptr + INTF_HEADER_LEN); -+ -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, -+ skb->data, skb->len, tx_param); -+ } -+ -+ switch (ret) { -+ case -EBUSY: -+ if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && -+ (adapter->pps_uapsd_mode) && -+ (adapter->tx_lock_flag)) { -+ priv->adapter->tx_lock_flag = false; -+ local_tx_pd->flags = 0; -+ } -+ dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); -+ break; -+ case -1: -+ adapter->data_sent = false; -+ dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", -+ ret); -+ adapter->dbg.num_tx_host_to_card_failure++; -+ mwifiex_write_data_complete(adapter, skb, ret); -+ break; -+ case -EINPROGRESS: -+ adapter->data_sent = false; -+ break; -+ case 0: -+ mwifiex_write_data_complete(adapter, skb, ret); -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+/* -+ * Packet send completion callback handler. -+ * -+ * It either frees the buffer directly or forwards it to another -+ * completion callback which checks conditions, updates statistics, -+ * wakes up stalled traffic queue if required, and then frees the buffer. -+ */ -+int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, int status) -+{ -+ struct mwifiex_private *priv = NULL, *tpriv = NULL; -+ struct mwifiex_txinfo *tx_info = NULL; -+ int i; -+ -+ if (!skb) -+ return 0; -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ priv = mwifiex_bss_index_to_priv(adapter, tx_info->bss_index); -+ if (!priv) -+ goto done; -+ -+ priv->netdev->trans_start = jiffies; -+ if (!status) { -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ } else { -+ priv->stats.tx_errors++; -+ } -+ atomic_dec(&adapter->tx_pending); -+ -+ for (i = 0; i < adapter->priv_num; i++) { -+ -+ tpriv = adapter->priv[i]; -+ -+ if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA) -+ && (tpriv->media_connected)) { -+ if (netif_queue_stopped(tpriv->netdev)) -+ netif_wake_queue(tpriv->netdev); -+ } -+ } -+done: -+ dev_kfree_skb_any(skb); -+ -+ return 0; -+} -+ -+/* -+ * Packet receive completion callback handler. -+ * -+ * This function calls another completion callback handler which -+ * updates the statistics, and optionally updates the parent buffer -+ * use count before freeing the received packet. -+ */ -+int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, int status) -+{ -+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); -+ struct mwifiex_rxinfo *rx_info_parent = NULL; -+ struct mwifiex_private *priv; -+ struct sk_buff *skb_parent = NULL; -+ unsigned long flags; -+ -+ priv = adapter->priv[rx_info->bss_index]; -+ -+ if (priv && (status == -1)) -+ priv->stats.rx_dropped++; -+ -+ if (rx_info->parent) { -+ skb_parent = rx_info->parent; -+ rx_info_parent = MWIFIEX_SKB_RXCB(skb_parent); -+ -+ spin_lock_irqsave(&priv->rx_pkt_lock, flags); -+ --rx_info_parent->use_count; -+ -+ if (!rx_info_parent->use_count) { -+ spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -+ dev_kfree_skb_any(skb_parent); -+ } else { -+ spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -+ } -+ } else { -+ dev_kfree_skb_any(skb); -+ } -+ -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/util.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/util.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/util.c 2011-05-05 23:29:45.453441477 +0200 -@@ -0,0 +1,227 @@ -+/* -+ * Marvell Wireless LAN device driver: utility functions -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+/* -+ * Firmware initialization complete callback handler. -+ * -+ * This function wakes up the function waiting on the init -+ * wait queue for the firmware initialization to complete. -+ */ -+int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter) -+{ -+ -+ adapter->init_wait_q_woken = true; -+ wake_up_interruptible(&adapter->init_wait_q); -+ return 0; -+} -+ -+/* -+ * Firmware shutdown complete callback handler. -+ * -+ * This function sets the hardware status to not ready and wakes up -+ * the function waiting on the init wait queue for the firmware -+ * shutdown to complete. -+ */ -+int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) -+{ -+ adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; -+ adapter->init_wait_q_woken = true; -+ wake_up_interruptible(&adapter->init_wait_q); -+ return 0; -+} -+ -+/* -+ * This function sends init/shutdown command -+ * to firmware. -+ */ -+int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, -+ u32 func_init_shutdown) -+{ -+ u16 cmd; -+ -+ if (func_init_shutdown == MWIFIEX_FUNC_INIT) { -+ cmd = HostCmd_CMD_FUNC_INIT; -+ } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) { -+ cmd = HostCmd_CMD_FUNC_SHUTDOWN; -+ } else { -+ dev_err(priv->adapter->dev, "unsupported parameter\n"); -+ return -1; -+ } -+ -+ 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. -+ * -+ * This function collates/sets the information from/to different driver -+ * structures. -+ */ -+int mwifiex_get_debug_info(struct mwifiex_private *priv, -+ struct mwifiex_debug_info *info) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ if (info) { -+ memcpy(info->packets_out, -+ priv->wmm.packets_out, -+ sizeof(priv->wmm.packets_out)); -+ info->max_tx_buf_size = (u32) adapter->max_tx_buf_size; -+ info->tx_buf_size = (u32) adapter->tx_buf_size; -+ info->rx_tbl_num = mwifiex_get_rx_reorder_tbl( -+ priv, info->rx_tbl); -+ info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl( -+ priv, info->tx_tbl); -+ info->ps_mode = adapter->ps_mode; -+ info->ps_state = adapter->ps_state; -+ info->is_deep_sleep = adapter->is_deep_sleep; -+ info->pm_wakeup_card_req = adapter->pm_wakeup_card_req; -+ info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; -+ info->is_hs_configured = adapter->is_hs_configured; -+ info->hs_activated = adapter->hs_activated; -+ info->num_cmd_host_to_card_failure -+ = adapter->dbg.num_cmd_host_to_card_failure; -+ info->num_cmd_sleep_cfm_host_to_card_failure -+ = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure; -+ info->num_tx_host_to_card_failure -+ = adapter->dbg.num_tx_host_to_card_failure; -+ info->num_event_deauth = adapter->dbg.num_event_deauth; -+ info->num_event_disassoc = adapter->dbg.num_event_disassoc; -+ info->num_event_link_lost = adapter->dbg.num_event_link_lost; -+ info->num_cmd_deauth = adapter->dbg.num_cmd_deauth; -+ info->num_cmd_assoc_success = -+ adapter->dbg.num_cmd_assoc_success; -+ info->num_cmd_assoc_failure = -+ adapter->dbg.num_cmd_assoc_failure; -+ info->num_tx_timeout = adapter->dbg.num_tx_timeout; -+ info->num_cmd_timeout = adapter->dbg.num_cmd_timeout; -+ info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; -+ info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; -+ memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, -+ sizeof(adapter->dbg.last_cmd_id)); -+ memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act, -+ sizeof(adapter->dbg.last_cmd_act)); -+ info->last_cmd_index = adapter->dbg.last_cmd_index; -+ memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id, -+ sizeof(adapter->dbg.last_cmd_resp_id)); -+ info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index; -+ memcpy(info->last_event, adapter->dbg.last_event, -+ sizeof(adapter->dbg.last_event)); -+ info->last_event_index = adapter->dbg.last_event_index; -+ info->data_sent = adapter->data_sent; -+ info->cmd_sent = adapter->cmd_sent; -+ info->cmd_resp_received = adapter->cmd_resp_received; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function processes the received packet before sending it to the -+ * kernel. -+ * -+ * It extracts the SKB from the received buffer and sends it to kernel. -+ * In case the received buffer does not contain the data in SKB format, -+ * the function creates a blank SKB, fills it with the data from the -+ * received buffer and then sends this new SKB to the kernel. -+ */ -+int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) -+{ -+ struct mwifiex_rxinfo *rx_info = NULL; -+ struct mwifiex_private *priv = NULL; -+ -+ if (!skb) -+ return -1; -+ -+ rx_info = MWIFIEX_SKB_RXCB(skb); -+ priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); -+ if (!priv) -+ return -1; -+ -+ skb->dev = priv->netdev; -+ skb->protocol = eth_type_trans(skb, priv->netdev); -+ skb->ip_summed = CHECKSUM_NONE; -+ priv->stats.rx_bytes += skb->len; -+ priv->stats.rx_packets++; -+ if (in_interrupt()) -+ netif_rx(skb); -+ else -+ netif_rx_ni(skb); -+ -+ return 0; -+} -+ -+/* -+ * Receive packet completion callback handler. -+ * -+ * This function updates the statistics and frees the buffer SKB. -+ */ -+int mwifiex_recv_complete(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb, int status) -+{ -+ struct mwifiex_private *priv = NULL; -+ struct mwifiex_rxinfo *rx_info = NULL; -+ -+ if (!skb) -+ return 0; -+ -+ rx_info = MWIFIEX_SKB_RXCB(skb); -+ priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); -+ -+ if (priv && (status == -1)) -+ priv->stats.rx_dropped++; -+ -+ dev_kfree_skb_any(skb); -+ -+ return 0; -+} -+ -+/* -+ * IOCTL completion callback handler. -+ * -+ * This function is called when a pending IOCTL is completed. -+ * -+ * If work queue support is enabled, the function wakes up the -+ * corresponding waiting function. Otherwise, it processes the -+ * IOCTL response and frees the response buffer. -+ */ -+int mwifiex_complete_cmd(struct mwifiex_adapter *adapter) -+{ -+ atomic_dec(&adapter->cmd_pending); -+ dev_dbg(adapter->dev, "cmd completed: status=%d\n", -+ adapter->cmd_wait_q.status); -+ -+ adapter->cmd_wait_q.condition = true; -+ -+ 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; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/util.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/util.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/util.h 2011-05-05 23:29:45.489441913 +0200 -@@ -0,0 +1,32 @@ -+/* -+ * Marvell Wireless LAN device driver: utility functions -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_UTIL_H_ -+#define _MWIFIEX_UTIL_H_ -+ -+static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) -+{ -+ return (struct mwifiex_rxinfo *)skb->cb; -+} -+ -+static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) -+{ -+ return (struct mwifiex_txinfo *)skb->cb; -+} -+#endif /* !_MWIFIEX_UTIL_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/wmm.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/wmm.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/wmm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/wmm.c 2011-05-05 23:29:45.472441707 +0200 -@@ -0,0 +1,1231 @@ -+/* -+ * Marvell Wireless LAN device driver: WMM -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#include "decl.h" -+#include "ioctl.h" -+#include "util.h" -+#include "fw.h" -+#include "main.h" -+#include "wmm.h" -+#include "11n.h" -+ -+ -+/* Maximum value FW can accept for driver delay in packet transmission */ -+#define DRV_PKT_DELAY_TO_FW_MAX 512 -+ -+ -+#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 -+ -+#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 -+ -+/* Offset for TOS field in the IP header */ -+#define IPTOS_OFFSET 5 -+ -+/* WMM information IE */ -+static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, -+ 0x00, 0x50, 0xf2, 0x02, -+ 0x00, 0x01, 0x00 -+}; -+ -+static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, -+ WMM_AC_BK, -+ WMM_AC_VI, -+ WMM_AC_VO -+}; -+ -+static u8 tos_to_tid[] = { -+ /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ -+ 0x01, /* 0 1 0 AC_BK */ -+ 0x02, /* 0 0 0 AC_BK */ -+ 0x00, /* 0 0 1 AC_BE */ -+ 0x03, /* 0 1 1 AC_BE */ -+ 0x04, /* 1 0 0 AC_VI */ -+ 0x05, /* 1 0 1 AC_VI */ -+ 0x06, /* 1 1 0 AC_VO */ -+ 0x07 /* 1 1 1 AC_VO */ -+}; -+ -+/* -+ * This table inverses the tos_to_tid operation to get a priority -+ * which is in sequential order, and can be compared. -+ * Use this to compare the priority of two different TIDs. -+ */ -+static u8 tos_to_tid_inv[] = { -+ 0x02, /* from tos_to_tid[2] = 0 */ -+ 0x00, /* from tos_to_tid[0] = 1 */ -+ 0x01, /* from tos_to_tid[1] = 2 */ -+ 0x03, -+ 0x04, -+ 0x05, -+ 0x06, -+ 0x07}; -+ -+static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; -+ -+/* -+ * This function debug prints the priority parameters for a WMM AC. -+ */ -+static void -+mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) -+{ -+ const char *ac_str[] = { "BK", "BE", "VI", "VO" }; -+ -+ pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " -+ "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", -+ ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap -+ & MWIFIEX_ACI) >> 5]], -+ (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5, -+ (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4, -+ ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN, -+ ac_param->ecw_bitmap & MWIFIEX_ECW_MIN, -+ (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4, -+ le16_to_cpu(ac_param->tx_op_limit)); -+} -+ -+/* -+ * This function allocates a route address list. -+ * -+ * The function also initializes the list with the provided RA. -+ */ -+static struct mwifiex_ra_list_tbl * -+mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) -+{ -+ struct mwifiex_ra_list_tbl *ra_list; -+ -+ ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC); -+ -+ if (!ra_list) { -+ dev_err(adapter->dev, "%s: failed to alloc ra_list\n", -+ __func__); -+ return NULL; -+ } -+ INIT_LIST_HEAD(&ra_list->list); -+ skb_queue_head_init(&ra_list->skb_head); -+ -+ memcpy(ra_list->ra, ra, ETH_ALEN); -+ -+ ra_list->total_pkts_size = 0; -+ -+ dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); -+ -+ return ra_list; -+} -+ -+/* -+ * This function allocates and adds a RA list for all TIDs -+ * with the given RA. -+ */ -+void -+mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) -+{ -+ int i; -+ struct mwifiex_ra_list_tbl *ra_list; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ -+ for (i = 0; i < MAX_NUM_TID; ++i) { -+ ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); -+ dev_dbg(adapter->dev, "info: created ra_list %p\n", ra_list); -+ -+ if (!ra_list) -+ break; -+ -+ if (!mwifiex_queuing_ra_based(priv)) -+ ra_list->is_11n_enabled = IS_11N_ENABLED(priv); -+ else -+ ra_list->is_11n_enabled = false; -+ -+ dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n", -+ ra_list, ra_list->is_11n_enabled); -+ -+ list_add_tail(&ra_list->list, -+ &priv->wmm.tid_tbl_ptr[i].ra_list); -+ -+ if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr) -+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list; -+ } -+} -+ -+/* -+ * This function sets the WMM queue priorities to their default values. -+ */ -+static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) -+{ -+ /* Default queue priorities: VO->VI->BE->BK */ -+ priv->wmm.queue_priority[0] = WMM_AC_VO; -+ priv->wmm.queue_priority[1] = WMM_AC_VI; -+ priv->wmm.queue_priority[2] = WMM_AC_BE; -+ priv->wmm.queue_priority[3] = WMM_AC_BK; -+} -+ -+/* -+ * This function map ACs to TIDs. -+ */ -+static void -+mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) -+{ -+ int i; -+ -+ for (i = 0; i < 4; ++i) { -+ tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; -+ tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; -+ } -+} -+ -+/* -+ * This function initializes WMM priority queues. -+ */ -+void -+mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, -+ struct ieee_types_wmm_parameter *wmm_ie) -+{ -+ u16 cw_min, avg_back_off, tmp[4]; -+ u32 i, j, num_ac; -+ u8 ac_idx; -+ -+ if (!wmm_ie || !priv->wmm_enabled) { -+ /* WMM is not enabled, just set the defaults and return */ -+ mwifiex_wmm_default_queue_priorities(priv); -+ return; -+ } -+ -+ dev_dbg(priv->adapter->dev, "info: WMM Parameter IE: version=%d, " -+ "qos_info Parameter Set Count=%d, Reserved=%#x\n", -+ wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & -+ IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, -+ wmm_ie->reserved); -+ -+ for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { -+ cw_min = (1 << (wmm_ie->ac_params[num_ac].ecw_bitmap & -+ MWIFIEX_ECW_MIN)) - 1; -+ avg_back_off = (cw_min >> 1) + -+ (wmm_ie->ac_params[num_ac].aci_aifsn_bitmap & -+ MWIFIEX_AIFSN); -+ -+ ac_idx = wmm_aci_to_qidx_map[(wmm_ie->ac_params[num_ac]. -+ aci_aifsn_bitmap & -+ MWIFIEX_ACI) >> 5]; -+ priv->wmm.queue_priority[ac_idx] = ac_idx; -+ tmp[ac_idx] = avg_back_off; -+ -+ dev_dbg(priv->adapter->dev, "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", -+ (1 << ((wmm_ie->ac_params[num_ac].ecw_bitmap & -+ MWIFIEX_ECW_MAX) >> 4)) - 1, -+ cw_min, avg_back_off); -+ mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); -+ } -+ -+ /* Bubble sort */ -+ for (i = 0; i < num_ac; i++) { -+ for (j = 1; j < num_ac - i; j++) { -+ if (tmp[j - 1] > tmp[j]) { -+ swap(tmp[j - 1], tmp[j]); -+ swap(priv->wmm.queue_priority[j - 1], -+ priv->wmm.queue_priority[j]); -+ } else if (tmp[j - 1] == tmp[j]) { -+ if (priv->wmm.queue_priority[j - 1] -+ < priv->wmm.queue_priority[j]) -+ swap(priv->wmm.queue_priority[j - 1], -+ priv->wmm.queue_priority[j]); -+ } -+ } -+ } -+ -+ mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); -+} -+ -+/* -+ * This function evaluates whether or not an AC is to be downgraded. -+ * -+ * In case the AC is not enabled, the highest AC is returned that is -+ * enabled and does not require admission control. -+ */ -+static enum mwifiex_wmm_ac_e -+mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, -+ enum mwifiex_wmm_ac_e eval_ac) -+{ -+ int down_ac; -+ enum mwifiex_wmm_ac_e ret_ac; -+ struct mwifiex_wmm_ac_status *ac_status; -+ -+ ac_status = &priv->wmm.ac_status[eval_ac]; -+ -+ if (!ac_status->disabled) -+ /* Okay to use this AC, its enabled */ -+ return eval_ac; -+ -+ /* Setup a default return value of the lowest priority */ -+ ret_ac = WMM_AC_BK; -+ -+ /* -+ * Find the highest AC that is enabled and does not require -+ * admission control. The spec disallows downgrading to an AC, -+ * which is enabled due to a completed admission control. -+ * Unadmitted traffic is not to be sent on an AC with admitted -+ * traffic. -+ */ -+ for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { -+ ac_status = &priv->wmm.ac_status[down_ac]; -+ -+ if (!ac_status->disabled && !ac_status->flow_required) -+ /* AC is enabled and does not require admission -+ control */ -+ ret_ac = (enum mwifiex_wmm_ac_e) down_ac; -+ } -+ -+ return ret_ac; -+} -+ -+/* -+ * This function downgrades WMM priority queue. -+ */ -+void -+mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) -+{ -+ int ac_val; -+ -+ dev_dbg(priv->adapter->dev, "info: WMM: AC Priorities:" -+ "BK(0), BE(1), VI(2), VO(3)\n"); -+ -+ if (!priv->wmm_enabled) { -+ /* WMM is not enabled, default priorities */ -+ for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) -+ priv->wmm.ac_down_graded_vals[ac_val] = -+ (enum mwifiex_wmm_ac_e) ac_val; -+ } else { -+ for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { -+ priv->wmm.ac_down_graded_vals[ac_val] -+ = mwifiex_wmm_eval_downgrade_ac(priv, -+ (enum mwifiex_wmm_ac_e) ac_val); -+ dev_dbg(priv->adapter->dev, "info: WMM: AC PRIO %d maps to %d\n", -+ ac_val, priv->wmm.ac_down_graded_vals[ac_val]); -+ } -+ } -+} -+ -+/* -+ * This function converts the IP TOS field to an WMM AC -+ * Queue assignment. -+ */ -+static enum mwifiex_wmm_ac_e -+mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) -+{ -+ /* Map of TOS UP values to WMM AC */ -+ const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, -+ WMM_AC_BK, -+ WMM_AC_BK, -+ WMM_AC_BE, -+ WMM_AC_VI, -+ WMM_AC_VI, -+ WMM_AC_VO, -+ WMM_AC_VO -+ }; -+ -+ if (tos >= ARRAY_SIZE(tos_to_ac)) -+ return WMM_AC_BE; -+ -+ return tos_to_ac[tos]; -+} -+ -+/* -+ * This function evaluates a given TID and downgrades it to a lower -+ * TID if the WMM Parameter IE received from the AP indicates that the -+ * AP is disabled (due to call admission control (ACM bit). Mapping -+ * of TID to AC is taken care of internally. -+ */ -+static u8 -+mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) -+{ -+ enum mwifiex_wmm_ac_e ac, ac_down; -+ u8 new_tid; -+ -+ ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); -+ ac_down = priv->wmm.ac_down_graded_vals[ac]; -+ -+ /* Send the index to tid array, picking from the array will be -+ * taken care by dequeuing function -+ */ -+ new_tid = ac_to_tid[ac_down][tid % 2]; -+ -+ return new_tid; -+} -+ -+/* -+ * This function initializes the WMM state information and the -+ * WMM data path queues. -+ */ -+void -+mwifiex_wmm_init(struct mwifiex_adapter *adapter) -+{ -+ int i, j; -+ struct mwifiex_private *priv; -+ -+ for (j = 0; j < adapter->priv_num; ++j) { -+ priv = adapter->priv[j]; -+ if (!priv) -+ continue; -+ -+ for (i = 0; i < MAX_NUM_TID; ++i) { -+ priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; -+ priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; -+ priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; -+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; -+ } -+ -+ priv->aggr_prio_tbl[6].amsdu -+ = priv->aggr_prio_tbl[6].ampdu_ap -+ = priv->aggr_prio_tbl[6].ampdu_user -+ = BA_STREAM_NOT_ALLOWED; -+ -+ priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap -+ = priv->aggr_prio_tbl[7].ampdu_user -+ = BA_STREAM_NOT_ALLOWED; -+ -+ priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; -+ priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; -+ priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; -+ } -+} -+ -+/* -+ * This function checks if WMM Tx queue is empty. -+ */ -+int -+mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) -+{ -+ int i, j; -+ struct mwifiex_private *priv; -+ -+ for (j = 0; j < adapter->priv_num; ++j) { -+ priv = adapter->priv[j]; -+ if (priv) { -+ for (i = 0; i < MAX_NUM_TID; i++) -+ if (!mwifiex_wmm_is_ra_list_empty( -+ &priv->wmm.tid_tbl_ptr[i].ra_list)) -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+/* -+ * This function deletes all packets in an RA list node. -+ * -+ * The packet sent completion callback handler are called with -+ * status failure, after they are dequeued to ensure proper -+ * cleanup. The RA list node itself is freed at the end. -+ */ -+static void -+mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ra_list) -+{ -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct sk_buff *skb, *tmp; -+ -+ skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) -+ mwifiex_write_data_complete(adapter, skb, -1); -+} -+ -+/* -+ * This function deletes all packets in an RA list. -+ * -+ * Each nodes in the RA list are freed individually first, and then -+ * the RA list itself is freed. -+ */ -+static void -+mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, -+ struct list_head *ra_list_head) -+{ -+ struct mwifiex_ra_list_tbl *ra_list; -+ -+ list_for_each_entry(ra_list, ra_list_head, list) -+ mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); -+} -+ -+/* -+ * This function deletes all packets in all RA lists. -+ */ -+static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) -+{ -+ int i; -+ -+ for (i = 0; i < MAX_NUM_TID; i++) -+ mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. -+ ra_list); -+} -+ -+/* -+ * This function deletes all route addresses from all RA lists. -+ */ -+static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) -+{ -+ struct mwifiex_ra_list_tbl *ra_list, *tmp_node; -+ int i; -+ -+ for (i = 0; i < MAX_NUM_TID; ++i) { -+ dev_dbg(priv->adapter->dev, -+ "info: ra_list: freeing buf for tid %d\n", i); -+ list_for_each_entry_safe(ra_list, tmp_node, -+ &priv->wmm.tid_tbl_ptr[i].ra_list, list) { -+ list_del(&ra_list->list); -+ kfree(ra_list); -+ } -+ -+ INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); -+ -+ priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL; -+ } -+} -+ -+/* -+ * This function cleans up the Tx and Rx queues. -+ * -+ * Cleanup includes - -+ * - All packets in RA lists -+ * - All entries in Rx reorder table -+ * - All entries in Tx BA stream table -+ * - MPA buffer (if required) -+ * - All RA lists -+ */ -+void -+mwifiex_clean_txrx(struct mwifiex_private *priv) -+{ -+ unsigned long flags; -+ -+ mwifiex_11n_cleanup_reorder_tbl(priv); -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); -+ -+ mwifiex_wmm_cleanup_queues(priv); -+ mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); -+ -+ if (priv->adapter->if_ops.cleanup_mpa_buf) -+ priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); -+ -+ mwifiex_wmm_delete_all_ralist(priv); -+ memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -+} -+ -+/* -+ * This function retrieves a particular RA list node, matching with the -+ * given TID and RA address. -+ */ -+static struct mwifiex_ra_list_tbl * -+mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, -+ u8 *ra_addr) -+{ -+ struct mwifiex_ra_list_tbl *ra_list; -+ -+ list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, -+ list) { -+ if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) -+ return ra_list; -+ } -+ -+ return NULL; -+} -+ -+/* -+ * This function retrieves an RA list node for a given TID and -+ * RA address pair. -+ * -+ * If no such node is found, a new node is added first and then -+ * retrieved. -+ */ -+static struct mwifiex_ra_list_tbl * -+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) -+{ -+ struct mwifiex_ra_list_tbl *ra_list; -+ -+ ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); -+ if (ra_list) -+ return ra_list; -+ mwifiex_ralist_add(priv, ra_addr); -+ -+ return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); -+} -+ -+/* -+ * This function checks if a particular RA list node exists in a given TID -+ * table index. -+ */ -+int -+mwifiex_is_ralist_valid(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ra_list, int ptr_index) -+{ -+ struct mwifiex_ra_list_tbl *rlist; -+ -+ list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, -+ list) { -+ if (rlist == ra_list) -+ return true; -+ } -+ -+ return false; -+} -+ -+/* -+ * This function adds a packet to WMM queue. -+ * -+ * In disconnected state the packet is immediately dropped and the -+ * packet send completion callback is called with status failure. -+ * -+ * Otherwise, the correct RA list node is located and the packet -+ * is queued at the list tail. -+ */ -+void -+mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb) -+{ -+ struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); -+ struct mwifiex_private *priv = adapter->priv[tx_info->bss_index]; -+ u32 tid; -+ struct mwifiex_ra_list_tbl *ra_list; -+ u8 ra[ETH_ALEN], tid_down; -+ unsigned long flags; -+ -+ if (!priv->media_connected) { -+ dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); -+ mwifiex_write_data_complete(adapter, skb, -1); -+ return; -+ } -+ -+ tid = skb->priority; -+ -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); -+ -+ tid_down = mwifiex_wmm_downgrade_tid(priv, tid); -+ -+ /* In case of infra as we have already created the list during -+ association we just don't have to call get_queue_raptr, we will -+ have only 1 raptr for a tid in case of infra */ -+ if (!mwifiex_queuing_ra_based(priv)) { -+ if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) -+ ra_list = list_first_entry( -+ &priv->wmm.tid_tbl_ptr[tid_down].ra_list, -+ struct mwifiex_ra_list_tbl, list); -+ else -+ ra_list = NULL; -+ } else { -+ memcpy(ra, skb->data, ETH_ALEN); -+ ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); -+ } -+ -+ if (!ra_list) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -+ mwifiex_write_data_complete(adapter, skb, -1); -+ return; -+ } -+ -+ skb_queue_tail(&ra_list->skb_head, skb); -+ -+ ra_list->total_pkts_size += skb->len; -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -+} -+ -+/* -+ * This function processes the get WMM status command response from firmware. -+ * -+ * The response may contain multiple TLVs - -+ * - AC Queue status TLVs -+ * - Current WMM Parameter IE TLV -+ * - Admission Control action frame TLVs -+ * -+ * This function parses the TLVs and then calls further specific functions -+ * to process any changes in the queue prioritize or state. -+ */ -+int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, -+ const struct host_cmd_ds_command *resp) -+{ -+ u8 *curr = (u8 *) &resp->params.get_wmm_status; -+ uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; -+ int valid = true; -+ -+ struct mwifiex_ie_types_data *tlv_hdr; -+ struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; -+ struct ieee_types_wmm_parameter *wmm_param_ie = NULL; -+ struct mwifiex_wmm_ac_status *ac_status; -+ -+ dev_dbg(priv->adapter->dev, "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", -+ resp_len); -+ -+ while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { -+ tlv_hdr = (struct mwifiex_ie_types_data *) curr; -+ tlv_len = le16_to_cpu(tlv_hdr->header.len); -+ -+ switch (le16_to_cpu(tlv_hdr->header.type)) { -+ case TLV_TYPE_WMMQSTATUS: -+ tlv_wmm_qstatus = -+ (struct mwifiex_ie_types_wmm_queue_status *) -+ tlv_hdr; -+ dev_dbg(priv->adapter->dev, -+ "info: CMD_RESP: WMM_GET_STATUS:" -+ " QSTATUS TLV: %d, %d, %d\n", -+ tlv_wmm_qstatus->queue_index, -+ tlv_wmm_qstatus->flow_required, -+ tlv_wmm_qstatus->disabled); -+ -+ ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> -+ queue_index]; -+ ac_status->disabled = tlv_wmm_qstatus->disabled; -+ ac_status->flow_required = -+ tlv_wmm_qstatus->flow_required; -+ ac_status->flow_created = tlv_wmm_qstatus->flow_created; -+ break; -+ -+ case WLAN_EID_VENDOR_SPECIFIC: -+ /* -+ * Point the regular IEEE IE 2 bytes into the Marvell IE -+ * and setup the IEEE IE type and length byte fields -+ */ -+ -+ wmm_param_ie = -+ (struct ieee_types_wmm_parameter *) (curr + -+ 2); -+ wmm_param_ie->vend_hdr.len = (u8) tlv_len; -+ wmm_param_ie->vend_hdr.element_id = -+ WLAN_EID_VENDOR_SPECIFIC; -+ -+ dev_dbg(priv->adapter->dev, -+ "info: CMD_RESP: WMM_GET_STATUS:" -+ " WMM Parameter Set Count: %d\n", -+ wmm_param_ie->qos_info_bitmap & -+ IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); -+ -+ memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. -+ wmm_ie, wmm_param_ie, -+ wmm_param_ie->vend_hdr.len + 2); -+ -+ break; -+ -+ default: -+ valid = false; -+ break; -+ } -+ -+ curr += (tlv_len + sizeof(tlv_hdr->header)); -+ resp_len -= (tlv_len + sizeof(tlv_hdr->header)); -+ } -+ -+ mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); -+ mwifiex_wmm_setup_ac_downgrade(priv); -+ -+ return 0; -+} -+ -+/* -+ * Callback handler from the command module to allow insertion of a WMM TLV. -+ * -+ * If the BSS we are associating to supports WMM, this function adds the -+ * required WMM Information IE to the association request command buffer in -+ * the form of a Marvell extended IEEE IE. -+ */ -+u32 -+mwifiex_wmm_process_association_req(struct mwifiex_private *priv, -+ u8 **assoc_buf, -+ struct ieee_types_wmm_parameter *wmm_ie, -+ struct ieee80211_ht_cap *ht_cap) -+{ -+ struct mwifiex_ie_types_wmm_param_set *wmm_tlv; -+ u32 ret_len = 0; -+ -+ /* Null checks */ -+ if (!assoc_buf) -+ return 0; -+ if (!(*assoc_buf)) -+ return 0; -+ -+ if (!wmm_ie) -+ return 0; -+ -+ dev_dbg(priv->adapter->dev, "info: WMM: process assoc req:" -+ "bss->wmmIe=0x%x\n", -+ wmm_ie->vend_hdr.element_id); -+ -+ if ((priv->wmm_required -+ || (ht_cap && (priv->adapter->config_bands & BAND_GN -+ || priv->adapter->config_bands & BAND_AN)) -+ ) -+ && wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { -+ wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; -+ wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); -+ wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); -+ memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], -+ le16_to_cpu(wmm_tlv->header.len)); -+ if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) -+ memcpy((u8 *) (wmm_tlv->wmm_ie -+ + le16_to_cpu(wmm_tlv->header.len) -+ - sizeof(priv->wmm_qosinfo)), -+ &priv->wmm_qosinfo, -+ sizeof(priv->wmm_qosinfo)); -+ -+ ret_len = sizeof(wmm_tlv->header) -+ + le16_to_cpu(wmm_tlv->header.len); -+ -+ *assoc_buf += ret_len; -+ } -+ -+ return ret_len; -+} -+ -+/* -+ * This function computes the time delay in the driver queues for a -+ * given packet. -+ * -+ * When the packet is received at the OS/Driver interface, the current -+ * time is set in the packet structure. The difference between the present -+ * time and that received time is computed in this function and limited -+ * based on pre-compiled limits in the driver. -+ */ -+u8 -+mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, -+ const struct sk_buff *skb) -+{ -+ u8 ret_val = 0; -+ struct timeval out_tstamp, in_tstamp; -+ u32 queue_delay; -+ -+ do_gettimeofday(&out_tstamp); -+ in_tstamp = ktime_to_timeval(skb->tstamp); -+ -+ queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000; -+ queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000; -+ -+ /* -+ * Queue delay is passed as a uint8 in units of 2ms (ms shifted -+ * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. -+ * -+ * Pass max value if queue_delay is beyond the uint8 range -+ */ -+ ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); -+ -+ dev_dbg(priv->adapter->dev, "data: WMM: Pkt Delay: %d ms," -+ " %d ms sent to FW\n", queue_delay, ret_val); -+ -+ return ret_val; -+} -+ -+/* -+ * This function retrieves the highest priority RA list table pointer. -+ */ -+static struct mwifiex_ra_list_tbl * -+mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, -+ struct mwifiex_private **priv, int *tid) -+{ -+ struct mwifiex_private *priv_tmp; -+ struct mwifiex_ra_list_tbl *ptr, *head; -+ struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; -+ struct mwifiex_tid_tbl *tid_ptr; -+ int is_list_empty; -+ unsigned long flags; -+ int i, j; -+ -+ for (j = adapter->priv_num - 1; j >= 0; --j) { -+ spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, -+ flags); -+ is_list_empty = list_empty(&adapter->bss_prio_tbl[j] -+ .bss_prio_head); -+ spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, -+ flags); -+ if (is_list_empty) -+ continue; -+ -+ if (adapter->bss_prio_tbl[j].bss_prio_cur == -+ (struct mwifiex_bss_prio_node *) -+ &adapter->bss_prio_tbl[j].bss_prio_head) { -+ bssprio_node = -+ list_first_entry(&adapter->bss_prio_tbl[j] -+ .bss_prio_head, -+ struct mwifiex_bss_prio_node, -+ list); -+ bssprio_head = bssprio_node; -+ } else { -+ bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; -+ bssprio_head = bssprio_node; -+ } -+ -+ do { -+ priv_tmp = bssprio_node->priv; -+ -+ for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { -+ -+ tid_ptr = &(priv_tmp)->wmm. -+ tid_tbl_ptr[tos_to_tid[i]]; -+ -+ spin_lock_irqsave(&tid_ptr->tid_tbl_lock, -+ flags); -+ is_list_empty = -+ list_empty(&adapter->bss_prio_tbl[j] -+ .bss_prio_head); -+ spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, -+ flags); -+ if (is_list_empty) -+ continue; -+ -+ /* -+ * Always choose the next ra we transmitted -+ * last time, this way we pick the ra's in -+ * round robin fashion. -+ */ -+ ptr = list_first_entry( -+ &tid_ptr->ra_list_curr->list, -+ struct mwifiex_ra_list_tbl, -+ list); -+ -+ head = ptr; -+ if (ptr == (struct mwifiex_ra_list_tbl *) -+ &tid_ptr->ra_list) { -+ /* Get next ra */ -+ ptr = list_first_entry(&ptr->list, -+ struct mwifiex_ra_list_tbl, list); -+ head = ptr; -+ } -+ -+ do { -+ is_list_empty = -+ skb_queue_empty(&ptr->skb_head); -+ if (!is_list_empty) { -+ *priv = priv_tmp; -+ *tid = tos_to_tid[i]; -+ return ptr; -+ } -+ /* Get next ra */ -+ ptr = list_first_entry(&ptr->list, -+ struct mwifiex_ra_list_tbl, -+ list); -+ if (ptr == -+ (struct mwifiex_ra_list_tbl *) -+ &tid_ptr->ra_list) -+ ptr = list_first_entry( -+ &ptr->list, -+ struct mwifiex_ra_list_tbl, -+ list); -+ } while (ptr != head); -+ } -+ -+ /* Get next bss priority node */ -+ bssprio_node = list_first_entry(&bssprio_node->list, -+ struct mwifiex_bss_prio_node, -+ list); -+ -+ if (bssprio_node == -+ (struct mwifiex_bss_prio_node *) -+ &adapter->bss_prio_tbl[j].bss_prio_head) -+ /* Get next bss priority node */ -+ bssprio_node = list_first_entry( -+ &bssprio_node->list, -+ struct mwifiex_bss_prio_node, -+ list); -+ } while (bssprio_node != bssprio_head); -+ } -+ return NULL; -+} -+ -+/* -+ * This function gets the number of packets in the Tx queue of a -+ * particular RA list. -+ */ -+static int -+mwifiex_num_pkts_in_txq(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr, int max_buf_size) -+{ -+ int count = 0, total_size = 0; -+ struct sk_buff *skb, *tmp; -+ -+ skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { -+ total_size += skb->len; -+ if (total_size < max_buf_size) -+ ++count; -+ else -+ break; -+ } -+ -+ return count; -+} -+ -+/* -+ * This function sends a single packet to firmware for transmission. -+ */ -+static void -+mwifiex_send_single_packet(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr, int ptr_index, -+ unsigned long ra_list_flags) -+ __releases(&priv->wmm.ra_list_spinlock) -+{ -+ struct sk_buff *skb, *skb_next; -+ struct mwifiex_tx_param tx_param; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ struct mwifiex_txinfo *tx_info; -+ -+ if (skb_queue_empty(&ptr->skb_head)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ dev_dbg(adapter->dev, "data: nothing to send\n"); -+ return; -+ } -+ -+ skb = skb_dequeue(&ptr->skb_head); -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); -+ -+ ptr->total_pkts_size -= skb->len; -+ -+ if (!skb_queue_empty(&ptr->skb_head)) -+ skb_next = skb_peek(&ptr->skb_head); -+ else -+ skb_next = NULL; -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ -+ tx_param.next_pkt_len = ((skb_next) ? skb_next->len + -+ sizeof(struct txpd) : 0); -+ -+ 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); -+ -+ if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ mwifiex_write_data_complete(adapter, skb, -1); -+ return; -+ } -+ -+ skb_queue_tail(&ptr->skb_head, skb); -+ -+ ptr->total_pkts_size += skb->len; -+ tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ } else { -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { -+ priv->wmm.packets_out[ptr_index]++; -+ priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; -+ } -+ adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = -+ list_first_entry( -+ &adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_cur->list, -+ struct mwifiex_bss_prio_node, -+ list); -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ } -+} -+ -+/* -+ * This function checks if the first packet in the given RA list -+ * is already processed or not. -+ */ -+static int -+mwifiex_is_ptr_processed(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr) -+{ -+ struct sk_buff *skb; -+ struct mwifiex_txinfo *tx_info; -+ -+ if (skb_queue_empty(&ptr->skb_head)) -+ return false; -+ -+ skb = skb_peek(&ptr->skb_head); -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) -+ return true; -+ -+ return false; -+} -+ -+/* -+ * This function sends a single processed packet to firmware for -+ * transmission. -+ */ -+static void -+mwifiex_send_processed_packet(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ptr, int ptr_index, -+ unsigned long ra_list_flags) -+ __releases(&priv->wmm.ra_list_spinlock) -+{ -+ struct mwifiex_tx_param tx_param; -+ struct mwifiex_adapter *adapter = priv->adapter; -+ int ret = -1; -+ struct sk_buff *skb, *skb_next; -+ struct mwifiex_txinfo *tx_info; -+ -+ if (skb_queue_empty(&ptr->skb_head)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ return; -+ } -+ -+ skb = skb_dequeue(&ptr->skb_head); -+ -+ if (!skb_queue_empty(&ptr->skb_head)) -+ skb_next = skb_peek(&ptr->skb_head); -+ else -+ skb_next = NULL; -+ -+ tx_info = MWIFIEX_SKB_TXCB(skb); -+ -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ tx_param.next_pkt_len = -+ ((skb_next) ? skb_next->len + -+ sizeof(struct txpd) : 0); -+ ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, -+ skb->data, skb->len, &tx_param); -+ switch (ret) { -+ case -EBUSY: -+ dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ -+ if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ mwifiex_write_data_complete(adapter, skb, -1); -+ return; -+ } -+ -+ skb_queue_tail(&ptr->skb_head, skb); -+ -+ tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ break; -+ case -1: -+ adapter->data_sent = false; -+ dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); -+ adapter->dbg.num_tx_host_to_card_failure++; -+ mwifiex_write_data_complete(adapter, skb, ret); -+ break; -+ case -EINPROGRESS: -+ adapter->data_sent = false; -+ default: -+ break; -+ } -+ if (ret != -EBUSY) { -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); -+ if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { -+ priv->wmm.packets_out[ptr_index]++; -+ priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr; -+ } -+ adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur = -+ list_first_entry( -+ &adapter->bss_prio_tbl[priv->bss_priority] -+ .bss_prio_cur->list, -+ struct mwifiex_bss_prio_node, -+ list); -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, -+ ra_list_flags); -+ } -+} -+ -+/* -+ * This function dequeues a packet from the highest priority list -+ * and transmits it. -+ */ -+static int -+mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) -+{ -+ struct mwifiex_ra_list_tbl *ptr; -+ struct mwifiex_private *priv = NULL; -+ int ptr_index = 0; -+ u8 ra[ETH_ALEN]; -+ int tid_del = 0, tid = 0; -+ unsigned long flags; -+ -+ ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); -+ if (!ptr) -+ return -1; -+ -+ tid = mwifiex_get_tid(ptr); -+ -+ dev_dbg(adapter->dev, "data: tid=%d\n", tid); -+ -+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); -+ if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { -+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -+ return -1; -+ } -+ -+ if (mwifiex_is_ptr_processed(priv, ptr)) { -+ mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); -+ /* ra_list_spinlock has been freed in -+ mwifiex_send_processed_packet() */ -+ return 0; -+ } -+ -+ if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) -+ || ((priv->sec_info.wpa_enabled -+ || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set) -+ ) { -+ mwifiex_send_single_packet(priv, ptr, ptr_index, flags); -+ /* ra_list_spinlock has been freed in -+ mwifiex_send_single_packet() */ -+ } else { -+ 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, tid, &tid_del, ra)) { -+ mwifiex_11n_create_tx_ba_stream_tbl(priv, -+ ptr->ra, tid, -+ BA_STREAM_SETUP_INPROGRESS); -+ mwifiex_send_delba(priv, tid_del, ra, 1); -+ } -+ } -+/* Minimum number of AMSDU */ -+#define MIN_NUM_AMSDU 2 -+ 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, -+ ptr_index, flags); -+ /* ra_list_spinlock has been freed in -+ mwifiex_11n_aggregate_pkt() */ -+ else -+ mwifiex_send_single_packet(priv, ptr, ptr_index, flags); -+ /* ra_list_spinlock has been freed in -+ mwifiex_send_single_packet() */ -+ } -+ return 0; -+} -+ -+/* -+ * This function transmits the highest priority packet awaiting in the -+ * WMM Queues. -+ */ -+void -+mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) -+{ -+ do { -+ /* Check if busy */ -+ if (adapter->data_sent || adapter->tx_lock_flag) -+ break; -+ -+ if (mwifiex_dequeue_tx_packet(adapter)) -+ break; -+ } while (true); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwifiex/wmm.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/wmm.h ---- linux-2.6.39-rc6/drivers/net/wireless/mwifiex/wmm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwifiex/wmm.h 2011-05-05 23:29:45.466441635 +0200 -@@ -0,0 +1,110 @@ -+/* -+ * Marvell Wireless LAN device driver: WMM -+ * -+ * Copyright (C) 2011, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available by writing to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ */ -+ -+#ifndef _MWIFIEX_WMM_H_ -+#define _MWIFIEX_WMM_H_ -+ -+enum ieee_types_wmm_aciaifsn_bitmasks { -+ MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), -+ MWIFIEX_ACM = BIT(4), -+ MWIFIEX_ACI = (BIT(5) | BIT(6)), -+}; -+ -+enum ieee_types_wmm_ecw_bitmasks { -+ MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), -+ MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)), -+}; -+ -+/* -+ * This function retrieves the TID of the given RA list. -+ */ -+static inline int -+mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr) -+{ -+ struct sk_buff *skb; -+ -+ if (skb_queue_empty(&ptr->skb_head)) -+ return 0; -+ -+ skb = skb_peek(&ptr->skb_head); -+ -+ return skb->priority; -+} -+ -+/* -+ * This function gets the length of a list. -+ */ -+static inline int -+mwifiex_wmm_list_len(struct list_head *head) -+{ -+ struct list_head *pos; -+ int count = 0; -+ -+ list_for_each(pos, head) -+ ++count; -+ -+ return count; -+} -+ -+/* -+ * This function checks if a RA list is empty or not. -+ */ -+static inline u8 -+mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) -+{ -+ struct mwifiex_ra_list_tbl *ra_list; -+ int is_list_empty; -+ -+ list_for_each_entry(ra_list, ra_list_hhead, list) { -+ is_list_empty = skb_queue_empty(&ra_list->skb_head); -+ if (!is_list_empty) -+ return false; -+ } -+ -+ return true; -+} -+ -+void mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, -+ struct sk_buff *skb); -+void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); -+ -+int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); -+void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); -+int mwifiex_is_ralist_valid(struct mwifiex_private *priv, -+ struct mwifiex_ra_list_tbl *ra_list, int tid); -+ -+u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, -+ const struct sk_buff *skb); -+void mwifiex_wmm_init(struct mwifiex_adapter *adapter); -+ -+extern u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, -+ u8 **assoc_buf, -+ struct ieee_types_wmm_parameter -+ *wmmie, -+ struct ieee80211_ht_cap -+ *htcap); -+ -+void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, -+ struct ieee_types_wmm_parameter -+ *wmm_ie); -+void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); -+extern int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, -+ const struct host_cmd_ds_command *resp); -+ -+#endif /* !_MWIFIEX_WMM_H_ */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/mwl8k.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwl8k.c ---- linux-2.6.39-rc6/drivers/net/wireless/mwl8k.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/mwl8k.c 2011-05-05 23:29:49.217486955 +0200 -@@ -63,6 +63,7 @@ - #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 - #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c - #define MWL8K_A2H_INT_DUMMY (1 << 20) -+#define MWL8K_A2H_INT_BA_WATCHDOG (1 << 14) - #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) - #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) - #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) -@@ -73,6 +74,14 @@ - #define MWL8K_A2H_INT_RX_READY (1 << 1) - #define MWL8K_A2H_INT_TX_DONE (1 << 0) - -+/* HW micro second timer register -+ * located at offset 0xA600. This -+ * will be used to timestamp tx -+ * packets. -+ */ -+ -+#define MWL8K_HW_TIMER_REGISTER 0x0000a600 -+ - #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ - MWL8K_A2H_INT_CHNL_SWITCHED | \ - MWL8K_A2H_INT_QUEUE_EMPTY | \ -@@ -82,10 +91,14 @@ - MWL8K_A2H_INT_MAC_EVENT | \ - MWL8K_A2H_INT_OPC_DONE | \ - MWL8K_A2H_INT_RX_READY | \ -- MWL8K_A2H_INT_TX_DONE) -+ MWL8K_A2H_INT_TX_DONE | \ -+ MWL8K_A2H_INT_BA_WATCHDOG) - - #define MWL8K_RX_QUEUES 1 --#define MWL8K_TX_QUEUES 4 -+#define MWL8K_TX_WMM_QUEUES 4 -+#define MWL8K_MAX_AMPDU_QUEUES 8 -+#define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES) -+#define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues) - - struct rxd_ops { - int rxd_size; -@@ -134,6 +147,21 @@ - struct sk_buff **skb; - }; - -+enum { -+ AMPDU_NO_STREAM, -+ AMPDU_STREAM_NEW, -+ AMPDU_STREAM_IN_PROGRESS, -+ AMPDU_STREAM_ACTIVE, -+}; -+ -+struct mwl8k_ampdu_stream { -+ struct ieee80211_sta *sta; -+ u8 tid; -+ u8 state; -+ u8 idx; -+ u8 txq_idx; /* index of this stream in priv->txq */ -+}; -+ - struct mwl8k_priv { - struct ieee80211_hw *hw; - struct pci_dev *pdev; -@@ -160,6 +188,12 @@ - u32 ap_macids_supported; - u32 sta_macids_supported; - -+ /* Ampdu stream information */ -+ u8 num_ampdu_queues; -+ spinlock_t stream_lock; -+ struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES]; -+ struct work_struct watchdog_ba_handle; -+ - /* firmware access */ - struct mutex fw_mutex; - struct task_struct *fw_mutex_owner; -@@ -191,7 +225,8 @@ - int pending_tx_pkts; - - struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; -- struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; -+ struct mwl8k_tx_queue txq[MWL8K_MAX_TX_QUEUES]; -+ u32 txq_offset[MWL8K_MAX_TX_QUEUES]; - - bool radio_on; - bool radio_short_preamble; -@@ -224,7 +259,7 @@ - * preserve the queue configurations so they can be restored if/when - * the firmware image is swapped. - */ -- struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_QUEUES]; -+ struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_WMM_QUEUES]; - - /* async firmware loading state */ - unsigned fw_state; -@@ -262,9 +297,17 @@ - #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)) - -@@ -352,10 +395,12 @@ - #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 - #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ - #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 -+#define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 - #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ - #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ - #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ - #define MWL8K_CMD_UPDATE_STADB 0x1123 -+#define MWL8K_CMD_BASTREAM 0x1125 - - static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) - { -@@ -395,6 +440,8 @@ - MWL8K_CMDNAME(SET_NEW_STN); - MWL8K_CMDNAME(UPDATE_ENCRYPTION); - MWL8K_CMDNAME(UPDATE_STADB); -+ MWL8K_CMDNAME(BASTREAM); -+ MWL8K_CMDNAME(GET_WATCHDOG_BITMAP); - default: - snprintf(buf, bufsize, "0x%x", cmd); - } -@@ -669,7 +716,7 @@ - "helper image\n", pci_name(priv->pdev)); - return rc; - } -- msleep(5); -+ msleep(20); - - rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); - } else { -@@ -734,8 +781,10 @@ - skb_pull(skb, sizeof(*tr) - hdrlen); - } - -+#define REDUCED_TX_HEADROOM 8 -+ - static void --mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad) -+mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) - { - struct ieee80211_hdr *wh; - int hdrlen; -@@ -751,6 +800,22 @@ - wh = (struct ieee80211_hdr *)skb->data; - - hdrlen = ieee80211_hdrlen(wh->frame_control); -+ -+ /* -+ * Check if skb_resize is required because of -+ * tx_headroom adjustment. -+ */ -+ if (priv->ap_fw && (hdrlen < (sizeof(struct ieee80211_cts) -+ + REDUCED_TX_HEADROOM))) { -+ if (pskb_expand_head(skb, REDUCED_TX_HEADROOM, 0, GFP_ATOMIC)) { -+ -+ wiphy_err(priv->hw->wiphy, -+ "Failed to reallocate TX buffer\n"); -+ return; -+ } -+ skb->truesize += REDUCED_TX_HEADROOM; -+ } -+ - reqd_hdrlen = sizeof(*tr); - - if (hdrlen != reqd_hdrlen) -@@ -773,7 +838,8 @@ - tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad); - } - --static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) -+static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, -+ struct sk_buff *skb) - { - struct ieee80211_hdr *wh; - struct ieee80211_tx_info *tx_info; -@@ -791,8 +857,8 @@ - /* - * 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) -@@ -814,7 +880,7 @@ - break; - } - } -- mwl8k_add_dma_header(skb, data_pad); -+ mwl8k_add_dma_header(priv, skb, data_pad); - } - - /* -@@ -1127,6 +1193,9 @@ - struct mwl8k_rx_queue *rxq = priv->rxq + index; - int i; - -+ if (rxq->rxd == NULL) -+ return; -+ - for (i = 0; i < MWL8K_RX_DESCS; i++) { - if (rxq->buf[i].skb != NULL) { - pci_unmap_single(priv->pdev, -@@ -1319,7 +1388,7 @@ - __le16 pkt_len; - __u8 dest_MAC_addr[ETH_ALEN]; - __le32 next_txd_phys_addr; -- __le32 reserved; -+ __le32 timestamp; - __le16 rate_info; - __u8 peer_id; - __u8 tx_frag_cnt; -@@ -1383,7 +1452,7 @@ - struct mwl8k_priv *priv = hw->priv; - int i; - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) { -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) { - struct mwl8k_tx_queue *txq = priv->txq + i; - int fw_owned = 0; - int drv_owned = 0; -@@ -1452,9 +1521,8 @@ - - if (timeout) { - WARN_ON(priv->pending_tx_pkts); -- if (retry) { -+ if (retry) - wiphy_notice(hw->wiphy, "tx rings drained\n"); -- } - break; - } - -@@ -1484,6 +1552,41 @@ - MWL8K_TXD_STATUS_OK_RETRY | \ - MWL8K_TXD_STATUS_OK_MORE_RETRY)) - -+static int mwl8k_tid_queue_mapping(u8 tid) -+{ -+ BUG_ON(tid > 7); -+ -+ switch (tid) { -+ case 0: -+ case 3: -+ return IEEE80211_AC_BE; -+ break; -+ case 1: -+ case 2: -+ return IEEE80211_AC_BK; -+ break; -+ case 4: -+ case 5: -+ return IEEE80211_AC_VI; -+ break; -+ case 6: -+ case 7: -+ return IEEE80211_AC_VO; -+ break; -+ default: -+ return -1; -+ break; -+ } -+} -+ -+/* The firmware will fill in the rate information -+ * for each packet that gets queued in the hardware -+ * and these macros will interpret that info. -+ */ -+ -+#define RI_FORMAT(a) (a & 0x0001) -+#define RI_RATE_ID_MCS(a) ((a & 0x01f8) >> 3) -+ - static int - mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) - { -@@ -1500,6 +1603,10 @@ - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u32 status; -+ struct ieee80211_sta *sta; -+ struct mwl8k_sta *sta_info = NULL; -+ u16 rate_info; -+ struct ieee80211_hdr *wh; - - tx = txq->head; - tx_desc = txq->txd + tx; -@@ -1528,18 +1635,40 @@ - - mwl8k_remove_dma_header(skb, tx_desc->qos_control); - -+ wh = (struct ieee80211_hdr *) skb->data; -+ - /* Mark descriptor as unused */ - tx_desc->pkt_phys_addr = 0; - tx_desc->pkt_len = 0; - - info = IEEE80211_SKB_CB(skb); -+ if (ieee80211_is_data(wh->frame_control)) { -+ sta = info->control.sta; -+ if (sta) { -+ sta_info = MWL8K_STA(sta); -+ BUG_ON(sta_info == NULL); -+ rate_info = le16_to_cpu(tx_desc->rate_info); -+ /* If rate is < 6.5 Mpbs for an ht station -+ * do not form an ampdu. If the station is a -+ * legacy station (format = 0), do not form an -+ * ampdu -+ */ -+ if (RI_RATE_ID_MCS(rate_info) < 1 || -+ RI_FORMAT(rate_info) == 0) { -+ sta_info->is_ampdu_allowed = false; -+ } else { -+ sta_info->is_ampdu_allowed = true; -+ } -+ } -+ } -+ - ieee80211_tx_info_clear_status(info); - - /* 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; -@@ -1549,9 +1678,6 @@ - processed++; - } - -- if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) -- ieee80211_wake_queue(hw, index); -- - return processed; - } - -@@ -1561,6 +1687,9 @@ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq = priv->txq + index; - -+ if (txq->txd == NULL) -+ return; -+ - mwl8k_txq_reclaim(hw, index, INT_MAX, 1); - - kfree(txq->skb); -@@ -1572,12 +1701,116 @@ - txq->txd = NULL; - } - -+/* caller must hold priv->stream_lock when calling the stream functions */ -+static struct mwl8k_ampdu_stream * -+mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) -+{ -+ struct mwl8k_ampdu_stream *stream; -+ struct mwl8k_priv *priv = hw->priv; -+ int i; -+ -+ for (i = 0; i < priv->num_ampdu_queues; i++) { -+ stream = &priv->ampdu[i]; -+ if (stream->state == AMPDU_NO_STREAM) { -+ stream->sta = sta; -+ stream->state = AMPDU_STREAM_NEW; -+ stream->tid = tid; -+ stream->idx = i; -+ stream->txq_idx = MWL8K_TX_WMM_QUEUES + i; -+ wiphy_debug(hw->wiphy, "Added a new stream for %pM %d", -+ sta->addr, tid); -+ return stream; -+ } -+ } -+ return NULL; -+} -+ -+static int -+mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -+{ -+ int ret; -+ -+ /* if the stream has already been started, don't start it again */ -+ if (stream->state != AMPDU_STREAM_NEW) -+ return 0; -+ ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0); -+ if (ret) -+ wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: " -+ "%d\n", stream->sta->addr, stream->tid, ret); -+ else -+ wiphy_debug(hw->wiphy, "Started stream for %pM %d\n", -+ stream->sta->addr, stream->tid); -+ return ret; -+} -+ -+static void -+mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -+{ -+ wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr, -+ stream->tid); -+ memset(stream, 0, sizeof(*stream)); -+} -+ -+static struct mwl8k_ampdu_stream * -+mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid) -+{ -+ struct mwl8k_priv *priv = hw->priv; -+ int i; -+ -+ for (i = 0 ; i < priv->num_ampdu_queues; i++) { -+ struct mwl8k_ampdu_stream *stream; -+ stream = &priv->ampdu[i]; -+ if (stream->state == AMPDU_NO_STREAM) -+ continue; -+ if (!memcmp(stream->sta->addr, addr, ETH_ALEN) && -+ stream->tid == tid) -+ return stream; -+ } -+ 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) - { - struct mwl8k_priv *priv = hw->priv; - struct ieee80211_tx_info *tx_info; - struct mwl8k_vif *mwl8k_vif; -+ struct ieee80211_sta *sta; - struct ieee80211_hdr *wh; - struct mwl8k_tx_queue *txq; - struct mwl8k_tx_desc *tx; -@@ -1585,6 +1818,12 @@ - u32 txstatus; - u8 txdatarate; - u16 qos; -+ int txpriority; -+ u8 tid = 0; -+ struct mwl8k_ampdu_stream *stream = NULL; -+ bool start_ba_session = false; -+ bool mgmtframe = false; -+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - - wh = (struct ieee80211_hdr *)skb->data; - if (ieee80211_is_data_qos(wh->frame_control)) -@@ -1592,14 +1831,18 @@ - else - qos = 0; - -+ if (ieee80211_is_mgmt(wh->frame_control)) -+ mgmtframe = true; -+ - if (priv->ap_fw) -- mwl8k_encapsulate_tx_frame(skb); -+ mwl8k_encapsulate_tx_frame(priv, skb); - else -- mwl8k_add_dma_header(skb, 0); -+ mwl8k_add_dma_header(priv, skb, 0); - - wh = &((struct mwl8k_dma_data *)skb->data)->wh; - - tx_info = IEEE80211_SKB_CB(skb); -+ sta = tx_info->control.sta; - mwl8k_vif = MWL8K_VIF(tx_info->control.vif); - - if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { -@@ -1627,12 +1870,91 @@ - qos |= MWL8K_QOS_ACK_POLICY_NORMAL; - } - -+ /* Queue ADDBA request in the respective data queue. While setting up -+ * the ampdu stream, mac80211 queues further packets for that -+ * particular ra/tid pair. However, packets piled up in the hardware -+ * for that ra/tid pair will still go out. ADDBA request and the -+ * related data packets going out from different queues asynchronously -+ * will cause a shift in the receiver window which might result in -+ * ampdu packets getting dropped at the receiver after the stream has -+ * been setup. -+ */ -+ if (unlikely(ieee80211_is_action(wh->frame_control) && -+ mgmt->u.action.category == WLAN_CATEGORY_BACK && -+ mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ && -+ priv->ap_fw)) { -+ u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); -+ tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; -+ index = mwl8k_tid_queue_mapping(tid); -+ } -+ -+ txpriority = index; -+ -+ if (ieee80211_is_data_qos(wh->frame_control) && -+ 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) { -+ if (stream->state == AMPDU_STREAM_ACTIVE) { -+ txpriority = stream->txq_idx; -+ index = stream->txq_idx; -+ } else if (stream->state == AMPDU_STREAM_NEW) { -+ /* We get here if the driver sends us packets -+ * after we've initiated a stream, but before -+ * our ampdu_action routine has been called -+ * with IEEE80211_AMPDU_TX_START to get the SSN -+ * for the ADDBA request. So this packet can -+ * go out with no risk of sequence number -+ * mismatch. No special handling is required. -+ */ -+ } else { -+ /* Drop packets that would go out after the -+ * ADDBA request was sent but before the ADDBA -+ * response is received. If we don't do this, -+ * the recipient would probably receive it -+ * after the ADDBA request with SSN 0. This -+ * will cause the recipient's BA receive window -+ * to shift, which would cause the subsequent -+ * packets in the BA stream to be discarded. -+ * mac80211 queues our packets for us in this -+ * case, so this is really just a safety check. -+ */ -+ wiphy_warn(hw->wiphy, -+ "Cannot send packet while ADDBA " -+ "dialog is underway.\n"); -+ spin_unlock(&priv->stream_lock); -+ dev_kfree_skb(skb); -+ return; -+ } -+ } else { -+ /* Defer calling mwl8k_start_stream so that the current -+ * skb can go out before the ADDBA request. This -+ * prevents sequence number mismatch at the recepient -+ * as described above. -+ */ -+ if (mwl8k_ampdu_allowed(sta, tid)) { -+ stream = mwl8k_add_stream(hw, sta, tid); -+ if (stream != NULL) -+ start_ba_session = true; -+ } -+ } -+ spin_unlock(&priv->stream_lock); -+ } -+ - dma = pci_map_single(priv->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(priv->pdev, dma)) { - wiphy_debug(hw->wiphy, - "failed to dma map skb, dropping TX frame.\n"); -+ if (start_ba_session) { -+ spin_lock(&priv->stream_lock); -+ mwl8k_remove_stream(hw, stream); -+ spin_unlock(&priv->stream_lock); -+ } - dev_kfree_skb(skb); - return; - } -@@ -1641,12 +1963,34 @@ - - txq = priv->txq + index; - -+ /* Mgmt frames that go out frequently are probe -+ * responses. Other mgmt frames got out relatively -+ * infrequently. Hence reserve 2 buffers so that -+ * other mgmt frames do not get dropped due to an -+ * already queued probe response in one of the -+ * reserved buffers. -+ */ -+ -+ if (txq->len >= MWL8K_TX_DESCS - 2) { -+ if (mgmtframe == false || -+ txq->len == MWL8K_TX_DESCS) { -+ if (start_ba_session) { -+ spin_lock(&priv->stream_lock); -+ mwl8k_remove_stream(hw, stream); -+ spin_unlock(&priv->stream_lock); -+ } -+ spin_unlock_bh(&priv->tx_lock); -+ dev_kfree_skb(skb); -+ return; -+ } -+ } -+ - BUG_ON(txq->skb[txq->tail] != NULL); - txq->skb[txq->tail] = skb; - - tx = txq->txd + txq->tail; - tx->data_rate = txdatarate; -- tx->tx_priority = index; -+ tx->tx_priority = txpriority; - tx->qos_control = cpu_to_le16(qos); - tx->pkt_phys_addr = cpu_to_le32(dma); - tx->pkt_len = cpu_to_le16(skb->len); -@@ -1655,6 +1999,11 @@ - tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; - else - tx->peer_id = 0; -+ -+ if (priv->ap_fw) -+ tx->timestamp = cpu_to_le32(ioread32(priv->regs + -+ MWL8K_HW_TIMER_REGISTER)); -+ - wmb(); - tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); - -@@ -1665,12 +2014,17 @@ - if (txq->tail == MWL8K_TX_DESCS) - txq->tail = 0; - -- if (txq->head == txq->tail) -- ieee80211_stop_queue(hw, index); -- - mwl8k_tx_start(priv); - - spin_unlock_bh(&priv->tx_lock); -+ -+ /* Initiate the ampdu session here */ -+ if (start_ba_session) { -+ spin_lock(&priv->stream_lock); -+ if (mwl8k_start_stream(hw, stream)) -+ mwl8k_remove_stream(hw, stream); -+ spin_unlock(&priv->stream_lock); -+ } - } - - -@@ -1868,7 +2222,7 @@ - __u8 mcs_bitmap[16]; - __le32 rx_queue_ptr; - __le32 num_tx_queues; -- __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; -+ __le32 tx_queue_ptrs[MWL8K_TX_WMM_QUEUES]; - __le32 caps2; - __le32 num_tx_desc_per_queue; - __le32 total_rxd; -@@ -1974,8 +2328,8 @@ - memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); - cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); -- cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); - cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); - cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); -@@ -2017,13 +2371,16 @@ - __le32 wcbbase2; - __le32 wcbbase3; - __le32 fw_api_version; -+ __le32 caps; -+ __le32 num_of_ampdu_queues; -+ __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES]; - } __packed; - - static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) - { - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_get_hw_spec_ap *cmd; -- int rc; -+ int rc, i; - u32 api_version; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -@@ -2055,27 +2412,31 @@ - priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); - priv->fw_rev = le32_to_cpu(cmd->fw_rev); - priv->hw_rev = cmd->hw_rev; -- mwl8k_setup_2ghz_band(hw); -+ mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); - priv->ap_macids_supported = 0x000000ff; - priv->sta_macids_supported = 0x00000000; -- -- off = le32_to_cpu(cmd->wcbbase0) & 0xffff; -- iowrite32(priv->txq[0].txd_dma, priv->sram + off); -- -+ priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues); -+ if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) { -+ wiphy_warn(hw->wiphy, "fw reported %d ampdu queues" -+ " but we only support %d.\n", -+ priv->num_ampdu_queues, -+ MWL8K_MAX_AMPDU_QUEUES); -+ priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES; -+ } - off = le32_to_cpu(cmd->rxwrptr) & 0xffff; - iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); - - off = le32_to_cpu(cmd->rxrdptr) & 0xffff; - iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); - -- off = le32_to_cpu(cmd->wcbbase1) & 0xffff; -- iowrite32(priv->txq[1].txd_dma, priv->sram + off); -- -- off = le32_to_cpu(cmd->wcbbase2) & 0xffff; -- iowrite32(priv->txq[2].txd_dma, priv->sram + off); -- -- off = le32_to_cpu(cmd->wcbbase3) & 0xffff; -- iowrite32(priv->txq[3].txd_dma, priv->sram + off); -+ priv->txq_offset[0] = le32_to_cpu(cmd->wcbbase0) & 0xffff; -+ priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; -+ priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; -+ priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; -+ -+ for (i = 0; i < priv->num_ampdu_queues; i++) -+ priv->txq_offset[i + MWL8K_TX_WMM_QUEUES] = -+ le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff; - } - - done: -@@ -2098,12 +2459,20 @@ - __le32 caps; - __le32 rx_queue_ptr; - __le32 num_tx_queues; -- __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; -+ __le32 tx_queue_ptrs[MWL8K_MAX_TX_QUEUES]; - __le32 flags; - __le32 num_tx_desc_per_queue; - __le32 total_rxd; - } __packed; - -+/* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause -+ * packets to expire 500 ms after the timestamp in the tx descriptor. That is, -+ * the packets that are queued for more than 500ms, will be dropped in the -+ * hardware. This helps minimizing the issues caused due to head-of-line -+ * blocking where a slow client can hog the bandwidth and affect traffic to a -+ * faster client. -+ */ -+#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 - #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 - #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 - #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 -@@ -2124,7 +2493,7 @@ - - cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); -- cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); -+ cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv)); - - /* - * Mac80211 stack has Q0 as highest priority and Q3 as lowest in -@@ -2132,14 +2501,15 @@ - * in that order. Map Q3 of mac80211 to Q0 of firmware so that the - * priority is interpreted the right way in firmware. - */ -- for (i = 0; i < MWL8K_TX_QUEUES; i++) { -- int j = MWL8K_TX_QUEUES - 1 - i; -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) { -+ int j = mwl8k_tx_queues(priv) - 1 - i; - cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma); - } - - cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | - MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | -- MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); -+ MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | -+ MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); - cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); - cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); - -@@ -2356,7 +2726,7 @@ - __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, -@@ -3123,6 +3493,65 @@ - } - - /* -+ * CMD_GET_WATCHDOG_BITMAP. -+ */ -+struct mwl8k_cmd_get_watchdog_bitmap { -+ struct mwl8k_cmd_pkt header; -+ u8 bitmap; -+} __packed; -+ -+static int mwl8k_cmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) -+{ -+ struct mwl8k_cmd_get_watchdog_bitmap *cmd; -+ int rc; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (cmd == NULL) -+ return -ENOMEM; -+ -+ cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_WATCHDOG_BITMAP); -+ cmd->header.length = cpu_to_le16(sizeof(*cmd)); -+ -+ rc = mwl8k_post_cmd(hw, &cmd->header); -+ if (!rc) -+ *bitmap = cmd->bitmap; -+ -+ kfree(cmd); -+ -+ return rc; -+} -+ -+#define INVALID_BA 0xAA -+static void mwl8k_watchdog_ba_events(struct work_struct *work) -+{ -+ int rc; -+ u8 bitmap = 0, stream_index; -+ struct mwl8k_ampdu_stream *streams; -+ struct mwl8k_priv *priv = -+ container_of(work, struct mwl8k_priv, watchdog_ba_handle); -+ -+ rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap); -+ if (rc) -+ return; -+ -+ if (bitmap == INVALID_BA) -+ return; -+ -+ /* the bitmap is the hw queue number. Map it to the ampdu queue. */ -+ stream_index = bitmap - MWL8K_TX_WMM_QUEUES; -+ -+ BUG_ON(stream_index >= priv->num_ampdu_queues); -+ -+ streams = &priv->ampdu[stream_index]; -+ -+ if (streams->state == AMPDU_STREAM_ACTIVE) -+ ieee80211_stop_tx_ba_session(streams->sta, streams->tid); -+ -+ return; -+} -+ -+ -+/* - * CMD_BSS_START. - */ - struct mwl8k_cmd_bss_start { -@@ -3151,6 +3580,152 @@ - } - - /* -+ * CMD_BASTREAM. -+ */ -+ -+/* -+ * UPSTREAM is tx direction -+ */ -+#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00 -+#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01 -+ -+enum ba_stream_action_type { -+ MWL8K_BA_CREATE, -+ MWL8K_BA_UPDATE, -+ MWL8K_BA_DESTROY, -+ MWL8K_BA_FLUSH, -+ MWL8K_BA_CHECK, -+}; -+ -+ -+struct mwl8k_create_ba_stream { -+ __le32 flags; -+ __le32 idle_thrs; -+ __le32 bar_thrs; -+ __le32 window_size; -+ u8 peer_mac_addr[6]; -+ u8 dialog_token; -+ u8 tid; -+ u8 queue_id; -+ u8 param_info; -+ __le32 ba_context; -+ u8 reset_seq_no_flag; -+ __le16 curr_seq_no; -+ u8 sta_src_mac_addr[6]; -+} __packed; -+ -+struct mwl8k_destroy_ba_stream { -+ __le32 flags; -+ __le32 ba_context; -+} __packed; -+ -+struct mwl8k_cmd_bastream { -+ struct mwl8k_cmd_pkt header; -+ __le32 action; -+ union { -+ struct mwl8k_create_ba_stream create_params; -+ struct mwl8k_destroy_ba_stream destroy_params; -+ }; -+} __packed; -+ -+static int -+mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream) -+{ -+ struct mwl8k_cmd_bastream *cmd; -+ int rc; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (cmd == NULL) -+ return -ENOMEM; -+ -+ cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); -+ cmd->header.length = cpu_to_le16(sizeof(*cmd)); -+ -+ cmd->action = cpu_to_le32(MWL8K_BA_CHECK); -+ -+ cmd->create_params.queue_id = stream->idx; -+ memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr, -+ ETH_ALEN); -+ cmd->create_params.tid = stream->tid; -+ -+ cmd->create_params.flags = -+ cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) | -+ cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM); -+ -+ rc = mwl8k_post_cmd(hw, &cmd->header); -+ -+ kfree(cmd); -+ -+ return rc; -+} -+ -+static int -+mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream, -+ u8 buf_size) -+{ -+ struct mwl8k_cmd_bastream *cmd; -+ int rc; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (cmd == NULL) -+ return -ENOMEM; -+ -+ -+ cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); -+ cmd->header.length = cpu_to_le16(sizeof(*cmd)); -+ -+ cmd->action = cpu_to_le32(MWL8K_BA_CREATE); -+ -+ cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size); -+ cmd->create_params.window_size = cpu_to_le32((u32)buf_size); -+ cmd->create_params.queue_id = stream->idx; -+ -+ memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN); -+ cmd->create_params.tid = stream->tid; -+ cmd->create_params.curr_seq_no = cpu_to_le16(0); -+ cmd->create_params.reset_seq_no_flag = 1; -+ -+ cmd->create_params.param_info = -+ (stream->sta->ht_cap.ampdu_factor & -+ IEEE80211_HT_AMPDU_PARM_FACTOR) | -+ ((stream->sta->ht_cap.ampdu_density << 2) & -+ IEEE80211_HT_AMPDU_PARM_DENSITY); -+ -+ cmd->create_params.flags = -+ cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE | -+ BASTREAM_FLAG_DIRECTION_UPSTREAM); -+ -+ rc = mwl8k_post_cmd(hw, &cmd->header); -+ -+ wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n", -+ stream->sta->addr, stream->tid); -+ kfree(cmd); -+ -+ return rc; -+} -+ -+static void mwl8k_destroy_ba(struct ieee80211_hw *hw, -+ struct mwl8k_ampdu_stream *stream) -+{ -+ struct mwl8k_cmd_bastream *cmd; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (cmd == NULL) -+ return; -+ -+ cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM); -+ cmd->header.length = cpu_to_le16(sizeof(*cmd)); -+ cmd->action = cpu_to_le32(MWL8K_BA_DESTROY); -+ -+ cmd->destroy_params.ba_context = cpu_to_le32(stream->idx); -+ mwl8k_post_cmd(hw, &cmd->header); -+ -+ wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx); -+ -+ kfree(cmd); -+} -+ -+/* - * CMD_SET_NEW_STN. - */ - struct mwl8k_cmd_set_new_stn { -@@ -3274,7 +3849,7 @@ - __u8 mac_addr[6]; - __u8 encr_type; - --} __attribute__((packed)); -+} __packed; - - struct mwl8k_cmd_set_key { - struct mwl8k_cmd_pkt header; -@@ -3294,7 +3869,7 @@ - __le16 tkip_tsc_low; - __le32 tkip_tsc_high; - __u8 mac_addr[6]; --} __attribute__((packed)); -+} __packed; - - enum { - MWL8K_ENCR_ENABLE, -@@ -3671,6 +4246,11 @@ - tasklet_schedule(&priv->poll_rx_task); - } - -+ if (status & MWL8K_A2H_INT_BA_WATCHDOG) { -+ status &= ~MWL8K_A2H_INT_BA_WATCHDOG; -+ ieee80211_queue_work(hw, &priv->watchdog_ba_handle); -+ } -+ - if (status) - iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - -@@ -3699,7 +4279,7 @@ - - spin_lock_bh(&priv->tx_lock); - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - limit -= mwl8k_txq_reclaim(hw, i, limit, 0); - - if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { -@@ -3774,6 +4354,8 @@ - - /* 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) { -@@ -3829,6 +4411,7 @@ - - /* Stop finalize join worker */ - cancel_work_sync(&priv->finalize_join_worker); -+ cancel_work_sync(&priv->watchdog_ba_handle); - if (priv->beacon_skb != NULL) - dev_kfree_skb(priv->beacon_skb); - -@@ -3837,7 +4420,7 @@ - tasklet_disable(&priv->poll_rx_task); - - /* Return all skbs to mac80211 */ -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_reclaim(hw, i, INT_MAX, 1); - } - -@@ -3958,9 +4541,12 @@ - conf->power_level = 18; - - if (priv->ap_fw) { -- rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); -- if (rc) -- goto out; -+ -+ if (conf->flags & IEEE80211_CONF_CHANGE_POWER) { -+ rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level); -+ if (rc) -+ goto out; -+ } - - rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3); - if (rc) -@@ -3987,7 +4573,7 @@ - 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; - -@@ -4312,6 +4898,8 @@ - ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); - if (ret >= 0) { - MWL8K_STA(sta)->peer_id = ret; -+ if (sta->ht_cap.ht_supported) -+ MWL8K_STA(sta)->is_ampdu_allowed = true; - ret = 0; - } - -@@ -4335,14 +4923,14 @@ - - rc = mwl8k_fw_lock(hw); - if (!rc) { -- BUG_ON(queue > MWL8K_TX_QUEUES - 1); -+ BUG_ON(queue > MWL8K_TX_WMM_QUEUES - 1); - memcpy(&priv->wmm_params[queue], params, sizeof(*params)); - - if (!priv->wmm_enabled) - rc = mwl8k_cmd_set_wmm_mode(hw, 1); - - if (!rc) { -- int q = MWL8K_TX_QUEUES - 1 - queue; -+ int q = MWL8K_TX_WMM_QUEUES - 1 - queue; - rc = mwl8k_cmd_set_edca_params(hw, q, - params->cw_min, - params->cw_max, -@@ -4378,21 +4966,118 @@ - return 0; - } - -+#define MAX_AMPDU_ATTEMPTS 5 -+ - static int - mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) - { -+ -+ int i, rc = 0; -+ struct mwl8k_priv *priv = hw->priv; -+ struct mwl8k_ampdu_stream *stream; -+ u8 *addr = sta->addr; -+ -+ if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) -+ return -ENOTSUPP; -+ -+ spin_lock(&priv->stream_lock); -+ stream = mwl8k_lookup_stream(hw, addr, tid); -+ - switch (action) { - case IEEE80211_AMPDU_RX_START: - case IEEE80211_AMPDU_RX_STOP: -- if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) -- return -ENOTSUPP; -- return 0; -+ break; -+ case IEEE80211_AMPDU_TX_START: -+ /* By the time we get here the hw queues may contain outgoing -+ * packets for this RA/TID that are not part of this BA -+ * session. The hw will assign sequence numbers to these -+ * packets as they go out. So if we query the hw for its next -+ * sequence number and use that for the SSN here, it may end up -+ * being wrong, which will lead to sequence number mismatch at -+ * the recipient. To avoid this, we reset the sequence number -+ * to O for the first MPDU in this BA stream. -+ */ -+ *ssn = 0; -+ if (stream == NULL) { -+ /* This means that somebody outside this driver called -+ * ieee80211_start_tx_ba_session. This is unexpected -+ * because we do our own rate control. Just warn and -+ * move on. -+ */ -+ wiphy_warn(hw->wiphy, "Unexpected call to %s. " -+ "Proceeding anyway.\n", __func__); -+ stream = mwl8k_add_stream(hw, sta, tid); -+ } -+ if (stream == NULL) { -+ wiphy_debug(hw->wiphy, "no free AMPDU streams\n"); -+ rc = -EBUSY; -+ break; -+ } -+ stream->state = AMPDU_STREAM_IN_PROGRESS; -+ -+ /* Release the lock before we do the time consuming stuff */ -+ spin_unlock(&priv->stream_lock); -+ for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) { -+ rc = mwl8k_check_ba(hw, stream); -+ -+ if (!rc) -+ break; -+ /* -+ * HW queues take time to be flushed, give them -+ * sufficient time -+ */ -+ -+ msleep(1000); -+ } -+ spin_lock(&priv->stream_lock); -+ if (rc) { -+ wiphy_err(hw->wiphy, "Stream for tid %d busy after %d" -+ " attempts\n", tid, MAX_AMPDU_ATTEMPTS); -+ mwl8k_remove_stream(hw, stream); -+ rc = -EBUSY; -+ break; -+ } -+ ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); -+ break; -+ case IEEE80211_AMPDU_TX_STOP: -+ if (stream == NULL) -+ break; -+ if (stream->state == AMPDU_STREAM_ACTIVE) { -+ spin_unlock(&priv->stream_lock); -+ mwl8k_destroy_ba(hw, stream); -+ spin_lock(&priv->stream_lock); -+ } -+ mwl8k_remove_stream(hw, stream); -+ ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); -+ break; -+ case IEEE80211_AMPDU_TX_OPERATIONAL: -+ BUG_ON(stream == NULL); -+ BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS); -+ spin_unlock(&priv->stream_lock); -+ rc = mwl8k_create_ba(hw, stream, buf_size); -+ spin_lock(&priv->stream_lock); -+ if (!rc) -+ stream->state = AMPDU_STREAM_ACTIVE; -+ else { -+ spin_unlock(&priv->stream_lock); -+ mwl8k_destroy_ba(hw, stream); -+ spin_lock(&priv->stream_lock); -+ wiphy_debug(hw->wiphy, -+ "Failed adding stream for sta %pM tid %d\n", -+ addr, tid); -+ mwl8k_remove_stream(hw, stream); -+ } -+ break; -+ - default: -- return -ENOTSUPP; -+ rc = -ENOTSUPP; - } -+ -+ spin_unlock(&priv->stream_lock); -+ return rc; - } - - static const struct ieee80211_ops mwl8k_ops = { -@@ -4441,7 +5126,7 @@ - MWL8366, - }; - --#define MWL8K_8366_AP_FW_API 1 -+#define MWL8K_8366_AP_FW_API 2 - #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" - #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) - -@@ -4607,6 +5292,23 @@ - return rc; - } - -+static int mwl8k_init_txqs(struct ieee80211_hw *hw) -+{ -+ struct mwl8k_priv *priv = hw->priv; -+ int rc = 0; -+ int i; -+ -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) { -+ rc = mwl8k_txq_init(hw, i); -+ if (rc) -+ break; -+ if (priv->ap_fw) -+ iowrite32(priv->txq[i].txd_dma, -+ priv->sram + priv->txq_offset[i]); -+ } -+ return rc; -+} -+ - /* initialize hw after successfully loading a firmware image */ - static int mwl8k_probe_hw(struct ieee80211_hw *hw) - { -@@ -4634,17 +5336,26 @@ - goto err_stop_firmware; - rxq_refill(hw, 0, INT_MAX); - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) { -- rc = mwl8k_txq_init(hw, i); -+ /* For the sta firmware, we need to know the dma addresses of tx queues -+ * before sending MWL8K_CMD_GET_HW_SPEC. So we must initialize them -+ * prior to issuing this command. But for the AP case, we learn the -+ * total number of queues from the result CMD_GET_HW_SPEC, so for this -+ * case we must initialize the tx queues after. -+ */ -+ priv->num_ampdu_queues = 0; -+ if (!priv->ap_fw) { -+ rc = mwl8k_init_txqs(hw); - if (rc) - goto err_free_queues; - } - - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); -- iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, -+ 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); -@@ -4653,6 +5364,8 @@ - goto err_free_queues; - } - -+ memset(priv->ampdu, 0, sizeof(priv->ampdu)); -+ - /* - * Temporarily enable interrupts. Initial firmware host - * commands use interrupts and avoid polling. Disable -@@ -4664,6 +5377,8 @@ - if (priv->ap_fw) { - rc = mwl8k_cmd_get_hw_spec_ap(hw); - if (!rc) -+ rc = mwl8k_init_txqs(hw); -+ if (!rc) - rc = mwl8k_cmd_set_hw_spec(hw); - } else { - rc = mwl8k_cmd_get_hw_spec_sta(hw); -@@ -4705,7 +5420,7 @@ - free_irq(priv->pdev->irq, hw); - - err_free_queues: -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_deinit(hw, i); - mwl8k_rxq_deinit(hw, 0); - -@@ -4727,7 +5442,7 @@ - mwl8k_stop(hw); - mwl8k_rxq_deinit(hw, 0); - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_deinit(hw, i); - - rc = mwl8k_init_firmware(hw, fw_image, false); -@@ -4746,7 +5461,7 @@ - if (rc) - goto fail; - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) { -+ for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) { - rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]); - if (rc) - goto fail; -@@ -4778,9 +5493,11 @@ - hw->extra_tx_headroom = - sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); - -+ hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0; -+ - hw->channel_change_time = 10; - -- hw->queues = MWL8K_TX_QUEUES; -+ hw->queues = MWL8K_TX_WMM_QUEUES; - - /* Set rssi values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; -@@ -4796,6 +5513,8 @@ - - /* Finalize join worker */ - INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); -+ /* Handle watchdog ba events */ -+ INIT_WORK(&priv->watchdog_ba_handle, mwl8k_watchdog_ba_events); - - /* TX reclaim and RX tasklets. */ - tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); -@@ -4815,6 +5534,8 @@ - - spin_lock_init(&priv->tx_lock); - -+ spin_lock_init(&priv->stream_lock); -+ - priv->tx_wait = NULL; - - rc = mwl8k_probe_hw(hw); -@@ -4836,7 +5557,7 @@ - return 0; - - err_unprobe_hw: -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_deinit(hw, i); - mwl8k_rxq_deinit(hw, 0); - -@@ -4995,10 +5716,10 @@ - mwl8k_hw_reset(priv); - - /* Return all skbs to mac80211 */ -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_reclaim(hw, i, INT_MAX, 1); - -- for (i = 0; i < MWL8K_TX_QUEUES; i++) -+ for (i = 0; i < mwl8k_tx_queues(priv); i++) - mwl8k_txq_deinit(hw, i); - - mwl8k_rxq_deinit(hw, 0); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/p54/eeprom.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/eeprom.c ---- linux-2.6.39-rc6/drivers/net/wireless/p54/eeprom.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/eeprom.c 2011-05-05 23:29:45.614443423 +0200 -@@ -491,7 +491,7 @@ - struct pda_rssi_cal_entry *cal = (void *) &data[offset]; - - for (i = 0; i < entries; i++) { -- u16 freq; -+ u16 freq = 0; - switch (i) { - case IEEE80211_BAND_2GHZ: - freq = 2437; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/p54/fwio.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/fwio.c ---- linux-2.6.39-rc6/drivers/net/wireless/p54/fwio.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/fwio.c 2011-05-05 23:29:45.605443315 +0200 -@@ -727,3 +727,34 @@ - p54_tx(priv, skb); - return 0; - } -+ -+int p54_set_groupfilter(struct p54_common *priv) -+{ -+ struct p54_group_address_table *grp; -+ struct sk_buff *skb; -+ bool on = false; -+ -+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), -+ P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); -+ if (!skb) -+ return -ENOMEM; -+ -+ grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp)); -+ -+ on = !(priv->filter_flags & FIF_ALLMULTI) && -+ (priv->mc_maclist_num > 0 && -+ priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); -+ -+ if (on) { -+ grp->filter_enable = cpu_to_le16(1); -+ grp->num_address = cpu_to_le16(priv->mc_maclist_num); -+ memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); -+ } else { -+ grp->filter_enable = cpu_to_le16(0); -+ grp->num_address = cpu_to_le16(0); -+ memset(grp->mac_list, 0, sizeof(grp->mac_list)); -+ } -+ -+ p54_tx(priv, skb); -+ return 0; -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/p54/lmac.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/lmac.h ---- linux-2.6.39-rc6/drivers/net/wireless/p54/lmac.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/lmac.h 2011-05-05 23:29:45.617443459 +0200 -@@ -540,6 +540,7 @@ - int p54_setup_mac(struct p54_common *priv); - int p54_set_ps(struct p54_common *priv); - int p54_fetch_statistics(struct p54_common *priv); -+int p54_set_groupfilter(struct p54_common *priv); - - /* e/v DCF setup */ - int p54_set_edcf(struct p54_common *priv); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/p54/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/p54/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/main.c 2011-05-05 23:29:45.619443483 +0200 -@@ -308,6 +308,31 @@ - return ret; - } - -+static u64 p54_prepare_multicast(struct ieee80211_hw *dev, -+ struct netdev_hw_addr_list *mc_list) -+{ -+ struct p54_common *priv = dev->priv; -+ struct netdev_hw_addr *ha; -+ int i; -+ -+ BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) != -+ ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list)); -+ /* -+ * The first entry is reserved for the global broadcast MAC. -+ * Otherwise the firmware will drop it and ARP will no longer work. -+ */ -+ i = 1; -+ priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i; -+ netdev_hw_addr_list_for_each(ha, mc_list) { -+ memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN); -+ i++; -+ if (i >= ARRAY_SIZE(priv->mc_maclist)) -+ break; -+ } -+ -+ return 1; /* update */ -+} -+ - static void p54_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, -@@ -316,12 +341,16 @@ - struct p54_common *priv = dev->priv; - - *total_flags &= FIF_PROMISC_IN_BSS | -+ FIF_ALLMULTI | - FIF_OTHER_BSS; - - priv->filter_flags = *total_flags; - - if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) - p54_setup_mac(priv); -+ -+ if (changed_flags & FIF_ALLMULTI || multicast) -+ p54_set_groupfilter(priv); - } - - static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, -@@ -591,6 +620,7 @@ - .config = p54_config, - .flush = p54_flush, - .bss_info_changed = p54_bss_info_changed, -+ .prepare_multicast = p54_prepare_multicast, - .configure_filter = p54_configure_filter, - .conf_tx = p54_conf_tx, - .get_stats = p54_get_stats, -@@ -660,6 +690,7 @@ - init_completion(&priv->beacon_comp); - INIT_DELAYED_WORK(&priv->work, p54_work); - -+ memset(&priv->mc_maclist[0], ~0, ETH_ALEN); - return dev; - } - EXPORT_SYMBOL_GPL(p54_init_common); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/p54/p54.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/p54.h ---- linux-2.6.39-rc6/drivers/net/wireless/p54/p54.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/p54/p54.h 2011-05-05 23:29:45.619443483 +0200 -@@ -211,8 +211,10 @@ - /* BBP/MAC state */ - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; -+ u8 mc_maclist[4][ETH_ALEN]; - u16 wakeup_timer; - unsigned int filter_flags; -+ int mc_maclist_num; - int mode; - u32 tsf_low32, tsf_high32; - u32 basic_rate_mask; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/Kconfig 2011-05-05 23:29:46.104449343 +0200 -@@ -59,7 +59,6 @@ - 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 @@ - 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_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 @@ - 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 @@ - 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 - tristate - --config RT2X00_LIB_HT -- boolean -- - config RT2X00_LIB_FIRMWARE - boolean - select FW_LOADER -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/Makefile 2011-05-05 23:29:46.071448945 +0200 -@@ -7,7 +7,6 @@ - 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 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2400pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2400pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2400pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2400pci.c 2011-05-05 23:29:46.105449355 +0200 -@@ -1314,8 +1314,8 @@ - } - } - --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; - -@@ -1368,8 +1368,10 @@ - static void rt2400pci_rxdone_tasklet(unsigned long data) - { - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; -- rt2x00pci_rxdone(rt2x00dev); -- rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); -+ if (rt2x00pci_rxdone(rt2x00dev)) -+ tasklet_schedule(&rt2x00dev->rxdone_tasklet); -+ else -+ rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); - } - - static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) -@@ -1534,13 +1536,13 @@ - * 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; - } -@@ -1638,9 +1640,9 @@ - /* - * 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. -@@ -1718,6 +1720,9 @@ - .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 = { -@@ -1738,6 +1743,7 @@ - .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, -@@ -1799,10 +1805,11 @@ - * 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."); -@@ -1810,10 +1817,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2500pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2500pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2500pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2500pci.c 2011-05-05 23:29:46.070448933 +0200 -@@ -1446,8 +1446,8 @@ - } - } - --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; - -@@ -1500,8 +1500,10 @@ - static void rt2500pci_rxdone_tasklet(unsigned long data) - { - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; -- rt2x00pci_rxdone(rt2x00dev); -- rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); -+ if (rt2x00pci_rxdone(rt2x00dev)) -+ tasklet_schedule(&rt2x00dev->rxdone_tasklet); -+ else -+ rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); - } - - static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) -@@ -1685,14 +1687,14 @@ - * 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. -@@ -1956,9 +1958,9 @@ - /* - * 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. -@@ -2011,6 +2013,9 @@ - .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 = { -@@ -2031,6 +2036,7 @@ - .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, -@@ -2092,7 +2098,7 @@ - * 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, } - }; - -@@ -2103,10 +2109,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2500usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2500usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2500usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2500usb.c 2011-05-05 23:29:46.087449138 +0200 -@@ -1519,7 +1519,7 @@ - * 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,14 +1790,14 @@ - /* - * 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_SUPPORT_WATCHDOG, &rt2x00dev->flags); -- __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); -+ __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); -+ __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); - - /* - * Set the rssi offset. -@@ -1824,6 +1824,9 @@ - .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 = { -@@ -1905,58 +1908,54 @@ - */ - 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, 0x705a), 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) }, -- /* CNet */ -- { USB_DEVICE(0x1371, 0x9022), 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, 0x2573), 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, } - }; - -@@ -1967,10 +1966,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800.h 2011-05-05 23:29:46.082449077 +0200 -@@ -2104,6 +2104,59 @@ - #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) - - /* -+ * EEPROM temperature compensation boundaries 802.11BG -+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -4) -+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -3) -+ */ -+#define EEPROM_TSSI_BOUND_BG1 0x0037 -+#define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11BG -+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -2) -+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -1) -+ */ -+#define EEPROM_TSSI_BOUND_BG2 0x0038 -+#define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11BG -+ * REF: Reference TSSI value, no tx power changes needed -+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 1) -+ */ -+#define EEPROM_TSSI_BOUND_BG3 0x0039 -+#define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11BG -+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 2) -+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 3) -+ */ -+#define EEPROM_TSSI_BOUND_BG4 0x003a -+#define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11BG -+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 4) -+ * AGC_STEP: Temperature compensation step. -+ */ -+#define EEPROM_TSSI_BOUND_BG5 0x003b -+#define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00) -+ -+/* - * EEPROM TXPOWER 802.11A - */ - #define EEPROM_TXPOWER_A1 0x003c -@@ -2113,6 +2166,59 @@ - #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) - - /* -+ * EEPROM temperature compensation boundaries 802.11A -+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -4) -+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -3) -+ */ -+#define EEPROM_TSSI_BOUND_A1 0x006a -+#define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11A -+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -2) -+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be -+ * reduced by (agc_step * -1) -+ */ -+#define EEPROM_TSSI_BOUND_A2 0x006b -+#define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11A -+ * REF: Reference TSSI value, no tx power changes needed -+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 1) -+ */ -+#define EEPROM_TSSI_BOUND_A3 0x006c -+#define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11A -+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 2) -+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 3) -+ */ -+#define EEPROM_TSSI_BOUND_A4 0x006d -+#define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00) -+ -+/* -+ * EEPROM temperature compensation boundaries 802.11A -+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be -+ * increased by (agc_step * 4) -+ * AGC_STEP: Temperature compensation step. -+ */ -+#define EEPROM_TSSI_BOUND_A5 0x006e -+#define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff) -+#define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00) -+ -+/* - * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode - */ - #define EEPROM_TXPOWER_BYRATE 0x006f -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800lib.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800lib.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800lib.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800lib.c 2011-05-05 23:29:46.076449005 +0200 -@@ -687,6 +687,9 @@ - mcs = real_mcs; - } - -+ if (aggr == 1 || ampdu == 1) -+ __set_bit(TXDONE_AMPDU, &txdesc.flags); -+ - /* - * Ralink has a retry mechanism using a global fallback - * table. We setup this fallback table to try the immediate -@@ -727,34 +730,20 @@ - 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, ®); -- if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) -- break; -+ while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { - -- /* -- * 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 -@@ -946,25 +935,49 @@ - unsigned int ledmode = - rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, - EEPROM_FREQ_LED_MODE); -+ u32 reg; -+ -+ /* Check for SoC (SOC devices don't support MCU requests) */ -+ if (rt2x00_is_soc(led->rt2x00dev)) { -+ rt2800_register_read(led->rt2x00dev, LED_CFG, ®); -+ -+ /* Set LED Polarity */ -+ rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); -+ -+ /* Set LED Mode */ -+ if (led->type == LED_TYPE_RADIO) { -+ rt2x00_set_field32(®, LED_CFG_G_LED_MODE, -+ enabled ? 3 : 0); -+ } else if (led->type == LED_TYPE_ASSOC) { -+ rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, -+ enabled ? 3 : 0); -+ } else if (led->type == LED_TYPE_QUALITY) { -+ rt2x00_set_field32(®, LED_CFG_R_LED_MODE, -+ enabled ? 3 : 0); -+ } -+ -+ rt2800_register_write(led->rt2x00dev, LED_CFG, 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); -+ } 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); -+ } - } - } - -@@ -1218,6 +1231,25 @@ - rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, 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, ®); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); -+ rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); -+ } else { -+ rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); -+ rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); -+ rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); -+ } - } - - if (flags & CONFIG_UPDATE_MAC) { -@@ -1608,7 +1640,6 @@ - struct channel_info *info) - { - u8 rfcsr; -- u16 eeprom; - - rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); - rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); -@@ -1638,11 +1669,10 @@ - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); - rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); - -- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - if (rf->channel <= 14) { - int idx = rf->channel-1; - -- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) { -+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { - /* r55/r59 value array of channel 1~14 */ - static const char r55_bt_rev[] = {0x83, 0x83, -@@ -1736,8 +1766,8 @@ - - 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 { -@@ -1748,7 +1778,7 @@ - } 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); -@@ -1813,17 +1843,131 @@ - rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); - } - -+static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) -+{ -+ u8 tssi_bounds[9]; -+ u8 current_tssi; -+ u16 eeprom; -+ u8 step; -+ int i; -+ -+ /* -+ * Read TSSI boundaries for temperature compensation from -+ * the EEPROM. -+ * -+ * Array idx 0 1 2 3 4 5 6 7 8 -+ * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4 -+ * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 -+ */ -+ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); -+ tssi_bounds[0] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG1_MINUS4); -+ tssi_bounds[1] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG1_MINUS3); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); -+ tssi_bounds[2] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG2_MINUS2); -+ tssi_bounds[3] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG2_MINUS1); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); -+ tssi_bounds[4] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG3_REF); -+ tssi_bounds[5] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG3_PLUS1); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); -+ tssi_bounds[6] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG4_PLUS2); -+ tssi_bounds[7] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG4_PLUS3); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); -+ tssi_bounds[8] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG5_PLUS4); -+ -+ step = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_BG5_AGC_STEP); -+ } else { -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); -+ tssi_bounds[0] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A1_MINUS4); -+ tssi_bounds[1] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A1_MINUS3); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); -+ tssi_bounds[2] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A2_MINUS2); -+ tssi_bounds[3] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A2_MINUS1); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); -+ tssi_bounds[4] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A3_REF); -+ tssi_bounds[5] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A3_PLUS1); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); -+ tssi_bounds[6] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A4_PLUS2); -+ tssi_bounds[7] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A4_PLUS3); -+ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); -+ tssi_bounds[8] = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A5_PLUS4); -+ -+ step = rt2x00_get_field16(eeprom, -+ EEPROM_TSSI_BOUND_A5_AGC_STEP); -+ } -+ -+ /* -+ * Check if temperature compensation is supported. -+ */ -+ if (tssi_bounds[4] == 0xff) -+ return 0; -+ -+ /* -+ * Read current TSSI (BBP 49). -+ */ -+ rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); -+ -+ /* -+ * Compare TSSI value (BBP49) with the compensation boundaries -+ * from the EEPROM and increase or decrease tx power. -+ */ -+ for (i = 0; i <= 3; i++) { -+ if (current_tssi > tssi_bounds[i]) -+ break; -+ } -+ -+ if (i == 4) { -+ for (i = 8; i >= 5; i--) { -+ if (current_tssi < tssi_bounds[i]) -+ break; -+ } -+ } -+ -+ return (i - 4) * step; -+} -+ - static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, - enum ieee80211_band band) - { - u16 eeprom; - u8 comp_en; - u8 comp_type; -- int comp_value; -+ int comp_value = 0; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); - -- if (eeprom == 0xffff) -+ /* -+ * HT40 compensation not required. -+ */ -+ if (eeprom == 0xffff || -+ !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) - return 0; - - if (band == IEEE80211_BAND_2GHZ) { -@@ -1853,11 +1997,9 @@ - return comp_value; - } - --static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev, -- int is_rate_b, -- enum ieee80211_band band, -- int power_level, -- u8 txpower) -+static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, -+ enum ieee80211_band band, int power_level, -+ u8 txpower, int delta) - { - u32 reg; - u16 eeprom; -@@ -1865,15 +2007,11 @@ - u8 eirp_txpower; - u8 eirp_txpower_criterion; - u8 reg_limit; -- int bw_comp = 0; - - if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) - return txpower; - -- if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) -- bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band); -- -- 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 -@@ -1895,18 +2033,19 @@ - EEPROM_EIRP_MAX_TX_POWER_5GHZ); - - eirp_txpower = eirp_txpower_criterion + (txpower - criterion) + -- (is_rate_b ? 4 : 0) + bw_comp; -+ (is_rate_b ? 4 : 0) + delta; - - reg_limit = (eirp_txpower > power_level) ? - (eirp_txpower - power_level) : 0; - } else - reg_limit = 0; - -- return txpower + bw_comp - reg_limit; -+ return txpower + delta - reg_limit; - } - - static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, -- struct ieee80211_conf *conf) -+ enum ieee80211_band band, -+ int power_level) - { - u8 txpower; - u16 eeprom; -@@ -1914,8 +2053,17 @@ - u32 reg; - u8 r1; - u32 offset; -- enum ieee80211_band band = conf->channel->band; -- int power_level = conf->power_level; -+ int delta; -+ -+ /* -+ * Calculate HT40 compensation delta -+ */ -+ delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); -+ -+ /* -+ * calculate temperature compensation delta -+ */ -+ delta += rt2800_get_gain_calibration_delta(rt2x00dev); - - /* - * set to normal bbp tx power control mode: +/- 0dBm -@@ -1944,8 +2092,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE0); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); - - /* -@@ -1955,8 +2103,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE1); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); - - /* -@@ -1966,8 +2114,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE2); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); - - /* -@@ -1977,8 +2125,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE3); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); - - /* read the next four txpower values */ -@@ -1993,8 +2141,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE0); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); - - /* -@@ -2004,8 +2152,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE1); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); - - /* -@@ -2015,8 +2163,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE2); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); - - /* -@@ -2026,8 +2174,8 @@ - */ - txpower = rt2x00_get_field16(eeprom, - EEPROM_TXPOWER_BYRATE_RATE3); -- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band, -- power_level, txpower); -+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, -+ power_level, txpower, delta); - rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower); - - rt2800_register_write(rt2x00dev, offset, reg); -@@ -2037,6 +2185,13 @@ - } - } - -+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) -+{ -+ rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, -+ rt2x00dev->tx_power); -+} -+EXPORT_SYMBOL_GPL(rt2800_gain_calibration); -+ - static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) - { -@@ -2090,10 +2245,12 @@ - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { - rt2800_config_channel(rt2x00dev, libconf->conf, - &libconf->rf, &libconf->channel); -- rt2800_config_txpower(rt2x00dev, libconf->conf); -+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, -+ libconf->conf->power_level); - } - if (flags & IEEE80211_CONF_CHANGE_POWER) -- rt2800_config_txpower(rt2x00dev, libconf->conf); -+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, -+ libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt2800_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) -@@ -2254,7 +2411,7 @@ - } 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); -@@ -2758,8 +2915,7 @@ - ant = (div_mode == 3) ? 1 : 0; - - /* check if this is a Bluetooth combo card */ -- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); -- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) { -+ if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { - u32 reg; - - rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); -@@ -3155,8 +3311,8 @@ - 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); -@@ -3568,26 +3724,30 @@ - } - - /* -- * Read frequency offset and RF programming sequence. -+ * Determine external LNA informations. - */ -- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); -- rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); -- -- /* -- * Read external LNA informations. -- */ -- 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); -+ -+ /* -+ * Detect if this device has Bluetooth co-existence. -+ */ -+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) -+ __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); -+ -+ /* -+ * Read frequency offset and RF programming sequence. -+ */ -+ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); -+ rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); - - /* - * Store led settings, for correct led behaviour. -@@ -3597,7 +3757,7 @@ - rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); - -- rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); -+ rt2x00dev->led_mcu_reg = eeprom; - #endif /* CONFIG_RT2X00_LIB_LEDS */ - - /* -@@ -3607,7 +3767,7 @@ - - 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; - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800lib.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800lib.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800lib.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800lib.h 2011-05-05 23:29:46.059448799 +0200 -@@ -181,6 +181,7 @@ - void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); - void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, - const u32 count); -+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); - - int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); - void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800pci.c 2011-05-05 23:29:46.103449331 +0200 -@@ -66,7 +66,7 @@ - return; - - for (i = 0; i < 200; i++) { -- rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); -+ rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); - - if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || - (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || -@@ -80,8 +80,8 @@ - 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 @@ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg; - -- rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); -+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); - - 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 @@ - rt2x00_set_field32(®, 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 @@ - struct eeprom_93cx6 eeprom; - u32 reg; - -- rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); -+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); - - eeprom.data = rt2x00dev; - eeprom.register_read = rt2800pci_eepromregister_read; -@@ -195,9 +195,9 @@ - - switch (queue->qid) { - case QID_RX: -- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, 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 @@ - tasklet_enable(&rt2x00dev->tbtt_tasklet); - tasklet_enable(&rt2x00dev->pretbtt_tasklet); - -- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); -+ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, 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, ®); -+ rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); - rt2x00_set_field32(®, 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 @@ - 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 @@ - - switch (queue->qid) { - case QID_RX: -- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, 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, ®); -+ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); - rt2x00_set_field32(®, 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, ®); -+ rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®); - rt2x00_set_field32(®, 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,19 +297,19 @@ - */ - reg = 0; - rt2x00_set_field32(®, 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. - */ -- rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, -- data, len); -+ rt2x00pci_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 @@ - * 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 @@ - * 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, ®); -+ rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2x00_set_field32(®, 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 @@ - * should clear the register to assure a clean state. - */ - if (state == STATE_RADIO_IRQ_ON) { -- rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -- rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); -+ rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -+ rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - - /* - * Enable tasklets. The beacon related tasklets are -@@ -440,7 +448,7 @@ - } - - spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); -- rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); -+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); - rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); - rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); - rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); -@@ -459,7 +467,7 @@ - rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); - rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); - rt2x00_set_field32(®, 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 @@ - /* - * Reset DMA indexes - */ -- rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); -+ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); -@@ -488,26 +496,26 @@ - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); - rt2x00_set_field32(®, 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, ®); -+ rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); - rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); - rt2x00_set_field32(®, 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, ®); -+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); - rt2x00_set_field32(®, 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 @@ - { - 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 @@ - 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); - } - -@@ -717,12 +727,13 @@ - rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); - } - --static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) -+static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) - { - struct data_queue *queue; - struct queue_entry *entry; - u32 status; - u8 qid; -+ int max_tx_done = 16; - - while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { - qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); -@@ -759,11 +770,16 @@ - - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - rt2800_txdone_entry(entry, status); -+ -+ if (--max_tx_done == 0) -+ break; - } -+ -+ 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; - -@@ -772,15 +788,17 @@ - * access needs locking. - */ - spin_lock_irq(&rt2x00dev->irqmask_lock); -- rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); -+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); - rt2x00_set_field32(®, 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); - } - - static void rt2800pci_txstatus_tasklet(unsigned long data) - { -- rt2800pci_txdone((struct rt2x00_dev *)data); -+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; -+ if (rt2800pci_txdone(rt2x00dev)) -+ tasklet_schedule(&rt2x00dev->txstatus_tasklet); - - /* - * No need to enable the tx status interrupt here as we always -@@ -806,8 +824,10 @@ - static void rt2800pci_rxdone_tasklet(unsigned long data) - { - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; -- rt2x00pci_rxdone(rt2x00dev); -- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); -+ if (rt2x00pci_rxdone(rt2x00dev)) -+ tasklet_schedule(&rt2x00dev->rxdone_tasklet); -+ else -+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); - } - - static void rt2800pci_autowake_tasklet(unsigned long data) -@@ -841,7 +861,7 @@ - * 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; -@@ -863,8 +883,8 @@ - u32 reg, mask; - - /* Read status and ACK all interrupts */ -- rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -- rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); -+ rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -+ rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - - if (!reg) - return IRQ_NONE; -@@ -904,9 +924,9 @@ - * the tasklet will reenable the appropriate interrupts. - */ - spin_lock(&rt2x00dev->irqmask_lock); -- rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); -+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); - 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; -@@ -956,28 +976,28 @@ - * 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. -@@ -1008,6 +1028,7 @@ - .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 = { -@@ -1043,9 +1064,11 @@ - .link_stats = rt2800_link_stats, - .reset_tuner = rt2800_reset_tuner, - .link_tuner = rt2800_link_tuner, -+ .gain_calibration = rt2800_gain_calibration, - .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, -@@ -1105,36 +1128,36 @@ - */ - #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, } - }; -@@ -1170,10 +1193,16 @@ - #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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2800usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2800usb.c 2011-05-05 23:29:46.077449017 +0200 -@@ -59,16 +59,16 @@ - - switch (queue->qid) { - case QID_RX: -- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, 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, ®); -+ rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, 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,16 +82,16 @@ - - switch (queue->qid) { - case QID_RX: -- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, 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, ®); -+ rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); - rt2x00_set_field32(®, 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; -@@ -99,6 +99,63 @@ - } - - /* -+ * 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 bool 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 false; -+ } -+ -+ /* 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 -+ return true; -+ } 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(2)); -+ } -+ -+ return false; -+} -+ -+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 - */ - static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) -@@ -129,11 +186,11 @@ - /* - * 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 +205,7 @@ - } - - msleep(10); -- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); -+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - - return 0; - } -@@ -166,22 +223,22 @@ - if (rt2800_wait_csr_ready(rt2x00dev)) - return -EBUSY; - -- rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); -- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); -+ rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); -+ 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, ®); -+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); - rt2x00_set_field32(®, 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 +250,7 @@ - if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev))) - return -EIO; - -- rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); -+ rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); - rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); -@@ -206,7 +263,7 @@ - / 1024) - 3); - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); - rt2x00_set_field32(®, 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 +339,12 @@ - unsigned int i; - u32 reg; - -- rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); -+ rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); - 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 +352,15 @@ - break; - } - -- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); -+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); - } - -- rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); -+ rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®); - 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 +368,7 @@ - break; - } - -- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); -+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); - } - - rt2x00usb_watchdog(rt2x00dev); -@@ -420,13 +477,24 @@ - 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(2)); - } - - /* -@@ -553,19 +621,24 @@ - * 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_SUPPORT_WATCHDOG, &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); -+ __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); -+ -+ setup_timer(&rt2x00dev->txstatus_timer, -+ rt2800usb_tx_sta_fifo_timeout, -+ (unsigned long) rt2x00dev); - - /* - * Set the rssi offset. -@@ -602,6 +675,7 @@ - .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 = { -@@ -630,11 +704,13 @@ - .link_stats = rt2800_link_stats, - .reset_tuner = rt2800_reset_tuner, - .link_tuner = rt2800_link_tuner, -+ .gain_calibration = rt2800_gain_calibration, - .watchdog = rt2800usb_watchdog, - .start_queue = rt2800usb_start_queue, - .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,294 +771,332 @@ - */ - 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, 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, } - }; -@@ -995,10 +1109,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00config.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00config.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00config.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00config.c 2011-05-05 23:29:46.061448823 +0200 -@@ -100,6 +100,10 @@ - erp.basic_rates = bss_conf->basic_rates; - erp.beacon_int = bss_conf->beacon_int; - -+ /* Update the AID, this is needed for dynamic PS support */ -+ rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0; -+ rt2x00dev->last_beacon = bss_conf->timestamp; -+ - /* Update global beacon interval time, this is needed for PS support */ - rt2x00dev->beacon_int = bss_conf->beacon_int; - -@@ -109,15 +113,6 @@ - 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 +121,35 @@ - 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. -- */ -- if (!(ant->flags & ANTENNA_RX_DIVERSITY)) -- config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); -- else if (config.rx == ANTENNA_SW_DIVERSITY) -+ * 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)) { -+ 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,12 +174,43 @@ - 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) - { - struct rt2x00lib_conf libconf; - u16 hw_value; -+ u16 autowake_timeout; -+ u16 beacon_int; -+ u16 beacon_diff; - - memset(&libconf, 0, sizeof(libconf)); - -@@ -176,10 +218,10 @@ - - 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; - } - -@@ -192,6 +234,10 @@ - sizeof(libconf.channel)); - } - -+ if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && -+ (ieee80211_flags & IEEE80211_CONF_CHANGE_PS)) -+ cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); -+ - /* - * Start configuration. - */ -@@ -204,6 +250,26 @@ - if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2x00link_reset_tuner(rt2x00dev, false); - -+ if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && -+ (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && -+ (conf->flags & IEEE80211_CONF_PS)) { -+ beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; -+ beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int); -+ -+ if (beacon_diff > beacon_int) -+ beacon_diff = 0; -+ -+ autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; -+ queue_delayed_work(rt2x00dev->workqueue, -+ &rt2x00dev->autowakeup_work, -+ autowake_timeout - 15); -+ } -+ -+ if (conf->flags & IEEE80211_CONF_PS) -+ set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); -+ else -+ clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); -+ - rt2x00dev->curr_band = conf->channel->band; - rt2x00dev->curr_freq = conf->channel->center_freq; - rt2x00dev->tx_power = conf->power_level; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00crypto.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00crypto.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00crypto.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00crypto.c 2011-05-05 23:29:46.088449151 +0200 -@@ -52,7 +52,7 @@ - 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 @@ - 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; - - /* -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00debug.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00debug.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00debug.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00debug.c 2011-05-05 23:29:46.105449355 +0200 -@@ -63,7 +63,8 @@ - * - 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 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 @@ - .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, -@@ -568,7 +599,6 @@ - blob->data = data; - data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); - data += sprintf(data, "version:\t%s\n", DRV_VERSION); -- data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__); - blob->size = strlen(blob->data); - - return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); -@@ -653,6 +683,12 @@ - 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) -@@ -706,7 +742,7 @@ - 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); -@@ -744,6 +780,7 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00dev.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00dev.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00dev.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00dev.c 2011-05-05 23:29:46.084449101 +0200 -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include "rt2x00.h" - #include "rt2x00lib.h" -@@ -70,6 +71,7 @@ - */ - rt2x00queue_start_queues(rt2x00dev); - rt2x00link_start_tuner(rt2x00dev); -+ rt2x00link_start_agc(rt2x00dev); - - /* - * Start watchdog monitoring. -@@ -92,6 +94,7 @@ - /* - * Stop all queues - */ -+ rt2x00link_stop_agc(rt2x00dev); - rt2x00link_stop_tuner(rt2x00dev); - rt2x00queue_stop_queues(rt2x00dev); - rt2x00queue_flush_queues(rt2x00dev, true); -@@ -138,6 +141,16 @@ - rt2x00dev); - } - -+static void rt2x00lib_autowakeup(struct work_struct *work) -+{ -+ struct rt2x00_dev *rt2x00dev = -+ container_of(work, struct rt2x00_dev, autowakeup_work.work); -+ -+ if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) -+ ERROR(rt2x00dev, "Device failed to wakeup.\n"); -+ clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); -+} -+ - /* - * Interrupt context handlers. - */ -@@ -197,7 +210,7 @@ - * 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 */ -@@ -222,7 +235,7 @@ - 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); - -@@ -230,7 +243,7 @@ - { - 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); - -@@ -268,7 +281,7 @@ - /* - * 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); - - /* -@@ -277,7 +290,7 @@ - * 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); - - /* -@@ -350,10 +363,14 @@ - * which would allow the rc algorithm to better decide on - * which rates are suitable. - */ -- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { -+ if (test_bit(TXDONE_AMPDU, &txdesc->flags) || -+ tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - tx_info->status.ampdu_len = 1; - tx_info->status.ampdu_ack_len = success ? 1 : 0; -+ -+ if (!success) -+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - } - - if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { -@@ -370,7 +387,7 @@ - * 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); -@@ -385,7 +402,7 @@ - - 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 -@@ -409,6 +426,77 @@ - } - EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); - -+static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie) -+{ -+ struct ieee80211_mgmt *mgmt = (void *)data; -+ u8 *pos, *end; -+ -+ pos = (u8 *)mgmt->u.beacon.variable; -+ end = data + len; -+ while (pos < end) { -+ if (pos + 2 + pos[1] > end) -+ return NULL; -+ -+ if (pos[0] == ie) -+ return pos; -+ -+ pos += 2 + pos[1]; -+ } -+ -+ return NULL; -+} -+ -+static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, -+ struct sk_buff *skb, -+ struct rxdone_entry_desc *rxdesc) -+{ -+ struct ieee80211_hdr *hdr = (void *) skb->data; -+ struct ieee80211_tim_ie *tim_ie; -+ u8 *tim; -+ u8 tim_len; -+ bool cam; -+ -+ /* If this is not a beacon, or if mac80211 has no powersaving -+ * configured, or if the device is already in powersaving mode -+ * we can exit now. */ -+ if (likely(!ieee80211_is_beacon(hdr->frame_control) || -+ !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS))) -+ return; -+ -+ /* min. beacon length + FCS_LEN */ -+ if (skb->len <= 40 + FCS_LEN) -+ return; -+ -+ /* and only beacons from the associated BSSID, please */ -+ if (!(rxdesc->dev_flags & RXDONE_MY_BSS) || -+ !rt2x00dev->aid) -+ return; -+ -+ rt2x00dev->last_beacon = jiffies; -+ -+ tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM); -+ if (!tim) -+ return; -+ -+ if (tim[1] < sizeof(*tim_ie)) -+ return; -+ -+ tim_len = tim[1]; -+ tim_ie = (struct ieee80211_tim_ie *) &tim[2]; -+ -+ /* Check whenever the PHY can be turned off again. */ -+ -+ /* 1. What about buffered unicast traffic for our AID? */ -+ cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid); -+ -+ /* 2. Maybe the AP wants to send multicast/broadcast data? */ -+ cam |= (tim_ie->bitmap_ctrl & 0x01); -+ -+ if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) -+ rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, -+ IEEE80211_CONF_CHANGE_PS); -+} -+ - static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, - struct rxdone_entry_desc *rxdesc) - { -@@ -511,8 +599,6 @@ - (rxdesc.size > header_length) && - (rxdesc.dev_flags & RXDONE_L2PAD)) - rt2x00queue_remove_l2pad(entry->skb, header_length); -- else -- rt2x00queue_align_payload(entry->skb, header_length); - - /* Trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); -@@ -526,6 +612,12 @@ - rxdesc.flags |= RX_FLAG_HT; - - /* -+ * Check if this is a beacon, and more frames have been -+ * buffered while we were in powersaving mode. -+ */ -+ rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); -+ -+ /* - * Update extra components - */ - rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); -@@ -554,7 +646,7 @@ - - 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); -@@ -801,23 +893,28 @@ - /* - * 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 txstatus fifo and tasklet, we use a size of 512 -- * for the kfifo which is big enough to store 512/4=128 tx -- * status reports. In the worst case (tx status for all tx -- * queues gets reported before we've got a chance to handle -- * them) 24*4=384 tx status reports need to be cached. -+ * Allocate the txstatus fifo. In the worst case the tx -+ * status fifo has to hold the tx status of all entries -+ * in all tx queues. Hence, calculate the kfifo size as -+ * tx_queues * entry_num and round up to the nearest -+ * power of 2. - */ -- status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512, -+ int kfifo_size = -+ roundup_pow_of_two(rt2x00dev->ops->tx_queues * -+ rt2x00dev->ops->tx->entry_num * -+ sizeof(u32)); -+ -+ status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size, - GFP_KERNEL); - if (status) - return status; -@@ -1007,6 +1104,7 @@ - } - - INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); -+ INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); - - /* - * Let the driver probe the device to detect the capabilities. -@@ -1061,6 +1159,7 @@ - /* - * 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00firmware.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00firmware.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00firmware.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00firmware.c 2011-05-05 23:29:46.042448595 +0200 -@@ -99,7 +99,7 @@ - { - int retval; - -- if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) -+ if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags)) - return 0; - - if (!rt2x00dev->fw) { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00.h 2011-05-05 23:29:46.060448811 +0200 -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - -@@ -348,6 +349,11 @@ - * to bring the device/driver back into the desired state. - */ - struct delayed_work watchdog_work; -+ -+ /* -+ * Work structure for scheduling periodic AGC adjustments. -+ */ -+ struct delayed_work agc_work; - }; - - enum rt2x00_delayed_flags { -@@ -556,6 +562,7 @@ - struct link_qual *qual); - void (*link_tuner) (struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count); -+ void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); - - /* - * Data queue handlers. -@@ -564,7 +571,8 @@ - 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 -@@ -637,11 +645,11 @@ - }; - - /* -- * 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, -@@ -651,40 +659,47 @@ - DEVICE_STATE_SCANNING, - - /* -- * Driver requirements -+ * Driver configuration - */ -- 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_SUPPORT_WATCHDOG, -+ CONFIG_CHANNEL_HT40, -+ CONFIG_POWERSAVING, -+}; - -+/* -+ * rt2x00 capability flags -+ */ -+enum rt2x00_capability_flags { - /* -- * Driver configuration -+ * Requirements - */ -- CONFIG_FRAME_TYPE, -- CONFIG_RF_SEQUENCE, -- CONFIG_EXTERNAL_LNA_A, -- CONFIG_EXTERNAL_LNA_BG, -- CONFIG_DOUBLE_ANTENNA, -- CONFIG_CHANNEL_HT40, -+ 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, -+ REQUIRE_PS_AUTOWAKE, -+ -+ /* -+ * 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, -+ CAPABILITY_BT_COEXIST, - }; - - /* -@@ -733,13 +748,20 @@ - #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) - */ - int irq; -@@ -855,10 +877,20 @@ - u8 calibration[2]; - - /* -+ * Association id. -+ */ -+ u16 aid; -+ -+ /* - * Beacon interval. - */ - u16 beacon_int; - -+ /** -+ * Timestamp of last received beacon -+ */ -+ unsigned long last_beacon; -+ - /* - * Low level statistics which will have - * to be kept up to date while device is running. -@@ -887,6 +919,11 @@ - struct work_struct txdone_work; - - /* -+ * Powersaving work -+ */ -+ struct delayed_work autowakeup_work; -+ -+ /* - * Data queue arrays for RX, TX, Beacon and ATIM. - */ - unsigned int data_queues; -@@ -906,6 +943,11 @@ - 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). - */ - struct tasklet_struct txstatus_tasklet; -@@ -1230,6 +1272,10 @@ - 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. -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00ht.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00ht.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00ht.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00ht.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,133 +0,0 @@ --/* -- Copyright (C) 2004 - 2009 Ivo van Doorn -- -- -- 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 --#include -- --#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? */ -- -- txdesc->u.ht.stbc = -- (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; -- -- /* -- * 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; --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00lib.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00lib.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00lib.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00lib.h 2011-05-05 23:29:46.080449053 +0200 -@@ -32,6 +32,7 @@ - */ - #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) - #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) -+#define AGC_INTERVAL round_jiffies_relative(4 * HZ) - - /* - * rt2x00_rate: Per rate device information -@@ -119,16 +120,6 @@ - void rt2x00queue_align_frame(struct sk_buff *skb); - - /** -- * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary -- * @skb: The skb to align -- * @header_length: Length of 802.11 header -- * -- * Align the 802.11 payload to a 4-byte boundary, this could -- * mean the header is not aligned properly though. -- */ --void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length); -- --/** - * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary - * @skb: The skb to align - * @header_length: Length of 802.11 header -@@ -184,14 +175,14 @@ - - /** - * 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 -@@ -281,6 +272,18 @@ - void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); - - /** -+ * rt2x00link_start_agc - Start periodic gain calibration -+ * @rt2x00dev: Pointer to &struct rt2x00_dev. -+ */ -+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); -+ -+/** -+ * rt2x00link_stop_agc - Stop periodic gain calibration -+ * @rt2x00dev: Pointer to &struct rt2x00_dev. -+ */ -+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); -+ -+/** - * rt2x00link_register - Initialize link tuning & watchdog functionality - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * -@@ -385,41 +388,17 @@ - #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); - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00link.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00link.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00link.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00link.c 2011-05-05 23:29:46.067448897 +0200 -@@ -192,17 +192,7 @@ - /* - * 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 @@ - * 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); - - /* -@@ -413,12 +403,11 @@ - { - struct link *link = &rt2x00dev->link; - -- if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || -- !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) -- return; -- -- ieee80211_queue_delayed_work(rt2x00dev->hw, -- &link->watchdog_work, WATCHDOG_INTERVAL); -+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && -+ rt2x00dev->ops->lib->watchdog) -+ ieee80211_queue_delayed_work(rt2x00dev->hw, -+ &link->watchdog_work, -+ WATCHDOG_INTERVAL); - } - - void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) -@@ -447,8 +436,46 @@ - WATCHDOG_INTERVAL); - } - -+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) -+{ -+ struct link *link = &rt2x00dev->link; -+ -+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && -+ rt2x00dev->ops->lib->gain_calibration) -+ ieee80211_queue_delayed_work(rt2x00dev->hw, -+ &link->agc_work, -+ AGC_INTERVAL); -+} -+ -+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) -+{ -+ cancel_delayed_work_sync(&rt2x00dev->link.agc_work); -+} -+ -+static void rt2x00link_agc(struct work_struct *work) -+{ -+ struct rt2x00_dev *rt2x00dev = -+ container_of(work, struct rt2x00_dev, link.agc_work.work); -+ struct link *link = &rt2x00dev->link; -+ -+ /* -+ * When the radio is shutting down we should -+ * immediately cease the watchdog monitoring. -+ */ -+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) -+ return; -+ -+ rt2x00dev->ops->lib->gain_calibration(rt2x00dev); -+ -+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) -+ ieee80211_queue_delayed_work(rt2x00dev->hw, -+ &link->agc_work, -+ AGC_INTERVAL); -+} -+ - void rt2x00link_register(struct rt2x00_dev *rt2x00dev) - { -+ INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); - INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); - INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00mac.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00mac.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00mac.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00mac.c 2011-05-05 23:29:46.038448546 +0200 -@@ -119,7 +119,7 @@ - * 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 @@ - 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 @@ - * 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 @@ - - 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 @@ - 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 @@ - 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 @@ - 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00pci.c 2011-05-05 23:29:46.023448365 +0200 -@@ -60,14 +60,15 @@ - } - EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); - --void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) -+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) - { - struct data_queue *queue = rt2x00dev->rx; - struct queue_entry *entry; - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; -+ int max_rx = 16; - -- while (1) { -+ while (--max_rx) { - entry = rt2x00queue_get_entry(queue, Q_INDEX); - entry_priv = entry->priv_data; - -@@ -93,9 +94,20 @@ - */ - rt2x00lib_rxdone(entry); - } -+ -+ return !max_rx; - } - 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. - */ -@@ -239,9 +251,8 @@ - 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; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00pci.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00pci.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00pci.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00pci.h 2011-05-05 23:29:46.072448957 +0200 -@@ -101,8 +101,21 @@ - /** - * rt2x00pci_rxdone - Handle RX done events - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. -+ * -+ * Returns true if there are still rx frames pending and false if all -+ * pending rx frames were processed. - */ --void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); -+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. -@@ -113,7 +126,7 @@ - /* - * 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00queue.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00queue.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-05-05 23:29:46.088449151 +0200 -@@ -60,7 +60,7 @@ - * 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 @@ - 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, -@@ -148,19 +148,6 @@ - skb_trim(skb, frame_length); - } - --void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) --{ -- unsigned int frame_length = skb->len; -- unsigned int align = ALIGN_SIZE(skb, header_length); -- -- if (!align) -- return; -- -- skb_push(skb, align); -- memmove(skb->data, skb->data + align, frame_length); -- skb_trim(skb, frame_length); --} -- - void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) - { - unsigned int payload_length = skb->len - header_length; -@@ -226,7 +213,7 @@ - - __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; - - /* -@@ -315,6 +302,85 @@ - } - } - -+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) - { -@@ -409,8 +475,8 @@ - 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); - } -@@ -449,7 +515,7 @@ - /* - * 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; -@@ -495,8 +561,11 @@ - struct skb_frame_desc *skbdesc; - u8 rate_idx, rate_flags; - -- if (unlikely(rt2x00queue_full(queue))) -+ if (unlikely(rt2x00queue_full(queue))) { -+ ERROR(queue->rt2x00dev, -+ "Dropping frame due to full tx queue %d.\n", queue->qid); - return -ENOBUFS; -+ } - - if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, - &entry->flags))) { -@@ -539,7 +608,7 @@ - */ - 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); -@@ -553,9 +622,9 @@ - * 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); - - /* -@@ -571,7 +640,7 @@ - - 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); - -@@ -660,10 +729,12 @@ - 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; -@@ -674,7 +745,7 @@ - ERROR(queue->rt2x00dev, - "Entry requested from invalid index range (%d - %d)\n", - start, end); -- return; -+ return true; - } - - /* -@@ -693,15 +764,23 @@ - * 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); - -@@ -727,8 +806,9 @@ - } - 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)) { -@@ -743,7 +823,7 @@ - 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++; -@@ -848,7 +928,6 @@ - - void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) - { -- unsigned int i; - bool started; - bool tx_queue = - (queue->qid == QID_AC_VO) || -@@ -883,20 +962,12 @@ - } - - /* -- * 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). -- */ -- 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. -+ * 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. - */ -- 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... -@@ -969,10 +1040,8 @@ - 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); - } -@@ -1079,7 +1148,7 @@ - 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) -@@ -1131,7 +1200,7 @@ - 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: -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00queue.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00queue.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00queue.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00queue.h 2011-05-05 23:29:46.104449343 +0200 -@@ -217,6 +217,7 @@ - TXDONE_FALLBACK, - TXDONE_FAILURE, - TXDONE_EXCESSIVE_RETRY, -+ TXDONE_AMPDU, - }; - - /** -@@ -363,6 +364,7 @@ - * 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). -@@ -372,6 +374,7 @@ - */ - struct queue_entry { - unsigned long flags; -+ unsigned long last_action; - - struct data_queue *queue; - -@@ -462,7 +465,6 @@ - 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; -@@ -579,16 +581,22 @@ - * @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. -@@ -628,22 +636,24 @@ - - /** - * 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. -+ * rt2x00queuedma__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)); - } - - /** -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00usb.c 2011-05-05 23:29:46.078449029 +0200 -@@ -165,6 +165,59 @@ - } - EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); - -+ -+struct rt2x00_async_read_data { -+ __le32 reg; -+ struct usb_ctrlrequest cr; -+ struct rt2x00_dev *rt2x00dev; -+ bool (*callback)(struct rt2x00_dev *, int, u32); -+}; -+ -+static void rt2x00usb_register_read_async_cb(struct urb *urb) -+{ -+ struct rt2x00_async_read_data *rd = urb->context; -+ if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) { -+ if (usb_submit_urb(urb, GFP_ATOMIC) < 0) -+ kfree(rd); -+ } else -+ kfree(rd); -+} -+ -+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, -+ const unsigned int offset, -+ bool (*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 +265,9 @@ - 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 +283,12 @@ - * 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 +298,7 @@ - - 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 +319,8 @@ - set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); - rt2x00lib_dmadone(entry); - } -+ -+ return false; - } - - /* -@@ -323,7 +383,7 @@ - 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 +392,7 @@ - - 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 +408,8 @@ - set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); - rt2x00lib_dmadone(entry); - } -+ -+ return false; - } - - void rt2x00usb_kick_queue(struct data_queue *queue) -@@ -358,12 +420,18 @@ - 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 +440,14 @@ - } - 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 +455,20 @@ - * 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 +487,7 @@ - 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 +527,31 @@ - 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 +576,7 @@ - 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 +670,7 @@ - * 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 +705,7 @@ - * 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 +794,9 @@ - } - - 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 +821,7 @@ - - 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) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt2x00usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt2x00usb.h 2011-05-05 23:29:46.088449151 +0200 -@@ -35,12 +35,6 @@ - }) - - /* -- * 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, - * however when loading firmware a higher value is -@@ -345,6 +339,23 @@ - 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(). -+ * When the callback function returns false, the memory will be cleaned up, -+ * when it returns true, the urb will be fired again. -+ */ -+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, -+ const unsigned int offset, -+ bool (*callback)(struct rt2x00_dev*, int, u32)); -+ - /* - * Radio handlers - */ -@@ -389,11 +400,13 @@ - /** - * 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 +429,7 @@ - * 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); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt61pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt61pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt61pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt61pci.c 2011-05-05 23:29:46.086449125 +0200 -@@ -683,7 +683,7 @@ - - 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 @@ - - 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 @@ - 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 @@ - 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 @@ - 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 @@ - 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; - -@@ -2313,8 +2313,10 @@ - static void rt61pci_rxdone_tasklet(unsigned long data) - { - struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; -- rt2x00pci_rxdone(rt2x00dev); -- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); -+ if (rt2x00pci_rxdone(rt2x00dev)) -+ rt2x00pci_rxdone(rt2x00dev); -+ else -+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); - } - - static void rt61pci_autowake_tasklet(unsigned long data) -@@ -2535,7 +2537,7 @@ - * 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. -@@ -2549,20 +2551,20 @@ - * 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); - -@@ -2572,9 +2574,9 @@ - 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, -@@ -2582,7 +2584,7 @@ - * 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 = -@@ -2797,7 +2799,7 @@ - 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 { -@@ -2867,16 +2869,16 @@ - * 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. -@@ -2977,6 +2979,9 @@ - .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 = { -@@ -3001,6 +3006,7 @@ - .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, -@@ -3058,11 +3064,11 @@ - */ - 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, } - }; - -@@ -3077,10 +3083,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt73usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt73usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/rt2x00/rt73usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rt2x00/rt73usb.c 2011-05-05 23:29:46.029448437 +0200 -@@ -595,7 +595,7 @@ - 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 @@ - - 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 @@ - - 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 @@ - 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 @@ - 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 @@ - 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 @@ - } - - 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 @@ - * 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 @@ - 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,16 +2200,16 @@ - * 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(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); -+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); -+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); -+ __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); - - /* - * Set the rssi offset. -@@ -2311,6 +2311,9 @@ - .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 = { -@@ -2389,114 +2392,113 @@ - */ - 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, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, -- { 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, } - }; - -@@ -2508,10 +2510,16 @@ - 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, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/base.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/base.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/base.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/base.c 2011-05-05 23:29:49.236487185 +0200 -@@ -50,8 +50,9 @@ - *3) functions called by core.c - *4) wq & timer callback functions - *5) frame process functions -- *6) sysfs functions -- *7) ... -+ *6) IOT functions -+ *7) sysfs functions -+ *8) ... - */ - - /********************************************************* -@@ -59,7 +60,7 @@ - * mac80211 init functions - * - *********************************************************/ --static struct ieee80211_channel rtl_channeltable[] = { -+static struct ieee80211_channel rtl_channeltable_2g[] = { - {.center_freq = 2412, .hw_value = 1,}, - {.center_freq = 2417, .hw_value = 2,}, - {.center_freq = 2422, .hw_value = 3,}, -@@ -76,7 +77,34 @@ - {.center_freq = 2484, .hw_value = 14,}, - }; - --static struct ieee80211_rate rtl_ratetable[] = { -+static struct ieee80211_channel rtl_channeltable_5g[] = { -+ {.center_freq = 5180, .hw_value = 36,}, -+ {.center_freq = 5200, .hw_value = 40,}, -+ {.center_freq = 5220, .hw_value = 44,}, -+ {.center_freq = 5240, .hw_value = 48,}, -+ {.center_freq = 5260, .hw_value = 52,}, -+ {.center_freq = 5280, .hw_value = 56,}, -+ {.center_freq = 5300, .hw_value = 60,}, -+ {.center_freq = 5320, .hw_value = 64,}, -+ {.center_freq = 5500, .hw_value = 100,}, -+ {.center_freq = 5520, .hw_value = 104,}, -+ {.center_freq = 5540, .hw_value = 108,}, -+ {.center_freq = 5560, .hw_value = 112,}, -+ {.center_freq = 5580, .hw_value = 116,}, -+ {.center_freq = 5600, .hw_value = 120,}, -+ {.center_freq = 5620, .hw_value = 124,}, -+ {.center_freq = 5640, .hw_value = 128,}, -+ {.center_freq = 5660, .hw_value = 132,}, -+ {.center_freq = 5680, .hw_value = 136,}, -+ {.center_freq = 5700, .hw_value = 140,}, -+ {.center_freq = 5745, .hw_value = 149,}, -+ {.center_freq = 5765, .hw_value = 153,}, -+ {.center_freq = 5785, .hw_value = 157,}, -+ {.center_freq = 5805, .hw_value = 161,}, -+ {.center_freq = 5825, .hw_value = 165,}, -+}; -+ -+static struct ieee80211_rate rtl_ratetable_2g[] = { - {.bitrate = 10, .hw_value = 0x00,}, - {.bitrate = 20, .hw_value = 0x01,}, - {.bitrate = 55, .hw_value = 0x02,}, -@@ -91,18 +119,57 @@ - {.bitrate = 540, .hw_value = 0x0b,}, - }; - -+static struct ieee80211_rate rtl_ratetable_5g[] = { -+ {.bitrate = 60, .hw_value = 0x04,}, -+ {.bitrate = 90, .hw_value = 0x05,}, -+ {.bitrate = 120, .hw_value = 0x06,}, -+ {.bitrate = 180, .hw_value = 0x07,}, -+ {.bitrate = 240, .hw_value = 0x08,}, -+ {.bitrate = 360, .hw_value = 0x09,}, -+ {.bitrate = 480, .hw_value = 0x0a,}, -+ {.bitrate = 540, .hw_value = 0x0b,}, -+}; -+ - static const struct ieee80211_supported_band rtl_band_2ghz = { - .band = IEEE80211_BAND_2GHZ, - -- .channels = rtl_channeltable, -- .n_channels = ARRAY_SIZE(rtl_channeltable), -+ .channels = rtl_channeltable_2g, -+ .n_channels = ARRAY_SIZE(rtl_channeltable_2g), - -- .bitrates = rtl_ratetable, -- .n_bitrates = ARRAY_SIZE(rtl_ratetable), -+ .bitrates = rtl_ratetable_2g, -+ .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), - - .ht_cap = {0}, - }; - -+static struct ieee80211_supported_band rtl_band_5ghz = { -+ .band = IEEE80211_BAND_5GHZ, -+ -+ .channels = rtl_channeltable_5g, -+ .n_channels = ARRAY_SIZE(rtl_channeltable_5g), -+ -+ .bitrates = rtl_ratetable_5g, -+ .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), -+ -+ .ht_cap = {0}, -+}; -+ -+static const u8 tid_to_ac[] = { -+ 2, /* IEEE80211_AC_BE */ -+ 3, /* IEEE80211_AC_BK */ -+ 3, /* IEEE80211_AC_BK */ -+ 2, /* IEEE80211_AC_BE */ -+ 1, /* IEEE80211_AC_VI */ -+ 1, /* IEEE80211_AC_VI */ -+ 0, /* IEEE80211_AC_VO */ -+ 0, /* IEEE80211_AC_VO */ -+}; -+ -+u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid) -+{ -+ return tid_to_ac[tid]; -+} -+ - static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, - struct ieee80211_sta_ht_cap *ht_cap) - { -@@ -115,6 +182,9 @@ - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; - -+ if (rtlpriv->rtlhal.disable_amsdu_8k) -+ ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; -+ - /* - *Maximum length of AMPDU that the STA can receive. - *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) -@@ -159,37 +229,99 @@ - - static void _rtl_init_mac80211(struct ieee80211_hw *hw) - { -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_supported_band *sband; - -- /* <1> use mac->bands as mem for hw->wiphy->bands */ -- sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - -- /* -- * <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] -- * to default value(1T1R) -- */ -- memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, -- sizeof(struct ieee80211_supported_band)); -+ if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && rtlhal->bandset == -+ BAND_ON_BOTH) { -+ /* 1: 2.4 G bands */ -+ /* <1> use mac->bands as mem for hw->wiphy->bands */ -+ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); -+ -+ /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] -+ * to default value(1T1R) */ -+ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, -+ sizeof(struct ieee80211_supported_band)); -+ -+ /* <3> init ht cap base on ant_num */ -+ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); -+ -+ /* <4> set mac->sband to wiphy->sband */ -+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; -+ -+ /* 2: 5 G bands */ -+ /* <1> use mac->bands as mem for hw->wiphy->bands */ -+ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); -+ -+ /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] -+ * to default value(1T1R) */ -+ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, -+ sizeof(struct ieee80211_supported_band)); - -- /* <3> init ht cap base on ant_num */ -- _rtl_init_hw_ht_capab(hw, &sband->ht_cap); -+ /* <3> init ht cap base on ant_num */ -+ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - -- /* <4> set mac->sband to wiphy->sband */ -- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; -+ /* <4> set mac->sband to wiphy->sband */ -+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; -+ } else { -+ if (rtlhal->current_bandtype == BAND_ON_2_4G) { -+ /* <1> use mac->bands as mem for hw->wiphy->bands */ -+ sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); -+ -+ /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] -+ * to default value(1T1R) */ -+ memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), -+ &rtl_band_2ghz, -+ sizeof(struct ieee80211_supported_band)); -+ -+ /* <3> init ht cap base on ant_num */ -+ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); -+ -+ /* <4> set mac->sband to wiphy->sband */ -+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; -+ } else if (rtlhal->current_bandtype == BAND_ON_5G) { -+ /* <1> use mac->bands as mem for hw->wiphy->bands */ -+ sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); -+ -+ /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] -+ * to default value(1T1R) */ -+ memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), -+ &rtl_band_5ghz, -+ sizeof(struct ieee80211_supported_band)); - -+ /* <3> init ht cap base on ant_num */ -+ _rtl_init_hw_ht_capab(hw, &sband->ht_cap); -+ -+ /* <4> set mac->sband to wiphy->sband */ -+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; -+ } else { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("Err BAND %d\n", -+ rtlhal->current_bandtype)); -+ } -+ } - /* <5> set hw caps */ - hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_RX_INCLUDES_FCS | -- IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/ -- /*IEEE80211_HW_SUPPORTS_PS | */ -- /*IEEE80211_HW_PS_NULLFUNC_STACK | */ -- /*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ -+ IEEE80211_HW_BEACON_FILTER | -+ IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; - -+ /* swlps or hwlps has been set in diff chip in init_sw_vars */ -+ if (rtlpriv->psc.swctrl_lps) -+ hw->flags |= IEEE80211_HW_SUPPORTS_PS | -+ IEEE80211_HW_PS_NULLFUNC_STACK | -+ /* IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */ -+ 0; -+ - hw->wiphy->interface_modes = -- BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); -+ BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_STATION) | -+ BIT(NL80211_IFTYPE_ADHOC); - - hw->wiphy->rts_threshold = 2347; - -@@ -199,9 +331,10 @@ - /* TODO: Correct this value for our hw */ - /* TODO: define these hard code value */ - hw->channel_change_time = 100; -- hw->max_listen_interval = 5; -+ hw->max_listen_interval = 10; - hw->max_rate_tries = 4; - /* hw->max_rates = 1; */ -+ hw->sta_data_size = sizeof(struct rtl_sta_info); - - /* <6> mac address */ - if (is_valid_ether_addr(rtlefuse->dev_addr)) { -@@ -230,6 +363,10 @@ - (void *)rtl_watchdog_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, - (void *)rtl_ips_nic_off_wq_callback); -+ INIT_DELAYED_WORK(&rtlpriv->works.ps_work, -+ (void *)rtl_swlps_wq_callback); -+ INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, -+ (void *)rtl_swlps_rfon_wq_callback); - - } - -@@ -241,6 +378,8 @@ - - cancel_delayed_work(&rtlpriv->works.watchdog_wq); - cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); -+ cancel_delayed_work(&rtlpriv->works.ps_work); -+ cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); - } - - void rtl_init_rfkill(struct ieee80211_hw *hw) -@@ -251,14 +390,16 @@ - 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; -@@ -308,6 +449,8 @@ - spin_lock_init(&rtlpriv->locks.rf_ps_lock); - spin_lock_init(&rtlpriv->locks.rf_lock); - spin_lock_init(&rtlpriv->locks.lps_lock); -+ spin_lock_init(&rtlpriv->locks.waitq_lock); -+ spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); - - rtlmac->link_state = MAC80211_NOLINK; - -@@ -327,12 +470,6 @@ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); -- rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER, -- (u8 *) (&mac->rx_mgt_filter)); -- rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER, -- (u8 *) (&mac->rx_ctrl_filter)); -- rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER, -- (u8 *) (&mac->rx_data_filter)); - } - - /********************************************************* -@@ -359,28 +496,40 @@ - } - - static void _rtl_query_shortgi(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc, - struct ieee80211_tx_info *info) - { - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 rate_flag = info->control.rates[0].flags; -- -+ u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; - tcb_desc->use_shortgi = false; - -- if (!mac->ht_enable) -+ if (sta == NULL) -+ return; -+ -+ sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; -+ sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; -+ -+ if (!(sta->ht_cap.ht_supported)) - return; - -- if (!mac->sgi_40 && !mac->sgi_20) -+ if (!sgi_40 && !sgi_20) - return; - -- if ((mac->bw_40 == true) && mac->sgi_40) -+ if (mac->opmode == NL80211_IFTYPE_STATION) -+ bw_40 = mac->bw_40; -+ else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) -+ bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ -+ if ((bw_40 == true) && sgi_40) - tcb_desc->use_shortgi = true; -- else if ((mac->bw_40 == false) && mac->sgi_20) -+ else if ((bw_40 == false) && sgi_20) - tcb_desc->use_shortgi = true; - - if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) - tcb_desc->use_shortgi = false; -- - } - - static void _rtl_query_protection_mode(struct ieee80211_hw *hw, -@@ -408,19 +557,25 @@ - tcb_desc->rts_enable = true; - tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; - } -- - } - - static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry = NULL; -+ u8 ratr_index = 7; - -+ if (sta) { -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ ratr_index = sta_entry->ratr_index; -+ } - if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { -- if (mac->opmode == NL80211_IFTYPE_STATION) -+ if (mac->opmode == NL80211_IFTYPE_STATION) { - tcb_desc->ratr_index = 0; -- else if (mac->opmode == NL80211_IFTYPE_ADHOC) { -+ } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { - if (tcb_desc->multicast || tcb_desc->broadcast) { - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; -@@ -428,36 +583,61 @@ - } else { - /* TODO */ - } -+ tcb_desc->ratr_index = ratr_index; -+ } else if (mac->opmode == NL80211_IFTYPE_AP) { -+ tcb_desc->ratr_index = ratr_index; - } - } - - if (rtlpriv->dm.useramask) { - /* TODO we will differentiate adhoc and station futrue */ -- tcb_desc->mac_id = 0; -+ if (mac->opmode == NL80211_IFTYPE_STATION) { -+ tcb_desc->mac_id = 0; - -- if ((mac->mode == WIRELESS_MODE_N_24G) || -- (mac->mode == WIRELESS_MODE_N_5G)) { -- tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; -- } else if (mac->mode & WIRELESS_MODE_G) { -- tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; -- } else if (mac->mode & WIRELESS_MODE_B) { -- tcb_desc->ratr_index = RATR_INX_WIRELESS_B; -+ if (mac->mode == WIRELESS_MODE_N_24G) -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; -+ else if (mac->mode == WIRELESS_MODE_N_5G) -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; -+ else if (mac->mode & WIRELESS_MODE_G) -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; -+ else if (mac->mode & WIRELESS_MODE_B) -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_B; -+ else if (mac->mode & WIRELESS_MODE_A) -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_G; -+ } else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (NULL != sta) { -+ if (sta->aid > 0) -+ tcb_desc->mac_id = sta->aid + 1; -+ else -+ tcb_desc->mac_id = 1; -+ } else { -+ tcb_desc->mac_id = 0; -+ } - } - } - - } - - static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - tcb_desc->packet_bw = false; -- -- if (!mac->bw_40 || !mac->ht_enable) -+ if (!sta) - return; -- -+ if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (!(sta->ht_cap.ht_supported) || -+ !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ return; -+ } else if (mac->opmode == NL80211_IFTYPE_STATION) { -+ if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) -+ return; -+ } - if (tcb_desc->multicast || tcb_desc->broadcast) - return; - -@@ -484,22 +664,21 @@ - - void rtl_get_tcb_desc(struct ieee80211_hw *hw, - struct ieee80211_tx_info *info, -+ struct ieee80211_sta *sta, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); -+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - struct ieee80211_rate *txrate; - __le16 fc = hdr->frame_control; - -- memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc)); -+ txrate = ieee80211_get_tx_rate(hw, info); -+ tcb_desc->hw_rate = txrate->hw_value; - - if (ieee80211_is_data(fc)) { -- txrate = ieee80211_get_tx_rate(hw, info); -- tcb_desc->hw_rate = txrate->hw_value; -- - /* -- *we set data rate RTL_RC_CCK_RATE1M -+ *we set data rate INX 0 - *in rtl_rc.c if skb is special data or - *mgt which need low data rate. - */ -@@ -508,12 +687,11 @@ - *So tcb_desc->hw_rate is just used for - *special data and mgt frames - */ -- if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) { -+ if (info->control.rates[0].idx == 0 && -+ ieee80211_is_nullfunc(fc)) { - tcb_desc->use_driver_rate = true; -- tcb_desc->ratr_index = 7; -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - -- tcb_desc->hw_rate = -- rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; - tcb_desc->disable_ratefallback = 1; - } else { - /* -@@ -523,7 +701,7 @@ - *and N rate will all be controlled by FW - *when tcb_desc->use_driver_rate = false - */ -- if (rtlmac->ht_enable) { -+ if (sta && (sta->ht_cap.ht_supported)) { - tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw); - } else { - if (rtlmac->mode == WIRELESS_MODE_B) { -@@ -541,43 +719,25 @@ - else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) - tcb_desc->broadcast = 1; - -- _rtl_txrate_selectmode(hw, tcb_desc); -- _rtl_query_bandwidth_mode(hw, tcb_desc); -+ _rtl_txrate_selectmode(hw, sta, tcb_desc); -+ _rtl_query_bandwidth_mode(hw, sta, tcb_desc); - _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); -- _rtl_query_shortgi(hw, tcb_desc, info); -+ _rtl_query_shortgi(hw, sta, tcb_desc, info); - _rtl_query_protection_mode(hw, tcb_desc, info); - } else { - tcb_desc->use_driver_rate = true; -- tcb_desc->ratr_index = 7; -+ tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - tcb_desc->disable_ratefallback = 1; - tcb_desc->mac_id = 0; -- -- tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; -+ tcb_desc->packet_bw = false; - } - } - EXPORT_SYMBOL(rtl_get_tcb_desc); - --bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) --{ -- struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); -- __le16 fc = hdr->frame_control; -- -- if (ieee80211_is_auth(fc)) { -- RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); -- rtl_ips_nic_on(hw); -- -- mac->link_state = MAC80211_LINKING; -- } -- -- return true; --} -- - bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) - { - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); -+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - struct rtl_priv *rtlpriv = rtl_priv(hw); - __le16 fc = hdr->frame_control; - u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN)); -@@ -622,22 +782,20 @@ - u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -- __le16 fc = hdr->frame_control; -+ __le16 fc = rtl_get_fc(skb); - u16 ether_type; - u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); - const struct iphdr *ip; - - if (!ieee80211_is_data(fc)) -- goto end; -+ return false; - -- if (ieee80211_is_nullfunc(fc)) -- return true; - - ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + - SNAP_SIZE + PROTOC_TYPE_SIZE); - ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); -+ /* ether_type = ntohs(ether_type); */ - - if (ETH_P_IP == ether_type) { - if (IPPROTO_UDP == ip->protocol) { -@@ -686,7 +844,6 @@ - return true; - } - --end: - return false; - } - -@@ -695,61 +852,92 @@ - * functions called by core.c - * - *********************************************************/ --int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn) -+int rtl_tx_agg_start(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u16 tid, u16 *ssn) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tid_data *tid_data; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry = NULL; - -- RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, -- ("on ra = %pM tid = %d\n", ra, tid)); -+ if (sta == NULL) -+ return -EINVAL; - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - -- if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -- ("Start AGG when state is not RTL_AGG_OFF !\n")); -+ sta_entry = (struct rtl_sta_info *)sta->drv_priv; -+ if (!sta_entry) - return -ENXIO; -- } -- -- tid_data = &mac->tids[tid]; -- *ssn = SEQ_TO_SN(tid_data->seq_number); -+ tid_data = &sta_entry->tids[tid]; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, -- ("HW queue is empty tid:%d\n", tid)); -- tid_data->agg.agg_state = RTL_AGG_ON; -+ ("on ra = %pM tid = %d seq:%d\n", sta->addr, tid, -+ tid_data->seq_number)); -+ -+ *ssn = tid_data->seq_number; -+ tid_data->agg.agg_state = RTL_AGG_START; - -- ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid); -+ ieee80211_start_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); - - return 0; - } - --int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid) -+int rtl_tx_agg_stop(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u16 tid) - { -- int ssn = -1; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_tid_data *tid_data; -+ struct rtl_sta_info *sta_entry = NULL; - -- if (!ra) { -+ if (sta == NULL) -+ return -EINVAL; -+ -+ if (!sta->addr) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); - return -EINVAL; - } - -+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, -+ ("on ra = %pM tid = %d\n", sta->addr, tid)); -+ - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - -- if (mac->tids[tid].agg.agg_state != RTL_AGG_ON) -- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -- ("Stopping AGG while state not ON or starting\n")); -+ sta_entry = (struct rtl_sta_info *)sta->drv_priv; -+ tid_data = &sta_entry->tids[tid]; -+ sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; - -- tid_data = &mac->tids[tid]; -- ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; -+ ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); - -- mac->tids[tid].agg.agg_state = RTL_AGG_OFF; -+ return 0; -+} - -- ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid); -+int rtl_tx_agg_oper(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u16 tid) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_tid_data *tid_data; -+ struct rtl_sta_info *sta_entry = NULL; -+ -+ if (sta == NULL) -+ return -EINVAL; -+ -+ if (!sta->addr) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n")); -+ return -EINVAL; -+ } -+ -+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, -+ ("on ra = %pM tid = %d\n", sta->addr, tid)); -+ -+ if (unlikely(tid >= MAX_TID_COUNT)) -+ return -EINVAL; -+ -+ sta_entry = (struct rtl_sta_info *)sta->drv_priv; -+ tid_data = &sta_entry->tids[tid]; -+ sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; - - return 0; - } -@@ -768,18 +956,16 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- - bool busytraffic = false; - bool higher_busytraffic = false; - bool higher_busyrxtraffic = false; -- bool higher_busytxtraffic = false; -- -- u8 idx = 0; -+ u8 idx, tid; - u32 rx_cnt_inp4eriod = 0; - u32 tx_cnt_inp4eriod = 0; - u32 aver_rx_cnt_inperiod = 0; - u32 aver_tx_cnt_inperiod = 0; -- -+ u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; -+ u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; - bool enter_ps = false; - - if (is_hal_stop(rtlhal)) -@@ -793,9 +979,6 @@ - mac->cnt_after_linked = 0; - } - -- /* <2> DM */ -- rtlpriv->cfg->ops->dm_watchdog(hw); -- - /* - *<3> to check if traffic busy, if - * busytraffic we don't change channel -@@ -834,8 +1017,27 @@ - /* Extremely high Rx data. */ - if (aver_rx_cnt_inperiod > 5000) - higher_busyrxtraffic = true; -+ } -+ -+ /* check every tid's tx traffic */ -+ for (tid = 0; tid <= 7; tid++) { -+ for (idx = 0; idx <= 2; idx++) -+ rtlpriv->link_info.tidtx_in4period[tid][idx] = -+ rtlpriv->link_info.tidtx_in4period[tid] -+ [idx + 1]; -+ rtlpriv->link_info.tidtx_in4period[tid][3] = -+ rtlpriv->link_info.tidtx_inperiod[tid]; -+ -+ for (idx = 0; idx <= 3; idx++) -+ tidtx_inp4eriod[tid] += -+ rtlpriv->link_info.tidtx_in4period[tid][idx]; -+ aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; -+ if (aver_tidtx_inperiod[tid] > 5000) -+ rtlpriv->link_info.higher_busytxtraffic[tid] = -+ true; - else -- higher_busytxtraffic = false; -+ rtlpriv->link_info.higher_busytxtraffic[tid] = -+ false; - } - - if (((rtlpriv->link_info.num_rx_inperiod + -@@ -854,11 +1056,15 @@ - - rtlpriv->link_info.num_rx_inperiod = 0; - rtlpriv->link_info.num_tx_inperiod = 0; -+ for (tid = 0; tid <= 7; tid++) -+ rtlpriv->link_info.tidtx_inperiod[tid] = 0; - - rtlpriv->link_info.busytraffic = busytraffic; - rtlpriv->link_info.higher_busytraffic = higher_busytraffic; - rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; - -+ /* <3> DM */ -+ rtlpriv->cfg->ops->dm_watchdog(hw); - } - - void rtl_watch_dog_timer_callback(unsigned long data) -@@ -875,6 +1081,268 @@ - - /********************************************************* - * -+ * frame process functions -+ * -+ *********************************************************/ -+u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) -+{ -+ struct ieee80211_mgmt *mgmt = (void *)data; -+ u8 *pos, *end; -+ -+ pos = (u8 *)mgmt->u.beacon.variable; -+ end = data + len; -+ while (pos < end) { -+ if (pos + 2 + pos[1] > end) -+ return NULL; -+ -+ if (pos[0] == ie) -+ return pos; -+ -+ pos += 2 + pos[1]; -+ } -+ return NULL; -+} -+ -+/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ -+/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ -+static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, -+ enum ieee80211_smps_mode smps, u8 *da, u8 *bssid) -+{ -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct sk_buff *skb; -+ struct ieee80211_mgmt *action_frame; -+ -+ /* 27 = header + category + action + smps mode */ -+ skb = dev_alloc_skb(27 + hw->extra_tx_headroom); -+ if (!skb) -+ return NULL; -+ -+ skb_reserve(skb, hw->extra_tx_headroom); -+ action_frame = (void *)skb_put(skb, 27); -+ memset(action_frame, 0, 27); -+ memcpy(action_frame->da, da, ETH_ALEN); -+ memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); -+ memcpy(action_frame->bssid, bssid, ETH_ALEN); -+ action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -+ IEEE80211_STYPE_ACTION); -+ action_frame->u.action.category = WLAN_CATEGORY_HT; -+ action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; -+ switch (smps) { -+ case IEEE80211_SMPS_AUTOMATIC:/* 0 */ -+ case IEEE80211_SMPS_NUM_MODES:/* 4 */ -+ WARN_ON(1); -+ case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ -+ action_frame->u.action.u.ht_smps.smps_control = -+ WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ -+ break; -+ case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ -+ action_frame->u.action.u.ht_smps.smps_control = -+ WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ -+ break; -+ case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ -+ action_frame->u.action.u.ht_smps.smps_control = -+ WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ -+ break; -+ } -+ -+ return skb; -+} -+ -+int rtl_send_smps_action(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 *da, u8 *bssid, -+ enum ieee80211_smps_mode smps) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); -+ struct rtl_tcb_desc tcb_desc; -+ memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); -+ -+ if (rtlpriv->mac80211.act_scanning) -+ goto err_free; -+ -+ if (!sta) -+ goto err_free; -+ -+ if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) -+ goto err_free; -+ -+ if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) -+ goto err_free; -+ -+ /* this is a type = mgmt * stype = action frame */ -+ if (skb) { -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct rtl_sta_info *sta_entry = -+ (struct rtl_sta_info *) sta->drv_priv; -+ sta_entry->mimo_ps = smps; -+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); -+ -+ info->control.rates[0].idx = 0; -+ info->control.sta = sta; -+ info->band = hw->conf.channel->band; -+ rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); -+ } -+err_free: -+ return 0; -+} -+ -+/********************************************************* -+ * -+ * IOT functions -+ * -+ *********************************************************/ -+static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, -+ struct octet_string vendor_ie) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ bool matched = false; -+ static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; -+ static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; -+ static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; -+ static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; -+ static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; -+ static u8 racap[] = { 0x00, 0x0c, 0x43 }; -+ static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; -+ static u8 marvcap[] = { 0x00, 0x50, 0x43 }; -+ -+ if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || -+ memcmp(vendor_ie.octet, athcap_2, 3) == 0) { -+ rtlpriv->mac80211.vendor = PEER_ATH; -+ matched = true; -+ } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || -+ memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || -+ memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { -+ rtlpriv->mac80211.vendor = PEER_BROAD; -+ matched = true; -+ } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { -+ rtlpriv->mac80211.vendor = PEER_RAL; -+ matched = true; -+ } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { -+ rtlpriv->mac80211.vendor = PEER_CISCO; -+ matched = true; -+ } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { -+ rtlpriv->mac80211.vendor = PEER_MARV; -+ matched = true; -+ } -+ -+ return matched; -+} -+ -+static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, -+ unsigned int len) -+{ -+ struct ieee80211_mgmt *mgmt = (void *)data; -+ struct octet_string vendor_ie; -+ u8 *pos, *end; -+ -+ pos = (u8 *)mgmt->u.beacon.variable; -+ end = data + len; -+ while (pos < end) { -+ if (pos[0] == 221) { -+ vendor_ie.length = pos[1]; -+ vendor_ie.octet = &pos[2]; -+ if (rtl_chk_vendor_ouisub(hw, vendor_ie)) -+ return true; -+ } -+ -+ if (pos + 2 + pos[1] > end) -+ return false; -+ -+ pos += 2 + pos[1]; -+ } -+ return false; -+} -+ -+void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct ieee80211_hdr *hdr = (void *)data; -+ u32 vendor = PEER_UNKNOWN; -+ -+ static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; -+ static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; -+ static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; -+ static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; -+ static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; -+ static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; -+ static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; -+ static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; -+ static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; -+ static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; -+ static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; -+ static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; -+ static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; -+ static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; -+ static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; -+ static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; -+ -+ if (mac->opmode != NL80211_IFTYPE_STATION) -+ return; -+ -+ if (mac->link_state == MAC80211_NOLINK) { -+ mac->vendor = PEER_UNKNOWN; -+ return; -+ } -+ -+ if (mac->cnt_after_linked > 2) -+ return; -+ -+ /* check if this really is a beacon */ -+ if (!ieee80211_is_beacon(hdr->frame_control)) -+ return; -+ -+ /* min. beacon length + FCS_LEN */ -+ if (len <= 40 + FCS_LEN) -+ return; -+ -+ /* and only beacons from the associated BSSID, please */ -+ if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) -+ return; -+ -+ if (rtl_find_221_ie(hw, data, len)) -+ vendor = mac->vendor; -+ -+ if ((memcmp(mac->bssid, ap5_1, 3) == 0) || -+ (memcmp(mac->bssid, ap5_2, 3) == 0) || -+ (memcmp(mac->bssid, ap5_3, 3) == 0) || -+ (memcmp(mac->bssid, ap5_4, 3) == 0) || -+ (memcmp(mac->bssid, ap5_5, 3) == 0) || -+ (memcmp(mac->bssid, ap5_6, 3) == 0) || -+ vendor == PEER_ATH) { -+ vendor = PEER_ATH; -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ath find\n")); -+ } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || -+ (memcmp(mac->bssid, ap4_5, 3) == 0) || -+ (memcmp(mac->bssid, ap4_1, 3) == 0) || -+ (memcmp(mac->bssid, ap4_2, 3) == 0) || -+ (memcmp(mac->bssid, ap4_3, 3) == 0) || -+ vendor == PEER_RAL) { -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>ral findn\n")); -+ vendor = PEER_RAL; -+ } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || -+ vendor == PEER_CISCO) { -+ vendor = PEER_CISCO; -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>cisco find\n")); -+ } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || -+ (memcmp(mac->bssid, ap3_2, 3) == 0) || -+ (memcmp(mac->bssid, ap3_3, 3) == 0) || -+ vendor == PEER_BROAD) { -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>broad find\n")); -+ vendor = PEER_BROAD; -+ } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || -+ vendor == PEER_MARV) { -+ vendor = PEER_MARV; -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("=>marv find\n")); -+ } -+ -+ mac->vendor = vendor; -+} -+ -+/********************************************************* -+ * - * sysfs functions - * - *********************************************************/ -@@ -940,12 +1408,13 @@ - if (rtl_rate_control_register()) - printk(KERN_ERR "rtlwifi: Unable to register rtl_rc," - "use default RC !!\n"); -+ - return 0; - } - - static void __exit rtl_core_module_exit(void) - { -- /*RC*/ -+ /*RC*/ - rtl_rate_control_unregister(); - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/base.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/base.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/base.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/base.h 2011-05-05 23:29:49.231487125 +0200 -@@ -24,13 +24,26 @@ - * Hsinchu 300, Taiwan. - * - * Larry Finger -+ * - *****************************************************************************/ - - #ifndef __RTL_BASE_H__ - #define __RTL_BASE_H__ - -+enum ap_peer { -+ PEER_UNKNOWN = 0, -+ PEER_RTL = 1, -+ PEER_RTL_92SE = 2, -+ PEER_BROAD = 3, -+ PEER_RAL = 4, -+ PEER_ATH = 5, -+ PEER_CISCO = 6, -+ PEER_MARV = 7, -+ PEER_AIRGO = 9, -+ PEER_MAX = 10, -+} ; -+ - #define RTL_DUMMY_OFFSET 0 --#define RTL_RX_DESC_SIZE 24 - #define RTL_DUMMY_UNIT 8 - #define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) - #define RTL_TX_DESC_SIZE 32 -@@ -53,6 +66,14 @@ - #define FRAME_OFFSET_SEQUENCE 22 - #define FRAME_OFFSET_ADDRESS4 24 - -+#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ -+ WRITEEF2BYTE(_hdr, _val) -+#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ -+ WRITEEF1BYTE(_hdr, _val) -+#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ -+ SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) -+#define SET_80211_HDR_TO_DS(_hdr, _val) \ -+ SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) - - #define SET_80211_PS_POLL_AID(_hdr, _val) \ - (*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val)) -@@ -64,11 +85,27 @@ - #define SET_80211_HDR_DURATION(_hdr, _val) \ - (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) - #define SET_80211_HDR_ADDRESS1(_hdr, _val) \ -- memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN) -+ CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) - #define SET_80211_HDR_ADDRESS2(_hdr, _val) \ -- memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN) -+ CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) - #define SET_80211_HDR_ADDRESS3(_hdr, _val) \ -- memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN) -+ CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) -+#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ -+ WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) -+ -+#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ -+ WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) -+#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ -+ WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) -+#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ -+ WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) -+#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ -+ READEF2BYTE(((u8 *)(__phdr)) + 34) -+#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ -+ WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) -+#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ -+ SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ -+ (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) - - int rtl_init_core(struct ieee80211_hw *hw); - void rtl_deinit_core(struct ieee80211_hw *hw); -@@ -80,18 +117,27 @@ - void rtl_deinit_deferred_work(struct ieee80211_hw *hw); - - bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); --bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); - u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); - - void rtl_watch_dog_timer_callback(unsigned long data); --int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, -+int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - u16 tid, u16 *ssn); --int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid); -+int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, -+ u16 tid); -+int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, -+ u16 tid); - void rtl_watchdog_wq_callback(void *data); - - void rtl_get_tcb_desc(struct ieee80211_hw *hw, - struct ieee80211_tx_info *info, -+ struct ieee80211_sta *sta, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); - -+int rtl_send_smps_action(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 *da, u8 *bssid, -+ enum ieee80211_smps_mode smps); -+u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); -+void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); -+u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid); - extern struct attribute_group rtl_attribute_group; - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/cam.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/cam.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/cam.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/cam.c 2011-05-05 23:29:49.303487995 +0200 -@@ -23,6 +23,8 @@ - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * -+ * Larry Finger -+ * - *****************************************************************************/ - - #include "wifi.h" -@@ -49,7 +51,7 @@ - u32 target_content = 0; - u8 entry_i; - -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("key_cont_128:\n %x:%x:%x:%x:%x:%x\n", - key_cont_128[0], key_cont_128[1], - key_cont_128[2], key_cont_128[3], -@@ -68,15 +70,13 @@ - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], - target_command); - -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): " -- "WRITE %x: %x\n", -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE %x: %x\n", - rtlpriv->cfg->maps[WCAMI], target_content)); -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("The Key ID is %d\n", entry_no)); -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): " -- "WRITE %x: %x\n", -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE %x: %x\n", - rtlpriv->cfg->maps[RWCAM], target_command)); - - } else if (entry_i == 1) { -@@ -91,12 +91,10 @@ - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], - target_command); - -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): WRITE A4: %x\n", -- target_content)); -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): WRITE A0: %x\n", -- target_command)); -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE A4: %x\n", target_content)); -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE A0: %x\n", target_command)); - - } else { - -@@ -113,16 +111,14 @@ - target_command); - udelay(100); - -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): WRITE A4: %x\n", -- target_content)); -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("rtl_cam_program_entry(): WRITE A0: %x\n", -- target_command)); -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE A4: %x\n", target_content)); -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("WRITE A0: %x\n", target_command)); - } - } - -- RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - ("after set key, usconfig:%x\n", us_config)); - } - -@@ -289,3 +285,71 @@ - - } - EXPORT_SYMBOL(rtl_cam_empty_entry); -+ -+u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; -+ u8 entry_idx = 0; -+ u8 i, *addr; -+ -+ if (NULL == sta_addr) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, -+ ("sta_addr is NULL.\n")); -+ return TOTAL_CAM_ENTRY; -+ } -+ /* Does STA already exist? */ -+ for (i = 4; i < TOTAL_CAM_ENTRY; i++) { -+ addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; -+ if (memcmp(addr, sta_addr, ETH_ALEN) == 0) -+ return i; -+ } -+ /* Get a free CAM entry. */ -+ for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { -+ if ((bitmap & BIT(0)) == 0) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, -+ ("-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", -+ rtlpriv->sec.hwsec_cam_bitmap, entry_idx)); -+ rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; -+ memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], -+ sta_addr, ETH_ALEN); -+ return entry_idx; -+ } -+ bitmap = bitmap >> 1; -+ } -+ return TOTAL_CAM_ENTRY; -+} -+EXPORT_SYMBOL(rtl_cam_get_free_entry); -+ -+void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 bitmap; -+ u8 i, *addr; -+ -+ if (NULL == sta_addr) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, -+ ("sta_addr is NULL.\n")); -+ } -+ -+ if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ -+ sta_addr[4]|sta_addr[5]) == 0) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, -+ ("sta_addr is 00:00:00:00:00:00.\n")); -+ return; -+ } -+ /* Does STA already exist? */ -+ for (i = 4; i < TOTAL_CAM_ENTRY; i++) { -+ addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; -+ bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; -+ if (((bitmap & BIT(0)) == BIT(0)) && -+ (memcmp(addr, sta_addr, ETH_ALEN) == 0)) { -+ /* Remove from HW Security CAM */ -+ memset(rtlpriv->sec.hwsec_cam_sta_addr[i], 0, ETH_ALEN); -+ rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); -+ printk(KERN_INFO "&&&&&&&&&del entry %d\n", i); -+ } -+ } -+ return; -+} -+EXPORT_SYMBOL(rtl_cam_del_entry); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/cam.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/cam.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/cam.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/cam.h 2011-05-05 23:29:49.324488249 +0200 -@@ -23,12 +23,13 @@ - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * -+ * Larry Finger -+ * - *****************************************************************************/ - - #ifndef __RTL_CAM_H_ - #define __RTL_CAM_H_ - --#define TOTAL_CAM_ENTRY 32 - #define CAM_CONTENT_COUNT 8 - - #define CFG_DEFAULT_KEY BIT(5) -@@ -49,5 +50,7 @@ - void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); - void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); - void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); -+u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); -+void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/core.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/core.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/core.c 2011-05-05 23:29:49.290487837 +0200 -@@ -24,6 +24,7 @@ - * Hsinchu 300, Taiwan. - * - * Larry Finger -+ * - *****************************************************************************/ - - #include "wifi.h" -@@ -35,7 +36,7 @@ - /*mutex for start & stop is must here. */ - static int rtl_op_start(struct ieee80211_hw *hw) - { -- int err = 0; -+ int err; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - -@@ -45,10 +46,8 @@ - return 0; - mutex_lock(&rtlpriv->locks.conf_mutex); - err = rtlpriv->intf_ops->adapter_start(hw); -- if (err) -- goto out; -- rtl_watch_dog_timer_callback((unsigned long)hw); --out: -+ if (!err) -+ rtl_watch_dog_timer_callback((unsigned long)hw); - mutex_unlock(&rtlpriv->locks.conf_mutex); - return err; - } -@@ -72,6 +71,7 @@ - - mac->link_state = MAC80211_NOLINK; - memset(mac->bssid, 0, 6); -+ mac->vendor = PEER_UNKNOWN; - - /*reset sec info */ - rtl_cam_reset_sec_info(hw); -@@ -87,6 +87,8 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct rtl_tcb_desc tcb_desc; -+ memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) - goto err_free; -@@ -94,8 +96,8 @@ - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - goto err_free; - -- -- rtlpriv->intf_ops->adapter_tx(hw, skb); -+ if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) -+ rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); - - return; - -@@ -136,10 +138,26 @@ - - mac->link_state = MAC80211_LINKED; - rtlpriv->cfg->ops->set_bcn_reg(hw); -+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) -+ mac->basic_rates = 0xfff; -+ else -+ mac->basic_rates = 0xff0; -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, -+ (u8 *) (&mac->basic_rates)); -+ - break; - case NL80211_IFTYPE_AP: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - ("NL80211_IFTYPE_AP\n")); -+ -+ mac->link_state = MAC80211_LINKED; -+ rtlpriv->cfg->ops->set_bcn_reg(hw); -+ if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) -+ mac->basic_rates = 0xfff; -+ else -+ mac->basic_rates = 0xff0; -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, -+ (u8 *) (&mac->basic_rates)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -@@ -186,13 +204,12 @@ - mac->vif = NULL; - mac->link_state = MAC80211_NOLINK; - memset(mac->bssid, 0, 6); -+ mac->vendor = PEER_UNKNOWN; - mac->opmode = NL80211_IFTYPE_UNSPECIFIED; - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); -- - mutex_unlock(&rtlpriv->locks.conf_mutex); - } - -- - static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -224,10 +241,25 @@ - - /*For LPS */ - if (changed & IEEE80211_CONF_CHANGE_PS) { -- if (conf->flags & IEEE80211_CONF_PS) -- rtl_lps_enter(hw); -- else -- rtl_lps_leave(hw); -+ cancel_delayed_work(&rtlpriv->works.ps_work); -+ cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); -+ if (conf->flags & IEEE80211_CONF_PS) { -+ rtlpriv->psc.sw_ps_enabled = true; -+ /* sleep here is must, or we may recv the beacon and -+ * cause mac80211 into wrong ps state, this will cause -+ * power save nullfunc send fail, and further cause -+ * pkt loss, So sleep must quickly but not immediatly -+ * because that will cause nullfunc send by mac80211 -+ * fail, and cause pkt loss, we have tested that 5mA -+ * is worked very well */ -+ if (!rtlpriv->psc.multi_buffered) -+ queue_delayed_work(rtlpriv->works.rtl_wq, -+ &rtlpriv->works.ps_work, -+ MSECS(5)); -+ } else { -+ rtl_swlps_rf_awake(hw); -+ rtlpriv->psc.sw_ps_enabled = false; -+ } - } - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { -@@ -259,7 +291,7 @@ - case NL80211_CHAN_NO_HT: - /* SC */ - mac->cur_40_prime_sc = -- PRIME_CHNL_OFFSET_DONT_CARE; -+ PRIME_CHNL_OFFSET_DONT_CARE; - rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20; - mac->bw_40 = false; - break; -@@ -267,7 +299,7 @@ - /* SC */ - mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER; - rtlphy->current_chan_bw = -- HT_CHANNEL_WIDTH_20_40; -+ HT_CHANNEL_WIDTH_20_40; - mac->bw_40 = true; - - /*wide channel */ -@@ -278,7 +310,7 @@ - /* SC */ - mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER; - rtlphy->current_chan_bw = -- HT_CHANNEL_WIDTH_20_40; -+ HT_CHANNEL_WIDTH_20_40; - mac->bw_40 = true; - - /*wide channel */ -@@ -288,16 +320,29 @@ - default: - mac->bw_40 = false; - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("switch case not processed\n")); -+ ("switch case not processed\n")); - break; - } - - if (wide_chan <= 0) - wide_chan = 1; -+ -+ /* In scanning, before we go offchannel we may send a ps=1 null -+ * to AP, and then we may send a ps = 0 null to AP quickly, but -+ * first null may have caused AP to put lots of packet to hw tx -+ * buffer. These packets must be tx'd before we go off channel -+ * so we must delay more time to let AP flush these packets -+ * before going offchannel, or dis-association or delete BA will -+ * happen by AP -+ */ -+ if (rtlpriv->mac80211.offchan_deley) { -+ rtlpriv->mac80211.offchan_deley = false; -+ mdelay(50); -+ } - rtlphy->current_channel = wide_chan; - -- rtlpriv->cfg->ops->set_channel_access(hw); - rtlpriv->cfg->ops->switch_channel(hw); -+ rtlpriv->cfg->ops->set_channel_access(hw); - rtlpriv->cfg->ops->set_bw_mode(hw, - hw->conf.channel_type); - } -@@ -345,27 +390,28 @@ - } - } - -- if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { -- /* -- *TODO: BIT(5) is probe response BIT(8) is beacon -- *TODO: Use define for BIT(5) and BIT(8) -- */ -- if (*new_flags & FIF_BCN_PRBRESP_PROMISC) -- mac->rx_mgt_filter |= (BIT(5) | BIT(8)); -- else -- mac->rx_mgt_filter &= ~(BIT(5) | BIT(8)); -+ /* if ssid not set to hw don't check bssid -+ * here just used for linked scanning, & linked -+ * and nolink check bssid is set in set network_type */ -+ if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && -+ (mac->link_state >= MAC80211_LINKED)) { -+ if (mac->opmode != NL80211_IFTYPE_AP) { -+ if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { -+ rtlpriv->cfg->ops->set_chk_bssid(hw, false); -+ } else { -+ rtlpriv->cfg->ops->set_chk_bssid(hw, true); -+ } -+ } - } - - if (changed_flags & FIF_CONTROL) { - if (*new_flags & FIF_CONTROL) { - mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; -- mac->rx_ctrl_filter |= RTL_SUPPORTED_CTRL_FILTER; - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - ("Enable receive control frame.\n")); - } else { - mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; -- mac->rx_ctrl_filter &= ~RTL_SUPPORTED_CTRL_FILTER; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - ("Disable receive control frame.\n")); - } -@@ -382,14 +428,54 @@ - ("Disable receive other BSS's frame.\n")); - } - } -- -- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); -- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, -- (u8 *) (&mac->rx_mgt_filter)); -- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, -- (u8 *) (&mac->rx_ctrl_filter)); - } -+static int rtl_op_sta_add(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry; -+ -+ if (sta) { -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ if (rtlhal->current_bandtype == BAND_ON_2_4G) { -+ sta_entry->wireless_mode = WIRELESS_MODE_G; -+ if (sta->supp_rates[0] <= 0xf) -+ sta_entry->wireless_mode = WIRELESS_MODE_B; -+ if (sta->ht_cap.ht_supported == true) -+ sta_entry->wireless_mode = WIRELESS_MODE_N_24G; -+ } else if (rtlhal->current_bandtype == BAND_ON_5G) { -+ sta_entry->wireless_mode = WIRELESS_MODE_A; -+ if (sta->ht_cap.ht_supported == true) -+ sta_entry->wireless_mode = WIRELESS_MODE_N_24G; -+ } - -+ /* I found some times mac80211 give wrong supp_rates for adhoc*/ -+ if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) -+ sta_entry->wireless_mode = WIRELESS_MODE_G; -+ -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, -+ ("Add sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); -+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); -+ } -+ return 0; -+} -+static int rtl_op_sta_remove(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_sta *sta) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_sta_info *sta_entry; -+ if (sta) { -+ RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, -+ ("Remove sta addr is "MAC_FMT"\n", MAC_ARG(sta->addr))); -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ sta_entry->wireless_mode = 0; -+ sta_entry->ratr_index = 0; -+ } -+ return 0; -+} - static int _rtl_get_hal_qnum(u16 queue) - { - int qnum; -@@ -446,19 +532,18 @@ - struct ieee80211_bss_conf *bss_conf, u32 changed) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct ieee80211_sta *sta = NULL; - - mutex_lock(&rtlpriv->locks.conf_mutex); -- - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { -- - if ((changed & BSS_CHANGED_BEACON) || - (changed & BSS_CHANGED_BEACON_ENABLED && - bss_conf->enable_beacon)) { -- - if (mac->beacon_enabled == 0) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("BSS_CHANGED_BEACON_ENABLED\n")); -@@ -470,8 +555,13 @@ - rtlpriv->cfg->maps - [RTL_IBSS_INT_MASKS], - 0); -+ -+ if (rtlpriv->cfg->ops->linked_set_reg) -+ rtlpriv->cfg->ops->linked_set_reg(hw); - } -- } else { -+ } -+ if ((changed & BSS_CHANGED_BEACON_ENABLED && -+ !bss_conf->enable_beacon)) { - if (mac->beacon_enabled == 1) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("ADHOC DISABLE BEACON\n")); -@@ -482,7 +572,6 @@ - [RTL_IBSS_INT_MASKS]); - } - } -- - if (changed & BSS_CHANGED_BEACON_INT) { - RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, - ("BSS_CHANGED_BEACON_INT\n")); -@@ -494,11 +583,25 @@ - /*TODO: reference to enum ieee80211_bss_change */ - if (changed & BSS_CHANGED_ASSOC) { - if (bss_conf->assoc) { -+ /* we should reset all sec info & cam -+ * before set cam after linked, we should not -+ * reset in disassoc, that will cause tkip->wep -+ * fail because some flag will be wrong */ -+ /* reset sec info */ -+ rtl_cam_reset_sec_info(hw); -+ /* reset cam to fix wep fail issue -+ * when change from wpa to wep */ -+ rtl_cam_reset_all_entry(hw); -+ - mac->link_state = MAC80211_LINKED; - mac->cnt_after_linked = 0; - mac->assoc_id = bss_conf->aid; - memcpy(mac->bssid, bss_conf->bssid, 6); - -+ if (rtlpriv->cfg->ops->linked_set_reg) -+ rtlpriv->cfg->ops->linked_set_reg(hw); -+ if (mac->opmode == NL80211_IFTYPE_STATION && sta) -+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("BSS_CHANGED_ASSOC\n")); - } else { -@@ -507,9 +610,7 @@ - - mac->link_state = MAC80211_NOLINK; - memset(mac->bssid, 0, 6); -- -- /* reset sec info */ -- rtl_cam_reset_sec_info(hw); -+ mac->vendor = PEER_UNKNOWN; - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - ("BSS_CHANGED_UN_ASSOC\n")); -@@ -546,14 +647,10 @@ - } - - if (changed & BSS_CHANGED_HT) { -- struct ieee80211_sta *sta = NULL; -- - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - ("BSS_CHANGED_HT\n")); -- - rcu_read_lock(); -- sta = ieee80211_find_sta(mac->vif, mac->bssid); -- -+ sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); - if (sta) { - if (sta->ht_cap.ampdu_density > - mac->current_ampdu_density) -@@ -575,9 +672,7 @@ - } - - if (changed & BSS_CHANGED_BSSID) { -- struct ieee80211_sta *sta = NULL; - u32 basic_rates; -- u8 i; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, - (u8 *) bss_conf->bssid); -@@ -585,96 +680,65 @@ - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - (MAC_FMT "\n", MAC_ARG(bss_conf->bssid))); - -+ mac->vendor = PEER_UNKNOWN; - memcpy(mac->bssid, bss_conf->bssid, 6); -- if (is_valid_ether_addr(bss_conf->bssid)) { -- switch (vif->type) { -- case NL80211_IFTYPE_UNSPECIFIED: -- break; -- case NL80211_IFTYPE_ADHOC: -- break; -- case NL80211_IFTYPE_STATION: -- break; -- case NL80211_IFTYPE_AP: -- break; -- default: -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("switch case not process\n")); -- break; -- } -- rtlpriv->cfg->ops->set_network_type(hw, vif->type); -- } else -- rtlpriv->cfg->ops->set_network_type(hw, -- NL80211_IFTYPE_UNSPECIFIED); -- -- memset(mac->mcs, 0, 16); -- mac->ht_enable = false; -- mac->sgi_40 = false; -- mac->sgi_20 = false; -- -- if (!bss_conf->use_short_slot) -- mac->mode = WIRELESS_MODE_B; -- else -- mac->mode = WIRELESS_MODE_G; -+ rtlpriv->cfg->ops->set_network_type(hw, vif->type); - - rcu_read_lock(); -- sta = ieee80211_find_sta(mac->vif, mac->bssid); -+ sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); -+ if (!sta) { -+ rcu_read_unlock(); -+ goto out; -+ } - -- if (sta) { -- if (sta->ht_cap.ht_supported) { -+ if (rtlhal->current_bandtype == BAND_ON_5G) { -+ mac->mode = WIRELESS_MODE_A; -+ } else { -+ if (sta->supp_rates[0] <= 0xf) -+ mac->mode = WIRELESS_MODE_B; -+ else -+ mac->mode = WIRELESS_MODE_G; -+ } -+ -+ if (sta->ht_cap.ht_supported) { -+ if (rtlhal->current_bandtype == BAND_ON_2_4G) - mac->mode = WIRELESS_MODE_N_24G; -- mac->ht_enable = true; -- } -+ else -+ mac->mode = WIRELESS_MODE_N_5G; -+ } - -- if (mac->ht_enable) { -- u16 ht_cap = sta->ht_cap.cap; -- memcpy(mac->mcs, (u8 *) (&sta->ht_cap.mcs), 16); -- -- for (i = 0; i < 16; i++) -- RT_TRACE(rtlpriv, COMP_MAC80211, -- DBG_LOUD, ("%x ", -- mac->mcs[i])); -- RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, -- ("\n")); -- -- if (ht_cap & IEEE80211_HT_CAP_SGI_40) -- mac->sgi_40 = true; -- -- if (ht_cap & IEEE80211_HT_CAP_SGI_20) -- mac->sgi_20 = true; -- -- /* -- * for cisco 1252 bw20 it's wrong -- * if (ht_cap & -- * IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -- * mac->bw_40 = true; -- * } -- */ -- } -+ /* just station need it, because ibss & ap mode will -+ * set in sta_add, and will be NULL here */ -+ if (mac->opmode == NL80211_IFTYPE_STATION) { -+ struct rtl_sta_info *sta_entry; -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ sta_entry->wireless_mode = mac->mode; -+ } -+ -+ if (sta->ht_cap.ht_supported) { -+ mac->ht_enable = true; -+ -+ /* -+ * for cisco 1252 bw20 it's wrong -+ * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -+ * mac->bw_40 = true; -+ * } -+ * */ - } -- rcu_read_unlock(); - -- /*mac80211 just give us CCK rates any time -- *So we add G rate in basic rates when -- not in B mode*/ - if (changed & BSS_CHANGED_BASIC_RATES) { -- if (mac->mode == WIRELESS_MODE_B) -- basic_rates = bss_conf->basic_rates | 0x00f; -+ /* for 5G must << RATE_6M_INDEX=4, -+ * because 5G have no cck rate*/ -+ if (rtlhal->current_bandtype == BAND_ON_5G) -+ basic_rates = sta->supp_rates[1] << 4; - else -- basic_rates = bss_conf->basic_rates | 0xff0; -- -- if (!vif) -- goto out; -+ basic_rates = sta->supp_rates[0]; - - mac->basic_rates = basic_rates; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *) (&basic_rates)); -- -- if (rtlpriv->dm.useramask) -- rtlpriv->cfg->ops->update_rate_mask(hw, 0); -- else -- rtlpriv->cfg->ops->update_rate_table(hw); -- - } -+ rcu_read_unlock(); - } - - /* -@@ -760,16 +824,17 @@ - case IEEE80211_AMPDU_TX_START: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - ("IEEE80211_AMPDU_TX_START: TID:%d\n", tid)); -- return rtl_tx_agg_start(hw, sta->addr, tid, ssn); -+ return rtl_tx_agg_start(hw, sta, tid, ssn); - break; - case IEEE80211_AMPDU_TX_STOP: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - ("IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid)); -- return rtl_tx_agg_stop(hw, sta->addr, tid); -+ return rtl_tx_agg_stop(hw, sta, tid); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - ("IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid)); -+ rtl_tx_agg_oper(hw, sta, tid); - break; - case IEEE80211_AMPDU_RX_START: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, -@@ -799,8 +864,12 @@ - if (mac->link_state == MAC80211_LINKED) { - rtl_lps_leave(hw); - mac->link_state = MAC80211_LINKED_SCANNING; -- } else -+ } else { - rtl_ips_nic_on(hw); -+ } -+ -+ /* Dual mac */ -+ rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; - - rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP); -@@ -812,22 +881,19 @@ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, ("\n")); -- -- rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); - mac->act_scanning = false; -+ /* Dual mac */ -+ rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; -+ - if (mac->link_state == MAC80211_LINKED_SCANNING) { - mac->link_state = MAC80211_LINKED; -- -- /* fix fwlps issue */ -- rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); -- -- if (rtlpriv->dm.useramask) -- rtlpriv->cfg->ops->update_rate_mask(hw, 0); -- else -- rtlpriv->cfg->ops->update_rate_table(hw); -- -+ if (mac->opmode == NL80211_IFTYPE_STATION) { -+ /* fix fwlps issue */ -+ rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); -+ } - } - -+ rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); - } - - static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, -@@ -858,49 +924,73 @@ - rtl_ips_nic_on(hw); - mutex_lock(&rtlpriv->locks.conf_mutex); - /* <1> get encryption alg */ -+ - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - key_type = WEP40_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:WEP40\n")); -- rtlpriv->sec.use_defaultkey = true; - break; - case WLAN_CIPHER_SUITE_WEP104: - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("alg:WEP104\n")); - key_type = WEP104_ENCRYPTION; -- rtlpriv->sec.use_defaultkey = true; - break; - case WLAN_CIPHER_SUITE_TKIP: - key_type = TKIP_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:TKIP\n")); -- if (mac->opmode == NL80211_IFTYPE_ADHOC) -- rtlpriv->sec.use_defaultkey = true; - break; - case WLAN_CIPHER_SUITE_CCMP: - key_type = AESCCMP_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("alg:CCMP\n")); -- if (mac->opmode == NL80211_IFTYPE_ADHOC) -- rtlpriv->sec.use_defaultkey = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("alg_err:%x!!!!:\n", key->cipher)); - goto out_unlock; - } -+ if (key_type == WEP40_ENCRYPTION || -+ key_type == WEP104_ENCRYPTION || -+ mac->opmode == NL80211_IFTYPE_ADHOC) -+ rtlpriv->sec.use_defaultkey = true; -+ - /* <2> get key_idx */ - key_idx = (u8) (key->keyidx); - if (key_idx > 3) - goto out_unlock; - /* <3> if pairwise key enable_hw_sec */ - group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); -- if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || -- rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { -- if (rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION && -- (key_type == WEP40_ENCRYPTION || -- key_type == WEP104_ENCRYPTION)) -- wep_only = true; -- rtlpriv->sec.pairwise_enc_algorithm = key_type; -- rtlpriv->cfg->ops->enable_hw_sec(hw); -+ -+ /* wep always be group key, but there are two conditions: -+ * 1) wep only: is just for wep enc, in this condition -+ * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION -+ * will be true & enable_hw_sec will be set when wep -+ * ke setting. -+ * 2) wep(group) + AES(pairwise): some AP like cisco -+ * may use it, in this condition enable_hw_sec will not -+ * be set when wep key setting */ -+ /* we must reset sec_info after lingked before set key, -+ * or some flag will be wrong*/ -+ if (mac->opmode == NL80211_IFTYPE_AP) { -+ if (!group_key || key_type == WEP40_ENCRYPTION || -+ key_type == WEP104_ENCRYPTION) { -+ if (group_key) -+ wep_only = true; -+ rtlpriv->cfg->ops->enable_hw_sec(hw); -+ } -+ } else { -+ if ((!group_key) || (mac->opmode == NL80211_IFTYPE_ADHOC) || -+ rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { -+ if (rtlpriv->sec.pairwise_enc_algorithm == -+ NO_ENCRYPTION && -+ (key_type == WEP40_ENCRYPTION || -+ key_type == WEP104_ENCRYPTION)) -+ wep_only = true; -+ rtlpriv->sec.pairwise_enc_algorithm = key_type; -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1" -+ " TKIP:2 AES:4 WEP104:5)\n", key_type)); -+ rtlpriv->cfg->ops->enable_hw_sec(hw); -+ } - } - /* <4> set key based on cmd */ - switch (cmd) { -@@ -932,6 +1022,7 @@ - if (!sta) { - RT_ASSERT(false, ("pairwise key withnot" - "mac_addr\n")); -+ - err = -EOPNOTSUPP; - goto out_unlock; - } -@@ -959,6 +1050,10 @@ - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - ("disable key delete one entry\n")); - /*set local buf about wep key. */ -+ if (mac->opmode == NL80211_IFTYPE_AP) { -+ if (sta) -+ rtl_cam_del_entry(hw, sta->addr); -+ } - memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); - rtlpriv->sec.key_len[key_idx] = 0; - memcpy(mac_addr, zero_addr, ETH_ALEN); -@@ -1011,6 +1106,18 @@ - mutex_unlock(&rtlpriv->locks.conf_mutex); - } - -+/* this function is called by mac80211 to flush tx buffer -+ * before switch channle or power save, or tx buffer packet -+ * maybe send after offchannel or rf sleep, this may cause -+ * dis-association by AP */ -+static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (rtlpriv->intf_ops->flush) -+ rtlpriv->intf_ops->flush(hw, drop); -+} -+ - const struct ieee80211_ops rtl_ops = { - .start = rtl_op_start, - .stop = rtl_op_stop, -@@ -1019,6 +1126,8 @@ - .remove_interface = rtl_op_remove_interface, - .config = rtl_op_config, - .configure_filter = rtl_op_configure_filter, -+ .sta_add = rtl_op_sta_add, -+ .sta_remove = rtl_op_sta_remove, - .set_key = rtl_op_set_key, - .conf_tx = rtl_op_conf_tx, - .bss_info_changed = rtl_op_bss_info_changed, -@@ -1030,4 +1139,5 @@ - .sw_scan_start = rtl_op_sw_scan_start, - .sw_scan_complete = rtl_op_sw_scan_complete, - .rfkill_poll = rtl_op_rfkill_poll, -+ .flush = rtl_op_flush, - }; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/core.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/core.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/core.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/core.h 2011-05-05 23:29:49.269487583 +0200 -@@ -24,6 +24,7 @@ - * Hsinchu 300, Taiwan. - * - * Larry Finger -+ * - *****************************************************************************/ - - #ifndef __RTL_CORE_H__ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/efuse.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/efuse.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/efuse.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/efuse.c 2011-05-05 23:29:49.301487971 +0200 -@@ -52,8 +52,6 @@ - {11, 0, 0, 28} - }; - --static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, -- u8 *pbuf); - static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, - u8 *value); - static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, -@@ -79,7 +77,7 @@ - u8 *targetdata); - static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, - u16 efuse_addr, u8 word_en, u8 *data); --static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, -+static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, - u8 pwrstate); - static u16 efuse_get_current_size(struct ieee80211_hw *hw); - static u8 efuse_calculate_word_cnts(u8 word_en); -@@ -115,8 +113,10 @@ - u8 bytetemp; - u8 temp; - u32 k = 0; -+ const u32 efuse_len = -+ rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - -- if (address < EFUSE_REAL_CONTENT_LEN) { -+ if (address < efuse_len) { - temp = address & 0xFF; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - temp); -@@ -158,11 +158,13 @@ - u8 bytetemp; - u8 temp; - u32 k = 0; -+ const u32 efuse_len = -+ rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("Addr=%x Data =%x\n", address, value)); - -- if (address < EFUSE_REAL_CONTENT_LEN) { -+ if (address < efuse_len) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); - - temp = address & 0xFF; -@@ -198,7 +200,7 @@ - - } - --static void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) -+void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 value32; -@@ -233,24 +235,28 @@ - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -- u8 efuse_tbl[EFUSE_MAP_LEN]; -+ u8 efuse_tbl[HWSET_MAX_SIZE]; - u8 rtemp8[1]; - u16 efuse_addr = 0; - u8 offset, wren; - u16 i; - u16 j; -+ const u16 efuse_max_section = -+ rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; -+ const u32 efuse_len = -+ rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; - u16 efuse_utilized = 0; - u8 efuse_usage; - -- if ((_offset + _size_byte) > EFUSE_MAP_LEN) { -+ if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("read_efuse(): Invalid offset(%#x) with read " - "bytes(%#x)!!\n", _offset, _size_byte)); - return; - } - -- for (i = 0; i < EFUSE_MAX_SECTION; i++) -+ for (i = 0; i < efuse_max_section; i++) - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - efuse_word[i][j] = 0xFFFF; - -@@ -262,10 +268,10 @@ - efuse_addr++; - } - -- while ((*rtemp8 != 0xFF) && (efuse_addr < EFUSE_REAL_CONTENT_LEN)) { -+ while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { - offset = ((*rtemp8 >> 4) & 0x0f); - -- if (offset < EFUSE_MAX_SECTION) { -+ if (offset < efuse_max_section) { - wren = (*rtemp8 & 0x0f); - RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - ("offset-%d Worden=%x\n", offset, wren)); -@@ -281,7 +287,7 @@ - efuse_utilized++; - efuse_word[offset][i] = (*rtemp8 & 0xff); - -- if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) -+ if (efuse_addr >= efuse_len) - break; - - RTPRINT(rtlpriv, FEEPROM, -@@ -294,7 +300,7 @@ - efuse_word[offset][i] |= - (((u16)*rtemp8 << 8) & 0xff00); - -- if (efuse_addr >= EFUSE_REAL_CONTENT_LEN) -+ if (efuse_addr >= efuse_len) - break; - } - -@@ -305,13 +311,13 @@ - RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - ("Addr=%d\n", efuse_addr)); - read_efuse_byte(hw, efuse_addr, rtemp8); -- if (*rtemp8 != 0xFF && (efuse_addr < 512)) { -+ if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { - efuse_utilized++; - efuse_addr++; - } - } - -- for (i = 0; i < EFUSE_MAX_SECTION; i++) { -+ for (i = 0; i < efuse_max_section; i++) { - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuse_tbl[(i * 8) + (j * 2)] = - (efuse_word[i][j] & 0xff); -@@ -324,7 +330,7 @@ - pbuf[i] = efuse_tbl[_offset + i]; - - rtlefuse->efuse_usedbytes = efuse_utilized; -- efuse_usage = (u8)((efuse_utilized * 100) / EFUSE_REAL_CONTENT_LEN); -+ efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); - rtlefuse->efuse_usedpercentage = efuse_usage; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, - (u8 *)&efuse_utilized); -@@ -338,11 +344,11 @@ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 section_idx, i, Base; - u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; -- bool bwordchanged, bresult = true; -+ bool wordchanged, result = true; - - for (section_idx = 0; section_idx < 16; section_idx++) { - Base = section_idx * 8; -- bwordchanged = false; -+ wordchanged = false; - - for (i = 0; i < 8; i = i + 2) { - if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != -@@ -351,11 +357,11 @@ - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + - 1])) { - words_need++; -- bwordchanged = true; -+ wordchanged = true; - } - } - -- if (bwordchanged == true) -+ if (wordchanged == true) - hdr_num++; - } - -@@ -364,14 +370,14 @@ - - if ((totalbytes + efuse_used) >= - (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) -- bresult = false; -+ result = false; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("efuse_shadow_update_chk(): totalbytes(%#x), " - "hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", - totalbytes, hdr_num, words_need, efuse_used)); - -- return bresult; -+ return result; - } - - void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, -@@ -394,7 +400,7 @@ - else if (type == 2) - efuse_shadow_write_2byte(hw, offset, (u16) value); - else if (type == 4) -- efuse_shadow_write_4byte(hw, offset, (u32) value); -+ efuse_shadow_write_4byte(hw, offset, value); - - } - -@@ -478,9 +484,10 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - -- if (rtlefuse->autoload_failflag == true) { -- memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128); -- } else -+ if (rtlefuse->autoload_failflag == true) -+ memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, -+ rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); -+ else - efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); - - memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], -@@ -572,7 +579,7 @@ - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmpidx = 0; -- int bresult; -+ int result; - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - (u8) (addr & 0xff)); -@@ -592,19 +599,18 @@ - - if (tmpidx < 100) { - *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); -- bresult = true; -+ result = true; - } else { - *data = 0xff; -- bresult = false; -+ result = false; - } -- return bresult; -+ return result; - } - - static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmpidx = 0; -- bool bresult; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("Addr = %x Data=%x\n", addr, data)); -@@ -626,17 +632,16 @@ - } - - if (tmpidx < 100) -- bresult = true; -- else -- bresult = false; -+ return true; - -- return bresult; -+ return false; - } - - static void efuse_read_all_map(struct ieee80211_hw *hw, u8 * efuse) - { -+ struct rtl_priv *rtlpriv = rtl_priv(hw); - efuse_power_switch(hw, false, true); -- read_efuse(hw, 0, 128, efuse); -+ read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); - efuse_power_switch(hw, false, false); - } - -@@ -644,7 +649,7 @@ - u8 efuse_data, u8 offset, u8 *tmpdata, - u8 *readstate) - { -- bool bdataempty = true; -+ bool dataempty = true; - u8 hoffset; - u8 tmpidx; - u8 hworden; -@@ -660,13 +665,13 @@ - &efuse_data)) { - tmpdata[tmpidx] = efuse_data; - if (efuse_data != 0xff) -- bdataempty = true; -+ dataempty = true; - } - } - -- if (bdataempty == true) -+ if (dataempty == true) { - *readstate = PG_STATE_DATA; -- else { -+ } else { - *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; - *readstate = PG_STATE_HEADER; - } -@@ -680,12 +685,9 @@ - static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) - { - u8 readstate = PG_STATE_HEADER; -- -- bool bcontinual = true; -- -+ bool continual = true; - u8 efuse_data, word_cnts = 0; - u16 efuse_addr = 0; -- u8 hworden = 0; - u8 tmpdata[8]; - - if (data == NULL) -@@ -696,7 +698,7 @@ - memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - -- while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) { -+ while (continual && (efuse_addr < EFUSE_MAX_SIZE)) { - if (readstate & PG_STATE_HEADER) { - if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) - && (efuse_data != 0xFF)) -@@ -705,9 +707,9 @@ - offset, tmpdata, - &readstate); - else -- bcontinual = false; -+ continual = false; - } else if (readstate & PG_STATE_DATA) { -- efuse_word_enable_data_read(hworden, tmpdata, data); -+ efuse_word_enable_data_read(0, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - readstate = PG_STATE_HEADER; - } -@@ -725,13 +727,13 @@ - } - - static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, -- u8 efuse_data, u8 offset, int *bcontinual, -+ u8 efuse_data, u8 offset, int *continual, - u8 *write_state, struct pgpkt_struct *target_pkt, -- int *repeat_times, int *bresult, u8 word_en) -+ int *repeat_times, int *result, u8 word_en) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct tmp_pkt; -- int bdataempty = true; -+ bool dataempty = true; - u8 originaldata[8 * sizeof(u8)]; - u8 badworden = 0x0F; - u8 match_word_en, tmp_word_en; -@@ -751,10 +753,10 @@ - u16 address = *efuse_addr + 1 + tmpindex; - if (efuse_one_byte_read(hw, address, - &efuse_data) && (efuse_data != 0xFF)) -- bdataempty = false; -+ dataempty = false; - } - -- if (bdataempty == false) { -+ if (dataempty == false) { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - *write_state = PG_STATE_HEADER; - } else { -@@ -799,24 +801,25 @@ - tmp_word_en &= (~BIT(1)); - - if ((target_pkt->word_en & BIT(2)) ^ -- (match_word_en & BIT(2))) -+ (match_word_en & BIT(2))) - tmp_word_en &= (~BIT(2)); - - if ((target_pkt->word_en & BIT(3)) ^ -- (match_word_en & BIT(3))) -+ (match_word_en & BIT(3))) - tmp_word_en &= (~BIT(3)); - - if ((tmp_word_en & 0x0F) != 0x0F) { - *efuse_addr = efuse_get_current_size(hw); - target_pkt->offset = offset; - target_pkt->word_en = tmp_word_en; -- } else -- *bcontinual = false; -+ } else { -+ *continual = false; -+ } - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { -- *bcontinual = false; -- *bresult = false; -+ *continual = false; -+ *result = false; - } - } else { - *efuse_addr += (2 * tmp_word_cnts) + 1; -@@ -830,9 +833,9 @@ - } - - static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, -- int *bcontinual, u8 *write_state, -+ int *continual, u8 *write_state, - struct pgpkt_struct target_pkt, -- int *repeat_times, int *bresult) -+ int *repeat_times, int *result) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct tmp_pkt; -@@ -846,14 +849,14 @@ - efuse_one_byte_write(hw, *efuse_addr, pg_header); - efuse_one_byte_read(hw, *efuse_addr, &tmp_header); - -- if (tmp_header == pg_header) -+ if (tmp_header == pg_header) { - *write_state = PG_STATE_DATA; -- else if (tmp_header == 0xFF) { -+ } else if (tmp_header == 0xFF) { - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { -- *bcontinual = false; -- *bresult = false; -+ *continual = false; -+ *result = false; - } - } else { - tmp_pkt.offset = (tmp_header >> 4) & 0x0F; -@@ -875,17 +878,19 @@ - reorg_worden, - originaldata); - *efuse_addr = efuse_get_current_size(hw); -- } else -+ } else { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) - + 1; -- } else -+ } -+ } else { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; -+ } - - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { -- *bcontinual = false; -- *bresult = false; -+ *continual = false; -+ *result = false; - } - - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, -@@ -899,7 +904,7 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct target_pkt; - u8 write_state = PG_STATE_HEADER; -- int bcontinual = true, bdataempty = true, bresult = true; -+ int continual = true, dataempty = true, result = true; - u16 efuse_addr = 0; - u8 efuse_data; - u8 target_word_cnts = 0; -@@ -923,11 +928,11 @@ - - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse Power ON\n")); - -- while (bcontinual && (efuse_addr < -+ while (continual && (efuse_addr < - (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { - - if (write_state == PG_STATE_HEADER) { -- bdataempty = true; -+ dataempty = true; - badworden = 0x0F; - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_HEADER\n")); -@@ -936,32 +941,30 @@ - (efuse_data != 0xFF)) - efuse_write_data_case1(hw, &efuse_addr, - efuse_data, offset, -- &bcontinual, -+ &continual, - &write_state, &target_pkt, -- &repeat_times, &bresult, -+ &repeat_times, &result, - word_en); - else - efuse_write_data_case2(hw, &efuse_addr, -- &bcontinual, -+ &continual, - &write_state, - target_pkt, - &repeat_times, -- &bresult); -+ &result); - - } else if (write_state == PG_STATE_DATA) { - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_DATA\n")); -- badworden = 0x0f; - badworden = - efuse_word_enable_data_write(hw, efuse_addr + 1, - target_pkt.word_en, - target_pkt.data); - - if ((badworden & 0x0F) == 0x0F) { -- bcontinual = false; -+ continual = false; - } else { -- efuse_addr = -- efuse_addr + (2 * target_word_cnts) + 1; -+ efuse_addr += (2 * target_word_cnts) + 1; - - target_pkt.offset = offset; - target_pkt.word_en = badworden; -@@ -971,8 +974,8 @@ - write_state = PG_STATE_HEADER; - repeat_times++; - if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { -- bcontinual = false; -- bresult = false; -+ continual = false; -+ result = false; - } - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_HEADER-3\n")); -@@ -1072,13 +1075,15 @@ - return badworden; - } - --static void efuse_power_switch(struct ieee80211_hw *hw, u8 bwrite, u8 pwrstate) -+static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tempval; - u16 tmpV16; - -- if (pwrstate == true) { -+ if (pwrstate && (rtlhal->hw_type != -+ HARDWARE_TYPE_RTL8192SE)) { - tmpV16 = rtl_read_word(rtlpriv, - rtlpriv->cfg->maps[SYS_ISO_CTRL]); - if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { -@@ -1106,20 +1111,29 @@ - } - } - -- if (pwrstate == true) { -- if (bwrite == true) { -+ if (pwrstate) { -+ if (write) { - tempval = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + - 3); -- tempval &= 0x0F; -- tempval |= (VOLTAGE_V25 << 4); -+ -+ if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { -+ tempval &= 0x0F; -+ tempval |= (VOLTAGE_V25 << 4); -+ } -+ - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + 3, - (tempval | 0x80)); - } - -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { -+ rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], -+ 0x03); -+ } -+ - } else { -- if (bwrite == true) { -+ if (write) { - tempval = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + - 3); -@@ -1128,18 +1142,23 @@ - (tempval & 0x7F)); - } - -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { -+ rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], -+ 0x02); -+ } -+ - } - - } - - static u16 efuse_get_current_size(struct ieee80211_hw *hw) - { -- int bcontinual = true; -+ int continual = true; - u16 efuse_addr = 0; - u8 hoffset, hworden; - u8 efuse_data, word_cnts; - -- while (bcontinual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) -+ while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) - && (efuse_addr < EFUSE_MAX_SIZE)) { - if (efuse_data != 0xFF) { - hoffset = (efuse_data >> 4) & 0x0F; -@@ -1147,7 +1166,7 @@ - word_cnts = efuse_calculate_word_cnts(hworden); - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - } else { -- bcontinual = false; -+ continual = false; - } - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/efuse.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/efuse.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/efuse.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/efuse.h 2011-05-05 23:29:49.304488007 +0200 -@@ -30,9 +30,10 @@ - #ifndef __RTL_EFUSE_H_ - #define __RTL_EFUSE_H_ - -+#define EFUSE_IC_ID_OFFSET 506 -+ - #define EFUSE_REAL_CONTENT_LEN 512 - #define EFUSE_MAP_LEN 128 --#define EFUSE_MAX_SECTION 16 - #define EFUSE_MAX_WORD_UNIT 4 - - #define EFUSE_INIT_MAP 0 -@@ -52,6 +53,7 @@ - #define _PRE_EXECUTE_READ_CMD_ - - #define EFUSE_REPEAT_THRESHOLD_ 3 -+#define EFUSE_ERROE_HANDLE 1 - - struct efuse_map { - u8 offset; -@@ -103,6 +105,7 @@ - u8 tx_power_g[14]; - }; - -+extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); - extern void efuse_initialize(struct ieee80211_hw *hw); - extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); - extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/Kconfig 2011-05-05 23:29:49.333488357 +0200 -@@ -10,6 +10,17 @@ - - If you choose to build it as a module, it will be called rtl8192ce - -+config RTL8192SE -+ tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" -+ depends on MAC80211 && EXPERIMENTAL -+ select FW_LOADER -+ select RTLWIFI -+ ---help--- -+ This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe -+ wireless network adapters. -+ -+ If you choose to build it as a module, it will be called rtl8192se -+ - config RTL8192CU - tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" - depends on MAC80211 && USB && EXPERIMENTAL -@@ -24,10 +35,10 @@ - - config RTLWIFI - tristate -- depends on RTL8192CE || RTL8192CU -+ depends on RTL8192CE || RTL8192CU || RTL8192SE - default m - - config RTL8192C_COMMON - tristate -- depends on RTL8192CE || RTL8192CU -+ depends on RTL8192CE || RTL8192CU || RTL8192SE - default m -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/Makefile 2011-05-05 23:29:49.303487995 +0200 -@@ -22,5 +22,6 @@ - obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ - obj-$(CONFIG_RTL8192CE) += rtl8192ce/ - obj-$(CONFIG_RTL8192CU) += rtl8192cu/ -+obj-$(CONFIG_RTL8192SE) += rtl8192se/ - - ccflags-y += -D__CHECK_ENDIAN__ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/pci.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/pci.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/pci.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/pci.c 2011-05-05 23:29:49.305488019 +0200 -@@ -32,6 +32,7 @@ - #include "pci.h" - #include "base.h" - #include "ps.h" -+#include "efuse.h" - - static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { - INTEL_VENDOR_ID, -@@ -40,6 +41,31 @@ - SIS_VENDOR_ID - }; - -+static const u8 ac_to_hwq[] = { -+ VO_QUEUE, -+ VI_QUEUE, -+ BE_QUEUE, -+ BK_QUEUE -+}; -+ -+static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, -+ struct sk_buff *skb) -+{ -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ __le16 fc = rtl_get_fc(skb); -+ u8 queue_index = skb_get_queue_mapping(skb); -+ -+ if (unlikely(ieee80211_is_beacon(fc))) -+ return BEACON_QUEUE; -+ if (ieee80211_is_mgmt(fc)) -+ return MGNT_QUEUE; -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) -+ if (ieee80211_is_nullfunc(fc)) -+ return HIGH_QUEUE; -+ -+ return ac_to_hwq[queue_index]; -+} -+ - /* Update PCI dependent default settings*/ - static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) - { -@@ -48,6 +74,7 @@ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; -+ u8 init_aspm; - - ppsc->reg_rfps_level = 0; - ppsc->support_aspm = 0; -@@ -125,7 +152,7 @@ - bool support_backdoor = true; - ppsc->support_aspm = support_aspm; - -- /*if(priv->oem_id == RT_CID_TOSHIBA && -+ /*if (priv->oem_id == RT_CID_TOSHIBA && - !priv->ndis_adapter.amd_l1_patch) - support_backdoor = false; */ - -@@ -145,6 +172,13 @@ - ("switch case not process\n")); - break; - } -+ -+ /* toshiba aspm issue, toshiba will set aspm selfly -+ * so we should not set aspm in driver */ -+ pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); -+ if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && -+ init_aspm == 0x43) -+ ppsc->support_aspm = false; - } - - static bool _rtl_pci_platform_switch_device_pci_aspm( -@@ -152,28 +186,28 @@ - u8 value) - { - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -- bool bresult = false; -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - -- value |= 0x40; -+ if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) -+ value |= 0x40; - - pci_write_config_byte(rtlpci->pdev, 0x80, value); - -- return bresult; -+ return false; - } - - /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ - static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) - { - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -- u8 buffer; -- bool bresult = false; -- -- buffer = value; -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pci_write_config_byte(rtlpci->pdev, 0x81, value); -- bresult = true; - -- return bresult; -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) -+ udelay(100); -+ -+ return true; - } - - /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ -@@ -191,6 +225,10 @@ - u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. - pcibridge_linkctrlreg; - u16 aspmlevel = 0; -+ u8 tmp_u1b = 0; -+ -+ if (!ppsc->support_aspm) -+ return; - - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, -@@ -204,11 +242,8 @@ - _rtl_pci_switch_clk_req(hw, 0x0); - } - -- if (1) { -- /*for promising device will in L0 state after an I/O. */ -- u8 tmp_u1b; -- pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); -- } -+ /*for promising device will in L0 state after an I/O. */ -+ pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); - - /*Set corresponding value. */ - aspmlevel |= BIT(0) | BIT(1); -@@ -224,7 +259,6 @@ - rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg); - - udelay(50); -- - } - - /* -@@ -249,6 +283,9 @@ - u8 u_pcibridge_aspmsetting; - u8 u_device_aspmsetting; - -+ if (!ppsc->support_aspm) -+ return; -+ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - ("PCI(Bridge) UNKNOWN.\n")); -@@ -293,7 +330,7 @@ - RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); - } -- udelay(200); -+ udelay(100); - } - - static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) -@@ -330,13 +367,13 @@ - u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; - u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport; - u8 linkctrl_reg; -- u8 num4bBytes; -+ u8 num4bbytes; - -- num4bBytes = (capabilityoffset + 0x10) / 4; -+ num4bbytes = (capabilityoffset + 0x10) / 4; - - /*Read Link Control Register */ - rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, -- pcicfg_addrport + (num4bBytes << 2)); -+ pcicfg_addrport + (num4bbytes << 2)); - rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg); - - pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; -@@ -369,7 +406,7 @@ - pci_write_config_byte(pdev, 0x70f, tmp); - } - --static void _rtl_pci_initialize_adapter_common(struct ieee80211_hw *hw) -+static void rtl_pci_init_aspm(struct ieee80211_hw *hw) - { - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - -@@ -383,52 +420,6 @@ - - } - --static void rtl_pci_init_aspm(struct ieee80211_hw *hw) --{ -- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -- -- /*close ASPM for AMD defaultly */ -- rtlpci->const_amdpci_aspm = 0; -- -- /* -- * ASPM PS mode. -- * 0 - Disable ASPM, -- * 1 - Enable ASPM without Clock Req, -- * 2 - Enable ASPM with Clock Req, -- * 3 - Always Enable ASPM with Clock Req, -- * 4 - Always Enable ASPM without Clock Req. -- * set defult to RTL8192CE:3 RTL8192E:2 -- * */ -- rtlpci->const_pci_aspm = 3; -- -- /*Setting for PCI-E device */ -- rtlpci->const_devicepci_aspm_setting = 0x03; -- -- /*Setting for PCI-E bridge */ -- rtlpci->const_hostpci_aspm_setting = 0x02; -- -- /* -- * In Hw/Sw Radio Off situation. -- * 0 - Default, -- * 1 - From ASPM setting without low Mac Pwr, -- * 2 - From ASPM setting with low Mac Pwr, -- * 3 - Bus D3 -- * set default to RTL8192CE:0 RTL8192SE:2 -- */ -- rtlpci->const_hwsw_rfoff_d3 = 0; -- -- /* -- * This setting works for those device with -- * backdoor ASPM setting such as EPHY setting. -- * 0 - Not support ASPM, -- * 1 - Support ASPM, -- * 2 - According to chipset. -- */ -- rtlpci->const_support_pciaspm = 1; -- -- _rtl_pci_initialize_adapter_common(hw); --} -- - static void _rtl_pci_io_handler_init(struct device *dev, - struct ieee80211_hw *hw) - { -@@ -450,6 +441,90 @@ - { - } - -+static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, -+ struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ u8 additionlen = FCS_LEN; -+ struct sk_buff *next_skb; -+ -+ /* here open is 4, wep/tkip is 8, aes is 12*/ -+ if (info->control.hw_key) -+ additionlen += info->control.hw_key->icv_len; -+ -+ /* The most skb num is 6 */ -+ tcb_desc->empkt_num = 0; -+ spin_lock_bh(&rtlpriv->locks.waitq_lock); -+ skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { -+ struct ieee80211_tx_info *next_info; -+ -+ next_info = IEEE80211_SKB_CB(next_skb); -+ if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { -+ tcb_desc->empkt_len[tcb_desc->empkt_num] = -+ next_skb->len + additionlen; -+ tcb_desc->empkt_num++; -+ } else { -+ break; -+ } -+ -+ if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], -+ next_skb)) -+ break; -+ -+ if (tcb_desc->empkt_num >= 5) -+ break; -+ } -+ spin_unlock_bh(&rtlpriv->locks.waitq_lock); -+ -+ return true; -+} -+ -+/* just for early mode now */ -+static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct sk_buff *skb = NULL; -+ struct ieee80211_tx_info *info = NULL; -+ int tid; /* should be int */ -+ -+ if (!rtlpriv->rtlhal.earlymode_enable) -+ return; -+ -+ /* we juse use em for BE/BK/VI/VO */ -+ for (tid = 7; tid >= 0; tid--) { -+ u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)]; -+ struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; -+ while (!mac->act_scanning && -+ rtlpriv->psc.rfpwr_state == ERFON) { -+ struct rtl_tcb_desc tcb_desc; -+ memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); -+ -+ spin_lock_bh(&rtlpriv->locks.waitq_lock); -+ if (!skb_queue_empty(&mac->skb_waitq[tid]) && -+ (ring->entries - skb_queue_len(&ring->queue) > 5)) { -+ skb = skb_dequeue(&mac->skb_waitq[tid]); -+ } else { -+ spin_unlock_bh(&rtlpriv->locks.waitq_lock); -+ break; -+ } -+ spin_unlock_bh(&rtlpriv->locks.waitq_lock); -+ -+ /* Some macaddr can't do early mode. like -+ * multicast/broadcast/no_qos data */ -+ info = IEEE80211_SKB_CB(skb); -+ if (info->flags & IEEE80211_TX_CTL_AMPDU) -+ _rtl_update_earlymode_info(hw, skb, -+ &tcb_desc, tid); -+ -+ rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); -+ } -+ } -+} -+ -+ - static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -461,6 +536,8 @@ - struct rtl_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - struct ieee80211_tx_info *info; -+ __le16 fc; -+ u8 tid; - - u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, - HW_DESC_OWN); -@@ -481,6 +558,10 @@ - HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - -+ /* remove early mode header */ -+ if (rtlpriv->rtlhal.earlymode_enable) -+ skb_pull(skb, EM_HDR_LEN); -+ - RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, - ("new ring->idx:%d, " - "free: skb_queue_len:%d, free: seq:%x\n", -@@ -488,6 +569,30 @@ - skb_queue_len(&ring->queue), - *(u16 *) (skb->data + 22))); - -+ if (prio == TXCMD_QUEUE) { -+ dev_kfree_skb(skb); -+ goto tx_status_ok; -+ -+ } -+ -+ /* for sw LPS, just after NULL skb send out, we can -+ * sure AP kown we are sleeped, our we should not let -+ * rf to sleep*/ -+ fc = rtl_get_fc(skb); -+ if (ieee80211_is_nullfunc(fc)) { -+ if (ieee80211_has_pm(fc)) { -+ rtlpriv->mac80211.offchan_deley = true; -+ rtlpriv->psc.state_inap = 1; -+ } else { -+ rtlpriv->psc.state_inap = 0; -+ } -+ } -+ -+ /* update tid tx pkt num */ -+ tid = rtl_get_tid(skb); -+ if (tid <= 7) -+ rtlpriv->link_info.tidtx_inperiod[tid]++; -+ - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - -@@ -510,7 +615,7 @@ - skb_get_queue_mapping - (skb)); - } -- -+tx_status_ok: - skb = NULL; - } - -@@ -582,23 +687,21 @@ - *skb_trim(skb, skb->len - 4); - */ - -- hdr = (struct ieee80211_hdr *)(skb->data); -- fc = hdr->frame_control; -+ hdr = rtl_get_hdr(skb); -+ fc = rtl_get_fc(skb); - -- if (!stats.crc) { -+ if (!stats.crc || !stats.hwerror) { - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, - sizeof(rx_status)); - -- if (is_broadcast_ether_addr(hdr->addr1)) -+ if (is_broadcast_ether_addr(hdr->addr1)) { - ;/*TODO*/ -- else { -- if (is_multicast_ether_addr(hdr->addr1)) -- ;/*TODO*/ -- else { -- unicast = true; -- rtlpriv->stats.rxbytesunicast += -- skb->len; -- } -+ } else if (is_multicast_ether_addr(hdr->addr1)) { -+ ;/*TODO*/ -+ } else { -+ unicast = true; -+ rtlpriv->stats.rxbytesunicast += -+ skb->len; - } - - rtl_is_special_data(hw, skb, false); -@@ -612,28 +715,38 @@ - num_rx_inperiod++; - } - -- if (unlikely(!rtl_action_proc(hw, skb, -- false))) { -+ /* for sw lps */ -+ rtl_swlps_beacon(hw, (void *)skb->data, -+ skb->len); -+ rtl_recognize_peer(hw, (void *)skb->data, -+ skb->len); -+ if ((rtlpriv->mac80211.opmode == -+ NL80211_IFTYPE_AP) && -+ (rtlpriv->rtlhal.current_bandtype == -+ BAND_ON_2_4G) && -+ (ieee80211_is_beacon(fc) || -+ ieee80211_is_probe_resp(fc))) { - dev_kfree_skb_any(skb); - } else { -- struct sk_buff *uskb = NULL; -- u8 *pdata; -- uskb = dev_alloc_skb(skb->len + 128); -- if (!uskb) { -- RT_TRACE(rtlpriv, -- (COMP_INTR | COMP_RECV), -- DBG_EMERG, -- ("can't alloc rx skb\n")); -- goto done; -- } -- memcpy(IEEE80211_SKB_RXCB(uskb), -- &rx_status, -- sizeof(rx_status)); -- pdata = (u8 *)skb_put(uskb, skb->len); -- memcpy(pdata, skb->data, skb->len); -- dev_kfree_skb_any(skb); -+ if (unlikely(!rtl_action_proc(hw, skb, -+ false))) { -+ dev_kfree_skb_any(skb); -+ } else { -+ struct sk_buff *uskb = NULL; -+ u8 *pdata; -+ uskb = dev_alloc_skb(skb->len -+ + 128); -+ memcpy(IEEE80211_SKB_RXCB(uskb), -+ &rx_status, -+ sizeof(rx_status)); -+ pdata = (u8 *)skb_put(uskb, -+ skb->len); -+ memcpy(pdata, skb->data, -+ skb->len); -+ dev_kfree_skb_any(skb); - -- ieee80211_rx_irqsafe(hw, uskb); -+ ieee80211_rx_irqsafe(hw, uskb); -+ } - } - } else { - dev_kfree_skb_any(skb); -@@ -648,7 +761,7 @@ - new_skb = dev_alloc_skb(rtlpci->rxbuffersize); - if (unlikely(!new_skb)) { - RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), -- DBG_EMERG, -+ DBG_DMESG, - ("can't alloc skb for rx\n")); - goto done; - } -@@ -666,7 +779,7 @@ - - } - done: -- bufferaddress = (u32)(*((dma_addr_t *) skb->cb)); -+ bufferaddress = (*((dma_addr_t *)skb->cb)); - tmp_one = 1; - rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, - HW_DESC_RXBUFF_ADDR, -@@ -695,6 +808,7 @@ - struct ieee80211_hw *hw = dev_id; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - unsigned long flags; - u32 inta = 0; - u32 intb = 0; -@@ -781,23 +895,36 @@ - _rtl_pci_tx_isr(hw, VO_QUEUE); - } - -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { -+ if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { -+ rtlpriv->link_info.num_tx_inperiod++; -+ -+ RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, -+ ("CMD TX OK interrupt!\n")); -+ _rtl_pci_tx_isr(hw, TXCMD_QUEUE); -+ } -+ } -+ - /*<2> Rx related */ - if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, ("Rx ok interrupt!\n")); -- tasklet_schedule(&rtlpriv->works.irq_tasklet); -+ _rtl_pci_rx_interrupt(hw); - } - - if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("rx descriptor unavailable!\n")); -- tasklet_schedule(&rtlpriv->works.irq_tasklet); -+ _rtl_pci_rx_interrupt(hw); - } - - if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("rx overflow !\n")); -- tasklet_schedule(&rtlpriv->works.irq_tasklet); -+ _rtl_pci_rx_interrupt(hw); - } - -+ if (rtlpriv->rtlhal.earlymode_enable) -+ tasklet_schedule(&rtlpriv->works.irq_tasklet); -+ - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - return IRQ_HANDLED; - -@@ -808,7 +935,7 @@ - - static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) - { -- _rtl_pci_rx_interrupt(hw); -+ _rtl_pci_tx_chk_waitq(hw); - } - - static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) -@@ -816,14 +943,15 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; -+ struct rtl8192_tx_ring *ring = NULL; - struct ieee80211_hdr *hdr = NULL; - struct ieee80211_tx_info *info = NULL; - struct sk_buff *pskb = NULL; - struct rtl_tx_desc *pdesc = NULL; -- unsigned int queue_index; -+ struct rtl_tcb_desc tcb_desc; - u8 temp_one = 1; - -+ memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - pskb = __skb_dequeue(&ring->queue); - if (pskb) -@@ -833,14 +961,11 @@ - pskb = ieee80211_beacon_get(hw, mac->vif); - if (pskb == NULL) - return; -- hdr = (struct ieee80211_hdr *)(pskb->data); -+ hdr = rtl_get_hdr(pskb); - info = IEEE80211_SKB_CB(pskb); -- -- queue_index = BEACON_QUEUE; -- - pdesc = &ring->desc[0]; - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, -- info, pskb, queue_index); -+ info, pskb, BEACON_QUEUE, &tcb_desc); - - __skb_queue_tail(&ring->queue, pskb); - -@@ -882,7 +1007,6 @@ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -- struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - rtlpci->up_first_time = true; - rtlpci->being_init_adapter = false; -@@ -890,31 +1014,20 @@ - rtlhal->hw = hw; - rtlpci->pdev = pdev; - -- ppsc->inactiveps = false; -- ppsc->leisure_ps = true; -- ppsc->fwctrl_lps = true; -- ppsc->reg_fwctrl_lps = 3; -- ppsc->reg_max_lps_awakeintvl = 5; -- -- if (ppsc->reg_fwctrl_lps == 1) -- ppsc->fwctrl_psmode = FW_PS_MIN_MODE; -- else if (ppsc->reg_fwctrl_lps == 2) -- ppsc->fwctrl_psmode = FW_PS_MAX_MODE; -- else if (ppsc->reg_fwctrl_lps == 3) -- ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; -- - /*Tx/Rx related var */ - _rtl_pci_init_trx_var(hw); - -- /*IBSS*/ mac->beacon_interval = 100; -+ /*IBSS*/ mac->beacon_interval = 100; - -- /*AMPDU*/ mac->min_space_cfg = 0; -+ /*AMPDU*/ -+ mac->min_space_cfg = 0; - mac->max_mss_density = 0; - /*set sane AMPDU defaults */ - mac->current_ampdu_density = 7; - mac->current_ampdu_factor = 3; - -- /*QOS*/ rtlpci->acm_method = eAcmWay2_SW; -+ /*QOS*/ -+ rtlpci->acm_method = eAcmWay2_SW; - - /*task */ - tasklet_init(&rtlpriv->works.irq_tasklet, -@@ -955,7 +1068,8 @@ - ("queue:%d, ring_addr:%p\n", prio, ring)); - - for (i = 0; i < entries; i++) { -- nextdescaddress = (u32) dma + ((i + 1) % entries) * -+ nextdescaddress = (u32) dma + -+ ((i + 1) % entries) * - sizeof(*ring); - - rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]), -@@ -1020,7 +1134,7 @@ - rtlpci->rxbuffersize, - PCI_DMA_FROMDEVICE); - -- bufferaddress = (u32)(*((dma_addr_t *)skb->cb)); -+ bufferaddress = (*((dma_addr_t *)skb->cb)); - rtlpriv->cfg->ops->set_desc((u8 *)entry, false, - HW_DESC_RXBUFF_ADDR, - (u8 *)&bufferaddress); -@@ -1203,72 +1317,73 @@ - return 0; - } - --static unsigned int _rtl_mac_to_hwqueue(__le16 fc, -- unsigned int mac80211_queue_index) -+static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, -+ struct sk_buff *skb) - { -- unsigned int hw_queue_index; -- -- if (unlikely(ieee80211_is_beacon(fc))) { -- hw_queue_index = BEACON_QUEUE; -- goto out; -- } -- -- if (ieee80211_is_mgmt(fc)) { -- hw_queue_index = MGNT_QUEUE; -- goto out; -- } -- -- switch (mac80211_queue_index) { -- case 0: -- hw_queue_index = VO_QUEUE; -- break; -- case 1: -- hw_queue_index = VI_QUEUE; -- break; -- case 2: -- hw_queue_index = BE_QUEUE;; -- break; -- case 3: -- hw_queue_index = BK_QUEUE; -- break; -- default: -- hw_queue_index = BE_QUEUE; -- RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n", -- mac80211_queue_index)); -- break; -- } -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct ieee80211_sta *sta = info->control.sta; -+ struct rtl_sta_info *sta_entry = NULL; -+ u8 tid = rtl_get_tid(skb); -+ -+ if (!sta) -+ return false; -+ sta_entry = (struct rtl_sta_info *)sta->drv_priv; -+ -+ if (!rtlpriv->rtlhal.earlymode_enable) -+ return false; -+ if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) -+ return false; -+ if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) -+ return false; -+ if (tid > 7) -+ return false; -+ -+ /* maybe every tid should be checked */ -+ if (!rtlpriv->link_info.higher_busytxtraffic[tid]) -+ return false; -+ -+ spin_lock_bh(&rtlpriv->locks.waitq_lock); -+ skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); -+ spin_unlock_bh(&rtlpriv->locks.waitq_lock); - --out: -- return hw_queue_index; -+ return true; - } - --static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -+static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, -+ struct rtl_tcb_desc *ptcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry = NULL; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct ieee80211_sta *sta = info->control.sta; - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - u8 idx; -- unsigned int queue_index, hw_queue; -+ u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); - unsigned long flags; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); -- __le16 fc = hdr->frame_control; -+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb); -+ __le16 fc = rtl_get_fc(skb); - u8 *pda_addr = hdr->addr1; - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - /*ssn */ -- u8 *qc = NULL; - u8 tid = 0; - u16 seq_number = 0; - u8 own; - u8 temp_one = 1; - -- if (ieee80211_is_mgmt(fc)) -- rtl_tx_mgmt_proc(hw, skb); -- rtl_action_proc(hw, skb, true); -+ if (ieee80211_is_auth(fc)) { -+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); -+ rtl_ips_nic_on(hw); -+ } -+ -+ if (rtlpriv->psc.sw_ps_enabled) { -+ if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && -+ !ieee80211_has_pm(fc)) -+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); -+ } - -- queue_index = skb_get_queue_mapping(skb); -- hw_queue = _rtl_mac_to_hwqueue(fc, queue_index); -+ rtl_action_proc(hw, skb, true); - - if (is_multicast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesmulticast += skb->len; -@@ -1278,7 +1393,6 @@ - rtlpriv->stats.txbytesunicast += skb->len; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); -- - ring = &rtlpci->tx_ring[hw_queue]; - if (hw_queue != BEACON_QUEUE) - idx = (ring->idx + skb_queue_len(&ring->queue)) % -@@ -1301,43 +1415,30 @@ - return skb->len; - } - -- /* -- *if(ieee80211_is_nullfunc(fc)) { -- * spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -- * return 1; -- *} -- */ -- - if (ieee80211_is_data_qos(fc)) { -- qc = ieee80211_get_qos_ctl(hdr); -- tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; -+ tid = rtl_get_tid(skb); -+ if (sta) { -+ sta_entry = (struct rtl_sta_info *)sta->drv_priv; -+ seq_number = (le16_to_cpu(hdr->seq_ctrl) & -+ IEEE80211_SCTL_SEQ) >> 4; -+ seq_number += 1; - -- seq_number = mac->tids[tid].seq_number; -- seq_number &= IEEE80211_SCTL_SEQ; -- /* -- *hdr->seq_ctrl = hdr->seq_ctrl & -- *cpu_to_le16(IEEE80211_SCTL_FRAG); -- *hdr->seq_ctrl |= cpu_to_le16(seq_number); -- */ -- -- seq_number += 1; -+ if (!ieee80211_has_morefrags(hdr->frame_control)) -+ sta_entry->tids[tid].seq_number = seq_number; -+ } - } - - if (ieee80211_is_data(fc)) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - -- rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, -- info, skb, hw_queue); -+ rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, -+ info, skb, hw_queue, ptcb_desc); - - __skb_queue_tail(&ring->queue, skb); - -- rtlpriv->cfg->ops->set_desc((u8 *) pdesc, true, -+ rtlpriv->cfg->ops->set_desc((u8 *)pdesc, true, - HW_DESC_OWN, (u8 *)&temp_one); - -- if (!ieee80211_has_morefrags(hdr->frame_control)) { -- if (qc) -- mac->tids[tid].seq_number = seq_number; -- } - - if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && - hw_queue != BEACON_QUEUE) { -@@ -1359,6 +1460,35 @@ - return 0; - } - -+static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u16 i = 0; -+ int queue_id; -+ struct rtl8192_tx_ring *ring; -+ -+ for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { -+ u32 queue_len; -+ ring = &pcipriv->dev.tx_ring[queue_id]; -+ queue_len = skb_queue_len(&ring->queue); -+ if (queue_len == 0 || queue_id == BEACON_QUEUE || -+ queue_id == TXCMD_QUEUE) { -+ queue_id--; -+ continue; -+ } else { -+ msleep(20); -+ i++; -+ } -+ -+ /* we just wait 1s for all queues */ -+ if (rtlpriv->psc.rfpwr_state == ERFOFF || -+ is_hal_stop(rtlhal) || i >= 200) -+ return; -+ } -+} -+ - static void rtl_pci_deinit(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -1477,11 +1607,13 @@ - struct pci_dev *bridge_pdev = pdev->bus->self; - u16 venderid; - u16 deviceid; -+ u8 revisionid; - u16 irqline; - u8 tmp; - - venderid = pdev->vendor; - deviceid = pdev->device; -+ pci_read_config_byte(pdev, 0x8, &revisionid); - pci_read_config_word(pdev, 0x3C, &irqline); - - if (deviceid == RTL_PCI_8192_DID || -@@ -1492,7 +1624,7 @@ - deviceid == RTL_PCI_8173_DID || - deviceid == RTL_PCI_8172_DID || - deviceid == RTL_PCI_8171_DID) { -- switch (pdev->revision) { -+ switch (revisionid) { - case RTL_PCI_REVISION_ID_8192PCIE: - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - ("8192 PCI-E is found - " -@@ -1521,6 +1653,12 @@ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - ("8192C PCI-E is found - " - "vid/did=%x/%x\n", venderid, deviceid)); -+ } else if (deviceid == RTL_PCI_8192DE_DID || -+ deviceid == RTL_PCI_8192DE_DID2) { -+ rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, -+ ("8192D PCI-E is found - " -+ "vid/did=%x/%x\n", venderid, deviceid)); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("Err: Unknown device -" -@@ -1529,6 +1667,25 @@ - rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; - } - -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { -+ if (revisionid == 0 || revisionid == 1) { -+ if (revisionid == 0) { -+ RT_TRACE(rtlpriv, COMP_INIT, -+ DBG_LOUD, ("Find 92DE MAC0.\n")); -+ rtlhal->interfaceindex = 0; -+ } else if (revisionid == 1) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("Find 92DE MAC1.\n")); -+ rtlhal->interfaceindex = 1; -+ } -+ } else { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("Unknown device - " -+ "VendorID/DeviceID=%x/%x, Revision=%x\n", -+ venderid, deviceid, revisionid)); -+ rtlhal->interfaceindex = 0; -+ } -+ } - /*find bus info */ - pcipriv->ndis_adapter.busnumber = pdev->bus->number; - pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); -@@ -1554,12 +1711,12 @@ - PCI_SLOT(bridge_pdev->devfn); - pcipriv->ndis_adapter.pcibridge_funcnum = - PCI_FUNC(bridge_pdev->devfn); -- pcipriv->ndis_adapter.pcibridge_pciehdr_offset = -- pci_pcie_cap(bridge_pdev); - pcipriv->ndis_adapter.pcicfg_addrport = - (pcipriv->ndis_adapter.pcibridge_busnum << 16) | - (pcipriv->ndis_adapter.pcibridge_devnum << 11) | - (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31); -+ pcipriv->ndis_adapter.pcibridge_pciehdr_offset = -+ pci_pcie_cap(bridge_pdev); - pcipriv->ndis_adapter.num4bytes = - (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; - -@@ -1642,6 +1799,11 @@ - pcipriv = (void *)rtlpriv->priv; - pcipriv->dev.pdev = pdev; - -+ /* init cfg & intf_ops */ -+ rtlpriv->rtlhal.interface = INTF_PCI; -+ rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); -+ rtlpriv->intf_ops = &rtl_pci_ops; -+ - /* - *init dbgp flags before all - *other functions, because we will -@@ -1659,13 +1821,14 @@ - return err; - } - -- pmem_start = pci_resource_start(pdev, 2); -- pmem_len = pci_resource_len(pdev, 2); -- pmem_flags = pci_resource_flags(pdev, 2); -+ pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); -+ pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); -+ pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); - - /*shared mem start */ - rtlpriv->io.pci_mem_start = -- (unsigned long)pci_iomap(pdev, 2, pmem_len); -+ (unsigned long)pci_iomap(pdev, -+ rtlpriv->cfg->bar_id, pmem_len); - if (rtlpriv->io.pci_mem_start == 0) { - RT_ASSERT(false, ("Can't map PCI mem\n")); - goto fail2; -@@ -1684,11 +1847,6 @@ - pci_write_config_byte(pdev, 0x04, 0x06); - pci_write_config_byte(pdev, 0x04, 0x07); - -- /* init cfg & intf_ops */ -- rtlpriv->rtlhal.interface = INTF_PCI; -- rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); -- rtlpriv->intf_ops = &rtl_pci_ops; -- - /* find adapter */ - _rtl_pci_find_adapter(pdev, hw); - -@@ -1806,7 +1964,6 @@ - - rtl_pci_deinit(hw); - rtl_deinit_core(hw); -- rtlpriv->cfg->ops->deinit_sw_leds(hw); - _rtl_pci_io_handler_release(hw); - rtlpriv->cfg->ops->deinit_sw_vars(hw); - -@@ -1821,6 +1978,9 @@ - } - - pci_disable_device(pdev); -+ -+ rtl_pci_disable_aspm(hw); -+ - pci_set_drvdata(pdev, NULL); - - ieee80211_free_hw(hw); -@@ -1844,10 +2004,15 @@ - ****************************************/ - int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state) - { -+ struct ieee80211_hw *hw = pci_get_drvdata(pdev); -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtlpriv->cfg->ops->hw_suspend(hw); -+ rtl_deinit_rfkill(hw); -+ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); -- - return 0; - } - EXPORT_SYMBOL(rtl_pci_suspend); -@@ -1855,6 +2020,8 @@ - int rtl_pci_resume(struct pci_dev *pdev) - { - int ret; -+ struct ieee80211_hw *hw = pci_get_drvdata(pdev); -+ struct rtl_priv *rtlpriv = rtl_priv(hw); - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); -@@ -1865,15 +2032,20 @@ - - pci_restore_state(pdev); - -+ rtlpriv->cfg->ops->hw_resume(hw); -+ rtl_init_rfkill(hw); - return 0; - } - EXPORT_SYMBOL(rtl_pci_resume); - - struct rtl_intf_ops rtl_pci_ops = { -+ .read_efuse_byte = read_efuse_byte, - .adapter_start = rtl_pci_start, - .adapter_stop = rtl_pci_stop, - .adapter_tx = rtl_pci_tx, -+ .flush = rtl_pci_flush, - .reset_trx_ring = rtl_pci_reset_trx_ring, -+ .waitq_insert = rtl_pci_tx_chk_waitq_insert, - - .disable_aspm = rtl_pci_disable_aspm, - .enable_aspm = rtl_pci_enable_aspm, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/pci.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/pci.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/pci.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/pci.h 2011-05-05 23:29:49.269487583 +0200 -@@ -102,8 +102,8 @@ - #define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ - #define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ - #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ --#define RTL_PCI_8192DE_DID 0x092D /*8192ce */ --#define RTL_PCI_8192DU_DID 0x092D /*8192ce */ -+#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ -+#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ - - /*8192 support 16 pages of IO registers*/ - #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 -@@ -129,6 +129,11 @@ - PCI_BRIDGE_VENDOR_MAX, - }; - -+struct rtl_pci_capabilities_header { -+ u8 capability_id; -+ u8 next; -+}; -+ - struct rtl_rx_desc { - u32 dword[8]; - } __packed; -@@ -161,7 +166,9 @@ - - bool driver_is_goingto_unload; - bool up_first_time; -+ bool first_init; - bool being_init_adapter; -+ bool init_ready; - bool irq_enabled; - - /*Tx */ -@@ -192,11 +199,14 @@ - u8 const_devicepci_aspm_setting; - /*If it supports ASPM, Offset[560h] = 0x40, - otherwise Offset[560h] = 0x00. */ -- bool b_support_aspm; -- bool b_support_backdoor; -+ bool support_aspm; -+ bool support_backdoor; - - /*QOS & EDCA */ - enum acm_method acm_method; -+ -+ u16 shortretry_limit; -+ u16 longretry_limit; - }; - - struct mp_adapter { -@@ -227,6 +237,7 @@ - struct rtl_pci dev; - struct mp_adapter ndis_adapter; - struct rtl_led_ctl ledctl; -+ struct bt_coexist_info bt_coexist; - }; - - #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/ps.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/ps.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/ps.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/ps.c 2011-05-05 23:29:49.310488079 +0200 -@@ -36,7 +36,6 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -- bool init_status = true; - - /*<1> reset trx ring */ - if (rtlhal->interface == INTF_PCI) -@@ -49,7 +48,6 @@ - /*<2> Enable Adapter */ - rtlpriv->cfg->ops->hw_init(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); -- /*init_status = false; */ - - /*<3> Enable Interrupt */ - rtlpriv->cfg->ops->enable_interrupt(hw); -@@ -57,13 +55,12 @@ - /* */ - rtl_watch_dog_timer_callback((unsigned long)hw); - -- return init_status; -+ return true; - } - EXPORT_SYMBOL(rtl_ps_enable_nic); - - bool rtl_ps_disable_nic(struct ieee80211_hw *hw) - { -- bool status = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /*<1> Stop all timer */ -@@ -75,7 +72,7 @@ - /*<3> Disable Adapter */ - rtlpriv->cfg->ops->hw_disable(hw); - -- return status; -+ return true; - } - EXPORT_SYMBOL(rtl_ps_disable_nic); - -@@ -193,12 +190,13 @@ - - ppsc->swrf_processing = true; - -- if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { -+ if (ppsc->inactive_pwrstate == ERFOFF && -+ rtlhal->interface == INTF_PCI) { - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && -- RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM) && -+ RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && - rtlhal->interface == INTF_PCI) { - rtlpriv->intf_ops->disable_aspm(hw); -- RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -+ RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - } - -@@ -207,9 +205,10 @@ - - if (ppsc->inactive_pwrstate == ERFOFF && - rtlhal->interface == INTF_PCI) { -- if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { -+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && -+ !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->enable_aspm(hw); -- RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -+ RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - } - -@@ -233,6 +232,9 @@ - return; - } - -+ if (mac->link_state > MAC80211_NOLINK) -+ return; -+ - if (is_hal_stop(rtlhal)) - return; - -@@ -284,10 +286,14 @@ - void rtl_ips_nic_on(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate rtstate; - unsigned long flags; - -+ if (mac->opmode != NL80211_IFTYPE_STATION) -+ return; -+ - spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); - - if (ppsc->inactiveps) { -@@ -370,8 +376,7 @@ - * mode and set RPWM to turn RF on. - */ - -- if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) && -- ppsc->report_linked) { -+ if ((ppsc->fwctrl_lps) && ppsc->report_linked) { - bool fw_current_inps; - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, -@@ -425,7 +430,7 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned long flag; - -- if (!(ppsc->fwctrl_lps && ppsc->leisure_ps)) -+ if (!ppsc->fwctrl_lps) - return; - - if (rtlpriv->sec.being_setkey) -@@ -446,17 +451,16 @@ - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - -- if (ppsc->leisure_ps) { -- /* Idle for a while if we connect to AP a while ago. */ -- if (mac->cnt_after_linked >= 2) { -- if (ppsc->dot11_psmode == EACTIVE) { -- RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ /* Idle for a while if we connect to AP a while ago. */ -+ if (mac->cnt_after_linked >= 2) { -+ if (ppsc->dot11_psmode == EACTIVE) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("Enter 802.11 power save mode...\n")); - -- rtl_lps_set_psmode(hw, EAUTOPS); -- } -+ rtl_lps_set_psmode(hw, EAUTOPS); - } - } -+ - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); - } - -@@ -470,17 +474,17 @@ - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - -- if (ppsc->fwctrl_lps && ppsc->leisure_ps) { -+ if (ppsc->fwctrl_lps) { - if (ppsc->dot11_psmode != EACTIVE) { - - /*FIX ME */ - rtlpriv->cfg->ops->enable_interrupt(hw); - - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && -- RT_IN_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM) && -+ RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && - rtlhal->interface == INTF_PCI) { - rtlpriv->intf_ops->disable_aspm(hw); -- RT_CLEAR_PS_LEVEL(ppsc, RT_RF_LPS_LEVEL_ASPM); -+ RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -@@ -491,3 +495,214 @@ - } - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); - } -+ -+/* For sw LPS*/ -+void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct ieee80211_hdr *hdr = (void *) data; -+ struct ieee80211_tim_ie *tim_ie; -+ u8 *tim; -+ u8 tim_len; -+ bool u_buffed; -+ bool m_buffed; -+ -+ if (mac->opmode != NL80211_IFTYPE_STATION) -+ return; -+ -+ if (!rtlpriv->psc.swctrl_lps) -+ return; -+ -+ if (rtlpriv->mac80211.link_state != MAC80211_LINKED) -+ return; -+ -+ if (!rtlpriv->psc.sw_ps_enabled) -+ return; -+ -+ if (rtlpriv->psc.fwctrl_lps) -+ return; -+ -+ if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) -+ return; -+ -+ /* check if this really is a beacon */ -+ if (!ieee80211_is_beacon(hdr->frame_control)) -+ return; -+ -+ /* min. beacon length + FCS_LEN */ -+ if (len <= 40 + FCS_LEN) -+ return; -+ -+ /* and only beacons from the associated BSSID, please */ -+ if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) -+ return; -+ -+ rtlpriv->psc.last_beacon = jiffies; -+ -+ tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); -+ if (!tim) -+ return; -+ -+ if (tim[1] < sizeof(*tim_ie)) -+ return; -+ -+ tim_len = tim[1]; -+ tim_ie = (struct ieee80211_tim_ie *) &tim[2]; -+ -+ if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) -+ rtlpriv->psc.dtim_counter = tim_ie->dtim_count; -+ -+ /* Check whenever the PHY can be turned off again. */ -+ -+ /* 1. What about buffered unicast traffic for our AID? */ -+ u_buffed = ieee80211_check_tim(tim_ie, tim_len, -+ rtlpriv->mac80211.assoc_id); -+ -+ /* 2. Maybe the AP wants to send multicast/broadcast data? */ -+ m_buffed = tim_ie->bitmap_ctrl & 0x01; -+ rtlpriv->psc.multi_buffered = m_buffed; -+ -+ /* unicast will process by mac80211 through -+ * set ~IEEE80211_CONF_PS, So we just check -+ * multicast frames here */ -+ if (!m_buffed) { -+ /* back to low-power land. and delay is -+ * prevent null power save frame tx fail */ -+ queue_delayed_work(rtlpriv->works.rtl_wq, -+ &rtlpriv->works.ps_work, MSECS(5)); -+ } else { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("u_bufferd: %x, " -+ "m_buffered: %x\n", u_buffed, m_buffed)); -+ } -+} -+ -+void rtl_swlps_rf_awake(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ unsigned long flag; -+ -+ if (!rtlpriv->psc.swctrl_lps) -+ return; -+ if (mac->link_state != MAC80211_LINKED) -+ return; -+ -+ if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && -+ RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { -+ rtlpriv->intf_ops->disable_aspm(hw); -+ RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); -+ } -+ -+ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); -+ rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); -+ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -+} -+ -+void rtl_swlps_rfon_wq_callback(void *data) -+{ -+ struct rtl_works *rtlworks = -+ container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); -+ struct ieee80211_hw *hw = rtlworks->hw; -+ -+ rtl_swlps_rf_awake(hw); -+} -+ -+void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ unsigned long flag; -+ u8 sleep_intv; -+ -+ if (!rtlpriv->psc.sw_ps_enabled) -+ return; -+ -+ if ((rtlpriv->sec.being_setkey) || -+ (mac->opmode == NL80211_IFTYPE_ADHOC)) -+ return; -+ -+ /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ -+ if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) -+ return; -+ -+ if (rtlpriv->link_info.busytraffic) -+ return; -+ -+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -+ if (rtlpriv->psc.rfchange_inprogress) { -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ return; -+ } -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ -+ spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); -+ rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false); -+ spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -+ -+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && -+ !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { -+ rtlpriv->intf_ops->enable_aspm(hw); -+ RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); -+ } -+ -+ /* here is power save alg, when this beacon is DTIM -+ * we will set sleep time to dtim_period * n; -+ * when this beacon is not DTIM, we will set sleep -+ * time to sleep_intv = rtlpriv->psc.dtim_counter or -+ * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ -+ -+ if (rtlpriv->psc.dtim_counter == 0) { -+ if (hw->conf.ps_dtim_period == 1) -+ sleep_intv = hw->conf.ps_dtim_period * 2; -+ else -+ sleep_intv = hw->conf.ps_dtim_period; -+ } else { -+ sleep_intv = rtlpriv->psc.dtim_counter; -+ } -+ -+ if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) -+ sleep_intv = MAX_SW_LPS_SLEEP_INTV; -+ -+ /* this print should always be dtim_conter = 0 & -+ * sleep = dtim_period, that meaons, we should -+ * awake before every dtim */ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, -+ ("dtim_counter:%x will sleep :%d" -+ " beacon_intv\n", rtlpriv->psc.dtim_counter, sleep_intv)); -+ -+ /* we tested that 40ms is enough for sw & hw sw delay */ -+ queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, -+ MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); -+} -+ -+ -+void rtl_swlps_wq_callback(void *data) -+{ -+ struct rtl_works *rtlworks = container_of_dwork_rtl(data, -+ struct rtl_works, -+ ps_work); -+ struct ieee80211_hw *hw = rtlworks->hw; -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ bool ps = false; -+ -+ ps = (hw->conf.flags & IEEE80211_CONF_PS); -+ -+ /* we can sleep after ps null send ok */ -+ if (rtlpriv->psc.state_inap) { -+ rtl_swlps_rf_sleep(hw); -+ -+ if (rtlpriv->psc.state && !ps) { -+ rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - -+ rtlpriv->psc.last_action); -+ } -+ -+ if (ps) -+ rtlpriv->psc.last_slept = jiffies; -+ -+ rtlpriv->psc.last_action = jiffies; -+ rtlpriv->psc.state = ps; -+ } -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/ps.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/ps.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/ps.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/ps.h 2011-05-05 23:29:49.268487571 +0200 -@@ -30,6 +30,8 @@ - #ifndef __REALTEK_RTL_PCI_PS_H__ - #define __REALTEK_RTL_PCI_PS_H__ - -+#define MAX_SW_LPS_SLEEP_INTV 5 -+ - bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, - enum rf_pwrstate state_toset, u32 changesource, - bool protect_or_not); -@@ -40,4 +42,11 @@ - void rtl_ips_nic_off_wq_callback(void *data); - void rtl_lps_enter(struct ieee80211_hw *hw); - void rtl_lps_leave(struct ieee80211_hw *hw); -+ -+void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); -+void rtl_swlps_wq_callback(void *data); -+void rtl_swlps_rfon_wq_callback(void *data); -+void rtl_swlps_rf_awake(struct ieee80211_hw *hw); -+void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); -+ - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rc.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rc.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rc.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rc.c 2011-05-05 23:29:49.333488357 +0200 -@@ -38,17 +38,14 @@ - *CCK11M or OFDM_54M based on wireless mode. - */ - static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, -+ struct ieee80211_sta *sta, - struct sk_buff *skb, bool not_data) - { - struct rtl_mac *rtlmac = rtl_mac(rtlpriv); -- -- /* -- *mgt use 1M, although we have check it -- *before this function use rate_control_send_low, -- *we still check it here -- */ -- if (not_data) -- return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; -+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_sta_info *sta_entry = NULL; -+ u8 wireless_mode = 0; - - /* - *this rate is no use for true rate, firmware -@@ -57,35 +54,78 @@ - *2.in rtl_get_tcb_desc when we check rate is - * 1M we will not use FW rate but user rate. - */ -- if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { -- return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; -+ if (rtlmac->opmode == NL80211_IFTYPE_AP || -+ rtlmac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (sta) { -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ wireless_mode = sta_entry->wireless_mode; -+ } else { -+ return 0; -+ } -+ } else { -+ wireless_mode = rtlmac->mode; -+ } -+ -+ if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) || -+ not_data) { -+ return 0; - } else { -- if (rtlmac->mode == WIRELESS_MODE_B) -- return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; -- else -- return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; -+ if (rtlhal->current_bandtype == BAND_ON_2_4G) { -+ if (wireless_mode == WIRELESS_MODE_B) { -+ return B_MODE_MAX_RIX; -+ } else if (wireless_mode == WIRELESS_MODE_G) { -+ return G_MODE_MAX_RIX; -+ } else { -+ if (get_rf_type(rtlphy) != RF_2T2R) -+ return N_MODE_MCS7_RIX; -+ else -+ return N_MODE_MCS15_RIX; -+ } -+ } else { -+ if (wireless_mode == WIRELESS_MODE_A) { -+ return A_MODE_MAX_RIX; -+ } else { -+ if (get_rf_type(rtlphy) != RF_2T2R) -+ return N_MODE_MCS7_RIX; -+ else -+ return N_MODE_MCS15_RIX; -+ } -+ } - } - } - - static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, -+ struct ieee80211_sta *sta, - struct ieee80211_tx_rate *rate, - struct ieee80211_tx_rate_control *txrc, -- u8 tries, u8 rix, int rtsctsenable, -+ u8 tries, char rix, int rtsctsenable, - bool not_data) - { - struct rtl_mac *mac = rtl_mac(rtlpriv); -+ u8 sgi_20 = 0, sgi_40 = 0; - -+ if (sta) { -+ sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; -+ sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; -+ } - rate->count = tries; -- rate->idx = (rix > 0x2) ? rix : 0x2; -+ rate->idx = rix >= 0x00 ? rix : 0x00; - - if (!not_data) { - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; -- if (mac->bw_40) -- rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -- if (mac->sgi_20 || mac->sgi_40) -+ if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (sta && (sta->ht_cap.cap & -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -+ } else { -+ if (mac->bw_40) -+ rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -+ } -+ if (sgi_20 || sgi_40) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; -- if (mac->ht_enable) -+ if (sta && sta->ht_cap.ht_supported) - rate->flags |= IEEE80211_TX_RC_MCS; - } - } -@@ -97,39 +137,39 @@ - struct sk_buff *skb = txrc->skb; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->control.rates; -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -- __le16 fc = hdr->frame_control; -+ __le16 fc = rtl_get_fc(skb); - u8 try_per_rate, i, rix; - bool not_data = !ieee80211_is_data(fc); - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - -- rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); -- -+ rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); - try_per_rate = 1; -- _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, -+ _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, - try_per_rate, rix, 1, not_data); - - if (!not_data) { - for (i = 1; i < 4; i++) -- _rtl_rc_rate_set_series(rtlpriv, &rates[i], -+ _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], - txrc, i, (rix - i), 1, - not_data); - } - } - --static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) -+static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, -+ struct rtl_sta_info *sta_entry, u16 tid) - { - struct rtl_mac *mac = rtl_mac(rtlpriv); - - if (mac->act_scanning) - return false; - -- if (mac->cnt_after_linked < 3) -+ if (mac->opmode == NL80211_IFTYPE_STATION && -+ mac->cnt_after_linked < 3) - return false; - -- if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) -+ if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) - return true; - - return false; -@@ -143,11 +183,9 @@ - { - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); -- struct ieee80211_hdr *hdr; -- __le16 fc; -- -- hdr = (struct ieee80211_hdr *)skb->data; -- fc = hdr->frame_control; -+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb); -+ __le16 fc = rtl_get_fc(skb); -+ struct rtl_sta_info *sta_entry; - - if (!priv_sta || !ieee80211_is_data(fc)) - return; -@@ -159,17 +197,21 @@ - || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) - return; - -- /* Check if aggregation has to be enabled for this tid */ -- if (conf_is_ht(&mac->hw->conf) && -- !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { -- if (ieee80211_is_data_qos(fc)) { -- u8 *qc, tid; -- -- qc = ieee80211_get_qos_ctl(hdr); -- tid = qc[0] & 0xf; -- -- if (_rtl_tx_aggr_check(rtlpriv, tid)) -- ieee80211_start_tx_ba_session(sta, tid, 5000); -+ if (sta) { -+ /* Check if aggregation has to be enabled for this tid */ -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ if ((sta->ht_cap.ht_supported == true) && -+ !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { -+ if (ieee80211_is_data_qos(fc)) { -+ u8 tid = rtl_get_tid(skb); -+ if (_rtl_tx_aggr_check(rtlpriv, sta_entry, -+ tid)) { -+ sta_entry->tids[tid].agg.agg_state = -+ RTL_AGG_PROGRESS; -+ ieee80211_start_tx_ba_session(sta, -+ tid, 5000); -+ } -+ } - } - } - } -@@ -178,43 +220,6 @@ - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) - { -- struct rtl_priv *rtlpriv = ppriv; -- struct rtl_mac *mac = rtl_mac(rtlpriv); -- u8 is_ht = conf_is_ht(&mac->hw->conf); -- -- if ((mac->opmode == NL80211_IFTYPE_STATION) || -- (mac->opmode == NL80211_IFTYPE_MESH_POINT) || -- (mac->opmode == NL80211_IFTYPE_ADHOC)) { -- -- switch (sband->band) { -- case IEEE80211_BAND_2GHZ: -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_G; -- if (is_ht) -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- case IEEE80211_BAND_5GHZ: -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_A; -- if (is_ht) -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- default: -- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -- ("Invalid band\n")); -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- } -- -- RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, -- ("Choosing rate table index: %d\n", -- rtlpriv->rate_priv->cur_ratetab_idx)); -- -- } -- - } - - static void rtl_rate_update(void *ppriv, -@@ -223,49 +228,6 @@ - u32 changed, - enum nl80211_channel_type oper_chan_type) - { -- struct rtl_priv *rtlpriv = ppriv; -- struct rtl_mac *mac = rtl_mac(rtlpriv); -- struct rtl_hal *rtlhal = rtl_hal(rtlpriv); -- bool oper_cw40 = false, oper_sgi40; -- bool local_cw40 = mac->bw_40; -- bool local_sgi40 = mac->sgi_40; -- u8 is_ht = conf_is_ht(&mac->hw->conf); -- -- if (changed & IEEE80211_RC_HT_CHANGED) { -- if (mac->opmode != NL80211_IFTYPE_STATION) -- return; -- -- if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || -- rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) -- oper_cw40 = true; -- -- oper_sgi40 = mac->sgi_40; -- -- if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { -- switch (sband->band) { -- case IEEE80211_BAND_2GHZ: -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_G; -- if (is_ht) -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- case IEEE80211_BAND_5GHZ: -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_A; -- if (is_ht) -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- default: -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Invalid band\n")); -- rtlpriv->rate_priv->cur_ratetab_idx = -- RATR_INX_WIRELESS_NGB; -- break; -- } -- } -- } - } - - static void *rtl_rate_alloc(struct ieee80211_hw *hw, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rc.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rc.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rc.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rc.h 2011-05-05 23:29:49.230487113 +0200 -@@ -30,8 +30,15 @@ - #ifndef __RTL_RC_H__ - #define __RTL_RC_H__ - -+#define B_MODE_MAX_RIX 3 -+#define G_MODE_MAX_RIX 11 -+#define A_MODE_MAX_RIX 7 -+ -+/* in mac80211 mcs0-mcs15 is idx0-idx15*/ -+#define N_MODE_MCS7_RIX 7 -+#define N_MODE_MCS15_RIX 15 -+ - struct rtl_rate_priv { -- u8 cur_ratetab_idx; - u8 ht_cap; - }; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/regd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/regd.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/regd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/regd.c 2011-05-05 23:29:49.236487185 +0200 -@@ -66,31 +66,83 @@ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_OFDM) - -+/* 5G chan 36 - chan 64*/ -+#define RTL819x_5GHZ_5150_5350 \ -+ REG_RULE(5150-10, 5350+10, 40, 0, 30, \ -+ NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IBSS) -+ -+/* 5G chan 100 - chan 165*/ -+#define RTL819x_5GHZ_5470_5850 \ -+ REG_RULE(5470-10, 5850+10, 40, 0, 30, \ -+ NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IBSS) -+ -+/* 5G chan 149 - chan 165*/ -+#define RTL819x_5GHZ_5725_5850 \ -+ REG_RULE(5725-10, 5850+10, 40, 0, 30, \ -+ NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IBSS) -+ -+#define RTL819x_5GHZ_ALL \ -+ (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) -+ - static const struct ieee80211_regdomain rtl_regdom_11 = { - .n_reg_rules = 1, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, -- } -+ } -+}; -+ -+static const struct ieee80211_regdomain rtl_regdom_12_13 = { -+ .n_reg_rules = 2, -+ .alpha2 = "99", -+ .reg_rules = { -+ RTL819x_2GHZ_CH01_11, -+ RTL819x_2GHZ_CH12_13, -+ } - }; - --static const struct ieee80211_regdomain rtl_regdom_global = { -+static const struct ieee80211_regdomain rtl_regdom_no_midband = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, -- RTL819x_2GHZ_CH12_13, -- RTL819x_2GHZ_CH14, -- } -+ RTL819x_5GHZ_5150_5350, -+ RTL819x_5GHZ_5725_5850, -+ } - }; - --static const struct ieee80211_regdomain rtl_regdom_world = { -- .n_reg_rules = 2, -+static const struct ieee80211_regdomain rtl_regdom_60_64 = { -+ .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, -- RTL819x_2GHZ_CH12_13, -- } -+ RTL819x_2GHZ_CH12_13, -+ RTL819x_5GHZ_5725_5850, -+ } -+}; -+ -+static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { -+ .n_reg_rules = 4, -+ .alpha2 = "99", -+ .reg_rules = { -+ RTL819x_2GHZ_CH01_11, -+ RTL819x_2GHZ_CH12_13, -+ RTL819x_2GHZ_CH14, -+ RTL819x_5GHZ_5725_5850, -+ } -+}; -+ -+static const struct ieee80211_regdomain rtl_regdom_14 = { -+ .n_reg_rules = 3, -+ .alpha2 = "99", -+ .reg_rules = { -+ RTL819x_2GHZ_CH01_11, -+ RTL819x_2GHZ_CH12_13, -+ RTL819x_2GHZ_CH14, -+ } - }; - - static bool _rtl_is_radar_freq(u16 center_freq) -@@ -162,6 +214,8 @@ - u32 bandwidth = 0; - int r; - -+ if (!wiphy->bands[IEEE80211_BAND_2GHZ]) -+ return; - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - - /* -@@ -292,25 +346,26 @@ - { - switch (reg->country_code) { - case COUNTRY_CODE_FCC: -+ return &rtl_regdom_no_midband; - case COUNTRY_CODE_IC: - return &rtl_regdom_11; - case COUNTRY_CODE_ETSI: -+ case COUNTRY_CODE_TELEC_NETGEAR: -+ return &rtl_regdom_60_64; - case COUNTRY_CODE_SPAIN: - case COUNTRY_CODE_FRANCE: - case COUNTRY_CODE_ISRAEL: -- case COUNTRY_CODE_TELEC_NETGEAR: -- return &rtl_regdom_world; -+ case COUNTRY_CODE_WORLD_WIDE_13: -+ return &rtl_regdom_12_13; - case COUNTRY_CODE_MKK: - case COUNTRY_CODE_MKK1: - case COUNTRY_CODE_TELEC: - case COUNTRY_CODE_MIC: -- return &rtl_regdom_global; -+ return &rtl_regdom_14_60_64; - case COUNTRY_CODE_GLOBAL_DOMAIN: -- return &rtl_regdom_global; -- case COUNTRY_CODE_WORLD_WIDE_13: -- return &rtl_regdom_world; -+ return &rtl_regdom_14; - default: -- return &rtl_regdom_world; -+ return &rtl_regdom_no_midband; - } - } - -@@ -323,9 +378,11 @@ - const struct ieee80211_regdomain *regd; - - wiphy->reg_notifier = reg_notifier; -+ - wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY; - wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS; -+ - regd = _rtl_regdomain_select(reg); - wiphy_apply_custom_regulatory(wiphy, regd); - _rtl_reg_apply_radar_flags(wiphy); -@@ -355,8 +412,8 @@ - if (wiphy == NULL || &rtlpriv->regd == NULL) - return -EINVAL; - -- /* force the channel plan to world wide 13 */ -- rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; -+ /* init country_code from efuse channel plan */ -+ rtlpriv->regd.country_code = rtlpriv->efuse.channel_plan; - - RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, - (KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", -@@ -373,8 +430,8 @@ - country = _rtl_regd_find_country(rtlpriv->regd.country_code); - - if (country) { -- rtlpriv->regd.alpha2[0] = country->isoName[0]; -- rtlpriv->regd.alpha2[1] = country->isoName[1]; -+ rtlpriv->regd.alpha2[0] = country->iso_name[0]; -+ rtlpriv->regd.alpha2[1] = country->iso_name[1]; - } else { - rtlpriv->regd.alpha2[0] = '0'; - rtlpriv->regd.alpha2[1] = '0'; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/regd.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/regd.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/regd.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/regd.h 2011-05-05 23:29:49.302487983 +0200 -@@ -32,7 +32,7 @@ - - struct country_code_to_enum_rd { - u16 countrycode; -- const char *isoName; -+ const char *iso_name; - }; - - enum country_code_type_t { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c 2011-05-05 23:29:49.321488212 +0200 -@@ -28,10 +28,26 @@ - *****************************************************************************/ - - #include "dm_common.h" -+#include "phy_common.h" -+#include "../pci.h" -+#include "../base.h" - - struct dig_t dm_digtable; - static struct ps_t dm_pstable; - -+#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -+#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -+#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -+#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -+#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) -+ -+#define RTLPRIV (struct rtl_priv *) -+#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ -+ ((RTLPRIV(_priv))->mac80211.opmode == \ -+ NL80211_IFTYPE_ADHOC) ? \ -+ ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \ -+ ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb) -+ - static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, - 0x788001e2, -@@ -304,7 +320,7 @@ - - static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) - { -- static u8 binitialized; /* initialized to false */ -+ static u8 initialized; /* initialized to false */ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -@@ -315,11 +331,11 @@ - - if ((multi_sta == false) || (dm_digtable.cursta_connectctate != - DIG_STA_DISCONNECT)) { -- binitialized = false; -+ initialized = false; - dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - return; -- } else if (binitialized == false) { -- binitialized = true; -+ } else if (initialized == false) { -+ initialized = true; - dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; - dm_digtable.cur_igvalue = 0x20; - rtl92c_dm_write_dig(hw); -@@ -461,10 +477,7 @@ - if (mac->act_scanning == true) - return; - -- if ((mac->link_state > MAC80211_NOLINK) && -- (mac->link_state < MAC80211_LINKED)) -- dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT; -- else if (mac->link_state >= MAC80211_LINKED) -+ if (mac->link_state >= MAC80211_LINKED) - dm_digtable.cursta_connectctate = DIG_STA_CONNECT; - else - dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT; -@@ -562,23 +575,42 @@ - static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ - static u64 last_txok_cnt; - static u64 last_rxok_cnt; -- u64 cur_txok_cnt; -- u64 cur_rxok_cnt; -+ static u32 last_bt_edca_ul; -+ static u32 last_bt_edca_dl; -+ u64 cur_txok_cnt = 0; -+ u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; -+ bool bt_change_edca = false; - -- if (mac->opmode == NL80211_IFTYPE_ADHOC) -- goto dm_checkedcaturbo_exit; -+ if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || -+ (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { -+ rtlpriv->dm.current_turbo_edca = false; -+ last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; -+ last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; -+ } -+ -+ if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { -+ edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; -+ bt_change_edca = true; -+ } -+ -+ if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { -+ edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; -+ bt_change_edca = true; -+ } - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - return; - } - -- if (!mac->ht_enable) { /*FIX MERGE */ -+ if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { - if (!(edca_be_ul & 0xffff0000)) - edca_be_ul |= 0x005e0000; - -@@ -586,10 +618,12 @@ - edca_be_dl |= 0x005e0000; - } - -- if ((!rtlpriv->dm.is_any_nonbepkts) && -- (!rtlpriv->dm.disable_framebursting)) { -+ if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && -+ (!rtlpriv->dm.disable_framebursting))) { -+ - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; -+ - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { -@@ -618,7 +652,6 @@ - } - } - --dm_checkedcaturbo_exit: - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -@@ -633,14 +666,14 @@ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(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; -+ long val_y, ele_c = 0; -+ 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}; - u8 ofdm_min_index = 6, rf; - -- rtlpriv->dm.txpower_trackingInit = true; -+ rtlpriv->dm.txpower_trackinginit = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n")); - -@@ -683,7 +716,6 @@ - for (i = 0; i < OFDM_TABLE_LENGTH; i++) { - if (ele_d == (ofdmswing_table[i] & - MASKOFDM_D)) { -- ofdm_index_old[1] = (u8) i; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, -@@ -1062,7 +1094,7 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; -- rtlpriv->dm.txpower_trackingInit = false; -+ rtlpriv->dm.txpower_trackinginit = false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - ("pMgntInfo->txpower_tracking = %d\n", -@@ -1132,6 +1164,7 @@ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *p_ra = &(rtlpriv->ra); - u32 low_rssithresh_for_ra, high_rssithresh_for_ra; -+ struct ieee80211_sta *sta = NULL; - - if (is_hal_stop(rtlhal)) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, -@@ -1145,8 +1178,8 @@ - return; - } - -- if (mac->link_state == MAC80211_LINKED) { -- -+ if (mac->link_state == MAC80211_LINKED && -+ mac->opmode == NL80211_IFTYPE_STATION) { - switch (p_ra->pre_ratr_state) { - case DM_RATR_STA_HIGH: - high_rssithresh_for_ra = 50; -@@ -1185,10 +1218,13 @@ - ("PreState = %d, CurState = %d\n", - p_ra->pre_ratr_state, p_ra->ratr_state)); - -- rtlpriv->cfg->ops->update_rate_mask(hw, -+ rcu_read_lock(); -+ sta = ieee80211_find_sta(mac->vif, mac->bssid); -+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta, - p_ra->ratr_state); - - p_ra->pre_ratr_state = p_ra->ratr_state; -+ rcu_read_unlock(); - } - } - } -@@ -1202,51 +1238,6 @@ - dm_pstable.rssi_val_min = 0; - } - --static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw) --{ -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_phy *rtlphy = &(rtlpriv->phy); -- -- if (dm_pstable.rssi_val_min != 0) { -- if (dm_pstable.pre_ccastate == CCA_2R) { -- if (dm_pstable.rssi_val_min >= 35) -- dm_pstable.cur_ccasate = CCA_1R; -- else -- dm_pstable.cur_ccasate = CCA_2R; -- } else { -- if (dm_pstable.rssi_val_min <= 30) -- dm_pstable.cur_ccasate = CCA_2R; -- else -- dm_pstable.cur_ccasate = CCA_1R; -- } -- } else { -- dm_pstable.cur_ccasate = CCA_MAX; -- } -- -- if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) { -- if (dm_pstable.cur_ccasate == CCA_1R) { -- if (get_rf_type(rtlphy) == RF_2T2R) { -- rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -- MASKBYTE0, 0x13); -- rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20); -- } else { -- rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -- MASKBYTE0, 0x23); -- rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c); -- } -- } else { -- rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, -- 0x33); -- rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63); -- } -- dm_pstable.pre_ccastate = dm_pstable.cur_ccasate; -- } -- -- RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n", -- (dm_pstable.cur_ccasate == -- 0) ? "1RCCA" : "2RCCA")); --} -- - void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) - { - static u8 initialize; -@@ -1352,7 +1343,9 @@ - } - - if (IS_92C_SERIAL(rtlhal->version)) -- rtl92c_dm_1r_cca(hw); -+ ;/* rtl92c_dm_1r_cca(hw); */ -+ else -+ rtl92c_dm_rf_saving(hw, false); - } - - void rtl92c_dm_init(struct ieee80211_hw *hw) -@@ -1369,6 +1362,84 @@ - } - EXPORT_SYMBOL(rtl92c_dm_init); - -+void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ long undecorated_smoothed_pwdb; -+ -+ if (!rtlpriv->dm.dynamic_txpower_enable) -+ return; -+ -+ if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { -+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -+ return; -+ } -+ -+ if ((mac->link_state < MAC80211_LINKED) && -+ (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, -+ ("Not connected to any\n")); -+ -+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -+ -+ rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; -+ return; -+ } -+ -+ if (mac->link_state >= MAC80211_LINKED) { -+ if (mac->opmode == NL80211_IFTYPE_ADHOC) { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("AP Client PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } else { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.undecorated_smoothed_pwdb; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("STA Default Port PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } -+ } else { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("AP Ext Port PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } -+ -+ if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { -+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); -+ } else if ((undecorated_smoothed_pwdb < -+ (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && -+ (undecorated_smoothed_pwdb >= -+ TX_POWER_NEAR_FIELD_THRESH_LVL1)) { -+ -+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); -+ } else if (undecorated_smoothed_pwdb < -+ (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { -+ rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("TXHIGHPWRLEVEL_NORMAL\n")); -+ } -+ -+ if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("PHY_SetTxPowerLevel8192S() Channel = %d\n", -+ rtlphy->current_channel)); -+ rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); -+ } -+ -+ rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -+} -+ - void rtl92c_dm_watchdog(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -1388,11 +1459,321 @@ - rtl92c_dm_dig(hw); - rtl92c_dm_false_alarm_counter_statistics(hw); - rtl92c_dm_dynamic_bb_powersaving(hw); -- rtlpriv->cfg->ops->dm_dynamic_txpower(hw); -+ rtl92c_dm_dynamic_txpower(hw); - rtl92c_dm_check_txpower_tracking(hw); - rtl92c_dm_refresh_rate_adaptive_mask(hw); -+ rtl92c_dm_bt_coexist(hw); - rtl92c_dm_check_edca_turbo(hw); -- - } - } - EXPORT_SYMBOL(rtl92c_dm_watchdog); -+ -+u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ long undecorated_smoothed_pwdb; -+ u8 curr_bt_rssi_state = 0x00; -+ -+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { -+ undecorated_smoothed_pwdb = -+ GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); -+ } else { -+ if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0) -+ undecorated_smoothed_pwdb = 100; -+ else -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -+ } -+ -+ /* Check RSSI to determine HighPower/NormalPower state for -+ * BT coexistence. */ -+ if (undecorated_smoothed_pwdb >= 67) -+ curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); -+ else if (undecorated_smoothed_pwdb < 62) -+ curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; -+ -+ /* Check RSSI to determine AMPDU setting for BT coexistence. */ -+ if (undecorated_smoothed_pwdb >= 40) -+ curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); -+ else if (undecorated_smoothed_pwdb <= 32) -+ curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; -+ -+ /* Marked RSSI state. It will be used to determine BT coexistence -+ * setting later. */ -+ if (undecorated_smoothed_pwdb < 35) -+ curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; -+ else -+ curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); -+ -+ /* Set Tx Power according to BT status. */ -+ if (undecorated_smoothed_pwdb >= 30) -+ curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; -+ else if (undecorated_smoothed_pwdb < 25) -+ curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); -+ -+ /* Check BT state related to BT_Idle in B/G mode. */ -+ if (undecorated_smoothed_pwdb < 15) -+ curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; -+ else -+ curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); -+ -+ if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { -+ rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; -+ return true; -+ } else { -+ return false; -+ } -+} -+EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); -+ -+static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ u32 polling, ratio_tx, ratio_pri; -+ u32 bt_tx, bt_pri; -+ u8 bt_state; -+ u8 cur_service_type; -+ -+ if (rtlpriv->mac80211.link_state < MAC80211_LINKED) -+ return false; -+ -+ bt_state = rtl_read_byte(rtlpriv, 0x4fd); -+ bt_tx = rtl_read_dword(rtlpriv, 0x488); -+ bt_tx = bt_tx & 0x00ffffff; -+ bt_pri = rtl_read_dword(rtlpriv, 0x48c); -+ bt_pri = bt_pri & 0x00ffffff; -+ polling = rtl_read_dword(rtlpriv, 0x490); -+ -+ if (bt_tx == 0xffffffff && bt_pri == 0xffffffff && -+ polling == 0xffffffff && bt_state == 0xff) -+ return false; -+ -+ bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); -+ if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { -+ rtlpcipriv->bt_coexist.bt_cur_state = bt_state; -+ -+ if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { -+ rtlpcipriv->bt_coexist.bt_service = BT_IDLE; -+ -+ bt_state = bt_state | -+ ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? -+ 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | -+ BIT_OFFSET_LEN_MASK_32(2, 1); -+ rtl_write_byte(rtlpriv, 0x4fd, bt_state); -+ } -+ return true; -+ } -+ -+ ratio_tx = bt_tx * 1000 / polling; -+ ratio_pri = bt_pri * 1000 / polling; -+ rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; -+ rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; -+ -+ if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { -+ -+ if ((ratio_tx < 30) && (ratio_pri < 30)) -+ cur_service_type = BT_IDLE; -+ else if ((ratio_pri > 110) && (ratio_pri < 250)) -+ cur_service_type = BT_SCO; -+ else if ((ratio_tx >= 200) && (ratio_pri >= 200)) -+ cur_service_type = BT_BUSY; -+ else if ((ratio_tx >= 350) && (ratio_tx < 500)) -+ cur_service_type = BT_OTHERBUSY; -+ else if (ratio_tx >= 500) -+ cur_service_type = BT_PAN; -+ else -+ cur_service_type = BT_OTHER_ACTION; -+ -+ if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { -+ rtlpcipriv->bt_coexist.bt_service = cur_service_type; -+ bt_state = bt_state | -+ ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? -+ 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | -+ ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? -+ 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); -+ -+ /* Add interrupt migration when bt is not ini -+ * idle state (no traffic). */ -+ if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { -+ rtl_write_word(rtlpriv, 0x504, 0x0ccc); -+ rtl_write_byte(rtlpriv, 0x506, 0x54); -+ rtl_write_byte(rtlpriv, 0x507, 0x54); -+ } else { -+ rtl_write_byte(rtlpriv, 0x506, 0x00); -+ rtl_write_byte(rtlpriv, 0x507, 0x00); -+ } -+ -+ rtl_write_byte(rtlpriv, 0x4fd, bt_state); -+ return true; -+ } -+ } -+ -+ return false; -+ -+} -+ -+static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ static bool media_connect; -+ -+ if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { -+ media_connect = false; -+ } else { -+ if (!media_connect) { -+ media_connect = true; -+ return true; -+ } -+ media_connect = true; -+ } -+ -+ return false; -+} -+ -+static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ -+ if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; -+ } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; -+ } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { -+ if (rtlpcipriv->bt_coexist.ratio_tx > 160) { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; -+ } else { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; -+ } -+ } else { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0; -+ } -+ -+ if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && -+ (rtlpriv->mac80211.mode == WIRELESS_MODE_G || -+ (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && -+ (rtlpcipriv->bt_coexist.bt_rssi_state & -+ BT_RSSI_STATE_BG_EDCA_LOW)) { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; -+ } -+} -+ -+static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ -+ /* Only enable HW BT coexist when BT in "Busy" state. */ -+ if (rtlpriv->mac80211.vendor == PEER_CISCO && -+ rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); -+ } else { -+ if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && -+ (rtlpcipriv->bt_coexist.bt_rssi_state & -+ BT_RSSI_STATE_NORMAL_POWER)) { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); -+ } else if ((rtlpcipriv->bt_coexist.bt_service == -+ BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < -+ WIRELESS_MODE_N_24G) && -+ (rtlpcipriv->bt_coexist.bt_rssi_state & -+ BT_RSSI_STATE_SPECIAL_LOW)) { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); -+ } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); -+ } else { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); -+ } -+ } -+ -+ if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) -+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); -+ else -+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); -+ -+ if (rtlpcipriv->bt_coexist.bt_rssi_state & -+ BT_RSSI_STATE_NORMAL_POWER) { -+ rtl92c_bt_set_normal(hw); -+ } else { -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0; -+ } -+ -+ if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { -+ rtlpriv->cfg->ops->set_rfreg(hw, -+ RF90_PATH_A, -+ 0x1e, -+ 0xf0, 0xf); -+ } else { -+ rtlpriv->cfg->ops->set_rfreg(hw, -+ RF90_PATH_A, 0x1e, 0xf0, -+ rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); -+ } -+ -+ if (!rtlpriv->dm.dynamic_txpower_enable) { -+ if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { -+ if (rtlpcipriv->bt_coexist.bt_rssi_state & -+ BT_RSSI_STATE_TXPOWER_LOW) { -+ rtlpriv->dm.dynamic_txhighpower_lvl = -+ TXHIGHPWRLEVEL_BT2; -+ } else { -+ rtlpriv->dm.dynamic_txhighpower_lvl = -+ TXHIGHPWRLEVEL_BT1; -+ } -+ } else { -+ rtlpriv->dm.dynamic_txhighpower_lvl = -+ TXHIGHPWRLEVEL_NORMAL; -+ } -+ rtl92c_phy_set_txpower_level(hw, -+ rtlpriv->phy.current_channel); -+ } -+} -+ -+static void rtl92c_check_bt_change(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ if (rtlpcipriv->bt_coexist.bt_cur_state) { -+ if (rtlpcipriv->bt_coexist.bt_ant_isolation) -+ rtl92c_bt_ant_isolation(hw); -+ } else { -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); -+ rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, -+ rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); -+ -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0; -+ } -+} -+ -+void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ bool wifi_connect_change; -+ bool bt_state_change; -+ bool rssi_state_change; -+ -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { -+ -+ wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); -+ bt_state_change = rtl92c_bt_state_change(hw); -+ rssi_state_change = rtl92c_bt_rssi_state_change(hw); -+ -+ if (wifi_connect_change || bt_state_change || rssi_state_change) -+ rtl92c_check_bt_change(hw); -+ } -+} -+EXPORT_SYMBOL(rtl92c_dm_bt_coexist); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h 2011-05-05 23:29:49.324488249 +0200 -@@ -200,5 +200,7 @@ - void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); - void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); - void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); -+void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); -+void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2011-05-05 23:29:49.323488237 +0200 -@@ -171,7 +171,6 @@ - static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -- int err = -EIO; - u32 counter = 0; - u32 value32; - -@@ -184,7 +183,7 @@ - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("chksum report faill ! REG_MCUFWDL:0x%08x .\n", - value32)); -- goto exit; -+ return -EIO; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, -@@ -204,8 +203,7 @@ - ("Polling FW ready success!!" - " REG_MCUFWDL:0x%08x .\n", - value32)); -- err = 0; -- goto exit; -+ return 0; - } - - mdelay(FW_8192C_POLLING_DELAY); -@@ -214,9 +212,7 @@ - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32)); -- --exit: -- return err; -+ return -EIO; - } - - int rtl92c_download_fw(struct ieee80211_hw *hw) -@@ -226,32 +222,16 @@ - struct rtl92c_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; -- int err; - enum version_8192c version = rtlhal->version; -- const struct firmware *firmware; - -- printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n", -+ printk(KERN_INFO "rtl8192c: Loading firmware file %s\n", - rtlpriv->cfg->fw_name); -- err = request_firmware(&firmware, rtlpriv->cfg->fw_name, -- rtlpriv->io.dev); -- if (err) { -- printk(KERN_ERR "rtl8192cu: Firmware loading failed\n"); -- return 1; -- } -- -- if (firmware->size > 0x4000) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("Firmware is too big!\n")); -- release_firmware(firmware); -+ if (!rtlhal->pfirmware) - return 1; -- } -- -- memcpy(rtlhal->pfirmware, firmware->data, firmware->size); -- fwsize = firmware->size; -- release_firmware(firmware); - - pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; - pfwdata = (u8 *) rtlhal->pfirmware; -+ fwsize = rtlhal->fwsize; - - if (IS_FW_HEADER_EXIST(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, -@@ -267,8 +247,7 @@ - _rtl92c_write_fw(hw, version, pfwdata, fwsize); - _rtl92c_enable_fw_download(hw, false); - -- err = _rtl92c_fw_free_to_go(hw); -- if (err) { -+ if (_rtl92c_fw_free_to_go(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is not ready to run!\n")); - } else { -@@ -300,10 +279,9 @@ - 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; -- u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limmit = 100; -@@ -414,7 +392,7 @@ - case 1: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *) (boxcontent) + 1, -- p_cmdbuffer + buf_index, 1); -+ p_cmdbuffer, 1); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, -@@ -424,7 +402,7 @@ - case 2: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *) (boxcontent) + 1, -- p_cmdbuffer + buf_index, 2); -+ p_cmdbuffer, 2); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, -@@ -434,7 +412,7 @@ - case 3: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *) (boxcontent) + 1, -- p_cmdbuffer + buf_index, 3); -+ p_cmdbuffer, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, -@@ -444,9 +422,9 @@ - case 4: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *) (boxextcontent), -- p_cmdbuffer + buf_index, 2); -+ p_cmdbuffer, 2); - memcpy((u8 *) (boxcontent) + 1, -- p_cmdbuffer + buf_index + 2, 2); -+ p_cmdbuffer + 2, 2); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, -@@ -461,9 +439,9 @@ - case 5: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *) (boxextcontent), -- p_cmdbuffer + buf_index, 2); -+ p_cmdbuffer, 2); - memcpy((u8 *) (boxcontent) + 1, -- p_cmdbuffer + buf_index + 2, 3); -+ p_cmdbuffer + 2, 3); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, -@@ -561,6 +539,39 @@ - } - EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); - -+static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, -+ struct sk_buff *skb) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl8192_tx_ring *ring; -+ struct rtl_tx_desc *pdesc; -+ u8 own; -+ unsigned long flags; -+ struct sk_buff *pskb = NULL; -+ -+ ring = &rtlpci->tx_ring[BEACON_QUEUE]; -+ -+ pskb = __skb_dequeue(&ring->queue); -+ if (pskb) -+ kfree_skb(pskb); -+ -+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); -+ -+ pdesc = &ring->desc[0]; -+ own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); -+ -+ rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); -+ -+ __skb_queue_tail(&ring->queue, skb); -+ -+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -+ -+ rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); -+ -+ return true; -+} -+ - #define BEACON_PG 0 /*->1*/ - #define PSPOLL_PG 2 - #define NULL_PG 3 -@@ -678,7 +689,7 @@ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - --void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) -+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -@@ -687,12 +698,12 @@ - u32 totalpacketlen; - bool rtstatus; - u8 u1RsvdPageLoc[3] = {0}; -- bool b_dlok = false; -+ bool dlok = false; - - u8 *beacon; -- u8 *p_pspoll; -+ u8 *pspoll; - u8 *nullfunc; -- u8 *p_probersp; -+ u8 *probersp; - /*--------------------------------------------------------- - (1) beacon - ---------------------------------------------------------*/ -@@ -703,10 +714,10 @@ - /*------------------------------------------------------- - (2) ps-poll - --------------------------------------------------------*/ -- p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; -- SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); -- SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); -- SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); -+ pspoll = &reserved_page_packet[PSPOLL_PG * 128]; -+ SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); -+ SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); -+ SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); - -@@ -723,10 +734,10 @@ - /*--------------------------------------------------------- - (4) probe response - ----------------------------------------------------------*/ -- p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; -- SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); -- SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); -- SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); -+ probersp = &reserved_page_packet[PROBERSP_PG * 128]; -+ SET_80211_HDR_ADDRESS1(probersp, mac->bssid); -+ SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); -+ SET_80211_HDR_ADDRESS3(probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); - -@@ -744,12 +755,12 @@ - memcpy((u8 *) skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - -- rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb); -+ rtstatus = _rtl92c_cmd_send_packet(hw, skb); - - if (rtstatus) -- b_dlok = true; -+ dlok = true; - -- if (b_dlok) { -+ if (dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - ("Set RSVD page location to Fw.\n")); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h 2011-05-05 23:29:49.323488237 +0200 -@@ -27,8 +27,8 @@ - * - *****************************************************************************/ - --#ifndef __RTL92C__FW__H__ --#define __RTL92C__FW__H__ -+#ifndef __RTL92C__FW__COMMON__H__ -+#define __RTL92C__FW__COMMON__H__ - - #define FW_8192C_SIZE 0x3000 - #define FW_8192C_START_ADDRESS 0x1000 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c 2011-05-05 23:29:49.322488225 +0200 -@@ -78,27 +78,29 @@ - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," - " data(%#x)\n", regaddr, bitmask, - data)); -+ - } - EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); - - u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 offset) -+ enum radio_path rfpath, u32 offset) - { - RT_ASSERT(false, ("deprecated!\n")); - return 0; -+ - } - EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); - - void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 offset, -- u32 data) -+ enum radio_path rfpath, u32 offset, -+ u32 data) - { - RT_ASSERT(false, ("deprecated!\n")); - } - EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); - - u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 offset) -+ enum radio_path rfpath, u32 offset) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -149,8 +151,8 @@ - EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); - - void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 offset, -- u32 data) -+ enum radio_path rfpath, u32 offset, -+ u32 data) - { - u32 data_and_addr; - u32 newoffset; -@@ -197,6 +199,7 @@ - rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); - } -+ - bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -241,13 +244,14 @@ - rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - 0x200)); -+ - return true; - } - EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); - - void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, -- u32 regaddr, u32 bitmask, -- u32 data) -+ u32 regaddr, u32 bitmask, -+ u32 data) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -317,61 +321,48 @@ - } - if (regaddr == RTXAGC_B_RATE54_24) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9])); - } -- - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14])); - } -- - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15])); - } -- - if (regaddr == RTXAGC_B_MCS03_MCS00) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10])); - } -- - if (regaddr == RTXAGC_B_MCS07_MCS04) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11])); - } -- - if (regaddr == RTXAGC_B_MCS11_MCS08) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12])); - } -- - if (regaddr == RTXAGC_B_MCS15_MCS12) { - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data; -- - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", - rtlphy->pwrgroup_cnt, -@@ -583,6 +574,7 @@ - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; -+ - } - - void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -@@ -611,7 +603,6 @@ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 idx; - u8 rf_path; -- - u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw, - WIRELESS_MODE_B, - power_indbm); -@@ -639,11 +630,6 @@ - } - EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); - --void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval) --{ --} --EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg); -- - u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - long power_indbm) -@@ -741,9 +727,9 @@ - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; -- if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) -- rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); -- else { -+ if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { -+ rtlphy->set_bwmode_inprogress = false; -+ } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("FALSE driver sleep or unload\n")); - rtlphy->set_bwmode_inprogress = false; -@@ -773,8 +759,9 @@ - mdelay(delay); - else - continue; -- } else -+ } else { - rtlphy->sw_chnl_inprogress = false; -+ } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); -@@ -811,9 +798,32 @@ - } - EXPORT_SYMBOL(rtl92c_phy_sw_chnl); - --static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, -- u8 channel, u8 *stage, u8 *step, -- u32 *delay) -+static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, -+ u32 cmdtableidx, u32 cmdtablesz, -+ enum swchnlcmd_id cmdid, -+ u32 para1, u32 para2, u32 msdelay) -+{ -+ struct swchnlcmd *pcmd; -+ -+ if (cmdtable == NULL) { -+ RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); -+ return false; -+ } -+ -+ if (cmdtableidx >= cmdtablesz) -+ return false; -+ -+ pcmd = cmdtable + cmdtableidx; -+ pcmd->cmdid = cmdid; -+ pcmd->para1 = para1; -+ pcmd->para2 = para2; -+ pcmd->msdelay = msdelay; -+ return true; -+} -+ -+bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, -+ u8 channel, u8 *stage, u8 *step, -+ u32 *delay) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -917,29 +927,6 @@ - return false; - } - --static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, -- u32 cmdtableidx, u32 cmdtablesz, -- enum swchnlcmd_id cmdid, -- u32 para1, u32 para2, u32 msdelay) --{ -- struct swchnlcmd *pcmd; -- -- if (cmdtable == NULL) { -- RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); -- return false; -- } -- -- if (cmdtableidx >= cmdtablesz) -- return false; -- -- pcmd = cmdtable + cmdtableidx; -- pcmd->cmdid = cmdid; -- pcmd->para1 = para1; -- pcmd->para2 = para2; -- pcmd->msdelay = msdelay; -- return true; --} -- - bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) - { - return true; -@@ -1002,13 +989,13 @@ - reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); -+ - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; -- - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) -@@ -1023,9 +1010,9 @@ - u32 oldval_0, x, tx0_a, reg; - long y, tx0_c; - -- if (final_candidate == 0xFF) -+ if (final_candidate == 0xFF) { - return; -- else if (iqk_ok) { -+ } else if (iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][0]; -@@ -1063,9 +1050,9 @@ - u32 oldval_1, x, tx1_a, reg; - long y, tx1_c; - -- if (final_candidate == 0xFF) -+ if (final_candidate == 0xFF) { - return; -- else if (iqk_ok) { -+ } else if (iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][4]; -@@ -1282,6 +1269,7 @@ - RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - } -+ - if (!rtlphy->rfpi_enable) - _rtl92c_phy_pi_mode_switch(hw, true); - if (t == 0) { -@@ -1317,9 +1305,10 @@ - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && patha_ok == 0x01) -+ - result[t][0] = (rtl_get_bbreg(hw, 0xe94, - MASKDWORD) & 0x3FF0000) >> -- 16; -+ 16; - result[t][1] = - (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; - -@@ -1375,8 +1364,7 @@ - static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, - char delta, bool is2t) - { -- /* This routine is deliberately dummied out for later fixes */ --#if 0 -+#if 0 /* This routine is deliberately dummied out for later fixes */ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -@@ -1434,7 +1422,7 @@ - 0x04db25a4, 0x0b1b25a4 - }; - -- u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; -+ const u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c }; - - u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 }; - -@@ -1463,13 +1451,15 @@ - 0x00050006 - }; - -- const u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; -+ u32 apk_result[PATH_NUM][APK_BB_REG_NUM]; - - long bb_offset, delta_v, delta_offset; - - if (!is2t) - pathbound = 1; - -+ return; -+ - for (index = 0; index < PATH_NUM; index++) { - apk_offset[index] = apk_normal_offset[index]; - apk_value[index] = apk_normal_value[index]; -@@ -1730,8 +1720,7 @@ - 0x08)); - - } -- -- rtlphy->apk_done = true; -+ rtlphy->b_apk_done = true; - #endif - } - -@@ -1758,6 +1747,7 @@ - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); - - } -+ - } - - #undef IQK_ADDA_REG_NUM -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h 2011-05-05 23:29:49.324488249 +0200 -@@ -27,8 +27,8 @@ - * - *****************************************************************************/ - --#ifndef __RTL92C_PHY_H__ --#define __RTL92C_PHY_H__ -+#ifndef __RTL92C_PHY_COMMON_H__ -+#define __RTL92C_PHY_COMMON_H__ - - #define MAX_PRECMD_CNT 16 - #define MAX_RFDEPENDCMD_CNT 16 -@@ -39,6 +39,7 @@ - #define RT_CANNOT_IO(hw) false - #define HIGHPOWER_RADIOA_ARRAYLEN 22 - -+#define IQK_ADDA_REG_NUM 16 - #define MAX_TOLERANCE 5 - #define IQK_DELAY_TIME 1 - -@@ -56,6 +57,7 @@ - #define IQK_ADDA_REG_NUM 16 - #define IQK_MAC_REG_NUM 4 - -+#define IQK_DELAY_TIME 1 - #define RF90_PATH_MAX 2 - - #define CT_OFFSET_MAC_ADDR 0X16 -@@ -77,6 +79,7 @@ - - #define RTL92C_MAX_PATH_NUM 2 - #define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 -+ - enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, -@@ -184,45 +187,41 @@ - u32 mcs_original_offset[4][16]; - }; - --extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, -+u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); --extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, -+void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); --extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, -+u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); --extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 regaddr, -- u32 bitmask, u32 data); --extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); --extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); --extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); --extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, -+bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -+bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -+bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -+bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); --extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); --extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, -+void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -+void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); --extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); --extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, -+void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -+bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, - long power_indbm); --extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, -+void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); --extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); --extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, -+void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); --extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); --extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); --extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); --extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, -+void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -+u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -+void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, - u16 beaconinterval); - void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); - void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); - void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); - bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); --extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, -+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, - u32 rfpath); --extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, -+bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); - void rtl92c_phy_set_io(struct ieee80211_hw *hw); -@@ -235,12 +234,25 @@ - enum wireless_mode wirelessmode, - long power_indbm); - void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); --static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, -- u32 cmdtableidx, u32 cmdtablesz, -- enum swchnlcmd_id cmdid, u32 para1, -- u32 para2, u32 msdelay); --static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, -- u8 channel, u8 *stage, u8 *step, -- u32 *delay); -+void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -+bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, -+ u8 channel, u8 *stage, u8 *step, -+ u32 *delay); -+u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); -+u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset); -+void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset, -+ u32 data); -+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset); -+void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset, -+ u32 data); -+bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, -+ u32 regaddr, u32 bitmask, -+ u32 data); -+bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/def.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/def.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/def.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/def.h 2011-05-05 23:29:49.330488321 +0200 -@@ -121,19 +121,6 @@ - #define CHIP_92C 0x01 - #define CHIP_88C 0x00 - --/* Add vendor information into chip version definition. -- * Add UMC B-Cut and RTL8723 chip info definition. -- * -- * BIT 7 Reserved -- * BIT 6 UMC BCut -- * BIT 5 Manufacturer(TSMC/UMC) -- * BIT 4 TEST/NORMAL -- * BIT 3 8723 Version -- * BIT 2 8723? -- * BIT 1 1T2R? -- * BIT 0 88C/92C --*/ -- - enum version_8192c { - VERSION_A_CHIP_92C = 0x01, - VERSION_A_CHIP_88C = 0x00, -@@ -280,20 +267,6 @@ - u8 *p_cmdbuffer; - }; - --static inline u8 _rtl92c_get_chnl_group(u8 chnl) --{ -- u8 group = 0; -- -- if (chnl < 3) -- group = 0; -- else if (chnl < 9) -- group = 1; -- else -- group = 2; -- -- return group; --} -- - /* NOTE: reference to rtl8192c_rates struct */ - static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, - u8 desc_rate, bool first_ampdu) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c 2011-05-05 23:29:49.332488345 +0200 -@@ -29,10 +29,12 @@ - - #include "../wifi.h" - #include "../base.h" -+#include "../pci.h" - #include "reg.h" - #include "def.h" - #include "phy.h" - #include "dm.h" -+#include "../rtl8192c/fw_common.h" - - void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) - { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h 2011-05-05 23:29:49.325488261 +0200 -@@ -192,6 +192,7 @@ - void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); - void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); - void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); -+void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); - void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c 2011-05-05 23:29:49.331488333 +0200 -@@ -30,12 +30,14 @@ - #include "../wifi.h" - #include "../efuse.h" - #include "../base.h" -+#include "../regd.h" - #include "../cam.h" - #include "../ps.h" - #include "../pci.h" - #include "reg.h" - #include "def.h" - #include "phy.h" -+#include "../rtl8192c/fw_common.h" - #include "dm.h" - #include "led.h" - #include "hw.h" -@@ -137,15 +139,6 @@ - - break; - } -- case HW_VAR_MGT_FILTER: -- *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); -- break; -- case HW_VAR_CTRL_FILTER: -- *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); -- break; -- case HW_VAR_DATA_FILTER: -- *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); -- break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("switch case not process\n")); -@@ -156,6 +149,7 @@ - void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -@@ -178,7 +172,7 @@ - rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, -- (rate_cfg >> 8)&0xff); -+ (rate_cfg >> 8) & 0xff); - while (rate_cfg > 0x1) { - rate_cfg = (rate_cfg >> 1); - rate_index++; -@@ -276,13 +270,19 @@ - break; - } - case HW_VAR_AMPDU_FACTOR:{ -- u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; -+ u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; -+ u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; - - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - -- p_regtoset = regtoset_normal; -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == -+ BT_CSR_BC4)) -+ p_regtoset = regtoset_bt; -+ else -+ p_regtoset = regtoset_normal; - - factor_toset = *((u8 *) val); - if (factor_toset <= 3) { -@@ -317,45 +317,7 @@ - } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *) val); -- u32 u4b_ac_param; -- u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); -- u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); -- u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); -- -- u4b_ac_param = (u32) mac->ac[e_aci].aifs; -- u4b_ac_param |= ((u32)cw_min -- & 0xF) << AC_PARAM_ECW_MIN_OFFSET; -- u4b_ac_param |= ((u32)cw_max & -- 0xF) << AC_PARAM_ECW_MAX_OFFSET; -- u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET; -- -- RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, -- ("queue:%x, ac_param:%x\n", e_aci, -- u4b_ac_param)); -- -- switch (e_aci) { -- case AC1_BK: -- rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, -- u4b_ac_param); -- break; -- case AC0_BE: -- rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, -- u4b_ac_param); -- break; -- case AC2_VI: -- rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, -- u4b_ac_param); -- break; -- case AC3_VO: -- rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, -- u4b_ac_param); -- break; -- default: -- RT_ASSERT(false, -- ("SetHwReg8185(): invalid aci: %d !\n", -- e_aci)); -- break; -- } -+ rtl92c_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != eAcmWay2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, -@@ -526,9 +488,6 @@ - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *) (val))[0]; - -- /*btype_ibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? -- 1 : 0;*/ -- - if (btype_ibss == true) - _rtl92ce_stop_tx_beacon(hw); - -@@ -537,7 +496,7 @@ - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32) (mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, -- (u32) ((mac->tsf >> 32)&0xffffffff)); -+ (u32) ((mac->tsf >> 32) & 0xffffffff)); - - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); - -@@ -547,15 +506,6 @@ - break; - - } -- case HW_VAR_MGT_FILTER: -- rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *) val); -- break; -- case HW_VAR_CTRL_FILTER: -- rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *) val); -- break; -- case HW_VAR_DATA_FILTER: -- rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *) val); -- break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " - "not process\n")); -@@ -679,12 +629,12 @@ - rtl92ce_sw_led_on(hw, pLed0); - else - rtl92ce_sw_led_off(hw, pLed0); -- - } - - static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - -@@ -693,9 +643,22 @@ - u16 retry; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); -+ if (rtlpcipriv->bt_coexist.bt_coexistence) { -+ u32 value32; -+ value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); -+ value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); -+ rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); -+ } - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); - -+ if (rtlpcipriv->bt_coexist.bt_coexistence) { -+ u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); -+ -+ u4b_tmp &= (~0x00024800); -+ rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); -+ } -+ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); - udelay(2); - -@@ -726,6 +689,11 @@ - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); - udelay(2); - -+ if (rtlpcipriv->bt_coexist.bt_coexistence) { -+ bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; -+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); -+ } -+ - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - if (_rtl92ce_llt_table_init(hw) == false) -@@ -793,6 +761,7 @@ - { - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - u8 reg_bw_opmode; - u32 reg_ratr, reg_prsr; - -@@ -824,7 +793,11 @@ - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - -- rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) -+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); -+ else -+ rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); - - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); - -@@ -840,11 +813,20 @@ - rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - -- rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); -- -- rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { -+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); -+ rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); -+ } else { -+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); -+ rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); -+ } - -- rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) -+ rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); -+ else -+ rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); - - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); - -@@ -948,8 +930,8 @@ - } - - rtlhal->last_hmeboxnum = 0; -- rtl92ce_phy_mac_config(hw); -- rtl92ce_phy_bb_config(hw); -+ rtl92c_phy_mac_config(hw); -+ rtl92c_phy_bb_config(hw); - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - rtl92c_phy_rf_config(hw); - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, -@@ -962,15 +944,20 @@ - _rtl92ce_hw_configure(hw); - rtl_cam_reset_all_entry(hw); - rtl92ce_enable_hw_security_config(hw); -+ - ppsc->rfpwr_state = ERFON; -+ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl92ce_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); -+ -+ rtl8192ce_bt_hw_init(hw); -+ - if (ppsc->rfpwr_state == ERFON) { - rtl92c_phy_set_rfpath_switch(hw, 1); -- if (iqk_initialized) -+ if (iqk_initialized) { - rtl92c_phy_iq_calibrate(hw, true); -- else { -+ } else { - rtl92c_phy_iq_calibrate(hw, false); - iqk_initialized = true; - } -@@ -1128,75 +1115,62 @@ - return 0; - } - --static void _rtl92ce_set_check_bssid(struct ieee80211_hw *hw, -- enum nl80211_iftype type) -+void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); -- u8 filterout_non_associated_bssid = false; - -- switch (type) { -- case NL80211_IFTYPE_ADHOC: -- case NL80211_IFTYPE_STATION: -- filterout_non_associated_bssid = true; -- break; -- case NL80211_IFTYPE_UNSPECIFIED: -- case NL80211_IFTYPE_AP: -- default: -- break; -- } -+ if (rtlpriv->psc.rfpwr_state != ERFON) -+ return; - -- if (filterout_non_associated_bssid == true) { -+ if (check_bssid == true) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *) (®_rcr)); - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); -- } else if (filterout_non_associated_bssid == false) { -+ } else if (check_bssid == false) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *) (®_rcr)); - } -+ - } - - int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) - { -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ - if (_rtl92ce_set_media_status(hw, type)) - return -EOPNOTSUPP; -- _rtl92ce_set_check_bssid(hw, type); -+ -+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { -+ if (type != NL80211_IFTYPE_AP) -+ rtl92ce_set_check_bssid(hw, true); -+ } else { -+ rtl92ce_set_check_bssid(hw, false); -+ } -+ - return 0; - } - -+/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ - void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- u32 u4b_ac_param; -- u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min); -- u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max); -- u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op); -- - rtl92c_dm_init_edca_turbo(hw); -- u4b_ac_param = (u32) mac->ac[aci].aifs; -- u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET); -- u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET); -- u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET); -- RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG, -- ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n", -- aci, u4b_ac_param, mac->ac[aci].aifs, cw_min, -- cw_max, tx_op)); - switch (aci) { - case AC1_BK: -- rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param); -+ rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: -- rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); -+ /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ - break; - case AC2_VI: -- rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param); -+ rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: -- rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param); -+ rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, ("invalid aci: %d !\n", aci)); -@@ -1227,8 +1201,10 @@ - static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; -+ u32 u4b_tmp; - - rtlpriv->intf_ops->enable_aspm(hw); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); -@@ -1243,13 +1219,27 @@ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); - u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); -- rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | -- (u1b_tmp << 8)); -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { -+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | -+ (u1b_tmp << 8)); -+ } else { -+ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | -+ (u1b_tmp << 8)); -+ } - rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); - rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); -- rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); -+ if (rtlpcipriv->bt_coexist.bt_coexistence) { -+ u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); -+ u4b_tmp |= 0x03824800; -+ rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); -+ } else { -+ rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); -+ } -+ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); - } -@@ -1327,6 +1317,7 @@ - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); -+ - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) -@@ -1582,7 +1573,7 @@ - ("RTL819X Not boot from eeprom, check it !!")); - } - -- RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"), -+ RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); -@@ -1610,6 +1601,10 @@ - rtlefuse->autoload_failflag, - hwinfo); - -+ rtl8192ce_read_bt_coexist_info_from_hwpg(hw, -+ rtlefuse->autoload_failflag, -+ hwinfo); -+ - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - rtlefuse->txpwr_fromeprom = true; -@@ -1618,6 +1613,9 @@ - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); - -+ /* set channel paln to world wide 13 */ -+ rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; -+ - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: -@@ -1701,30 +1699,36 @@ - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); - } -- - _rtl92ce_hal_customized_behavior(hw); - } - --void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw) -+static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- -- u32 ratr_value = (u32) mac->basic_rates; -- u8 *mcsrate = mac->mcs; -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u32 ratr_value; - u8 ratr_index = 0; - u8 nmode = mac->ht_enable; -- u8 mimo_ps = 1; -+ u8 mimo_ps = IEEE80211_SMPS_OFF; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; -- u8 curshortgi_40mhz = mac->sgi_40; -- u8 curshortgi_20mhz = mac->sgi_20; -+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? -+ 1 : 0; -+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? -+ 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - -- ratr_value |= ((*(u16 *) (mcsrate))) << 12; -- -+ if (rtlhal->current_bandtype == BAND_ON_5G) -+ ratr_value = sta->supp_rates[1] << 4; -+ else -+ ratr_value = sta->supp_rates[0]; -+ ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | -+ sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) -@@ -1738,7 +1742,7 @@ - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - nmode = 1; -- if (mimo_ps == 0) { -+ if (mimo_ps == IEEE80211_SMPS_STATIC) { - ratr_value &= 0x0007F005; - } else { - u32 ratr_mask; -@@ -1761,10 +1765,19 @@ - break; - } - -- ratr_value &= 0x0FFFFFFF; -+ if ((rtlpcipriv->bt_coexist.bt_coexistence) && -+ (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && -+ (rtlpcipriv->bt_coexist.bt_cur_state) && -+ (rtlpcipriv->bt_coexist.bt_ant_isolation) && -+ ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || -+ (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) -+ ratr_value &= 0x0fffcfc0; -+ else -+ ratr_value &= 0x0FFFFFFF; - -- if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz && -- curshortgi_20mhz))) { -+ if (nmode && ((curtxbw_40mhz && -+ curshortgi_40mhz) || (!curtxbw_40mhz && -+ curshortgi_20mhz))) { - - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); -@@ -1784,24 +1797,42 @@ - ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); - } - --void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) -+static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- u32 ratr_bitmap = (u32) mac->basic_rates; -- u8 *p_mcsrate = mac->mcs; -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry = NULL; -+ u32 ratr_bitmap; - u8 ratr_index; -- u8 curtxbw_40mhz = mac->bw_40; -- u8 curshortgi_40mhz = mac->sgi_40; -- u8 curshortgi_20mhz = mac->sgi_20; -- enum wireless_mode wirelessmode = mac->mode; -+ u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) -+ ? 1 : 0; -+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? -+ 1 : 0; -+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? -+ 1 : 0; -+ enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u8 rate_mask[5]; - u8 macid = 0; -- u8 mimops = 1; -+ u8 mimo_ps = IEEE80211_SMPS_OFF; -+ -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ wirelessmode = sta_entry->wireless_mode; -+ if (mac->opmode == NL80211_IFTYPE_STATION) -+ curtxbw_40mhz = mac->bw_40; -+ else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) -+ macid = sta->aid + 1; - -- ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12); -+ if (rtlhal->current_bandtype == BAND_ON_5G) -+ ratr_bitmap = sta->supp_rates[1] << 4; -+ else -+ ratr_bitmap = sta->supp_rates[0]; -+ ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | -+ sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; -@@ -1828,7 +1859,7 @@ - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - -- if (mimops == 0) { -+ if (mimo_ps == IEEE80211_SMPS_STATIC) { - if (rssi_level == 1) - ratr_bitmap &= 0x00070000; - else if (rssi_level == 2) -@@ -1892,8 +1923,8 @@ - } - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - ("ratr_bitmap :%x\n", ratr_bitmap)); -- *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | -- (ratr_index << 28); -+ *(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | -+ (ratr_index << 28)); - rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, " - "ratr_val:%x, %x:%x:%x:%x:%x\n", -@@ -1902,6 +1933,20 @@ - rate_mask[2], rate_mask[3], - rate_mask[4])); - rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); -+ -+ if (macid != 0) -+ sta_entry->ratr_index = ratr_index; -+} -+ -+void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (rtlpriv->dm.useramask) -+ rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); -+ else -+ rtl92ce_update_hal_rate_table(hw, sta); - } - - void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) -@@ -1919,7 +1964,7 @@ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); - } - --bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) -+bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -@@ -1929,7 +1974,7 @@ - bool actuallyset = false; - unsigned long flag; - -- if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) -+ if (rtlpci->being_init_adapter) - return false; - - if (ppsc->swrf_processing) -@@ -1946,12 +1991,6 @@ - - cur_rfstate = ppsc->rfpwr_state; - -- if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && -- RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { -- rtlpriv->intf_ops->disable_aspm(hw); -- RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -- } -- - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, - REG_MAC_PINMUX_CFG)&~(BIT(3))); - -@@ -1976,38 +2015,13 @@ - } - - if (actuallyset) { -- if (e_rfpowerstate_toset == ERFON) { -- if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && -- RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) { -- rtlpriv->intf_ops->disable_aspm(hw); -- RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -- } -- } -- - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -- -- if (e_rfpowerstate_toset == ERFOFF) { -- if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { -- rtlpriv->intf_ops->enable_aspm(hw); -- RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -- } -- } -- -- } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { -+ } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - -- if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) { -- rtlpriv->intf_ops->enable_aspm(hw); -- RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); -- } -- -- spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -- ppsc->rfchange_inprogress = false; -- spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -- } else { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -@@ -2086,15 +2100,31 @@ - macaddr = cam_const_broad; - entry_id = key_index; - } else { -+ if (mac->opmode == NL80211_IFTYPE_AP) { -+ entry_id = rtl_cam_get_free_entry(hw, -+ p_macaddr); -+ if (entry_id >= TOTAL_CAM_ENTRY) { -+ RT_TRACE(rtlpriv, COMP_SEC, -+ DBG_EMERG, -+ ("Can not find free hw" -+ " security cam entry\n")); -+ return; -+ } -+ } else { -+ entry_id = CAM_PAIRWISE_KEY_POSITION; -+ } -+ - key_index = PAIRWISE_KEYIDX; -- entry_id = CAM_PAIRWISE_KEY_POSITION; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -- ("delete one entry\n")); -+ ("delete one entry, entry_id is %d\n", -+ entry_id)); -+ if (mac->opmode == NL80211_IFTYPE_AP) -+ rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -@@ -2146,3 +2176,132 @@ - } - } - } -+ -+static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ rtlpcipriv->bt_coexist.bt_coexistence = -+ rtlpcipriv->bt_coexist.eeprom_bt_coexist; -+ rtlpcipriv->bt_coexist.bt_ant_num = -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_num; -+ rtlpcipriv->bt_coexist.bt_coexist_type = -+ rtlpcipriv->bt_coexist.eeprom_bt_type; -+ -+ if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) -+ rtlpcipriv->bt_coexist.bt_ant_isolation = -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation; -+ else -+ rtlpcipriv->bt_coexist.bt_ant_isolation = -+ rtlpcipriv->bt_coexist.reg_bt_iso; -+ -+ rtlpcipriv->bt_coexist.bt_radio_shared_type = -+ rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; -+ -+ if (rtlpcipriv->bt_coexist.bt_coexistence) { -+ -+ if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) -+ rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; -+ else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) -+ rtlpcipriv->bt_coexist.bt_service = BT_SCO; -+ else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) -+ rtlpcipriv->bt_coexist.bt_service = BT_BUSY; -+ else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) -+ rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; -+ else -+ rtlpcipriv->bt_coexist.bt_service = BT_IDLE; -+ -+ rtlpcipriv->bt_coexist.bt_edca_ul = 0; -+ rtlpcipriv->bt_coexist.bt_edca_dl = 0; -+ rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; -+ } -+} -+ -+void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, -+ bool auto_load_fail, u8 *hwinfo) -+{ -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ u8 value; -+ -+ if (!auto_load_fail) { -+ rtlpcipriv->bt_coexist.eeprom_bt_coexist = -+ ((hwinfo[RF_OPTION1] & 0xe0) >> 5); -+ value = hwinfo[RF_OPTION4]; -+ rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1); -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1); -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = -+ ((value & 0x10) >> 4); -+ rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = -+ ((value & 0x20) >> 5); -+ } else { -+ rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; -+ rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; -+ rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0; -+ rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; -+ } -+ -+ rtl8192ce_bt_var_init(hw); -+} -+ -+void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ /* 0:Low, 1:High, 2:From Efuse. */ -+ rtlpcipriv->bt_coexist.reg_bt_iso = 2; -+ /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ -+ rtlpcipriv->bt_coexist.reg_bt_sco = 3; -+ /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ -+ rtlpcipriv->bt_coexist.reg_bt_sco = 0; -+} -+ -+ -+void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); -+ -+ u8 u1_tmp; -+ -+ if (rtlpcipriv->bt_coexist.bt_coexistence && -+ ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || -+ rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { -+ -+ if (rtlpcipriv->bt_coexist.bt_ant_isolation) -+ rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); -+ -+ u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & -+ BIT_OFFSET_LEN_MASK_32(0, 1); -+ u1_tmp = u1_tmp | -+ ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? -+ 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | -+ ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? -+ 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); -+ rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); -+ -+ rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); -+ rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); -+ rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); -+ -+ /* Config to 1T1R. */ -+ if (rtlphy->rf_type == RF_1T1R) { -+ u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); -+ u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); -+ rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); -+ -+ u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); -+ u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); -+ rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); -+ } -+ } -+} -+ -+void rtl92ce_suspend(struct ieee80211_hw *hw) -+{ -+} -+ -+void rtl92ce_resume(struct ieee80211_hw *hw) -+{ -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h 2011-05-05 23:29:49.329488309 +0200 -@@ -30,7 +30,18 @@ - #ifndef __RTL92CE_HW_H__ - #define __RTL92CE_HW_H__ - --#define H2C_RA_MASK 6 -+static inline u8 _rtl92c_get_chnl_group(u8 chnl) -+{ -+ u8 group; -+ -+ if (chnl < 3) -+ group = 0; -+ else if (chnl < 9) -+ group = 1; -+ else -+ group = 2; -+ return group; -+} - - void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); - void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); -@@ -41,28 +52,27 @@ - void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); - void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); - int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -+void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); - void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); - void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); - void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); - void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); - void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); --void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw); --void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); -+void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level); - void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); - bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); - void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); - void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); --bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); --void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); --void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); --void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); --int rtl92c_download_fw(struct ieee80211_hw *hw); --void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); --void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, -- u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); --bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw); -+ -+void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, -+ bool autoload_fail, u8 *hwinfo); -+void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); -+void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); -+void rtl92ce_suspend(struct ieee80211_hw *hw); -+void rtl92ce_resume(struct ieee80211_hw *hw); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/led.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/led.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/led.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/led.c 2011-05-05 23:29:49.329488309 +0200 -@@ -32,6 +32,14 @@ - #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,13 +105,12 @@ - - void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) - { -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(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_deinit_sw_leds(struct ieee80211_hw *hw) --{ --} -- --void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, -+static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) - { - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -@@ -138,7 +145,7 @@ - ledaction == LED_CTL_POWER_ON)) { - return; - } -- RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", -+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d.\n", - ledaction)); - _rtl92ce_sw_led_control(hw, ledaction); - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/led.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/led.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/led.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/led.h 2011-05-05 23:29:49.328488297 +0200 -@@ -31,11 +31,8 @@ - #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); --void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, -- enum led_ctl_mode ledaction); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c 2011-05-05 23:29:49.326488273 +0200 -@@ -38,7 +38,9 @@ - #include "dm.h" - #include "table.h" - --u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, -+static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -+ -+u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -73,9 +75,47 @@ - return readback_value; - } - -+bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ bool is92c = IS_92C_SERIAL(rtlhal->version); -+ bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); -+ -+ if (is92c) -+ rtl_write_byte(rtlpriv, 0x14, 0x71); -+ return rtstatus; -+} -+ -+bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) -+{ -+ bool rtstatus = true; -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u16 regval; -+ u32 regvaldw; -+ u8 reg_hwparafile = 1; -+ -+ _rtl92c_phy_init_bb_rf_register_definition(hw); -+ regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, -+ regval | BIT(13) | BIT(0) | BIT(1)); -+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); -+ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); -+ rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, -+ FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | -+ FEN_BB_GLB_RSTn | FEN_BBRSTB); -+ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); -+ regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); -+ rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); -+ if (reg_hwparafile == 1) -+ rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); -+ return rtstatus; -+} -+ - void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, -- u32 regaddr, u32 bitmask, u32 data) -+ enum radio_path rfpath, -+ u32 regaddr, u32 bitmask, u32 data) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -121,45 +161,7 @@ - bitmask, data, rfpath)); - } - --bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw) --{ -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -- bool is92c = IS_92C_SERIAL(rtlhal->version); -- bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw); -- -- if (is92c) -- rtl_write_byte(rtlpriv, 0x14, 0x71); -- return rtstatus; --} -- --bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw) --{ -- bool rtstatus = true; -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- u16 regval; -- u32 regvaldw; -- u8 reg_hwparafile = 1; -- -- _rtl92c_phy_init_bb_rf_register_definition(hw); -- regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); -- rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, -- regval | BIT(13) | BIT(0) | BIT(1)); -- rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); -- rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); -- rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); -- rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, -- FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | -- FEN_BB_GLB_RSTn | FEN_BBRSTB); -- rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); -- regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); -- rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); -- if (reg_hwparafile == 1) -- rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); -- return rtstatus; --} -- --bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -+static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; -@@ -177,7 +179,7 @@ - } - - bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, -- u8 configtype) -+ u8 configtype) - { - int i; - u32 *phy_regarray_table; -@@ -236,7 +238,7 @@ - } - - bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, -- u8 configtype) -+ u8 configtype) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; -@@ -274,7 +276,7 @@ - return true; - } - --bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, -+bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) - { - -@@ -364,74 +366,6 @@ - return true; - } - --void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) --{ -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -- struct rtl_phy *rtlphy = &(rtlpriv->phy); -- struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -- u8 reg_bw_opmode; -- u8 reg_prsr_rsc; -- -- RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, -- ("Switch to %s bandwidth\n", -- rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? -- "20MHz" : "40MHz")) -- -- if (is_hal_stop(rtlhal)) -- return; -- -- reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); -- reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); -- -- switch (rtlphy->current_chan_bw) { -- case HT_CHANNEL_WIDTH_20: -- reg_bw_opmode |= BW_OPMODE_20MHZ; -- rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); -- break; -- -- case HT_CHANNEL_WIDTH_20_40: -- reg_bw_opmode &= ~BW_OPMODE_20MHZ; -- rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); -- -- reg_prsr_rsc = -- (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); -- rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); -- break; -- -- default: -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); -- break; -- } -- -- switch (rtlphy->current_chan_bw) { -- case HT_CHANNEL_WIDTH_20: -- rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); -- rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); -- rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); -- break; -- case HT_CHANNEL_WIDTH_20_40: -- rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); -- rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); -- rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, -- (mac->cur_40_prime_sc >> 1)); -- rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); -- rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); -- rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), -- (mac->cur_40_prime_sc == -- HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); -- break; -- default: -- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); -- break; -- } -- rtl92c_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); -- rtlphy->set_bwmode_inprogress = false; -- RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); --} -- - void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) - { - u8 tmpreg; -@@ -477,6 +411,36 @@ - } - } - -+static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) -+{ -+ u32 u4b_tmp; -+ u8 delay = 5; -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); -+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); -+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); -+ u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); -+ while (u4b_tmp != 0 && delay > 0) { -+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); -+ rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); -+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); -+ u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); -+ delay--; -+ } -+ if (delay == 0) { -+ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); -+ rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, -+ ("Switch RF timeout !!!.\n")); -+ return; -+ } -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); -+ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -+} -+ - static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) - { -@@ -523,33 +487,6 @@ - break; - } - case ERFOFF:{ -- for (queue_id = 0, i = 0; -- queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { -- ring = &pcipriv->dev.tx_ring[queue_id]; -- if (skb_queue_len(&ring->queue) == 0 || -- queue_id == BEACON_QUEUE) { -- queue_id++; -- continue; -- } else { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -- ("eRf Off/Sleep: %d times " -- "TcbBusyQueue[%d] " -- "=%d before doze!\n", (i + 1), -- queue_id, -- skb_queue_len(&ring->queue))); -- udelay(10); -- i++; -- } -- if (i >= MAX_DOZE_WAITING_TIMES_9x) { -- RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -- ("\nERFOFF: %d times " -- "TcbBusyQueue[%d] = %d !\n", -- MAX_DOZE_WAITING_TIMES_9x, -- queue_id, -- skb_queue_len(&ring->queue))); -- break; -- } -- } - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - ("IPS Set eRf nic disable\n")); -@@ -581,6 +518,7 @@ - "TcbBusyQueue[%d] =%d before " - "doze!\n", (i + 1), queue_id, - skb_queue_len(&ring->queue))); -+ - udelay(10); - i++; - } -@@ -599,7 +537,7 @@ - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies))); - ppsc->last_sleep_jiffies = jiffies; -- _rtl92c_phy_set_rf_sleep(hw); -+ _rtl92ce_phy_set_rf_sleep(hw); - break; - } - default: -@@ -614,10 +552,11 @@ - return bresult; - } - --bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, -+bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) - { - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h 2011-05-05 23:29:49.327488285 +0200 -@@ -39,6 +39,7 @@ - #define RT_CANNOT_IO(hw) false - #define HIGHPOWER_RADIOA_ARRAYLEN 22 - -+#define IQK_ADDA_REG_NUM 16 - #define MAX_TOLERANCE 5 - #define IQK_DELAY_TIME 1 - -@@ -56,6 +57,8 @@ - #define IQK_ADDA_REG_NUM 16 - #define IQK_MAC_REG_NUM 4 - -+#define IQK_DELAY_TIME 1 -+ - #define RF90_PATH_MAX 2 - - #define CT_OFFSET_MAC_ADDR 0X16 -@@ -76,7 +79,7 @@ - #define CT_OFFSET_CUSTOMER_ID 0x7F - - #define RTL92C_MAX_PATH_NUM 2 --#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 -+ - enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, -@@ -184,43 +187,44 @@ - u32 mcs_original_offset[4][16]; - }; - --extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, -+bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -+u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); --extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, -+void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); --extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, -+u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); - extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 regaddr, -- u32 bitmask, u32 data); --extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -+ enum radio_path rfpath, u32 regaddr, -+ u32 bitmask, u32 data); -+bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); - bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); --extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); --extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, -+bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -+bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); --extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); --extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, -+void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -+void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); --extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); --extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, -+void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -+bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, - long power_indbm); --extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, -+void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); --extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw); --extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, -+void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); --extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); --extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); --extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); --extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, -+void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -+u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -+void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, - u16 beaconinterval); - void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); - void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); -+void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); - void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); - bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); --extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, -+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, - u32 rfpath); - bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); - bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, -@@ -237,9 +241,6 @@ - void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); --void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, -- u32 regaddr, u32 bitmask, -- u32 data); - void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -@@ -250,5 +251,11 @@ - void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); - bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); - void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -+bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, -+ enum rf_pwrstate rfpwr_state); -+bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, -+ u8 configtype); -+bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, -+ u8 configtype); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h 2011-05-05 23:29:49.332488345 +0200 -@@ -72,6 +72,7 @@ - #define REG_GPIO_IO_SEL_2 0x0062 - /* RTL8723 WIFI/BT/GPS Multi-Function control source. */ - #define REG_MULTI_FUNC_CTRL 0x0068 -+ - #define REG_MCUFWDL 0x0080 - - #define REG_HMEBOX_EXT_0 0x0088 -@@ -542,7 +543,7 @@ - #define IMR_OCPINT BIT(1) - #define IMR_WLANOFF BIT(0) - --#define HWSET_MAX_SIZE 128 -+#define EFUSE_REAL_CONTENT_LEN 512 - - #define EEPROM_DEFAULT_TSSI 0x0 - #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -@@ -656,6 +657,7 @@ - #define STOPBE BIT(1) - #define STOPBK BIT(0) - -+#define RCR_APPFCS BIT(31) - #define RCR_APP_FCS BIT(31) - #define RCR_APP_MIC BIT(30) - #define RCR_APP_ICV BIT(29) -@@ -688,6 +690,7 @@ - - #define REG_USB_INFO 0xFE17 - #define REG_USB_SPECIAL_OPTION 0xFE55 -+ - #define REG_USB_DMA_AGG_TO 0xFE5B - #define REG_USB_AGG_TO 0xFE5C - #define REG_USB_AGG_TH 0xFE5D -@@ -775,7 +778,6 @@ - - #define BOOT_FROM_EEPROM BIT(4) - #define EEPROM_EN BIT(5) --#define EEPROMSEL BOOT_FROM_EEPROM - - #define AFE_BGEN BIT(0) - #define AFE_MBEN BIT(1) -@@ -901,28 +903,7 @@ - #define BD_PKG_SEL BIT(25) - #define BD_HCI_SEL BIT(26) - #define TYPE_ID BIT(27) -- --/* REG_GPIO_OUTSTS (For RTL8723 only) */ --#define EFS_HCI_SEL (BIT(0)|BIT(1)) --#define PAD_HCI_SEL (BIT(2)|BIT(3)) --#define HCI_SEL (BIT(4)|BIT(5)) --#define PKG_SEL_HCI BIT(6) --#define FEN_GPS BIT(7) --#define FEN_BT BIT(8) --#define FEN_WL BIT(9) --#define FEN_PCI BIT(10) --#define FEN_USB BIT(11) --#define BTRF_HWPDN_N BIT(12) --#define WLRF_HWPDN_N BIT(13) --#define PDN_BT_N BIT(14) --#define PDN_GPS_N BIT(15) --#define BT_CTL_HWPDN BIT(16) --#define GPS_CTL_HWPDN BIT(17) --#define PPHY_SUSB BIT(20) --#define UPHY_SUSB BIT(21) --#define PCI_SUSEN BIT(22) --#define USB_SUSEN BIT(23) --#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) -+#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) - - #define CHIP_VER_RTL_MASK 0xF000 - #define CHIP_VER_RTL_SHIFT 12 -@@ -1077,6 +1058,7 @@ - #define _RARF_RC8(x) (((x) & 0x1F) << 24) - - #define AC_PARAM_TXOP_OFFSET 16 -+#define AC_PARAM_TXOP_LIMIT_OFFSET 16 - #define AC_PARAM_ECW_MAX_OFFSET 12 - #define AC_PARAM_ECW_MIN_OFFSET 8 - #define AC_PARAM_AIFS_OFFSET 0 -@@ -1221,33 +1203,11 @@ - #define EPROM_CMD_CONFIG 0x3 - #define EPROM_CMD_LOAD 1 - --#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE -+#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - --#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) -- --/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */ --/* Enable GPIO[9] as WiFi HW PDn source */ - #define WL_HWPDN_EN BIT(0) --/* WiFi HW PDn polarity control */ --#define WL_HWPDN_SL BIT(1) --/* WiFi function enable */ --#define WL_FUNC_EN BIT(2) --/* Enable GPIO[9] as WiFi RF HW PDn source */ --#define WL_HWROF_EN BIT(3) --/* Enable GPIO[11] as BT HW PDn source */ --#define BT_HWPDN_EN BIT(16) --/* BT HW PDn polarity control */ --#define BT_HWPDN_SL BIT(17) --/* BT function enable */ --#define BT_FUNC_EN BIT(18) --/* Enable GPIO[11] as BT/GPS RF HW PDn source */ --#define BT_HWROF_EN BIT(19) --/* Enable GPIO[10] as GPS HW PDn source */ --#define GPS_HWPDN_EN BIT(20) --/* GPS HW PDn polarity control */ --#define GPS_HWPDN_SL BIT(21) --/* GPS function enable */ --#define GPS_FUNC_EN BIT(22) -+ -+#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - - #define RPMAC_RESET 0x100 - #define RPMAC_TXSTART 0x104 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c 2011-05-05 23:29:49.328488297 +0200 -@@ -34,9 +34,9 @@ - #include "rf.h" - #include "dm.h" - --static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); -+static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - --void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -+void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -62,7 +62,7 @@ - } - - void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel) -+ u8 *ppowerlevel) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -128,8 +128,7 @@ - - tmpval = tx_agc[RF90_PATH_A] >> 8; - -- if (mac->mode == WIRELESS_MODE_B) -- tmpval = tmpval & 0xff00ffff; -+ tmpval = tmpval & 0xff00ffff; - - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - -@@ -202,7 +201,7 @@ - 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++) { -@@ -440,16 +439,17 @@ - else - rtlphy->num_total_rfpath = 2; - -- return _rtl92c_phy_rf6052_config_parafile(hw); -+ return _rtl92ce_phy_rf6052_config_parafile(hw); -+ - } - --static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -+static bool _rtl92ce_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; -+ bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { -@@ -484,12 +484,12 @@ - - switch (rfpath) { - case RF90_PATH_A: -- rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, -- (enum radio_path) rfpath); -+ rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, -+ (enum radio_path)rfpath); - break; - case RF90_PATH_B: -- rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw, -- (enum radio_path) rfpath); -+ rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, -+ (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h 2011-05-05 23:29:49.329488309 +0200 -@@ -34,14 +34,11 @@ - #define RF6052_MAX_REG 0x3F - #define RF6052_MAX_PATH 2 - --extern void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, -- u8 bandwidth); --extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel); --extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel, u8 channel); --bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); --bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, -- enum radio_path rfpath); -- -+extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, -+ u8 bandwidth); -+extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -+ u8 *ppowerlevel); -+extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, -+ u8 *ppowerlevel, u8 channel); -+extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c 2011-05-05 23:29:49.332488345 +0200 -@@ -42,10 +42,58 @@ - #include "trx.h" - #include "led.h" - -+static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ /*close ASPM for AMD defaultly */ -+ rtlpci->const_amdpci_aspm = 0; -+ -+ /* -+ * ASPM PS mode. -+ * 0 - Disable ASPM, -+ * 1 - Enable ASPM without Clock Req, -+ * 2 - Enable ASPM with Clock Req, -+ * 3 - Alwyas Enable ASPM with Clock Req, -+ * 4 - Always Enable ASPM without Clock Req. -+ * set defult to RTL8192CE:3 RTL8192E:2 -+ * */ -+ rtlpci->const_pci_aspm = 3; -+ -+ /*Setting for PCI-E device */ -+ rtlpci->const_devicepci_aspm_setting = 0x03; -+ -+ /*Setting for PCI-E bridge */ -+ rtlpci->const_hostpci_aspm_setting = 0x02; -+ -+ /* -+ * In Hw/Sw Radio Off situation. -+ * 0 - Default, -+ * 1 - From ASPM setting without low Mac Pwr, -+ * 2 - From ASPM setting with low Mac Pwr, -+ * 3 - Bus D3 -+ * set default to RTL8192CE:0 RTL8192SE:2 -+ */ -+ rtlpci->const_hwsw_rfoff_d3 = 0; -+ -+ /* -+ * This setting works for those device with -+ * backdoor ASPM setting such as EPHY setting. -+ * 0 - Not support ASPM, -+ * 1 - Support ASPM, -+ * 2 - According to chipset. -+ */ -+ rtlpci->const_support_pciaspm = 1; -+} -+ - int rtl92c_init_sw_vars(struct ieee80211_hw *hw) - { -+ int err; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ const struct firmware *firmware; -+ -+ rtl8192ce_bt_reg_init(hw); - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; -@@ -53,7 +101,12 @@ - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - -- rtlpci->receive_config = (RCR_APP_FCS | -+ /* compatible 5G band 88ce just 2.4G band & smsp */ -+ rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; -+ rtlpriv->rtlhal.bandset = BAND_ON_2_4G; -+ rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; -+ -+ rtlpci->receive_config = (RCR_APPFCS | - RCR_AMF | - RCR_ADF | - RCR_APP_MIC | -@@ -76,13 +129,49 @@ - - rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD | 0); - -- rtlpriv->rtlhal.pfirmware = (u8 *) vmalloc(0x4000); -+ /* for LPS & IPS */ -+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; -+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; -+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; -+ rtlpriv->psc.reg_fwctrl_lps = 3; -+ rtlpriv->psc.reg_max_lps_awakeintvl = 5; -+ /* for ASPM, you can close aspm through -+ * set const_support_pciaspm = 0 */ -+ rtl92c_init_aspm_vars(hw); -+ -+ if (rtlpriv->psc.reg_fwctrl_lps == 1) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; -+ else if (rtlpriv->psc.reg_fwctrl_lps == 2) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; -+ else if (rtlpriv->psc.reg_fwctrl_lps == 3) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; -+ -+ /* for firmware buf */ -+ rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Can't alloc buffer for fw.\n")); - return 1; - } - -+ /* request fw */ -+ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, -+ rtlpriv->io.dev); -+ if (err) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Failed to request firmware!\n")); -+ return 1; -+ } -+ if (firmware->size > 0x4000) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Firmware is too big!\n")); -+ release_firmware(firmware); -+ return 1; -+ } -+ memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); -+ rtlpriv->rtlhal.fwsize = firmware->size; -+ release_firmware(firmware); -+ - return 0; - } - -@@ -103,17 +192,19 @@ - .interrupt_recognized = rtl92ce_interrupt_recognized, - .hw_init = rtl92ce_hw_init, - .hw_disable = rtl92ce_card_disable, -+ .hw_suspend = rtl92ce_suspend, -+ .hw_resume = rtl92ce_resume, - .enable_interrupt = rtl92ce_enable_interrupt, - .disable_interrupt = rtl92ce_disable_interrupt, - .set_network_type = rtl92ce_set_network_type, -+ .set_chk_bssid = rtl92ce_set_check_bssid, - .set_qos = rtl92ce_set_qos, - .set_bcn_reg = rtl92ce_set_beacon_related_registers, - .set_bcn_intv = rtl92ce_set_beacon_interval, - .update_interrupt_mask = rtl92ce_update_interrupt_mask, - .get_hw_reg = rtl92ce_get_hw_reg, - .set_hw_reg = rtl92ce_set_hw_reg, -- .update_rate_table = rtl92ce_update_hal_rate_table, -- .update_rate_mask = rtl92ce_update_hal_rate_mask, -+ .update_rate_tbl = rtl92ce_update_hal_rate_tbl, - .fill_tx_desc = rtl92ce_tx_fill_desc, - .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, - .query_rx_desc = rtl92ce_rx_query_desc, -@@ -123,7 +214,7 @@ - .switch_channel = rtl92c_phy_sw_chnl, - .dm_watchdog = rtl92c_dm_watchdog, - .scan_operation_backup = rtl92c_phy_scan_operation_backup, -- .set_rf_power_state = rtl92ce_phy_set_rf_power_state, -+ .set_rf_power_state = rtl92c_phy_set_rf_power_state, - .led_control = rtl92ce_led_control, - .set_desc = rtl92ce_set_desc, - .get_desc = rtl92ce_get_desc, -@@ -131,27 +222,29 @@ - .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, - .set_rfreg = rtl92ce_phy_set_rf_reg, -- .cmd_send_packet = _rtl92c_cmd_send_packet, -+ .get_rfreg = rtl92c_phy_query_rf_reg, - .phy_rf6052_config = rtl92ce_phy_rf6052_config, - .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, - .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, - .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, - .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, - .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, -- .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, - .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, - }; - - static struct rtl_mod_params rtl92ce_mod_params = { -- .sw_crypto = 0, -+ .sw_crypto = false, -+ .inactiveps = true, -+ .swctrl_lps = false, -+ .fwctrl_lps = true, - }; - - static struct rtl_hal_cfg rtl92ce_hal_cfg = { -+ .bar_id = 2, -+ .write_readback = true, - .name = "rtl92c_pci", - .fw_name = "rtlwifi/rtl8192cfw.bin", - .ops = &rtl8192ce_hal_ops, -@@ -175,6 +268,8 @@ - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = EFUSE_ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, -+ .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, -+ .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, -@@ -239,7 +334,7 @@ - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, - }; - --static struct pci_device_id rtl92ce_pci_ids[] __devinitdata = { -+DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, -@@ -257,7 +352,13 @@ - MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); - - module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); -+module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); -+module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); -+module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); - MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); -+MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); -+MODULE_PARM_DESC(fwlps, "using linked fw control power save " -+ "(default 1 is open)\n"); - - static struct pci_driver rtl92ce_driver = { - .name = KBUILD_MODNAME, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h 2011-05-05 23:29:49.325488261 +0200 -@@ -33,19 +33,9 @@ - int rtl92c_init_sw_vars(struct ieee80211_hw *hw); - void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); - void rtl92c_init_var_map(struct ieee80211_hw *hw); --bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, -- struct sk_buff *skb); --void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel); --void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel, u8 channel); - bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, -- u8 configtype); -+ u8 configtype); - bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, -- u8 configtype); --void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); --u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 regaddr, u32 bitmask); --void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -+ u8 configtype); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c 2011-05-05 23:29:49.327488285 +0200 -@@ -36,42 +36,16 @@ - #include "trx.h" - #include "led.h" - --static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc, -- unsigned int -- skb_queue) -+static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) - { -- enum rtl_desc_qsel qsel; -+ __le16 fc = rtl_get_fc(skb); - -- if (unlikely(ieee80211_is_beacon(fc))) { -- qsel = QSLT_BEACON; -- return qsel; -- } -- -- if (ieee80211_is_mgmt(fc)) { -- qsel = QSLT_MGNT; -- return qsel; -- } -+ if (unlikely(ieee80211_is_beacon(fc))) -+ return QSLT_BEACON; -+ if (ieee80211_is_mgmt(fc)) -+ return QSLT_MGNT; - -- switch (skb_queue) { -- case VO_QUEUE: -- qsel = QSLT_VO; -- break; -- case VI_QUEUE: -- qsel = QSLT_VI; -- break; -- case BE_QUEUE: -- qsel = QSLT_BE; -- break; -- case BK_QUEUE: -- qsel = QSLT_BK; -- break; -- default: -- qsel = QSLT_BE; -- RT_ASSERT(false, ("BE queue, skb_queue:%d," -- " set qsel = 0x%X\n", skb_queue, QSLT_BE)); -- break; -- } -- return qsel; -+ return skb->priority; - } - - static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -@@ -255,6 +229,7 @@ - u8 evm, pwdb_all, rf_rx_num = 0; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; -+ bool in_powersavemode = false; - bool is_cck_rate; - - is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); -@@ -270,9 +245,13 @@ - u8 report, cck_highpwr; - cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - -- cck_highpwr = (u8) rtl_get_bbreg(hw, -- RFPGA0_XA_HSSIPARAMETER2, -- BIT(9)); -+ if (!in_powersavemode) -+ cck_highpwr = (u8) rtl_get_bbreg(hw, -+ RFPGA0_XA_HSSIPARAMETER2, -+ BIT(9)); -+ else -+ cck_highpwr = false; -+ - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; -@@ -398,6 +377,7 @@ - - if (rtlpriv->stats.ui_rssi.total_num++ >= - PHY_RSSI_SLID_WIN_MAX) { -+ - rtlpriv->stats.ui_rssi.total_num = - PHY_RSSI_SLID_WIN_MAX; - last_rssi = -@@ -424,10 +404,6 @@ - if (!pstats->is_cck && pstats->packet_toself) { - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { -- -- if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) -- continue; -- - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - pstats->rx_mimo_signalstrength[rfpath]; -@@ -723,7 +699,7 @@ - void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, -- unsigned int queue_index) -+ u8 hw_queue, struct rtl_tcb_desc *tcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -@@ -732,16 +708,9 @@ - bool defaultadapter = true; - struct ieee80211_sta *sta; - u8 *pdesc = (u8 *) pdesc_tx; -- struct rtl_tcb_desc tcb_desc; -- u8 *qc = ieee80211_get_qos_ctl(hdr); -- u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u16 seq_number; - __le16 fc = hdr->frame_control; -- u8 rate_flag = info->control.rates[0].flags; -- -- enum rtl_desc_qsel fw_qsel = -- _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index); -- -+ u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - -@@ -751,56 +720,68 @@ - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); -+ u8 bw_40 = 0; -+ -+ rcu_read_lock(); -+ sta = get_sta(hw, mac->vif, mac->bssid); -+ if (mac->opmode == NL80211_IFTYPE_STATION) { -+ bw_40 = mac->bw_40; -+ } else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (sta) -+ bw_40 = sta->ht_cap.cap & -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ } - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - -- rtl_get_tcb_desc(hw, info, skb, &tcb_desc); -+ rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); - - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); - -+ if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { -+ firstseg = true; -+ lastseg = true; -+ } - if (firstseg) { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - -- SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate); -+ SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); - -- if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) -+ if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - -- if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && -- info->flags & IEEE80211_TX_CTL_AMPDU) { -+ if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_BREAK(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - -- SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable && -- !tcb_desc. -+ SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && -+ !tcb_desc-> - cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, -- ((tcb_desc.rts_enable -- || tcb_desc.cts_enable) ? 1 : 0)); -- SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0)); -- SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); -+ ((tcb_desc->rts_enable -+ || tcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - -- SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate); -+ SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); -- SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc); -+ SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, -- ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? -- (tcb_desc.rts_use_shortpreamble ? 1 : 0) -- : (tcb_desc.rts_use_shortgi ? 1 : 0))); -+ ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? -+ (tcb_desc->rts_use_shortpreamble ? 1 : 0) -+ : (tcb_desc->rts_use_shortgi ? 1 : 0))); - -- if (mac->bw_40) { -- if (tcb_desc.packet_bw) { -+ if (bw_40) { -+ if (tcb_desc->packet_bw) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); -- -- if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { -- SET_TX_DESC_TX_SUB_CARRIER(pdesc, -- mac->cur_40_prime_sc); -- } -+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, -+ mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); -@@ -810,13 +791,10 @@ - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - -- rcu_read_lock(); -- sta = ieee80211_find_sta(mac->vif, mac->bssid); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } -- rcu_read_unlock(); - - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = -@@ -844,7 +822,7 @@ - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, 0); -- SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0); -+ SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); - - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { -@@ -855,24 +833,24 @@ - } - } - } -+ rcu_read_unlock(); - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - -- SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); -+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - if (rtlpriv->dm.useramask) { -- SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index); -- SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id); -+ SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); -+ SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); - } else { -- SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index); -- SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index); -+ SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); -+ SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); - } - -- if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && -- ppsc->fwctrl_lps) { -+ if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - -@@ -923,7 +901,7 @@ - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - -- SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); -+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); -@@ -1021,7 +999,7 @@ - return ret; - } - --void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue) -+void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) { -@@ -1032,35 +1010,3 @@ - } - } - --bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, -- struct sk_buff *skb) --{ -- struct rtl_priv *rtlpriv = rtl_priv(hw); -- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -- struct rtl8192_tx_ring *ring; -- struct rtl_tx_desc *pdesc; -- u8 own; -- unsigned long flags; -- struct sk_buff *pskb = NULL; -- -- ring = &rtlpci->tx_ring[BEACON_QUEUE]; -- -- spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); -- -- pskb = __skb_dequeue(&ring->queue); -- if (pskb) -- kfree_skb(pskb); -- -- pdesc = &ring->desc[0]; -- own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); -- -- rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); -- -- __skb_queue_tail(&ring->queue, skb); -- -- spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -- -- rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); -- -- return true; --} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h 2011-05-05 23:29:49.330488321 +0200 -@@ -532,9 +532,9 @@ - #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ - do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ -- memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ -+ memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ -- memset((void *)__pdesc, 0, _size); \ -+ memset(__pdesc, 0, _size); \ - } while (0); - - #define RX_HAL_IS_CCK_RATE(_pdesc)\ -@@ -724,17 +724,16 @@ - void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, - u8 *pdesc, struct ieee80211_tx_info *info, -- struct sk_buff *skb, unsigned int qsel); -+ struct sk_buff *skb, u8 hw_queue, -+ struct rtl_tcb_desc *ptcb_desc); - bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); - void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); - u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); --void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue); -+void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); - void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, - struct sk_buff *skb); --bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); -- - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c 2011-05-05 23:29:49.267487559 +0200 -@@ -39,6 +39,7 @@ - #include "mac.h" - #include "dm.h" - #include "hw.h" -+#include "../rtl8192ce/hw.h" - #include "trx.h" - #include "led.h" - #include "table.h" -@@ -605,10 +606,10 @@ - if (!IS_NORMAL_CHIP(rtlhal->version)) - return; - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); -- rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ? -+ rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? - EEPROM_93C46 : EEPROM_BOOT_EFUSE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n", -- (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE")); -+ (tmp_u1b & BOOT_FROM_EEPROM) ? "EERROM" : "EFUSE")); - rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n", - (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!")); -@@ -921,7 +922,7 @@ - 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) { -@@ -977,7 +978,7 @@ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - -- mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS | -+ mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | - RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | - RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); - rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf); -@@ -2182,7 +2183,9 @@ - } - } - --void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw) -+void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, -+ u8 rssi_level) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h 2011-05-05 23:29:49.263487511 +0200 -@@ -98,13 +98,14 @@ - u32 add_msr, u32 rm_msr); - void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); - void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); --void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw); -+void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, -+ u8 rssi_level); - void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level); - - void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); - bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); - void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); --u8 _rtl92c_get_chnl_group(u8 chnl); - int rtl92c_download_fw(struct ieee80211_hw *hw); - void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); - void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c 2011-05-05 23:29:49.246487305 +0200 -@@ -38,7 +38,7 @@ - #include "table.h" - - u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, u32 regaddr, u32 bitmask) -+ enum radio_path rfpath, u32 regaddr, u32 bitmask) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; -@@ -64,8 +64,8 @@ - } - - void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, -- enum radio_path rfpath, -- u32 regaddr, u32 bitmask, u32 data) -+ enum radio_path rfpath, -+ u32 regaddr, u32 bitmask, u32 data) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -163,7 +163,7 @@ - } - - bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, -- u8 configtype) -+ u8 configtype) - { - int i; - u32 *phy_regarray_table; -@@ -223,7 +223,7 @@ - } - - bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, -- u8 configtype) -+ u8 configtype) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -459,7 +459,7 @@ - } - } - --bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, -+static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -@@ -595,7 +595,7 @@ - } - - bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, -- enum rf_pwrstate rfpwr_state) -+ enum rf_pwrstate rfpwr_state) - { - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = false; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h 2011-05-05 23:29:49.247487318 +0200 -@@ -34,3 +34,17 @@ - void rtl92c_phy_set_io(struct ieee80211_hw *hw); - bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); - bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); -+u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 regaddr, u32 bitmask); -+void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, -+ enum radio_path rfpath, -+ u32 regaddr, u32 bitmask, u32 data); -+bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); -+bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, -+ u8 configtype); -+void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -+bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, -+ u8 configtype); -+void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -+bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, -+ enum rf_pwrstate rfpwr_state); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c 2011-05-05 23:29:49.248487331 +0200 -@@ -62,7 +62,7 @@ - } - - void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel) -+ u8 *ppowerlevel) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); -@@ -389,7 +389,7 @@ - } - - void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, -- u8 *ppowerlevel, u8 channel) -+ u8 *ppowerlevel, u8 channel) - { - u32 writeVal[2], powerBase0[2], powerBase1[2]; - u8 index = 0; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h 2011-05-05 23:29:49.265487535 +0200 -@@ -43,5 +43,9 @@ - bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); - bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -+void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, -+ u8 *ppowerlevel); -+void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, -+ u8 *ppowerlevel, u8 channel); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c 2011-05-05 23:29:49.268487571 +0200 -@@ -94,7 +94,7 @@ - .update_interrupt_mask = rtl92cu_update_interrupt_mask, - .get_hw_reg = rtl92cu_get_hw_reg, - .set_hw_reg = rtl92cu_set_hw_reg, -- .update_rate_table = rtl92cu_update_hal_rate_table, -+ .update_rate_tbl = rtl92cu_update_hal_rate_table, - .update_rate_mask = rtl92cu_update_hal_rate_mask, - .fill_tx_desc = rtl92cu_tx_fill_desc, - .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c 2011-05-05 23:29:49.248487331 +0200 -@@ -498,14 +498,14 @@ - void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, -- unsigned int queue_index) -+ u8 queue_index, -+ struct rtl_tcb_desc *tcb_desc) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool defaultadapter = true; -- struct ieee80211_sta *sta; -- struct rtl_tcb_desc tcb_desc; -+ struct ieee80211_sta *sta = info->control.sta = info->control.sta; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u16 seq_number; -@@ -517,15 +517,15 @@ - u8 *txdesc; - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; -- rtl_get_tcb_desc(hw, info, skb, &tcb_desc); -+ rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); - txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); - memset(txdesc, 0, RTL_TX_HEADER_SIZE); - SET_TX_DESC_PKT_SIZE(txdesc, pktlen); - SET_TX_DESC_LINIP(txdesc, 0); - SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); - SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); -- SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate); -- if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble) -+ SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); -+ if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(txdesc, 1); - if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && - info->flags & IEEE80211_TX_CTL_AMPDU) { -@@ -535,21 +535,21 @@ - SET_TX_DESC_AGG_BREAK(txdesc, 1); - } - SET_TX_DESC_SEQ(txdesc, seq_number); -- SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable && -- !tcb_desc.cts_enable) ? 1 : 0)); -- SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable || -- tcb_desc.cts_enable) ? 1 : 0)); -- SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0)); -- SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0)); -- SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate); -+ SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && -+ !tcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || -+ tcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); -+ SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(txdesc, 0); -- SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc); -+ SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(txdesc, -- ((tcb_desc.rts_rate <= DESC92C_RATE54M) ? -- (tcb_desc.rts_use_shortpreamble ? 1 : 0) -- : (tcb_desc.rts_use_shortgi ? 1 : 0))); -+ ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? -+ (tcb_desc->rts_use_shortpreamble ? 1 : 0) -+ : (tcb_desc->rts_use_shortgi ? 1 : 0))); - if (mac->bw_40) { -- if (tcb_desc.packet_bw) { -+ if (tcb_desc->packet_bw) { - SET_TX_DESC_DATA_BW(txdesc, 1); - SET_TX_DESC_DATA_SC(txdesc, 3); - } else { -@@ -590,7 +590,7 @@ - SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); - SET_TX_DESC_DISABLE_FB(txdesc, 0); -- SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0); -+ SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, -@@ -600,11 +600,11 @@ - } - } - if (rtlpriv->dm.useramask) { -- SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index); -- SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id); -+ SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); -+ SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); - } else { -- SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index); -- SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index); -+ SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); -+ SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); - } - if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && - ppsc->fwctrl_lps) { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h 2011-05-05 23:29:49.266487547 +0200 -@@ -37,6 +37,8 @@ - #define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ - #define RX_DRV_INFO_SIZE_UNIT 8 - -+#define RTL_AGG_ON 1 -+ - enum usb_rx_agg_mode { - USB_RX_AGG_DISABLE, - USB_RX_AGG_DMA, -@@ -419,7 +421,8 @@ - void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, -- unsigned int queue_index); -+ u8 queue_index, -+ struct rtl_tcb_desc *tcb_desc); - void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, - u32 buffer_len, bool bIsPsPoll); - void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/def.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/def.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/def.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/def.h 2011-05-05 23:29:49.281487729 +0200 -@@ -0,0 +1,598 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_92S_DEF_H__ -+#define __REALTEK_92S_DEF_H__ -+ -+#define RX_MPDU_QUEUE 0 -+#define RX_CMD_QUEUE 1 -+#define RX_MAX_QUEUE 2 -+ -+#define DESC92S_RATE1M 0x00 -+#define DESC92S_RATE2M 0x01 -+#define DESC92S_RATE5_5M 0x02 -+#define DESC92S_RATE11M 0x03 -+#define DESC92S_RATE6M 0x04 -+#define DESC92S_RATE9M 0x05 -+#define DESC92S_RATE12M 0x06 -+#define DESC92S_RATE18M 0x07 -+#define DESC92S_RATE24M 0x08 -+#define DESC92S_RATE36M 0x09 -+#define DESC92S_RATE48M 0x0a -+#define DESC92S_RATE54M 0x0b -+#define DESC92S_RATEMCS0 0x0c -+#define DESC92S_RATEMCS1 0x0d -+#define DESC92S_RATEMCS2 0x0e -+#define DESC92S_RATEMCS3 0x0f -+#define DESC92S_RATEMCS4 0x10 -+#define DESC92S_RATEMCS5 0x11 -+#define DESC92S_RATEMCS6 0x12 -+#define DESC92S_RATEMCS7 0x13 -+#define DESC92S_RATEMCS8 0x14 -+#define DESC92S_RATEMCS9 0x15 -+#define DESC92S_RATEMCS10 0x16 -+#define DESC92S_RATEMCS11 0x17 -+#define DESC92S_RATEMCS12 0x18 -+#define DESC92S_RATEMCS13 0x19 -+#define DESC92S_RATEMCS14 0x1a -+#define DESC92S_RATEMCS15 0x1b -+#define DESC92S_RATEMCS15_SG 0x1c -+#define DESC92S_RATEMCS32 0x20 -+ -+#define SHORT_SLOT_TIME 9 -+#define NON_SHORT_SLOT_TIME 20 -+ -+/* Rx smooth factor */ -+#define RX_SMOOTH_FACTOR 20 -+ -+/* Queue Select Value in TxDesc */ -+#define QSLT_BK 0x2 -+#define QSLT_BE 0x0 -+#define QSLT_VI 0x5 -+#define QSLT_VO 0x6 -+#define QSLT_BEACON 0x10 -+#define QSLT_HIGH 0x11 -+#define QSLT_MGNT 0x12 -+#define QSLT_CMD 0x13 -+ -+#define PHY_RSSI_SLID_WIN_MAX 100 -+#define PHY_LINKQUALITY_SLID_WIN_MAX 20 -+#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 -+ -+/* Tx Desc */ -+#define TX_DESC_SIZE_RTL8192S (16 * 4) -+#define TX_CMDDESC_SIZE_RTL8192S (16 * 4) -+ -+/* Define a macro that takes a le32 word, converts it to host ordering, -+ * right shifts by a specified count, creates a mask of the specified -+ * bit count, and extracts that number of bits. -+ */ -+ -+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \ -+ ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ -+ BIT_LEN_MASK_32(__mask)) -+ -+/* Define a macro that clears a bit field in an le32 word and -+ * sets the specified value into that bit field. The resulting -+ * value remains in le32 ordering; however, it is properly converted -+ * to host ordering for the clear and set operations before conversion -+ * back to le32. -+ */ -+ -+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \ -+ (*(__le32 *)(__pdesc) = \ -+ (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \ -+ (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \ -+ (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); -+ -+/* macros to read/write various fields in RX or TX descriptors */ -+ -+/* Dword 0 */ -+#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) -+#define SET_TX_DESC_OFFSET(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) -+#define SET_TX_DESC_TYPE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) -+#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -+#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -+#define SET_TX_DESC_LINIP(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -+#define SET_TX_DESC_AMSDU(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -+#define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -+#define SET_TX_DESC_OWN(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) -+ -+#define GET_TX_DESC_OWN(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 31, 1) -+ -+/* Dword 1 */ -+#define SET_TX_DESC_MACID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) -+#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val) -+#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val) -+#define SET_TX_DESC_PIFS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val) -+#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val) -+#define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val) -+#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) -+#define SET_TX_DESC_NON_QOS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val) -+#define SET_TX_DESC_KEY_ID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val) -+#define SET_TX_DESC_OUI(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val) -+#define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val) -+#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val) -+#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val) -+#define SET_TX_DESC_WDS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) -+#define SET_TX_DESC_HTC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) -+#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val) -+#define SET_TX_DESC_HWPC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) -+ -+/* Dword 2 */ -+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val) -+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val) -+#define SET_TX_DESC_TSFL(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val) -+#define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val) -+#define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val) -+#define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val) -+#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val) -+#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) -+#define SET_TX_DESC_OWN_MAC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val) -+ -+/* Dword 3 */ -+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val) -+#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val) -+#define SET_TX_DESC_SEQ(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val) -+#define SET_TX_DESC_FRAG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val) -+ -+/* Dword 4 */ -+#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val) -+#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val) -+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val) -+#define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val) -+#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val) -+#define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val) -+#define SET_TX_DESC_TXHT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val) -+#define SET_TX_DESC_TX_SHORT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val) -+#define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val) -+#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val) -+#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val) -+#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val) -+#define SET_TX_DESC_RTS_HT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val) -+#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val) -+#define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val) -+#define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val) -+#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val) -+#define SET_TX_DESC_USER_RATE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val) -+ -+/* Dword 5 */ -+#define SET_TX_DESC_PACKET_ID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val) -+#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val) -+#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val) -+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val) -+#define SET_TX_DESC_TX_AGC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val) -+ -+/* Dword 6 */ -+#define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val) -+#define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val) -+ -+/* Dword 7 */ -+#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val) -+#define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val) -+#define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val) -+ -+/* Dword 8 */ -+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val) -+#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32) -+ -+/* Dword 9 */ -+#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val) -+ -+/* Because the PCI Tx descriptors are chaied at the -+ * initialization and all the NextDescAddresses in -+ * these descriptors cannot not be cleared (,or -+ * driver/HW cannot find the next descriptor), the -+ * offset 36 (NextDescAddresses) is reserved when -+ * the desc is cleared. */ -+#define TX_DESC_NEXT_DESC_OFFSET 36 -+#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -+do { \ -+ if (_size > TX_DESC_NEXT_DESC_OFFSET) \ -+ memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ -+ else \ -+ memset(__pdesc, 0, _size); \ -+} while (0); -+ -+/* Rx Desc */ -+#define RX_STATUS_DESC_SIZE 24 -+#define RX_DRV_INFO_SIZE_UNIT 8 -+ -+/* DWORD 0 */ -+#define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) -+#define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val) -+#define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val) -+#define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val) -+#define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val) -+#define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val) -+#define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) -+#define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -+#define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -+#define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -+#define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -+#define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -+#define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) -+ -+#define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 0, 14) -+#define GET_RX_STATUS_DESC_CRC32(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 14, 1) -+#define GET_RX_STATUS_DESC_ICV(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 15, 1) -+#define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 16, 4) -+#define GET_RX_STATUS_DESC_SECURITY(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 20, 3) -+#define GET_RX_STATUS_DESC_QOS(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 23, 1) -+#define GET_RX_STATUS_DESC_SHIFT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 24, 2) -+#define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 26, 1) -+#define GET_RX_STATUS_DESC_SWDEC(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 27, 1) -+#define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 28, 1) -+#define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 29, 1) -+#define GET_RX_STATUS_DESC_EOR(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 30, 1) -+#define GET_RX_STATUS_DESC_OWN(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc, 31, 1) -+ -+/* DWORD 1 */ -+#define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) -+#define SET_RX_STATUS_DESC_TID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val) -+#define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val) -+#define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) -+#define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val) -+#define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val) -+#define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) -+#define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) -+#define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val) -+#define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) -+#define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val) -+#define SET_RX_STATUS_DESC_MC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val) -+#define SET_RX_STATUS_DESC_BC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val) -+ -+#define GET_RX_STATUS_DEC_MACID(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5) -+#define GET_RX_STATUS_DESC_TID(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4) -+#define GET_RX_STATUS_DESC_PAGGR(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1) -+#define GET_RX_STATUS_DESC_FAGGR(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1) -+#define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4) -+#define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4) -+#define GET_RX_STATUS_DESC_PAM(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1) -+#define GET_RX_STATUS_DESC_PWR(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1) -+#define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1) -+#define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1) -+#define GET_RX_STATUS_DESC_TYPE(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2) -+#define GET_RX_STATUS_DESC_MC(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1) -+#define GET_RX_STATUS_DESC_BC(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1) -+ -+/* DWORD 2 */ -+#define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val) -+#define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val) -+#define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val) -+#define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) -+ -+#define GET_RX_STATUS_DESC_SEQ(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12) -+#define GET_RX_STATUS_DESC_FRAG(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4) -+#define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8) -+#define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1) -+ -+/* DWORD 3 */ -+#define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val) -+#define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val) -+#define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val) -+#define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val) -+#define SET_RX_STATUS_DESC_BW(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val) -+#define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val) -+#define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val) -+#define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val) -+#define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val) -+#define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val) -+#define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val) -+#define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val) -+ -+#define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6) -+#define GET_RX_STATUS_DESC_RX_HT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1) -+#define GET_RX_STATUS_DESC_AMSDU(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1) -+#define GET_RX_STATUS_DESC_SPLCP(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1) -+#define GET_RX_STATUS_DESC_BW(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1) -+#define GET_RX_STATUS_DESC_HTC(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1) -+#define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1) -+#define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1) -+#define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1) -+#define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1) -+#define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1) -+#define GET_RX_STATUS_DESC_IV0(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16) -+ -+/* DWORD 4 */ -+#define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val) -+#define GET_RX_STATUS_DESC_IV1(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32) -+ -+/* DWORD 5 */ -+#define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val) -+#define GET_RX_STATUS_DESC_TSFL(__pdesc) \ -+ SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32) -+ -+/* DWORD 6 */ -+#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ -+ SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) -+ -+#define RX_HAL_IS_CCK_RATE(_pdesc)\ -+ (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \ -+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \ -+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ -+ GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) -+ -+enum rf_optype { -+ RF_OP_BY_SW_3WIRE = 0, -+ RF_OP_BY_FW, -+ RF_OP_MAX -+}; -+ -+enum ic_inferiority { -+ IC_INFERIORITY_A = 0, -+ IC_INFERIORITY_B = 1, -+}; -+ -+enum fwcmd_iotype { -+ /* For DIG DM */ -+ FW_CMD_DIG_ENABLE = 0, -+ FW_CMD_DIG_DISABLE = 1, -+ FW_CMD_DIG_HALT = 2, -+ FW_CMD_DIG_RESUME = 3, -+ /* For High Power DM */ -+ FW_CMD_HIGH_PWR_ENABLE = 4, -+ FW_CMD_HIGH_PWR_DISABLE = 5, -+ /* For Rate adaptive DM */ -+ FW_CMD_RA_RESET = 6, -+ FW_CMD_RA_ACTIVE = 7, -+ FW_CMD_RA_REFRESH_N = 8, -+ FW_CMD_RA_REFRESH_BG = 9, -+ FW_CMD_RA_INIT = 10, -+ /* For FW supported IQK */ -+ FW_CMD_IQK_INIT = 11, -+ /* Tx power tracking switch, -+ * MP driver only */ -+ FW_CMD_TXPWR_TRACK_ENABLE = 12, -+ /* Tx power tracking switch, -+ * MP driver only */ -+ FW_CMD_TXPWR_TRACK_DISABLE = 13, -+ /* Tx power tracking with thermal -+ * indication, for Normal driver */ -+ FW_CMD_TXPWR_TRACK_THERMAL = 14, -+ FW_CMD_PAUSE_DM_BY_SCAN = 15, -+ FW_CMD_RESUME_DM_BY_SCAN = 16, -+ FW_CMD_RA_REFRESH_N_COMB = 17, -+ FW_CMD_RA_REFRESH_BG_COMB = 18, -+ FW_CMD_ANTENNA_SW_ENABLE = 19, -+ FW_CMD_ANTENNA_SW_DISABLE = 20, -+ /* Tx Status report for CCX from FW */ -+ FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, -+ /* Indifate firmware that driver -+ * enters LPS, For PS-Poll issue */ -+ FW_CMD_LPS_ENTER = 22, -+ /* Indicate firmware that driver -+ * leave LPS*/ -+ FW_CMD_LPS_LEAVE = 23, -+ /* Set DIG mode to signal strength */ -+ FW_CMD_DIG_MODE_SS = 24, -+ /* Set DIG mode to false alarm. */ -+ FW_CMD_DIG_MODE_FA = 25, -+ FW_CMD_ADD_A2_ENTRY = 26, -+ FW_CMD_CTRL_DM_BY_DRIVER = 27, -+ FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, -+ FW_CMD_PAPE_CONTROL = 29, -+ FW_CMD_IQK_ENABLE = 30, -+}; -+ -+/* -+ * Driver info contain PHY status -+ * and other variabel size info -+ * PHY Status content as below -+ */ -+struct rx_fwinfo { -+ /* DWORD 0 */ -+ u8 gain_trsw[4]; -+ /* DWORD 1 */ -+ u8 pwdb_all; -+ u8 cfosho[4]; -+ /* DWORD 2 */ -+ u8 cfotail[4]; -+ /* DWORD 3 */ -+ s8 rxevm[2]; -+ s8 rxsnr[4]; -+ /* DWORD 4 */ -+ u8 pdsnr[2]; -+ /* DWORD 5 */ -+ u8 csi_current[2]; -+ u8 csi_target[2]; -+ /* DWORD 6 */ -+ u8 sigevm; -+ u8 max_ex_pwr; -+ u8 ex_intf_flag:1; -+ u8 sgi_en:1; -+ u8 rxsc:2; -+ u8 reserve:4; -+}; -+ -+struct phy_sts_cck_8192s_t { -+ u8 adc_pwdb_x[4]; -+ u8 sq_rpt; -+ u8 cck_agc_rpt; -+}; -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/dm.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/dm.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/dm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/dm.c 2011-05-05 23:29:49.284487765 +0200 -@@ -0,0 +1,733 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../base.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "dm.h" -+#include "fw.h" -+ -+struct dig_t digtable; -+static const u32 edca_setting_dl[PEER_MAX] = { -+ 0xa44f, /* 0 UNKNOWN */ -+ 0x5ea44f, /* 1 REALTEK_90 */ -+ 0x5ea44f, /* 2 REALTEK_92SE */ -+ 0xa630, /* 3 BROAD */ -+ 0xa44f, /* 4 RAL */ -+ 0xa630, /* 5 ATH */ -+ 0xa630, /* 6 CISCO */ -+ 0xa42b, /* 7 MARV */ -+}; -+ -+static const u32 edca_setting_dl_gmode[PEER_MAX] = { -+ 0x4322, /* 0 UNKNOWN */ -+ 0xa44f, /* 1 REALTEK_90 */ -+ 0x5ea44f, /* 2 REALTEK_92SE */ -+ 0xa42b, /* 3 BROAD */ -+ 0x5e4322, /* 4 RAL */ -+ 0x4322, /* 5 ATH */ -+ 0xa430, /* 6 CISCO */ -+ 0x5ea44f, /* 7 MARV */ -+}; -+ -+static const u32 edca_setting_ul[PEER_MAX] = { -+ 0x5e4322, /* 0 UNKNOWN */ -+ 0xa44f, /* 1 REALTEK_90 */ -+ 0x5ea44f, /* 2 REALTEK_92SE */ -+ 0x5ea322, /* 3 BROAD */ -+ 0x5ea422, /* 4 RAL */ -+ 0x5ea322, /* 5 ATH */ -+ 0x3ea44f, /* 6 CISCO */ -+ 0x5ea44f, /* 7 MARV */ -+}; -+ -+static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ -+ static u64 last_txok_cnt; -+ static u64 last_rxok_cnt; -+ u64 cur_txok_cnt = 0; -+ u64 cur_rxok_cnt = 0; -+ -+ u32 edca_be_ul = edca_setting_ul[mac->vendor]; -+ u32 edca_be_dl = edca_setting_dl[mac->vendor]; -+ u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; -+ -+ if (mac->link_state != MAC80211_LINKED) { -+ rtlpriv->dm.current_turbo_edca = false; -+ goto dm_checkedcaturbo_exit; -+ } -+ -+ if ((!rtlpriv->dm.is_any_nonbepkts) && -+ (!rtlpriv->dm.disable_framebursting)) { -+ cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; -+ cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; -+ -+ if (rtlpriv->phy.rf_type == RF_1T2R) { -+ if (cur_txok_cnt > 4 * cur_rxok_cnt) { -+ /* Uplink TP is present. */ -+ if (rtlpriv->dm.is_cur_rdlstate || -+ !rtlpriv->dm.current_turbo_edca) { -+ rtl_write_dword(rtlpriv, EDCAPARA_BE, -+ edca_be_ul); -+ rtlpriv->dm.is_cur_rdlstate = false; -+ } -+ } else {/* Balance TP is present. */ -+ if (!rtlpriv->dm.is_cur_rdlstate || -+ !rtlpriv->dm.current_turbo_edca) { -+ if (mac->mode == WIRELESS_MODE_G || -+ mac->mode == WIRELESS_MODE_B) -+ rtl_write_dword(rtlpriv, -+ EDCAPARA_BE, -+ edca_gmode); -+ else -+ rtl_write_dword(rtlpriv, -+ EDCAPARA_BE, -+ edca_be_dl); -+ rtlpriv->dm.is_cur_rdlstate = true; -+ } -+ } -+ rtlpriv->dm.current_turbo_edca = true; -+ } else { -+ if (cur_rxok_cnt > 4 * cur_txok_cnt) { -+ if (!rtlpriv->dm.is_cur_rdlstate || -+ !rtlpriv->dm.current_turbo_edca) { -+ if (mac->mode == WIRELESS_MODE_G || -+ mac->mode == WIRELESS_MODE_B) -+ rtl_write_dword(rtlpriv, -+ EDCAPARA_BE, -+ edca_gmode); -+ else -+ rtl_write_dword(rtlpriv, -+ EDCAPARA_BE, -+ edca_be_dl); -+ rtlpriv->dm.is_cur_rdlstate = true; -+ } -+ } else { -+ if (rtlpriv->dm.is_cur_rdlstate || -+ !rtlpriv->dm.current_turbo_edca) { -+ rtl_write_dword(rtlpriv, EDCAPARA_BE, -+ edca_be_ul); -+ rtlpriv->dm.is_cur_rdlstate = false; -+ } -+ } -+ rtlpriv->dm.current_turbo_edca = true; -+ } -+ } else { -+ if (rtlpriv->dm.current_turbo_edca) { -+ u8 tmp = AC0_BE; -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, -+ (u8 *)(&tmp)); -+ rtlpriv->dm.current_turbo_edca = false; -+ } -+ } -+ -+dm_checkedcaturbo_exit: -+ rtlpriv->dm.is_any_nonbepkts = false; -+ last_txok_cnt = rtlpriv->stats.txbytesunicast; -+ last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -+} -+ -+static void _rtl92s_dm_txpowertracking_callback_thermalmeter( -+ struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u8 thermalvalue = 0; -+ -+ rtlpriv->dm.txpower_trackinginit = true; -+ -+ thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); -+ -+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, -+ ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " -+ "eeprom_thermalmeter 0x%x\n", thermalvalue, -+ rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter)); -+ -+ if (thermalvalue) { -+ rtlpriv->dm.thermalvalue = thermalvalue; -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); -+ } -+ -+ rtlpriv->dm.txpowercount = 0; -+} -+ -+static void _rtl92s_dm_check_txpowertracking_thermalmeter( -+ struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ static u8 tm_trigger; -+ u8 tx_power_checkcnt = 5; -+ -+ /* 2T2R TP issue */ -+ if (rtlphy->rf_type == RF_2T2R) -+ return; -+ -+ if (!rtlpriv->dm.txpower_tracking) -+ return; -+ -+ if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { -+ rtlpriv->dm.txpowercount++; -+ return; -+ } -+ -+ if (!tm_trigger) { -+ rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, -+ RFREG_OFFSET_MASK, 0x60); -+ tm_trigger = 1; -+ } else { -+ _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); -+ tm_trigger = 0; -+ } -+} -+ -+static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rate_adaptive *ra = &(rtlpriv->ra); -+ -+ u32 low_rssi_thresh = 0; -+ u32 middle_rssi_thresh = 0; -+ u32 high_rssi_thresh = 0; -+ u8 rssi_level; -+ struct ieee80211_sta *sta = NULL; -+ -+ if (is_hal_stop(rtlhal)) -+ return; -+ -+ if (!rtlpriv->dm.useramask) -+ return; -+ -+ if (!rtlpriv->dm.inform_fw_driverctrldm) { -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); -+ rtlpriv->dm.inform_fw_driverctrldm = true; -+ } -+ -+ rcu_read_lock(); -+ if (mac->opmode == NL80211_IFTYPE_STATION) -+ sta = get_sta(hw, mac->vif, mac->bssid); -+ if ((mac->link_state == MAC80211_LINKED) && -+ (mac->opmode == NL80211_IFTYPE_STATION)) { -+ switch (ra->pre_ratr_state) { -+ case DM_RATR_STA_HIGH: -+ high_rssi_thresh = 40; -+ middle_rssi_thresh = 30; -+ low_rssi_thresh = 20; -+ break; -+ case DM_RATR_STA_MIDDLE: -+ high_rssi_thresh = 44; -+ middle_rssi_thresh = 30; -+ low_rssi_thresh = 20; -+ break; -+ case DM_RATR_STA_LOW: -+ high_rssi_thresh = 44; -+ middle_rssi_thresh = 34; -+ low_rssi_thresh = 20; -+ break; -+ case DM_RATR_STA_ULTRALOW: -+ high_rssi_thresh = 44; -+ middle_rssi_thresh = 34; -+ low_rssi_thresh = 24; -+ break; -+ default: -+ high_rssi_thresh = 44; -+ middle_rssi_thresh = 34; -+ low_rssi_thresh = 24; -+ break; -+ } -+ -+ if (rtlpriv->dm.undecorated_smoothed_pwdb > -+ (long)high_rssi_thresh) { -+ ra->ratr_state = DM_RATR_STA_HIGH; -+ rssi_level = 1; -+ } else if (rtlpriv->dm.undecorated_smoothed_pwdb > -+ (long)middle_rssi_thresh) { -+ ra->ratr_state = DM_RATR_STA_LOW; -+ rssi_level = 3; -+ } else if (rtlpriv->dm.undecorated_smoothed_pwdb > -+ (long)low_rssi_thresh) { -+ ra->ratr_state = DM_RATR_STA_LOW; -+ rssi_level = 5; -+ } else { -+ ra->ratr_state = DM_RATR_STA_ULTRALOW; -+ rssi_level = 6; -+ } -+ -+ if (ra->pre_ratr_state != ra->ratr_state) { -+ RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, ("RSSI = %ld " -+ "RSSI_LEVEL = %d PreState = %d, CurState = %d\n", -+ rtlpriv->dm.undecorated_smoothed_pwdb, -+ ra->ratr_state, -+ ra->pre_ratr_state, ra->ratr_state)); -+ -+ rtlpriv->cfg->ops->update_rate_tbl(hw, sta, -+ ra->ratr_state); -+ ra->pre_ratr_state = ra->ratr_state; -+ } -+ } -+ rcu_read_unlock(); -+} -+ -+static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ bool current_mrc; -+ bool enable_mrc = true; -+ long tmpentry_maxpwdb = 0; -+ u8 rssi_a = 0; -+ u8 rssi_b = 0; -+ -+ if (is_hal_stop(rtlhal)) -+ return; -+ -+ if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) -+ return; -+ -+ rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); -+ -+ if (mac->link_state >= MAC80211_LINKED) { -+ if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) { -+ rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; -+ rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; -+ } -+ } -+ -+ /* MRC settings would NOT affect TP on Wireless B mode. */ -+ if (mac->mode != WIRELESS_MODE_B) { -+ if ((rssi_a == 0) && (rssi_b == 0)) { -+ enable_mrc = true; -+ } else if (rssi_b > 30) { -+ /* Turn on B-Path */ -+ enable_mrc = true; -+ } else if (rssi_b < 5) { -+ /* Turn off B-path */ -+ enable_mrc = false; -+ /* Take care of RSSI differentiation. */ -+ } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { -+ if ((rssi_a - rssi_b) > 15) -+ /* Turn off B-path */ -+ enable_mrc = false; -+ else if ((rssi_a - rssi_b) < 10) -+ /* Turn on B-Path */ -+ enable_mrc = true; -+ else -+ enable_mrc = current_mrc; -+ } else { -+ /* Turn on B-Path */ -+ enable_mrc = true; -+ } -+ } -+ -+ /* Update MRC settings if needed. */ -+ if (enable_mrc != current_mrc) -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, -+ (u8 *)&enable_mrc); -+ -+} -+ -+void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtlpriv->dm.current_turbo_edca = false; -+ rtlpriv->dm.is_any_nonbepkts = false; -+ rtlpriv->dm.is_cur_rdlstate = false; -+} -+ -+static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rate_adaptive *ra = &(rtlpriv->ra); -+ -+ ra->ratr_state = DM_RATR_STA_MAX; -+ ra->pre_ratr_state = DM_RATR_STA_MAX; -+ -+ if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) -+ rtlpriv->dm.useramask = true; -+ else -+ rtlpriv->dm.useramask = false; -+ -+ rtlpriv->dm.useramask = false; -+ rtlpriv->dm.inform_fw_driverctrldm = false; -+} -+ -+static void _rtl92s_dm_init_txpowertracking_thermalmeter( -+ struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtlpriv->dm.txpower_tracking = true; -+ rtlpriv->dm.txpowercount = 0; -+ rtlpriv->dm.txpower_trackinginit = false; -+} -+ -+static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); -+ u32 ret_value; -+ -+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); -+ falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); -+ -+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); -+ falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); -+ falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); -+ ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); -+ falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); -+ -+ falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + -+ falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + -+ falsealm_cnt->cnt_mcs_fail; -+ -+ /* read CCK false alarm */ -+ ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); -+ falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); -+ falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + -+ falsealm_cnt->cnt_cck_fail; -+} -+ -+static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); -+ -+ if (falsealm_cnt->cnt_all > digtable.fa_highthresh) { -+ if ((digtable.backoff_val - 6) < -+ digtable.backoffval_range_min) -+ digtable.backoff_val = digtable.backoffval_range_min; -+ else -+ digtable.backoff_val -= 6; -+ } else if (falsealm_cnt->cnt_all < digtable.fa_lowthresh) { -+ if ((digtable.backoff_val + 6) > -+ digtable.backoffval_range_max) -+ digtable.backoff_val = -+ digtable.backoffval_range_max; -+ else -+ digtable.backoff_val += 6; -+ } -+} -+ -+static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); -+ static u8 initialized, force_write; -+ u8 initial_gain = 0; -+ -+ if ((digtable.pre_sta_connectstate == digtable.cur_sta_connectstate) || -+ (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) { -+ if (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) { -+ if (rtlpriv->psc.rfpwr_state != ERFON) -+ return; -+ -+ if (digtable.backoff_enable_flag == true) -+ rtl92s_backoff_enable_flag(hw); -+ else -+ digtable.backoff_val = DM_DIG_BACKOFF; -+ -+ if ((digtable.rssi_val + 10 - digtable.backoff_val) > -+ digtable.rx_gain_range_max) -+ digtable.cur_igvalue = -+ digtable.rx_gain_range_max; -+ else if ((digtable.rssi_val + 10 - digtable.backoff_val) -+ < digtable.rx_gain_range_min) -+ digtable.cur_igvalue = -+ digtable.rx_gain_range_min; -+ else -+ digtable.cur_igvalue = digtable.rssi_val + 10 - -+ digtable.backoff_val; -+ -+ if (falsealm_cnt->cnt_all > 10000) -+ digtable.cur_igvalue = -+ (digtable.cur_igvalue > 0x33) ? -+ digtable.cur_igvalue : 0x33; -+ -+ if (falsealm_cnt->cnt_all > 16000) -+ digtable.cur_igvalue = -+ digtable.rx_gain_range_max; -+ /* connected -> connected or disconnected -> disconnected */ -+ } else { -+ /* Firmware control DIG, do nothing in driver dm */ -+ return; -+ } -+ /* disconnected -> connected or connected -> -+ * disconnected or beforeconnect->(dis)connected */ -+ } else { -+ /* Enable FW DIG */ -+ digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); -+ -+ digtable.backoff_val = DM_DIG_BACKOFF; -+ digtable.cur_igvalue = rtlpriv->phy.default_initialgain[0]; -+ digtable.pre_igvalue = 0; -+ return; -+ } -+ -+ /* Forced writing to prevent from fw-dig overwriting. */ -+ if (digtable.pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, -+ MASKBYTE0)) -+ force_write = 1; -+ -+ if ((digtable.pre_igvalue != digtable.cur_igvalue) || -+ !initialized || force_write) { -+ /* Disable FW DIG */ -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); -+ -+ initial_gain = (u8)digtable.cur_igvalue; -+ -+ /* Set initial gain. */ -+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); -+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); -+ digtable.pre_igvalue = digtable.cur_igvalue; -+ initialized = 1; -+ force_write = 0; -+ } -+} -+ -+static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (rtlpriv->mac80211.act_scanning) -+ return; -+ -+ /* Decide the current status and if modify initial gain or not */ -+ if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || -+ rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) -+ digtable.cur_sta_connectstate = DIG_STA_CONNECT; -+ else -+ digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; -+ -+ digtable.rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb; -+ -+ /* Change dig mode to rssi */ -+ if (digtable.cur_sta_connectstate != DIG_STA_DISCONNECT) { -+ if (digtable.dig_twoport_algorithm == -+ DIG_TWO_PORT_ALGO_FALSE_ALARM) { -+ digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); -+ } -+ } -+ -+ _rtl92s_dm_false_alarm_counter_statistics(hw); -+ _rtl92s_dm_initial_gain_sta_beforeconnect(hw); -+ -+ digtable.pre_sta_connectstate = digtable.cur_sta_connectstate; -+} -+ -+static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ /* 2T2R TP issue */ -+ if (rtlphy->rf_type == RF_2T2R) -+ return; -+ -+ if (!rtlpriv->dm.dm_initialgain_enable) -+ return; -+ -+ if (digtable.dig_enable_flag == false) -+ return; -+ -+ _rtl92s_dm_ctrl_initgain_bytwoport(hw); -+} -+ -+static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ long undecorated_smoothed_pwdb; -+ long txpwr_threshold_lv1, txpwr_threshold_lv2; -+ -+ /* 2T2R TP issue */ -+ if (rtlphy->rf_type == RF_2T2R) -+ return; -+ -+ if (!rtlpriv->dm.dynamic_txpower_enable || -+ rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ return; -+ } -+ -+ if ((mac->link_state < MAC80211_LINKED) && -+ (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, -+ ("Not connected to any\n")); -+ -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ -+ rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ return; -+ } -+ -+ if (mac->link_state >= MAC80211_LINKED) { -+ if (mac->opmode == NL80211_IFTYPE_ADHOC) { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("AP Client PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } else { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.undecorated_smoothed_pwdb; -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("STA Default Port PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } -+ } else { -+ undecorated_smoothed_pwdb = -+ rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("AP Ext Port PWDB = 0x%lx\n", -+ undecorated_smoothed_pwdb)); -+ } -+ -+ txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; -+ txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; -+ -+ if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2) -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; -+ else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) && -+ (undecorated_smoothed_pwdb >= txpwr_threshold_lv1)) -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; -+ else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3)) -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ -+ if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) -+ rtl92s_phy_set_txpower(hw, rtlphy->current_channel); -+ -+ rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -+} -+ -+static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ /* Disable DIG scheme now.*/ -+ digtable.dig_enable_flag = true; -+ digtable.backoff_enable_flag = true; -+ -+ if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && -+ (hal_get_firmwareversion(rtlpriv) >= 0x3c)) -+ digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT; -+ else -+ digtable.dig_algorithm = -+ DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; -+ -+ digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; -+ digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; -+ /* off=by real rssi value, on=by digtable.rssi_val for new dig */ -+ digtable.dig_dbgmode = DM_DBG_OFF; -+ digtable.dig_slgorithm_switch = 0; -+ -+ /* 2007/10/04 MH Define init gain threshol. */ -+ digtable.dig_state = DM_STA_DIG_MAX; -+ digtable.dig_highpwrstate = DM_STA_DIG_MAX; -+ -+ digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; -+ digtable.pre_sta_connectstate = DIG_STA_DISCONNECT; -+ digtable.cur_ap_connectstate = DIG_AP_DISCONNECT; -+ digtable.pre_ap_connectstate = DIG_AP_DISCONNECT; -+ -+ digtable.rssi_lowthresh = DM_DIG_THRESH_LOW; -+ digtable.rssi_highthresh = DM_DIG_THRESH_HIGH; -+ -+ digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW; -+ digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH; -+ -+ digtable.rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; -+ digtable.rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; -+ -+ /* for dig debug rssi value */ -+ digtable.rssi_val = 50; -+ digtable.backoff_val = DM_DIG_BACKOFF; -+ digtable.rx_gain_range_max = DM_DIG_MAX; -+ -+ digtable.rx_gain_range_min = DM_DIG_MIN; -+ -+ digtable.backoffval_range_max = DM_DIG_BACKOFF_MAX; -+ digtable.backoffval_range_min = DM_DIG_BACKOFF_MIN; -+} -+ -+static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if ((hal_get_firmwareversion(rtlpriv) >= 60) && -+ (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) -+ rtlpriv->dm.dynamic_txpower_enable = true; -+ else -+ rtlpriv->dm.dynamic_txpower_enable = false; -+ -+ rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+ rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -+} -+ -+void rtl92s_dm_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; -+ rtlpriv->dm.undecorated_smoothed_pwdb = -1; -+ -+ _rtl92s_dm_init_dynamic_txpower(hw); -+ rtl92s_dm_init_edca_turbo(hw); -+ _rtl92s_dm_init_rate_adaptive_mask(hw); -+ _rtl92s_dm_init_txpowertracking_thermalmeter(hw); -+ _rtl92s_dm_init_dig(hw); -+ -+ rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); -+} -+ -+void rtl92s_dm_watchdog(struct ieee80211_hw *hw) -+{ -+ _rtl92s_dm_check_edca_turbo(hw); -+ _rtl92s_dm_check_txpowertracking_thermalmeter(hw); -+ _rtl92s_dm_ctrl_initgain_byrssi(hw); -+ _rtl92s_dm_dynamic_txpower(hw); -+ _rtl92s_dm_refresh_rateadaptive_mask(hw); -+ _rtl92s_dm_switch_baseband_mrc(hw); -+} -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/dm.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/dm.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/dm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/dm.h 2011-05-05 23:29:49.269487583 +0200 -@@ -0,0 +1,164 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __RTL_92S_DM_H__ -+#define __RTL_92S_DM_H__ -+ -+struct dig_t { -+ u8 dig_enable_flag; -+ u8 dig_algorithm; -+ u8 dig_twoport_algorithm; -+ u8 dig_ext_port_stage; -+ u8 dig_dbgmode; -+ u8 dig_slgorithm_switch; -+ -+ long rssi_lowthresh; -+ long rssi_highthresh; -+ -+ u32 fa_lowthresh; -+ u32 fa_highthresh; -+ -+ long rssi_highpower_lowthresh; -+ long rssi_highpower_highthresh; -+ -+ u8 dig_state; -+ u8 dig_highpwrstate; -+ u8 cur_sta_connectstate; -+ u8 pre_sta_connectstate; -+ u8 cur_ap_connectstate; -+ u8 pre_ap_connectstate; -+ -+ u8 cur_pd_thstate; -+ u8 pre_pd_thstate; -+ u8 cur_cs_ratiostate; -+ u8 pre_cs_ratiostate; -+ -+ u32 pre_igvalue; -+ u32 cur_igvalue; -+ -+ u8 backoff_enable_flag; -+ char backoff_val; -+ char backoffval_range_max; -+ char backoffval_range_min; -+ u8 rx_gain_range_max; -+ u8 rx_gain_range_min; -+ -+ long rssi_val; -+}; -+ -+enum dm_dig_alg { -+ DIG_ALGO_BY_FALSE_ALARM = 0, -+ DIG_ALGO_BY_RSSI = 1, -+ DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, -+ DIG_ALGO_BY_TOW_PORT = 3, -+ DIG_ALGO_MAX -+}; -+ -+enum dm_dig_two_port_alg { -+ DIG_TWO_PORT_ALGO_RSSI = 0, -+ DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, -+}; -+ -+enum dm_dig_dbg { -+ DM_DBG_OFF = 0, -+ DM_DBG_ON = 1, -+ DM_DBG_MAX -+}; -+ -+enum dm_dig_sta { -+ DM_STA_DIG_OFF = 0, -+ DM_STA_DIG_ON, -+ DM_STA_DIG_MAX -+}; -+ -+enum dm_dig_connect { -+ DIG_STA_DISCONNECT = 0, -+ DIG_STA_CONNECT = 1, -+ DIG_STA_BEFORE_CONNECT = 2, -+ DIG_AP_DISCONNECT = 3, -+ DIG_AP_CONNECT = 4, -+ DIG_AP_ADD_STATION = 5, -+ DIG_CONNECT_MAX -+}; -+ -+enum dm_dig_ext_port_alg { -+ DIG_EXT_PORT_STAGE_0 = 0, -+ DIG_EXT_PORT_STAGE_1 = 1, -+ DIG_EXT_PORT_STAGE_2 = 2, -+ DIG_EXT_PORT_STAGE_3 = 3, -+ DIG_EXT_PORT_STAGE_MAX = 4, -+}; -+ -+enum dm_ratr_sta { -+ DM_RATR_STA_HIGH = 0, -+ DM_RATR_STA_MIDDLEHIGH = 1, -+ DM_RATR_STA_MIDDLE = 2, -+ DM_RATR_STA_MIDDLELOW = 3, -+ DM_RATR_STA_LOW = 4, -+ DM_RATR_STA_ULTRALOW = 5, -+ DM_RATR_STA_MAX -+}; -+ -+#define DM_TYPE_BYFW 0 -+#define DM_TYPE_BYDRIVER 1 -+ -+#define TX_HIGH_PWR_LEVEL_NORMAL 0 -+#define TX_HIGH_PWR_LEVEL_LEVEL1 1 -+#define TX_HIGH_PWR_LEVEL_LEVEL2 2 -+ -+#define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */ -+#define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */ -+ -+#define TX_HIGHPWR_LEVEL_NORMAL 0 -+#define TX_HIGHPWR_LEVEL_NORMAL1 1 -+#define TX_HIGHPWR_LEVEL_NORMAL2 2 -+ -+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -+ -+#define DM_DIG_THRESH_HIGH 40 -+#define DM_DIG_THRESH_LOW 35 -+#define DM_FALSEALARM_THRESH_LOW 40 -+#define DM_FALSEALARM_THRESH_HIGH 1000 -+#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 -+#define DM_DIG_HIGH_PWR_THRESH_LOW 70 -+#define DM_DIG_BACKOFF 12 -+#define DM_DIG_MAX 0x3e -+#define DM_DIG_MIN 0x1c -+#define DM_DIG_MIN_Netcore 0x12 -+#define DM_DIG_BACKOFF_MAX 12 -+#define DM_DIG_BACKOFF_MIN -4 -+ -+extern struct dig_t digtable; -+ -+void rtl92s_dm_watchdog(struct ieee80211_hw *hw); -+void rtl92s_dm_init(struct ieee80211_hw *hw); -+void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw); -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/fw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/fw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/fw.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/fw.c 2011-05-05 23:29:49.270487595 +0200 -@@ -0,0 +1,654 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../pci.h" -+#include "../base.h" -+#include "reg.h" -+#include "def.h" -+#include "fw.h" -+ -+static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ rtl_write_dword(rtlpriv, RQPN, 0xffffffff); -+ rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); -+ rtl_write_byte(rtlpriv, RQPN + 8, 0xff); -+ rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); -+} -+ -+static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 ichecktime = 200; -+ u16 tmpu2b; -+ u8 tmpu1b, cpustatus = 0; -+ -+ _rtl92s_fw_set_rqpn(hw); -+ -+ /* Enable CPU. */ -+ tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); -+ /* AFE source */ -+ rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); -+ -+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); -+ -+ /* Polling IMEM Ready after CPU has refilled. */ -+ do { -+ cpustatus = rtl_read_byte(rtlpriv, TCR); -+ if (cpustatus & IMEM_RDY) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("IMEM Ready after CPU has refilled.\n")); -+ break; -+ } -+ -+ udelay(100); -+ } while (ichecktime--); -+ -+ if (!(cpustatus & IMEM_RDY)) -+ return false; -+ -+ return true; -+} -+ -+static enum fw_status _rtl92s_firmware_get_nextstatus( -+ enum fw_status fw_currentstatus) -+{ -+ enum fw_status next_fwstatus = 0; -+ -+ switch (fw_currentstatus) { -+ case FW_STATUS_INIT: -+ next_fwstatus = FW_STATUS_LOAD_IMEM; -+ break; -+ case FW_STATUS_LOAD_IMEM: -+ next_fwstatus = FW_STATUS_LOAD_EMEM; -+ break; -+ case FW_STATUS_LOAD_EMEM: -+ next_fwstatus = FW_STATUS_LOAD_DMEM; -+ break; -+ case FW_STATUS_LOAD_DMEM: -+ next_fwstatus = FW_STATUS_READY; -+ break; -+ default: -+ break; -+ } -+ -+ return next_fwstatus; -+} -+ -+static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ switch (rtlphy->rf_type) { -+ case RF_1T1R: -+ return 0x11; -+ break; -+ case RF_1T2R: -+ return 0x12; -+ break; -+ case RF_2T2R: -+ return 0x22; -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("Unknown RF type(%x)\n", -+ rtlphy->rf_type)); -+ break; -+ } -+ return 0x22; -+} -+ -+static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, -+ struct fw_priv *pfw_priv) -+{ -+ /* Update RF types for RATR settings. */ -+ pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); -+} -+ -+ -+ -+static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, -+ struct sk_buff *skb, u8 last) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl8192_tx_ring *ring; -+ struct rtl_tx_desc *pdesc; -+ unsigned long flags; -+ u8 idx = 0; -+ -+ ring = &rtlpci->tx_ring[TXCMD_QUEUE]; -+ -+ spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); -+ -+ idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; -+ pdesc = &ring->desc[idx]; -+ rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); -+ __skb_queue_tail(&ring->queue, skb); -+ -+ spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -+ -+ return true; -+} -+ -+static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, -+ u8 *code_virtual_address, u32 buffer_len) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct sk_buff *skb; -+ struct rtl_tcb_desc *tcb_desc; -+ unsigned char *seg_ptr; -+ u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; -+ u16 frag_length, frag_offset = 0; -+ u16 extra_descoffset = 0; -+ u8 last_inipkt = 0; -+ -+ _rtl92s_fw_set_rqpn(hw); -+ -+ if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Size over FIRMWARE_CODE_SIZE!\n")); -+ -+ return false; -+ } -+ -+ extra_descoffset = 0; -+ -+ do { -+ if ((buffer_len - frag_offset) > frag_threshold) { -+ frag_length = frag_threshold + extra_descoffset; -+ } else { -+ frag_length = (u16)(buffer_len - frag_offset + -+ extra_descoffset); -+ last_inipkt = 1; -+ } -+ -+ /* Allocate skb buffer to contain firmware */ -+ /* info and tx descriptor info. */ -+ skb = dev_alloc_skb(frag_length); -+ skb_reserve(skb, extra_descoffset); -+ seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - -+ extra_descoffset)); -+ memcpy(seg_ptr, code_virtual_address + frag_offset, -+ (u32)(frag_length - extra_descoffset)); -+ -+ tcb_desc = (struct rtl_tcb_desc *)(skb->cb); -+ tcb_desc->queue_index = TXCMD_QUEUE; -+ tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; -+ tcb_desc->last_inipkt = last_inipkt; -+ -+ _rtl92s_cmd_send_packet(hw, skb, last_inipkt); -+ -+ frag_offset += (frag_length - extra_descoffset); -+ -+ } while (frag_offset < buffer_len); -+ -+ rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); -+ -+ return true ; -+} -+ -+static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, -+ u8 loadfw_status) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; -+ u32 tmpu4b; -+ u8 cpustatus = 0; -+ short pollingcnt = 1000; -+ bool rtstatus = true; -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("LoadStaus(%d)\n", -+ loadfw_status)); -+ -+ firmware->fwstatus = (enum fw_status)loadfw_status; -+ -+ switch (loadfw_status) { -+ case FW_STATUS_LOAD_IMEM: -+ /* Polling IMEM code done. */ -+ do { -+ cpustatus = rtl_read_byte(rtlpriv, TCR); -+ if (cpustatus & IMEM_CODE_DONE) -+ break; -+ udelay(5); -+ } while (pollingcnt--); -+ -+ if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("FW_STATUS_LOAD_IMEM" -+ " FAIL CPU, Status=%x\r\n", cpustatus)); -+ goto status_check_fail; -+ } -+ break; -+ -+ case FW_STATUS_LOAD_EMEM: -+ /* Check Put Code OK and Turn On CPU */ -+ /* Polling EMEM code done. */ -+ do { -+ cpustatus = rtl_read_byte(rtlpriv, TCR); -+ if (cpustatus & EMEM_CODE_DONE) -+ break; -+ udelay(5); -+ } while (pollingcnt--); -+ -+ if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("FW_STATUS_LOAD_EMEM" -+ " FAIL CPU, Status=%x\r\n", cpustatus)); -+ goto status_check_fail; -+ } -+ -+ /* Turn On CPU */ -+ rtstatus = _rtl92s_firmware_enable_cpu(hw); -+ if (rtstatus != true) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Enable CPU fail!\n")); -+ goto status_check_fail; -+ } -+ break; -+ -+ case FW_STATUS_LOAD_DMEM: -+ /* Polling DMEM code done */ -+ do { -+ cpustatus = rtl_read_byte(rtlpriv, TCR); -+ if (cpustatus & DMEM_CODE_DONE) -+ break; -+ udelay(5); -+ } while (pollingcnt--); -+ -+ if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Polling DMEM code done" -+ " fail ! cpustatus(%#x)\n", cpustatus)); -+ goto status_check_fail; -+ } -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("DMEM code download success," -+ " cpustatus(%#x)\n", cpustatus)); -+ -+ /* Prevent Delay too much and being scheduled out */ -+ /* Polling Load Firmware ready */ -+ pollingcnt = 2000; -+ do { -+ cpustatus = rtl_read_byte(rtlpriv, TCR); -+ if (cpustatus & FWRDY) -+ break; -+ udelay(40); -+ } while (pollingcnt--); -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("Polling Load Firmware ready," -+ " cpustatus(%x)\n", cpustatus)); -+ -+ if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || -+ (pollingcnt <= 0)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Polling Load Firmware" -+ " ready fail ! cpustatus(%x)\n", cpustatus)); -+ goto status_check_fail; -+ } -+ -+ /* If right here, we can set TCR/RCR to desired value */ -+ /* and config MAC lookback mode to normal mode */ -+ tmpu4b = rtl_read_dword(rtlpriv, TCR); -+ rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); -+ -+ tmpu4b = rtl_read_dword(rtlpriv, RCR); -+ rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | -+ RCR_APP_ICV | RCR_APP_MIC)); -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("Current RCR settings(%#x)\n", tmpu4b)); -+ -+ /* Set to normal mode. */ -+ rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); -+ break; -+ -+ default: -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("Unknown status check!\n")); -+ rtstatus = false; -+ break; -+ } -+ -+status_check_fail: -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("loadfw_status(%d), " -+ "rtstatus(%x)\n", loadfw_status, rtstatus)); -+ return rtstatus; -+} -+ -+int rtl92s_download_fw(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rt_firmware *firmware = NULL; -+ struct fw_hdr *pfwheader; -+ struct fw_priv *pfw_priv = NULL; -+ u8 *puc_mappedfile = NULL; -+ u32 ul_filelength = 0; -+ u32 file_length = 0; -+ u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; -+ u8 fwstatus = FW_STATUS_INIT; -+ bool rtstatus = true; -+ -+ if (!rtlhal->pfirmware) -+ return 1; -+ -+ firmware = (struct rt_firmware *)rtlhal->pfirmware; -+ firmware->fwstatus = FW_STATUS_INIT; -+ -+ puc_mappedfile = firmware->sz_fw_tmpbuffer; -+ file_length = firmware->sz_fw_tmpbufferlen; -+ -+ /* 1. Retrieve FW header. */ -+ firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; -+ pfwheader = firmware->pfwheader; -+ firmware->firmwareversion = byte(pfwheader->version, 0); -+ firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("signature:%x, version:" -+ "%x, size:%x," -+ "imemsize:%x, sram size:%x\n", pfwheader->signature, -+ pfwheader->version, pfwheader->dmem_size, -+ pfwheader->img_imem_size, pfwheader->img_sram_size)); -+ -+ /* 2. Retrieve IMEM image. */ -+ if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > -+ sizeof(firmware->fw_imem))) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("memory for data image is less than IMEM required\n")); -+ goto fail; -+ } else { -+ puc_mappedfile += fwhdr_size; -+ -+ memcpy(firmware->fw_imem, puc_mappedfile, -+ pfwheader->img_imem_size); -+ firmware->fw_imem_len = pfwheader->img_imem_size; -+ } -+ -+ /* 3. Retriecve EMEM image. */ -+ if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("memory for data image is less than EMEM required\n")); -+ goto fail; -+ } else { -+ puc_mappedfile += firmware->fw_imem_len; -+ -+ memcpy(firmware->fw_emem, puc_mappedfile, -+ pfwheader->img_sram_size); -+ firmware->fw_emem_len = pfwheader->img_sram_size; -+ } -+ -+ /* 4. download fw now */ -+ fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); -+ while (fwstatus != FW_STATUS_READY) { -+ /* Image buffer redirection. */ -+ switch (fwstatus) { -+ case FW_STATUS_LOAD_IMEM: -+ puc_mappedfile = firmware->fw_imem; -+ ul_filelength = firmware->fw_imem_len; -+ break; -+ case FW_STATUS_LOAD_EMEM: -+ puc_mappedfile = firmware->fw_emem; -+ ul_filelength = firmware->fw_emem_len; -+ break; -+ case FW_STATUS_LOAD_DMEM: -+ /* Partial update the content of header private. */ -+ pfwheader = firmware->pfwheader; -+ pfw_priv = &pfwheader->fwpriv; -+ _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); -+ puc_mappedfile = (u8 *)(firmware->pfwheader) + -+ RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; -+ ul_filelength = fwhdr_size - -+ RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Unexpected Download step!!\n")); -+ goto fail; -+ break; -+ } -+ -+ /* <2> Download image file */ -+ rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, -+ ul_filelength); -+ -+ if (rtstatus != true) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); -+ goto fail; -+ } -+ -+ /* <3> Check whether load FW process is ready */ -+ rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); -+ if (rtstatus != true) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); -+ goto fail; -+ } -+ -+ fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); -+ } -+ -+ return rtstatus; -+fail: -+ return 0; -+} -+ -+static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, -+ u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, -+ u8 **pcmb_buffer, u8 *cmd_start_seq) -+{ -+ u32 totallen = 0, len = 0, tx_desclen = 0; -+ u32 pre_continueoffset = 0; -+ u8 *ph2c_buffer; -+ u8 i = 0; -+ -+ do { -+ /* 8 - Byte aligment */ -+ len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); -+ -+ /* Buffer length is not enough */ -+ if (h2cbufferlen < totallen + len + tx_desclen) -+ break; -+ -+ /* Clear content */ -+ ph2c_buffer = (u8 *)skb_put(skb, (u32)len); -+ memset((ph2c_buffer + totallen + tx_desclen), 0, len); -+ -+ /* CMD len */ -+ SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), -+ 0, 16, pcmd_len[i]); -+ -+ /* CMD ID */ -+ SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), -+ 16, 8, pelement_id[i]); -+ -+ /* CMD Sequence */ -+ *cmd_start_seq = *cmd_start_seq % 0x80; -+ SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), -+ 24, 7, *cmd_start_seq); -+ ++*cmd_start_seq; -+ -+ /* Copy memory */ -+ memcpy((ph2c_buffer + totallen + tx_desclen + -+ H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); -+ -+ /* CMD continue */ -+ /* set the continue in prevoius cmd. */ -+ if (i < cmd_num - 1) -+ SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), -+ 31, 1, 1); -+ -+ pre_continueoffset = totallen; -+ -+ totallen += len; -+ } while (++i < cmd_num); -+ -+ return totallen; -+} -+ -+static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) -+{ -+ u32 totallen = 0, len = 0, tx_desclen = 0; -+ u8 i = 0; -+ -+ do { -+ /* 8 - Byte aligment */ -+ len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); -+ -+ /* Buffer length is not enough */ -+ if (h2cbufferlen < totallen + len + tx_desclen) -+ break; -+ -+ totallen += len; -+ } while (++i < cmd_num); -+ -+ return totallen + tx_desclen; -+} -+ -+static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, -+ u8 *pcmd_buffer) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_tcb_desc *cb_desc; -+ struct sk_buff *skb; -+ u32 element_id = 0; -+ u32 cmd_len = 0; -+ u32 len; -+ -+ switch (h2c_cmd) { -+ case FW_H2C_SETPWRMODE: -+ element_id = H2C_SETPWRMODE_CMD ; -+ cmd_len = sizeof(struct h2c_set_pwrmode_parm); -+ break; -+ case FW_H2C_JOINBSSRPT: -+ element_id = H2C_JOINBSSRPT_CMD; -+ cmd_len = sizeof(struct h2c_joinbss_rpt_parm); -+ break; -+ case FW_H2C_WOWLAN_UPDATE_GTK: -+ element_id = H2C_WOWLAN_UPDATE_GTK_CMD; -+ cmd_len = sizeof(struct h2c_wpa_two_way_parm); -+ break; -+ case FW_H2C_WOWLAN_UPDATE_IV: -+ element_id = H2C_WOWLAN_UPDATE_IV_CMD; -+ cmd_len = sizeof(unsigned long long); -+ break; -+ case FW_H2C_WOWLAN_OFFLOAD: -+ element_id = H2C_WOWLAN_FW_OFFLOAD; -+ cmd_len = sizeof(u8); -+ break; -+ default: -+ break; -+ } -+ -+ len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); -+ skb = dev_alloc_skb(len); -+ cb_desc = (struct rtl_tcb_desc *)(skb->cb); -+ cb_desc->queue_index = TXCMD_QUEUE; -+ cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; -+ cb_desc->last_inipkt = false; -+ -+ _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, -+ &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); -+ _rtl92s_cmd_send_packet(hw, skb, false); -+ rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); -+ -+ return true; -+} -+ -+void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) -+{ -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct h2c_set_pwrmode_parm pwrmode; -+ u16 max_wakeup_period = 0; -+ -+ pwrmode.mode = Mode; -+ pwrmode.flag_low_traffic_en = 0; -+ pwrmode.flag_lpnav_en = 0; -+ pwrmode.flag_rf_low_snr_en = 0; -+ pwrmode.flag_dps_en = 0; -+ pwrmode.bcn_rx_en = 0; -+ pwrmode.bcn_to = 0; -+ SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, -+ mac->vif->bss_conf.beacon_int); -+ pwrmode.app_itv = 0; -+ pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; -+ pwrmode.smart_ps = 1; -+ pwrmode.bcn_pass_period = 10; -+ -+ /* Set beacon pass count */ -+ if (pwrmode.mode == FW_PS_MIN_MODE) -+ max_wakeup_period = mac->vif->bss_conf.beacon_int; -+ else if (pwrmode.mode == FW_PS_MAX_MODE) -+ max_wakeup_period = mac->vif->bss_conf.beacon_int * -+ mac->vif->bss_conf.dtim_period; -+ -+ if (max_wakeup_period >= 500) -+ pwrmode.bcn_pass_cnt = 1; -+ else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) -+ pwrmode.bcn_pass_cnt = 2; -+ else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) -+ pwrmode.bcn_pass_cnt = 3; -+ else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) -+ pwrmode.bcn_pass_cnt = 5; -+ else -+ pwrmode.bcn_pass_cnt = 1; -+ -+ _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); -+ -+} -+ -+void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, -+ u8 mstatus, u8 ps_qosinfo) -+{ -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct h2c_joinbss_rpt_parm joinbss_rpt; -+ -+ joinbss_rpt.opmode = mstatus; -+ joinbss_rpt.ps_qos_info = ps_qosinfo; -+ joinbss_rpt.bssid[0] = mac->bssid[0]; -+ joinbss_rpt.bssid[1] = mac->bssid[1]; -+ joinbss_rpt.bssid[2] = mac->bssid[2]; -+ joinbss_rpt.bssid[3] = mac->bssid[3]; -+ joinbss_rpt.bssid[4] = mac->bssid[4]; -+ joinbss_rpt.bssid[5] = mac->bssid[5]; -+ SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, -+ mac->vif->bss_conf.beacon_int); -+ SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); -+ -+ _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); -+} -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/fw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/fw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/fw.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/fw.h 2011-05-05 23:29:49.276487669 +0200 -@@ -0,0 +1,375 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_FIRMWARE92S_H__ -+#define __REALTEK_FIRMWARE92S_H__ -+ -+#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 -+#define RTL8190_CPU_START_OFFSET 0x80 -+/* Firmware Local buffer size. 64k */ -+#define MAX_FIRMWARE_CODE_SIZE 0xFF00 -+ -+#define RT_8192S_FIRMWARE_HDR_SIZE 80 -+#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 -+ -+/* support till 64 bit bus width OS */ -+#define MAX_DEV_ADDR_SIZE 8 -+#define MAX_FIRMWARE_INFORMATION_SIZE 32 -+#define MAX_802_11_HEADER_LENGTH (40 + \ -+ MAX_FIRMWARE_INFORMATION_SIZE) -+#define ENCRYPTION_MAX_OVERHEAD 128 -+#define MAX_FRAGMENT_COUNT 8 -+#define MAX_TRANSMIT_BUFFER_SIZE (1600 + \ -+ (MAX_802_11_HEADER_LENGTH + \ -+ ENCRYPTION_MAX_OVERHEAD) *\ -+ MAX_FRAGMENT_COUNT) -+ -+#define H2C_TX_CMD_HDR_LEN 8 -+ -+/* The following DM control code are for Reg0x364, */ -+#define FW_DIG_ENABLE_CTL BIT(0) -+#define FW_HIGH_PWR_ENABLE_CTL BIT(1) -+#define FW_SS_CTL BIT(2) -+#define FW_RA_INIT_CTL BIT(3) -+#define FW_RA_BG_CTL BIT(4) -+#define FW_RA_N_CTL BIT(5) -+#define FW_PWR_TRK_CTL BIT(6) -+#define FW_IQK_CTL BIT(7) -+#define FW_FA_CTL BIT(8) -+#define FW_DRIVER_CTRL_DM_CTL BIT(9) -+#define FW_PAPE_CTL_BY_SW_HW BIT(10) -+#define FW_DISABLE_ALL_DM 0 -+#define FW_PWR_TRK_PARAM_CLR 0x0000ffff -+#define FW_RA_PARAM_CLR 0xffff0000 -+ -+enum desc_packet_type { -+ DESC_PACKET_TYPE_INIT = 0, -+ DESC_PACKET_TYPE_NORMAL = 1, -+}; -+ -+/* 8-bytes alignment required */ -+struct fw_priv { -+ /* --- long word 0 ---- */ -+ /* 0x12: CE product, 0x92: IT product */ -+ u8 signature_0; -+ /* 0x87: CE product, 0x81: IT product */ -+ u8 signature_1; -+ /* 0x81: PCI-AP, 01:PCIe, 02: 92S-U, -+ * 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */ -+ u8 hci_sel; -+ /* the same value as reigster value */ -+ u8 chip_version; -+ /* customer ID low byte */ -+ u8 customer_id_0; -+ /* customer ID high byte */ -+ u8 customer_id_1; -+ /* 0x11: 1T1R, 0x12: 1T2R, -+ * 0x92: 1T2R turbo, 0x22: 2T2R */ -+ u8 rf_config; -+ /* 4: 4EP, 6: 6EP, 11: 11EP */ -+ u8 usb_ep_num; -+ -+ /* --- long word 1 ---- */ -+ /* regulatory class bit map 0 */ -+ u8 regulatory_class_0; -+ /* regulatory class bit map 1 */ -+ u8 regulatory_class_1; -+ /* regulatory class bit map 2 */ -+ u8 regulatory_class_2; -+ /* regulatory class bit map 3 */ -+ u8 regulatory_class_3; -+ /* 0:SWSI, 1:HWSI, 2:HWPI */ -+ u8 rfintfs; -+ u8 def_nettype; -+ u8 rsvd010; -+ u8 rsvd011; -+ -+ /* --- long word 2 ---- */ -+ /* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */ -+ u8 lbk_mode; -+ /* 1: for MP use, 0: for normal -+ * driver (to be discussed) */ -+ u8 mp_mode; -+ u8 rsvd020; -+ u8 rsvd021; -+ u8 rsvd022; -+ u8 rsvd023; -+ u8 rsvd024; -+ u8 rsvd025; -+ -+ /* --- long word 3 ---- */ -+ /* QoS enable */ -+ u8 qos_en; -+ /* 40MHz BW enable */ -+ /* 4181 convert AMSDU to AMPDU, 0: disable */ -+ u8 bw_40mhz_en; -+ u8 amsdu2ampdu_en; -+ /* 11n AMPDU enable */ -+ u8 ampdu_en; -+ /* FW offloads, 0: driver handles */ -+ u8 rate_control_offload; -+ /* FW offloads, 0: driver handles */ -+ u8 aggregation_offload; -+ u8 rsvd030; -+ u8 rsvd031; -+ -+ /* --- long word 4 ---- */ -+ /* 1. FW offloads, 0: driver handles */ -+ u8 beacon_offload; -+ /* 2. FW offloads, 0: driver handles */ -+ u8 mlme_offload; -+ /* 3. FW offloads, 0: driver handles */ -+ u8 hwpc_offload; -+ /* 4. FW offloads, 0: driver handles */ -+ u8 tcp_checksum_offload; -+ /* 5. FW offloads, 0: driver handles */ -+ u8 tcp_offload; -+ /* 6. FW offloads, 0: driver handles */ -+ u8 ps_control_offload; -+ /* 7. FW offloads, 0: driver handles */ -+ u8 wwlan_offload; -+ u8 rsvd040; -+ -+ /* --- long word 5 ---- */ -+ /* tcp tx packet length low byte */ -+ u8 tcp_tx_frame_len_L; -+ /* tcp tx packet length high byte */ -+ u8 tcp_tx_frame_len_H; -+ /* tcp rx packet length low byte */ -+ u8 tcp_rx_frame_len_L; -+ /* tcp rx packet length high byte */ -+ u8 tcp_rx_frame_len_H; -+ u8 rsvd050; -+ u8 rsvd051; -+ u8 rsvd052; -+ u8 rsvd053; -+}; -+ -+/* 8-byte alinment required */ -+struct fw_hdr { -+ -+ /* --- LONG WORD 0 ---- */ -+ u16 signature; -+ /* 0x8000 ~ 0x8FFF for FPGA version, -+ * 0x0000 ~ 0x7FFF for ASIC version, */ -+ u16 version; -+ /* define the size of boot loader */ -+ u32 dmem_size; -+ -+ -+ /* --- LONG WORD 1 ---- */ -+ /* define the size of FW in IMEM */ -+ u32 img_imem_size; -+ /* define the size of FW in SRAM */ -+ u32 img_sram_size; -+ -+ /* --- LONG WORD 2 ---- */ -+ /* define the size of DMEM variable */ -+ u32 fw_priv_size; -+ u32 rsvd0; -+ -+ /* --- LONG WORD 3 ---- */ -+ u32 rsvd1; -+ u32 rsvd2; -+ -+ struct fw_priv fwpriv; -+ -+} ; -+ -+enum fw_status { -+ FW_STATUS_INIT = 0, -+ FW_STATUS_LOAD_IMEM = 1, -+ FW_STATUS_LOAD_EMEM = 2, -+ FW_STATUS_LOAD_DMEM = 3, -+ FW_STATUS_READY = 4, -+}; -+ -+struct rt_firmware { -+ struct fw_hdr *pfwheader; -+ enum fw_status fwstatus; -+ u16 firmwareversion; -+ u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; -+ u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; -+ u32 fw_imem_len; -+ u32 fw_emem_len; -+ u8 sz_fw_tmpbuffer[164000]; -+ u32 sz_fw_tmpbufferlen; -+ u16 cmdpacket_fragthresold; -+}; -+ -+struct h2c_set_pwrmode_parm { -+ u8 mode; -+ u8 flag_low_traffic_en; -+ u8 flag_lpnav_en; -+ u8 flag_rf_low_snr_en; -+ /* 1: dps, 0: 32k */ -+ u8 flag_dps_en; -+ u8 bcn_rx_en; -+ u8 bcn_pass_cnt; -+ /* beacon TO (ms). ¡§=0¡¨ no limit. */ -+ u8 bcn_to; -+ u16 bcn_itv; -+ /* only for VOIP mode. */ -+ u8 app_itv; -+ u8 awake_bcn_itvl; -+ u8 smart_ps; -+ /* unit: 100 ms */ -+ u8 bcn_pass_period; -+}; -+ -+struct h2c_joinbss_rpt_parm { -+ u8 opmode; -+ u8 ps_qos_info; -+ u8 bssid[6]; -+ u16 bcnitv; -+ u16 aid; -+} ; -+ -+struct h2c_wpa_ptk { -+ /* EAPOL-Key Key Confirmation Key (KCK) */ -+ u8 kck[16]; -+ /* EAPOL-Key Key Encryption Key (KEK) */ -+ u8 kek[16]; -+ /* Temporal Key 1 (TK1) */ -+ u8 tk1[16]; -+ union { -+ /* Temporal Key 2 (TK2) */ -+ u8 tk2[16]; -+ struct { -+ u8 tx_mic_key[8]; -+ u8 rx_mic_key[8]; -+ } athu; -+ } u; -+}; -+ -+struct h2c_wpa_two_way_parm { -+ /* algorithm TKIP or AES */ -+ u8 pairwise_en_alg; -+ u8 group_en_alg; -+ struct h2c_wpa_ptk wpa_ptk_value; -+} ; -+ -+enum h2c_cmd { -+ FW_H2C_SETPWRMODE = 0, -+ FW_H2C_JOINBSSRPT = 1, -+ FW_H2C_WOWLAN_UPDATE_GTK = 2, -+ FW_H2C_WOWLAN_UPDATE_IV = 3, -+ FW_H2C_WOWLAN_OFFLOAD = 4, -+}; -+ -+enum fw_h2c_cmd { -+ H2C_READ_MACREG_CMD, /*0*/ -+ H2C_WRITE_MACREG_CMD, -+ H2C_READBB_CMD, -+ H2C_WRITEBB_CMD, -+ H2C_READRF_CMD, -+ H2C_WRITERF_CMD, /*5*/ -+ H2C_READ_EEPROM_CMD, -+ H2C_WRITE_EEPROM_CMD, -+ H2C_READ_EFUSE_CMD, -+ H2C_WRITE_EFUSE_CMD, -+ H2C_READ_CAM_CMD, /*10*/ -+ H2C_WRITE_CAM_CMD, -+ H2C_SETBCNITV_CMD, -+ H2C_SETMBIDCFG_CMD, -+ H2C_JOINBSS_CMD, -+ H2C_DISCONNECT_CMD, /*15*/ -+ H2C_CREATEBSS_CMD, -+ H2C_SETOPMode_CMD, -+ H2C_SITESURVEY_CMD, -+ H2C_SETAUTH_CMD, -+ H2C_SETKEY_CMD, /*20*/ -+ H2C_SETSTAKEY_CMD, -+ H2C_SETASSOCSTA_CMD, -+ H2C_DELASSOCSTA_CMD, -+ H2C_SETSTAPWRSTATE_CMD, -+ H2C_SETBASICRATE_CMD, /*25*/ -+ H2C_GETBASICRATE_CMD, -+ H2C_SETDATARATE_CMD, -+ H2C_GETDATARATE_CMD, -+ H2C_SETPHYINFO_CMD, -+ H2C_GETPHYINFO_CMD, /*30*/ -+ H2C_SETPHY_CMD, -+ H2C_GETPHY_CMD, -+ H2C_READRSSI_CMD, -+ H2C_READGAIN_CMD, -+ H2C_SETATIM_CMD, /*35*/ -+ H2C_SETPWRMODE_CMD, -+ H2C_JOINBSSRPT_CMD, -+ H2C_SETRATABLE_CMD, -+ H2C_GETRATABLE_CMD, -+ H2C_GETCCXREPORT_CMD, /*40*/ -+ H2C_GETDTMREPORT_CMD, -+ H2C_GETTXRATESTATICS_CMD, -+ H2C_SETUSBSUSPEND_CMD, -+ H2C_SETH2CLBK_CMD, -+ H2C_TMP1, /*45*/ -+ H2C_WOWLAN_UPDATE_GTK_CMD, -+ H2C_WOWLAN_FW_OFFLOAD, -+ H2C_TMP2, -+ H2C_TMP3, -+ H2C_WOWLAN_UPDATE_IV_CMD, /*50*/ -+ H2C_TMP4, -+ MAX_H2CCMD /*52*/ -+}; -+ -+/* The following macros are used for FW -+ * CMD map and parameter updated. */ -+#define FW_CMD_IO_CLR(rtlpriv, _Bit) \ -+ do { \ -+ udelay(1000); \ -+ rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ -+ } while (0); -+ -+#define FW_CMD_IO_UPDATE(rtlpriv, _val) \ -+ rtlpriv->rtlhal.fwcmd_iomap = _val; -+ -+#define FW_CMD_IO_SET(rtlpriv, _val) \ -+ do { \ -+ rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ -+ FW_CMD_IO_UPDATE(rtlpriv, _val); \ -+ } while (0); -+ -+#define FW_CMD_PARA_SET(rtlpriv, _val) \ -+ do { \ -+ rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ -+ rtlpriv->rtlhal.fwcmd_ioparam = _val; \ -+ } while (0); -+ -+#define FW_CMD_IO_QUERY(rtlpriv) \ -+ (u16)(rtlpriv->rtlhal.fwcmd_iomap) -+#define FW_CMD_IO_PARA_QUERY(rtlpriv) \ -+ ((u32)(rtlpriv->rtlhal.fwcmd_ioparam)) -+ -+int rtl92s_download_fw(struct ieee80211_hw *hw); -+void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -+void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, -+ u8 mstatus, u8 ps_qosinfo); -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/hw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/hw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/hw.c 2011-05-05 23:29:49.283487753 +0200 -@@ -0,0 +1,2512 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../efuse.h" -+#include "../base.h" -+#include "../regd.h" -+#include "../cam.h" -+#include "../ps.h" -+#include "../pci.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "dm.h" -+#include "fw.h" -+#include "led.h" -+#include "hw.h" -+ -+void rtl92se_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ switch (variable) { -+ case HW_VAR_RCR: { -+ *((u32 *) (val)) = rtlpci->receive_config; -+ break; -+ } -+ case HW_VAR_RF_STATE: { -+ *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; -+ break; -+ } -+ case HW_VAR_FW_PSMODE_STATUS: { -+ *((bool *) (val)) = ppsc->fw_current_inpsmode; -+ break; -+ } -+ case HW_VAR_CORRECT_TSF: { -+ u64 tsf; -+ u32 *ptsf_low = (u32 *)&tsf; -+ u32 *ptsf_high = ((u32 *)&tsf) + 1; -+ -+ *ptsf_high = rtl_read_dword(rtlpriv, (TSFR + 4)); -+ *ptsf_low = rtl_read_dword(rtlpriv, TSFR); -+ -+ *((u64 *) (val)) = tsf; -+ -+ break; -+ } -+ case HW_VAR_MRC: { -+ *((bool *)(val)) = rtlpriv->dm.current_mrc_switch; -+ break; -+ } -+ default: { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ } -+} -+ -+void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ -+ switch (variable) { -+ case HW_VAR_ETHER_ADDR:{ -+ rtl_write_dword(rtlpriv, IDR0, ((u32 *)(val))[0]); -+ rtl_write_word(rtlpriv, IDR4, ((u16 *)(val + 4))[0]); -+ break; -+ } -+ case HW_VAR_BASIC_RATE:{ -+ u16 rate_cfg = ((u16 *) val)[0]; -+ u8 rate_index = 0; -+ -+ if (rtlhal->version == VERSION_8192S_ACUT) -+ rate_cfg = rate_cfg & 0x150; -+ else -+ rate_cfg = rate_cfg & 0x15f; -+ -+ rate_cfg |= 0x01; -+ -+ rtl_write_byte(rtlpriv, RRSR, rate_cfg & 0xff); -+ rtl_write_byte(rtlpriv, RRSR + 1, -+ (rate_cfg >> 8) & 0xff); -+ -+ while (rate_cfg > 0x1) { -+ rate_cfg = (rate_cfg >> 1); -+ rate_index++; -+ } -+ rtl_write_byte(rtlpriv, INIRTSMCS_SEL, rate_index); -+ -+ break; -+ } -+ case HW_VAR_BSSID:{ -+ rtl_write_dword(rtlpriv, BSSIDR, ((u32 *)(val))[0]); -+ rtl_write_word(rtlpriv, BSSIDR + 4, -+ ((u16 *)(val + 4))[0]); -+ break; -+ } -+ case HW_VAR_SIFS:{ -+ rtl_write_byte(rtlpriv, SIFS_OFDM, val[0]); -+ rtl_write_byte(rtlpriv, SIFS_OFDM + 1, val[1]); -+ break; -+ } -+ case HW_VAR_SLOT_TIME:{ -+ u8 e_aci; -+ -+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, -+ ("HW_VAR_SLOT_TIME %x\n", val[0])); -+ -+ rtl_write_byte(rtlpriv, SLOT_TIME, val[0]); -+ -+ for (e_aci = 0; e_aci < AC_MAX; e_aci++) { -+ rtlpriv->cfg->ops->set_hw_reg(hw, -+ HW_VAR_AC_PARAM, -+ (u8 *)(&e_aci)); -+ } -+ break; -+ } -+ case HW_VAR_ACK_PREAMBLE:{ -+ u8 reg_tmp; -+ u8 short_preamble = (bool) (*(u8 *) val); -+ reg_tmp = (mac->cur_40_prime_sc) << 5; -+ if (short_preamble) -+ reg_tmp |= 0x80; -+ -+ rtl_write_byte(rtlpriv, RRSR + 2, reg_tmp); -+ break; -+ } -+ case HW_VAR_AMPDU_MIN_SPACE:{ -+ u8 min_spacing_to_set; -+ u8 sec_min_space; -+ -+ min_spacing_to_set = *((u8 *)val); -+ if (min_spacing_to_set <= 7) { -+ if (rtlpriv->sec.pairwise_enc_algorithm == -+ NO_ENCRYPTION) -+ sec_min_space = 0; -+ else -+ sec_min_space = 1; -+ -+ if (min_spacing_to_set < sec_min_space) -+ min_spacing_to_set = sec_min_space; -+ if (min_spacing_to_set > 5) -+ min_spacing_to_set = 5; -+ -+ mac->min_space_cfg = -+ ((mac->min_space_cfg & 0xf8) | -+ min_spacing_to_set); -+ -+ *val = min_spacing_to_set; -+ -+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, -+ ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", -+ mac->min_space_cfg)); -+ -+ rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, -+ mac->min_space_cfg); -+ } -+ break; -+ } -+ case HW_VAR_SHORTGI_DENSITY:{ -+ u8 density_to_set; -+ -+ density_to_set = *((u8 *) val); -+ mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; -+ mac->min_space_cfg |= (density_to_set << 3); -+ -+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, -+ ("Set HW_VAR_SHORTGI_DENSITY: %#x\n", -+ mac->min_space_cfg)); -+ -+ rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, -+ mac->min_space_cfg); -+ -+ break; -+ } -+ case HW_VAR_AMPDU_FACTOR:{ -+ u8 factor_toset; -+ u8 regtoset; -+ u8 factorlevel[18] = { -+ 2, 4, 4, 7, 7, 13, 13, -+ 13, 2, 7, 7, 13, 13, -+ 15, 15, 15, 15, 0}; -+ u8 index = 0; -+ -+ factor_toset = *((u8 *) val); -+ if (factor_toset <= 3) { -+ factor_toset = (1 << (factor_toset + 2)); -+ if (factor_toset > 0xf) -+ factor_toset = 0xf; -+ -+ for (index = 0; index < 17; index++) { -+ if (factorlevel[index] > factor_toset) -+ factorlevel[index] = -+ factor_toset; -+ } -+ -+ for (index = 0; index < 8; index++) { -+ regtoset = ((factorlevel[index * 2]) | -+ (factorlevel[index * -+ 2 + 1] << 4)); -+ rtl_write_byte(rtlpriv, -+ AGGLEN_LMT_L + index, -+ regtoset); -+ } -+ -+ regtoset = ((factorlevel[16]) | -+ (factorlevel[17] << 4)); -+ rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset); -+ -+ RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, -+ ("Set HW_VAR_AMPDU_FACTOR: %#x\n", -+ factor_toset)); -+ } -+ break; -+ } -+ case HW_VAR_AC_PARAM:{ -+ u8 e_aci = *((u8 *) val); -+ rtl92s_dm_init_edca_turbo(hw); -+ -+ if (rtlpci->acm_method != eAcmWay2_SW) -+ rtlpriv->cfg->ops->set_hw_reg(hw, -+ HW_VAR_ACM_CTRL, -+ (u8 *)(&e_aci)); -+ break; -+ } -+ case HW_VAR_ACM_CTRL:{ -+ u8 e_aci = *((u8 *) val); -+ union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( -+ mac->ac[0].aifs)); -+ u8 acm = p_aci_aifsn->f.acm; -+ u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); -+ -+ acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? -+ 0x0 : 0x1); -+ -+ if (acm) { -+ switch (e_aci) { -+ case AC0_BE: -+ acm_ctrl |= AcmHw_BeqEn; -+ break; -+ case AC2_VI: -+ acm_ctrl |= AcmHw_ViqEn; -+ break; -+ case AC3_VO: -+ acm_ctrl |= AcmHw_VoqEn; -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -+ ("HW_VAR_ACM_CTRL acm set " -+ "failed: eACI is %d\n", acm)); -+ break; -+ } -+ } else { -+ switch (e_aci) { -+ case AC0_BE: -+ acm_ctrl &= (~AcmHw_BeqEn); -+ break; -+ case AC2_VI: -+ acm_ctrl &= (~AcmHw_ViqEn); -+ break; -+ case AC3_VO: -+ acm_ctrl &= (~AcmHw_BeqEn); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ } -+ -+ RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, -+ ("HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl)); -+ rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); -+ break; -+ } -+ case HW_VAR_RCR:{ -+ rtl_write_dword(rtlpriv, RCR, ((u32 *) (val))[0]); -+ rtlpci->receive_config = ((u32 *) (val))[0]; -+ break; -+ } -+ case HW_VAR_RETRY_LIMIT:{ -+ u8 retry_limit = ((u8 *) (val))[0]; -+ -+ rtl_write_word(rtlpriv, RETRY_LIMIT, -+ retry_limit << RETRY_LIMIT_SHORT_SHIFT | -+ retry_limit << RETRY_LIMIT_LONG_SHIFT); -+ break; -+ } -+ case HW_VAR_DUAL_TSF_RST: { -+ break; -+ } -+ case HW_VAR_EFUSE_BYTES: { -+ rtlefuse->efuse_usedbytes = *((u16 *) val); -+ break; -+ } -+ case HW_VAR_EFUSE_USAGE: { -+ rtlefuse->efuse_usedpercentage = *((u8 *) val); -+ break; -+ } -+ case HW_VAR_IO_CMD: { -+ break; -+ } -+ case HW_VAR_WPA_CONFIG: { -+ rtl_write_byte(rtlpriv, REG_SECR, *((u8 *) val)); -+ break; -+ } -+ case HW_VAR_SET_RPWM:{ -+ break; -+ } -+ case HW_VAR_H2C_FW_PWRMODE:{ -+ break; -+ } -+ case HW_VAR_FW_PSMODE_STATUS: { -+ ppsc->fw_current_inpsmode = *((bool *) val); -+ break; -+ } -+ case HW_VAR_H2C_FW_JOINBSSRPT:{ -+ break; -+ } -+ case HW_VAR_AID:{ -+ break; -+ } -+ case HW_VAR_CORRECT_TSF:{ -+ break; -+ } -+ case HW_VAR_MRC: { -+ bool bmrc_toset = *((bool *)val); -+ u8 u1bdata = 0; -+ -+ if (bmrc_toset) { -+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -+ MASKBYTE0, 0x33); -+ u1bdata = (u8)rtl_get_bbreg(hw, -+ ROFDM1_TRXPATHENABLE, -+ MASKBYTE0); -+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, -+ MASKBYTE0, -+ ((u1bdata & 0xf0) | 0x03)); -+ u1bdata = (u8)rtl_get_bbreg(hw, -+ ROFDM0_TRXPATHENABLE, -+ MASKBYTE1); -+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -+ MASKBYTE1, -+ (u1bdata | 0x04)); -+ -+ /* Update current settings. */ -+ rtlpriv->dm.current_mrc_switch = bmrc_toset; -+ } else { -+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -+ MASKBYTE0, 0x13); -+ u1bdata = (u8)rtl_get_bbreg(hw, -+ ROFDM1_TRXPATHENABLE, -+ MASKBYTE0); -+ rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, -+ MASKBYTE0, -+ ((u1bdata & 0xf0) | 0x01)); -+ u1bdata = (u8)rtl_get_bbreg(hw, -+ ROFDM0_TRXPATHENABLE, -+ MASKBYTE1); -+ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, -+ MASKBYTE1, (u1bdata & 0xfb)); -+ -+ /* Update current settings. */ -+ rtlpriv->dm.current_mrc_switch = bmrc_toset; -+ } -+ -+ break; -+ } -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ -+} -+ -+void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 sec_reg_value = 0x0; -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("PairwiseEncAlgorithm = %d " -+ "GroupEncAlgorithm = %d\n", -+ rtlpriv->sec.pairwise_enc_algorithm, -+ rtlpriv->sec.group_enc_algorithm)); -+ -+ if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("not open hw encryption\n")); -+ return; -+ } -+ -+ sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; -+ -+ if (rtlpriv->sec.use_defaultkey) { -+ sec_reg_value |= SCR_TXUSEDK; -+ sec_reg_value |= SCR_RXUSEDK; -+ } -+ -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("The SECR-value %x\n", -+ sec_reg_value)); -+ -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -+ -+} -+ -+static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 waitcount = 100; -+ bool bresult = false; -+ u8 tmpvalue; -+ -+ rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); -+ -+ /* Wait the MAC synchronized. */ -+ udelay(400); -+ -+ /* Check if it is set ready. */ -+ tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); -+ bresult = ((tmpvalue & BIT(7)) == (data & BIT(7))); -+ -+ if ((data & (BIT(6) | BIT(7))) == false) { -+ waitcount = 100; -+ tmpvalue = 0; -+ -+ while (1) { -+ waitcount--; -+ -+ tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); -+ if ((tmpvalue & BIT(6))) -+ break; -+ -+ printk(KERN_ERR "wait for BIT(6) return value %x\n", -+ tmpvalue); -+ if (waitcount == 0) -+ break; -+ -+ udelay(10); -+ } -+ -+ if (waitcount == 0) -+ bresult = false; -+ else -+ bresult = true; -+ } -+ -+ return bresult; -+} -+ -+void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 u1tmp; -+ -+ /* The following config GPIO function */ -+ rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); -+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); -+ -+ /* config GPIO3 to input */ -+ u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; -+ rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); -+ -+} -+ -+static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 u1tmp; -+ u8 retval = ERFON; -+ -+ /* The following config GPIO function */ -+ rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); -+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); -+ -+ /* config GPIO3 to input */ -+ u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; -+ rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); -+ -+ /* On some of the platform, driver cannot read correct -+ * value without delay between Write_GPIO_SEL and Read_GPIO_IN */ -+ mdelay(10); -+ -+ /* check GPIO3 */ -+ u1tmp = rtl_read_byte(rtlpriv, GPIO_IN); -+ retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF; -+ -+ return retval; -+} -+ -+static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ -+ u8 i; -+ u8 tmpu1b; -+ u16 tmpu2b; -+ u8 pollingcnt = 20; -+ -+ if (rtlpci->first_init) { -+ /* Reset PCIE Digital */ -+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); -+ tmpu1b &= 0xFE; -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); -+ udelay(1); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b | BIT(0)); -+ } -+ -+ /* Switch to SW IO control */ -+ tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); -+ if (tmpu1b & BIT(7)) { -+ tmpu1b &= ~(BIT(6) | BIT(7)); -+ -+ /* Set failed, return to prevent hang. */ -+ if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) -+ return; -+ } -+ -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); -+ udelay(50); -+ rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); -+ udelay(50); -+ -+ /* Clear FW RPWM for FW control LPS.*/ -+ rtl_write_byte(rtlpriv, RPWM, 0x0); -+ -+ /* Reset MAC-IO and CPU and Core Digital BIT(10)/11/15 */ -+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); -+ tmpu1b &= 0x73; -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); -+ /* wait for BIT 10/11/15 to pull high automatically!! */ -+ mdelay(1); -+ -+ rtl_write_byte(rtlpriv, CMDR, 0); -+ rtl_write_byte(rtlpriv, TCR, 0); -+ -+ /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ -+ tmpu1b = rtl_read_byte(rtlpriv, 0x562); -+ tmpu1b |= 0x08; -+ rtl_write_byte(rtlpriv, 0x562, tmpu1b); -+ tmpu1b &= ~(BIT(3)); -+ rtl_write_byte(rtlpriv, 0x562, tmpu1b); -+ -+ /* Enable AFE clock source */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); -+ /* Delay 1.5ms */ -+ mdelay(2); -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); -+ -+ /* Enable AFE Macro Block's Bandgap */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); -+ rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); -+ mdelay(1); -+ -+ /* Enable AFE Mbias */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); -+ rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); -+ mdelay(1); -+ -+ /* Enable LDOA15 block */ -+ tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); -+ rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); -+ -+ /* Set Digital Vdd to Retention isolation Path. */ -+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); -+ rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); -+ -+ /* For warm reboot NIC disappera bug. */ -+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); -+ -+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); -+ -+ /* Enable AFE PLL Macro Block */ -+ /* We need to delay 100u before enabling PLL. */ -+ udelay(200); -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); -+ -+ /* for divider reset */ -+ udelay(100); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | -+ BIT(4) | BIT(6))); -+ udelay(10); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); -+ udelay(10); -+ -+ /* Enable MAC 80MHZ clock */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); -+ mdelay(1); -+ -+ /* Release isolation AFE PLL & MD */ -+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); -+ -+ /* Enable MAC clock */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); -+ rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); -+ -+ /* Enable Core digital and enable IOREG R/W */ -+ tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); -+ -+ tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b & ~(BIT(7))); -+ -+ /* enable REG_EN */ -+ rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); -+ -+ /* Switch the control path. */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); -+ rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); -+ -+ tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); -+ tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); -+ if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) -+ return; /* Set failed, return to prevent hang. */ -+ -+ rtl_write_word(rtlpriv, CMDR, 0x07FC); -+ -+ /* MH We must enable the section of code to prevent load IMEM fail. */ -+ /* Load MAC register from WMAc temporarily We simulate macreg. */ -+ /* txt HW will provide MAC txt later */ -+ rtl_write_byte(rtlpriv, 0x6, 0x30); -+ rtl_write_byte(rtlpriv, 0x49, 0xf0); -+ -+ rtl_write_byte(rtlpriv, 0x4b, 0x81); -+ -+ rtl_write_byte(rtlpriv, 0xb5, 0x21); -+ -+ rtl_write_byte(rtlpriv, 0xdc, 0xff); -+ rtl_write_byte(rtlpriv, 0xdd, 0xff); -+ rtl_write_byte(rtlpriv, 0xde, 0xff); -+ rtl_write_byte(rtlpriv, 0xdf, 0xff); -+ -+ rtl_write_byte(rtlpriv, 0x11a, 0x00); -+ rtl_write_byte(rtlpriv, 0x11b, 0x00); -+ -+ for (i = 0; i < 32; i++) -+ rtl_write_byte(rtlpriv, INIMCS_SEL + i, 0x1b); -+ -+ rtl_write_byte(rtlpriv, 0x236, 0xff); -+ -+ rtl_write_byte(rtlpriv, 0x503, 0x22); -+ -+ if (ppsc->support_aspm && !ppsc->support_backdoor) -+ rtl_write_byte(rtlpriv, 0x560, 0x40); -+ else -+ rtl_write_byte(rtlpriv, 0x560, 0x00); -+ -+ rtl_write_byte(rtlpriv, DBG_PORT, 0x91); -+ -+ /* Set RX Desc Address */ -+ rtl_write_dword(rtlpriv, RDQDA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); -+ rtl_write_dword(rtlpriv, RCDA, rtlpci->rx_ring[RX_CMD_QUEUE].dma); -+ -+ /* Set TX Desc Address */ -+ rtl_write_dword(rtlpriv, TBKDA, rtlpci->tx_ring[BK_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TBEDA, rtlpci->tx_ring[BE_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TVIDA, rtlpci->tx_ring[VI_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TVODA, rtlpci->tx_ring[VO_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TBDA, rtlpci->tx_ring[BEACON_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TCDA, rtlpci->tx_ring[TXCMD_QUEUE].dma); -+ rtl_write_dword(rtlpriv, TMDA, rtlpci->tx_ring[MGNT_QUEUE].dma); -+ rtl_write_dword(rtlpriv, THPDA, rtlpci->tx_ring[HIGH_QUEUE].dma); -+ rtl_write_dword(rtlpriv, HDA, rtlpci->tx_ring[HCCA_QUEUE].dma); -+ -+ rtl_write_word(rtlpriv, CMDR, 0x37FC); -+ -+ /* To make sure that TxDMA can ready to download FW. */ -+ /* We should reset TxDMA if IMEM RPT was not ready. */ -+ do { -+ tmpu1b = rtl_read_byte(rtlpriv, TCR); -+ if ((tmpu1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) -+ break; -+ -+ udelay(5); -+ } while (pollingcnt--); -+ -+ if (pollingcnt <= 0) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Polling TXDMA_INIT_VALUE " -+ "timeout!! Current TCR(%#x)\n", tmpu1b)); -+ tmpu1b = rtl_read_byte(rtlpriv, CMDR); -+ rtl_write_byte(rtlpriv, CMDR, tmpu1b & (~TXDMA_EN)); -+ udelay(2); -+ /* Reset TxDMA */ -+ rtl_write_byte(rtlpriv, CMDR, tmpu1b | TXDMA_EN); -+ } -+ -+ /* After MACIO reset,we must refresh LED state. */ -+ if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || -+ (ppsc->rfoff_reason == 0)) { -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); -+ enum rf_pwrstate rfpwr_state_toset; -+ rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); -+ -+ if (rfpwr_state_toset == ERFON) -+ rtl92se_sw_led_on(hw, pLed0); -+ } -+} -+ -+static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ u8 i; -+ u16 tmpu2b; -+ -+ /* 1. System Configure Register (Offset: 0x0000 - 0x003F) */ -+ -+ /* 2. Command Control Register (Offset: 0x0040 - 0x004F) */ -+ /* Turn on 0x40 Command register */ -+ rtl_write_word(rtlpriv, CMDR, (BBRSTN | BB_GLB_RSTN | -+ SCHEDULE_EN | MACRXEN | MACTXEN | DDMA_EN | FW2HW_EN | -+ RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN)); -+ -+ /* Set TCR TX DMA pre 2 FULL enable bit */ -+ rtl_write_dword(rtlpriv, TCR, rtl_read_dword(rtlpriv, TCR) | -+ TXDMAPRE2FULL); -+ -+ /* Set RCR */ -+ rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); -+ -+ /* 3. MACID Setting Register (Offset: 0x0050 - 0x007F) */ -+ -+ /* 4. Timing Control Register (Offset: 0x0080 - 0x009F) */ -+ /* Set CCK/OFDM SIFS */ -+ /* CCK SIFS shall always be 10us. */ -+ rtl_write_word(rtlpriv, SIFS_CCK, 0x0a0a); -+ rtl_write_word(rtlpriv, SIFS_OFDM, 0x1010); -+ -+ /* Set AckTimeout */ -+ rtl_write_byte(rtlpriv, ACK_TIMEOUT, 0x40); -+ -+ /* Beacon related */ -+ rtl_write_word(rtlpriv, BCN_INTERVAL, 100); -+ rtl_write_word(rtlpriv, ATIMWND, 2); -+ -+ /* 5. FIFO Control Register (Offset: 0x00A0 - 0x015F) */ -+ /* 5.1 Initialize Number of Reserved Pages in Firmware Queue */ -+ /* Firmware allocate now, associate with FW internal setting.!!! */ -+ -+ /* 5.2 Setting TX/RX page size 0/1/2/3/4=64/128/256/512/1024 */ -+ /* 5.3 Set driver info, we only accept PHY status now. */ -+ /* 5.4 Set RXDMA arbitration to control RXDMA/MAC/FW R/W for RXFIFO */ -+ rtl_write_byte(rtlpriv, RXDMA, rtl_read_byte(rtlpriv, RXDMA) | BIT(6)); -+ -+ /* 6. Adaptive Control Register (Offset: 0x0160 - 0x01CF) */ -+ /* Set RRSR to all legacy rate and HT rate -+ * CCK rate is supported by default. -+ * CCK rate will be filtered out only when associated -+ * AP does not support it. -+ * Only enable ACK rate to OFDM 24M -+ * Disable RRSR for CCK rate in A-Cut */ -+ -+ if (rtlhal->version == VERSION_8192S_ACUT) -+ rtl_write_byte(rtlpriv, RRSR, 0xf0); -+ else if (rtlhal->version == VERSION_8192S_BCUT) -+ rtl_write_byte(rtlpriv, RRSR, 0xff); -+ rtl_write_byte(rtlpriv, RRSR + 1, 0x01); -+ rtl_write_byte(rtlpriv, RRSR + 2, 0x00); -+ -+ /* A-Cut IC do not support CCK rate. We forbid ARFR to */ -+ /* fallback to CCK rate */ -+ for (i = 0; i < 8; i++) { -+ /*Disable RRSR for CCK rate in A-Cut */ -+ if (rtlhal->version == VERSION_8192S_ACUT) -+ rtl_write_dword(rtlpriv, ARFR0 + i * 4, 0x1f0ff0f0); -+ } -+ -+ /* Different rate use different AMPDU size */ -+ /* MCS32/ MCS15_SG use max AMPDU size 15*2=30K */ -+ rtl_write_byte(rtlpriv, AGGLEN_LMT_H, 0x0f); -+ /* MCS0/1/2/3 use max AMPDU size 4*2=8K */ -+ rtl_write_word(rtlpriv, AGGLEN_LMT_L, 0x7442); -+ /* MCS4/5 use max AMPDU size 8*2=16K 6/7 use 10*2=20K */ -+ rtl_write_word(rtlpriv, AGGLEN_LMT_L + 2, 0xddd7); -+ /* MCS8/9 use max AMPDU size 8*2=16K 10/11 use 10*2=20K */ -+ rtl_write_word(rtlpriv, AGGLEN_LMT_L + 4, 0xd772); -+ /* MCS12/13/14/15 use max AMPDU size 15*2=30K */ -+ rtl_write_word(rtlpriv, AGGLEN_LMT_L + 6, 0xfffd); -+ -+ /* Set Data / Response auto rate fallack retry count */ -+ rtl_write_dword(rtlpriv, DARFRC, 0x04010000); -+ rtl_write_dword(rtlpriv, DARFRC + 4, 0x09070605); -+ rtl_write_dword(rtlpriv, RARFRC, 0x04010000); -+ rtl_write_dword(rtlpriv, RARFRC + 4, 0x09070605); -+ -+ /* 7. EDCA Setting Register (Offset: 0x01D0 - 0x01FF) */ -+ /* Set all rate to support SG */ -+ rtl_write_word(rtlpriv, SG_RATE, 0xFFFF); -+ -+ /* 8. WMAC, BA, and CCX related Register (Offset: 0x0200 - 0x023F) */ -+ /* Set NAV protection length */ -+ rtl_write_word(rtlpriv, NAV_PROT_LEN, 0x0080); -+ /* CF-END Threshold */ -+ rtl_write_byte(rtlpriv, CFEND_TH, 0xFF); -+ /* Set AMPDU minimum space */ -+ rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, 0x07); -+ /* Set TXOP stall control for several queue/HI/BCN/MGT/ */ -+ rtl_write_byte(rtlpriv, TXOP_STALL_CTRL, 0x00); -+ -+ /* 9. Security Control Register (Offset: 0x0240 - 0x025F) */ -+ /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ -+ /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ -+ /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ -+ /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ -+ -+ /* 14. Set driver info, we only accept PHY status now. */ -+ rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); -+ -+ /* 15. For EEPROM R/W Workaround */ -+ /* 16. For EFUSE to share REG_SYS_FUNC_EN with EEPROM!!! */ -+ tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmpu2b | BIT(13)); -+ tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); -+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, tmpu2b & (~BIT(8))); -+ -+ /* 17. For EFUSE */ -+ /* We may R/W EFUSE in EEPROM mode */ -+ if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { -+ u8 tempval; -+ -+ tempval = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL + 1); -+ tempval &= 0xFE; -+ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, tempval); -+ -+ /* Change Program timing */ -+ rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("EFUSE CONFIG OK\n")); -+ } -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("OK\n")); -+ -+} -+ -+static void _rtl92se_hw_configure(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ -+ u8 reg_bw_opmode = 0; -+ u32 reg_ratr = 0, reg_rrsr = 0; -+ u8 regtmp = 0; -+ -+ reg_bw_opmode = BW_OPMODE_20MHZ; -+ reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | -+ RATE_ALL_OFDM_2SS; -+ reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; -+ -+ regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); -+ reg_rrsr = ((reg_rrsr & 0x000fffff) << 8) | regtmp; -+ rtl_write_dword(rtlpriv, INIRTSMCS_SEL, reg_rrsr); -+ rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); -+ -+ /* Set Retry Limit here */ -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, -+ (u8 *)(&rtlpci->shortretry_limit)); -+ -+ rtl_write_byte(rtlpriv, MLT, 0x8f); -+ -+ /* For Min Spacing configuration. */ -+ switch (rtlphy->rf_type) { -+ case RF_1T2R: -+ case RF_1T1R: -+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); -+ break; -+ case RF_2T2R: -+ case RF_2T2R_GREEN: -+ rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); -+ break; -+ } -+ rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, rtlhal->minspace_cfg); -+} -+ -+int rtl92se_hw_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u8 tmp_byte = 0; -+ -+ bool rtstatus = true; -+ u8 tmp_u1b; -+ int err = false; -+ u8 i; -+ int wdcapra_add[] = { -+ EDCAPARA_BE, EDCAPARA_BK, -+ EDCAPARA_VI, EDCAPARA_VO}; -+ u8 secr_value = 0x0; -+ -+ rtlpci->being_init_adapter = true; -+ -+ rtlpriv->intf_ops->disable_aspm(hw); -+ -+ /* 1. MAC Initialize */ -+ /* Before FW download, we have to set some MAC register */ -+ _rtl92se_macconfig_before_fwdownload(hw); -+ -+ rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, -+ PMC_FSM) >> 16) & 0xF); -+ -+ rtl8192se_gpiobit3_cfg_inputmode(hw); -+ -+ /* 2. download firmware */ -+ rtstatus = rtl92s_download_fw(hw); -+ if (!rtstatus) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -+ ("Failed to download FW. " -+ "Init HW without FW now.., Please copy FW into" -+ "/lib/firmware/rtlwifi\n")); -+ rtlhal->fw_ready = false; -+ } else { -+ rtlhal->fw_ready = true; -+ } -+ -+ /* After FW download, we have to reset MAC register */ -+ _rtl92se_macconfig_after_fwdownload(hw); -+ -+ /*Retrieve default FW Cmd IO map. */ -+ rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, LBUS_MON_ADDR); -+ rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, LBUS_ADDR_MASK); -+ -+ /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ -+ if (rtl92s_phy_mac_config(hw) != true) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("MAC Config failed\n")); -+ return rtstatus; -+ } -+ -+ /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ -+ /* We must set flag avoid BB/RF config period later!! */ -+ rtl_write_dword(rtlpriv, CMDR, 0x37FC); -+ -+ /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ -+ if (rtl92s_phy_bb_config(hw) != true) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("BB Config failed\n")); -+ return rtstatus; -+ } -+ -+ /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ -+ /* Before initalizing RF. We can not use FW to do RF-R/W. */ -+ -+ rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; -+ -+ /* RF Power Save */ -+#if 0 -+ /* H/W or S/W RF OFF before sleep. */ -+ if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) { -+ u32 rfoffreason = rtlpriv->psc.rfoff_reason; -+ -+ rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT; -+ rtlpriv->psc.rfpwr_state = ERFON; -+ rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true); -+ } else { -+ /* gpio radio on/off is out of adapter start */ -+ if (rtlpriv->psc.hwradiooff == false) { -+ rtlpriv->psc.rfpwr_state = ERFON; -+ rtlpriv->psc.rfoff_reason = 0; -+ } -+ } -+#endif -+ -+ /* Before RF-R/W we must execute the IO from Scott's suggestion. */ -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); -+ if (rtlhal->version == VERSION_8192S_ACUT) -+ rtl_write_byte(rtlpriv, SPS1_CTRL + 3, 0x07); -+ else -+ rtl_write_byte(rtlpriv, RF_CTRL, 0x07); -+ -+ if (rtl92s_phy_rf_config(hw) != true) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("RF Config failed\n")); -+ return rtstatus; -+ } -+ -+ /* After read predefined TXT, we must set BB/MAC/RF -+ * register as our requirement */ -+ -+ rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, -+ (enum radio_path)0, -+ RF_CHNLBW, -+ RFREG_OFFSET_MASK); -+ rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, -+ (enum radio_path)1, -+ RF_CHNLBW, -+ RFREG_OFFSET_MASK); -+ -+ /*---- Set CCK and OFDM Block "ON"----*/ -+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); -+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); -+ -+ /*3 Set Hardware(Do nothing now) */ -+ _rtl92se_hw_configure(hw); -+ -+ /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ -+ /* TX power index for different rate set. */ -+ /* Get original hw reg values */ -+ rtl92s_phy_get_hw_reg_originalvalue(hw); -+ /* Write correct tx power index */ -+ rtl92s_phy_set_txpower(hw, rtlphy->current_channel); -+ -+ /* We must set MAC address after firmware download. */ -+ for (i = 0; i < 6; i++) -+ rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); -+ -+ /* EEPROM R/W workaround */ -+ tmp_u1b = rtl_read_byte(rtlpriv, MAC_PINMUX_CFG); -+ rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, tmp_u1b & (~BIT(3))); -+ -+ rtl_write_byte(rtlpriv, 0x4d, 0x0); -+ -+ if (hal_get_firmwareversion(rtlpriv) >= 0x49) { -+ tmp_byte = rtl_read_byte(rtlpriv, FW_RSVD_PG_CRTL) & (~BIT(4)); -+ tmp_byte = tmp_byte | BIT(5); -+ rtl_write_byte(rtlpriv, FW_RSVD_PG_CRTL, tmp_byte); -+ rtl_write_dword(rtlpriv, TXDESC_MSK, 0xFFFFCFFF); -+ } -+ -+ /* We enable high power and RA related mechanism after NIC -+ * initialized. */ -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); -+ -+ /* Add to prevent ASPM bug. */ -+ /* Always enable hst and NIC clock request. */ -+ rtl92s_phy_switch_ephy_parameter(hw); -+ -+ /* Security related -+ * 1. Clear all H/W keys. -+ * 2. Enable H/W encryption/decryption. */ -+ rtl_cam_reset_all_entry(hw); -+ secr_value |= SCR_TXENCENABLE; -+ secr_value |= SCR_RXENCENABLE; -+ secr_value |= SCR_NOSKMC; -+ rtl_write_byte(rtlpriv, REG_SECR, secr_value); -+ -+ for (i = 0; i < 4; i++) -+ rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); -+ -+ if (rtlphy->rf_type == RF_1T2R) { -+ bool mrc2set = true; -+ /* Turn on B-Path */ -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); -+ } -+ -+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); -+ rtl92s_dm_init(hw); -+ rtlpci->being_init_adapter = false; -+ -+ return err; -+} -+ -+void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr) -+{ -+} -+ -+void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ u32 reg_rcr = rtlpci->receive_config; -+ -+ if (rtlpriv->psc.rfpwr_state != ERFON) -+ return; -+ -+ if (check_bssid == true) { -+ reg_rcr |= (RCR_CBSSID); -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); -+ } else if (check_bssid == false) { -+ reg_rcr &= (~RCR_CBSSID); -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); -+ } -+ -+} -+ -+static int _rtl92se_set_media_status(struct ieee80211_hw *hw, -+ enum nl80211_iftype type) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 bt_msr = rtl_read_byte(rtlpriv, MSR); -+ enum led_ctl_mode ledaction = LED_CTL_NO_LINK; -+ u32 temp; -+ bt_msr &= ~MSR_LINK_MASK; -+ -+ switch (type) { -+ case NL80211_IFTYPE_UNSPECIFIED: -+ bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); -+ ledaction = LED_CTL_LINK; -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, -+ ("Set Network type to NO LINK!\n")); -+ break; -+ case NL80211_IFTYPE_ADHOC: -+ bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, -+ ("Set Network type to Ad Hoc!\n")); -+ break; -+ case NL80211_IFTYPE_STATION: -+ bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); -+ ledaction = LED_CTL_LINK; -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, -+ ("Set Network type to STA!\n")); -+ break; -+ case NL80211_IFTYPE_AP: -+ bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, -+ ("Set Network type to AP!\n")); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Network type %d not support!\n", type)); -+ return 1; -+ break; -+ -+ } -+ -+ rtl_write_byte(rtlpriv, (MSR), bt_msr); -+ -+ temp = rtl_read_dword(rtlpriv, TCR); -+ rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); -+ rtl_write_dword(rtlpriv, TCR, temp | BIT(8)); -+ -+ -+ return 0; -+} -+ -+/* HW_VAR_MEDIA_STATUS & HW_VAR_CECHK_BSSID */ -+int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (_rtl92se_set_media_status(hw, type)) -+ return -EOPNOTSUPP; -+ -+ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { -+ if (type != NL80211_IFTYPE_AP) -+ rtl92se_set_check_bssid(hw, true); -+ } else { -+ rtl92se_set_check_bssid(hw, false); -+ } -+ -+ return 0; -+} -+ -+/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ -+void rtl92se_set_qos(struct ieee80211_hw *hw, int aci) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ rtl92s_dm_init_edca_turbo(hw); -+ -+ switch (aci) { -+ case AC1_BK: -+ rtl_write_dword(rtlpriv, EDCAPARA_BK, 0xa44f); -+ break; -+ case AC0_BE: -+ /* rtl_write_dword(rtlpriv, EDCAPARA_BE, u4b_ac_param); */ -+ break; -+ case AC2_VI: -+ rtl_write_dword(rtlpriv, EDCAPARA_VI, 0x5e4322); -+ break; -+ case AC3_VO: -+ rtl_write_dword(rtlpriv, EDCAPARA_VO, 0x2f3222); -+ break; -+ default: -+ RT_ASSERT(false, ("invalid aci: %d !\n", aci)); -+ break; -+ } -+} -+ -+void rtl92se_enable_interrupt(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); -+ /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ -+ rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); -+ -+ rtlpci->irq_enabled = true; -+} -+ -+void rtl92se_disable_interrupt(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ rtl_write_dword(rtlpriv, INTA_MASK, 0); -+ rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); -+ -+ rtlpci->irq_enabled = false; -+} -+ -+ -+static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 waitcnt = 100; -+ bool result = false; -+ u8 tmp; -+ -+ rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); -+ -+ /* Wait the MAC synchronized. */ -+ udelay(400); -+ -+ /* Check if it is set ready. */ -+ tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); -+ result = ((tmp & BIT(7)) == (data & BIT(7))); -+ -+ if ((data & (BIT(6) | BIT(7))) == false) { -+ waitcnt = 100; -+ tmp = 0; -+ -+ while (1) { -+ waitcnt--; -+ tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); -+ -+ if ((tmp & BIT(6))) -+ break; -+ -+ printk(KERN_ERR "wait for BIT(6) return value %x\n", -+ tmp); -+ -+ if (waitcnt == 0) -+ break; -+ udelay(10); -+ } -+ -+ if (waitcnt == 0) -+ result = false; -+ else -+ result = true; -+ } -+ -+ return result; -+} -+ -+static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ u8 u1btmp; -+ -+ if (rtlhal->driver_going2unload) -+ rtl_write_byte(rtlpriv, 0x560, 0x0); -+ -+ /* Power save for BB/RF */ -+ u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); -+ u1btmp |= BIT(0); -+ rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); -+ rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); -+ rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); -+ rtl_write_word(rtlpriv, CMDR, 0x57FC); -+ udelay(100); -+ rtl_write_word(rtlpriv, CMDR, 0x77FC); -+ rtl_write_byte(rtlpriv, PHY_CCA, 0x0); -+ udelay(10); -+ rtl_write_word(rtlpriv, CMDR, 0x37FC); -+ udelay(10); -+ rtl_write_word(rtlpriv, CMDR, 0x77FC); -+ udelay(10); -+ rtl_write_word(rtlpriv, CMDR, 0x57FC); -+ rtl_write_word(rtlpriv, CMDR, 0x0000); -+ -+ if (rtlhal->driver_going2unload) { -+ u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); -+ u1btmp &= ~(BIT(0)); -+ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); -+ } -+ -+ u1btmp = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); -+ -+ /* Add description. After switch control path. register -+ * after page1 will be invisible. We can not do any IO -+ * for register>0x40. After resume&MACIO reset, we need -+ * to remember previous reg content. */ -+ if (u1btmp & BIT(7)) { -+ u1btmp &= ~(BIT(6) | BIT(7)); -+ if (!_rtl92s_set_sysclk(hw, u1btmp)) { -+ printk(KERN_ERR "Switch ctrl path fail\n"); -+ return; -+ } -+ } -+ -+ /* Power save for MAC */ -+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && -+ !rtlhal->driver_going2unload) { -+ /* enable LED function */ -+ rtl_write_byte(rtlpriv, 0x03, 0xF9); -+ /* SW/HW radio off or halt adapter!! For example S3/S4 */ -+ } else { -+ /* LED function disable. Power range is about 8mA now. */ -+ /* if write 0xF1 disconnet_pci power -+ * ifconfig wlan0 down power are both high 35:70 */ -+ /* if write oxF9 disconnet_pci power -+ * ifconfig wlan0 down power are both low 12:45*/ -+ rtl_write_byte(rtlpriv, 0x03, 0xF9); -+ } -+ -+ rtl_write_byte(rtlpriv, SYS_CLKR + 1, 0x70); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, 0x68); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x00); -+ rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, 0x0E); -+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); -+ -+} -+ -+static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); -+ -+ if (rtlpci->up_first_time == 1) -+ return; -+ -+ if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) -+ rtl92se_sw_led_on(hw, pLed0); -+ else -+ rtl92se_sw_led_off(hw, pLed0); -+} -+ -+ -+static void _rtl92se_power_domain_init(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u16 tmpu2b; -+ u8 tmpu1b; -+ -+ rtlpriv->psc.pwrdomain_protect = true; -+ -+ tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); -+ if (tmpu1b & BIT(7)) { -+ tmpu1b &= ~(BIT(6) | BIT(7)); -+ if (!_rtl92s_set_sysclk(hw, tmpu1b)) { -+ rtlpriv->psc.pwrdomain_protect = false; -+ return; -+ } -+ } -+ -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); -+ rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); -+ -+ /* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */ -+ tmpu1b = rtl_read_byte(rtlpriv, SYS_FUNC_EN + 1); -+ -+ /* If IPS we need to turn LED on. So we not -+ * not disable BIT 3/7 of reg3. */ -+ if (rtlpriv->psc.rfoff_reason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) -+ tmpu1b &= 0xFB; -+ else -+ tmpu1b &= 0x73; -+ -+ rtl_write_byte(rtlpriv, SYS_FUNC_EN + 1, tmpu1b); -+ /* wait for BIT 10/11/15 to pull high automatically!! */ -+ mdelay(1); -+ -+ rtl_write_byte(rtlpriv, CMDR, 0); -+ rtl_write_byte(rtlpriv, TCR, 0); -+ -+ /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ -+ tmpu1b = rtl_read_byte(rtlpriv, 0x562); -+ tmpu1b |= 0x08; -+ rtl_write_byte(rtlpriv, 0x562, tmpu1b); -+ tmpu1b &= ~(BIT(3)); -+ rtl_write_byte(rtlpriv, 0x562, tmpu1b); -+ -+ /* Enable AFE clock source */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); -+ /* Delay 1.5ms */ -+ udelay(1500); -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); -+ rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); -+ -+ /* Enable AFE Macro Block's Bandgap */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); -+ rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); -+ mdelay(1); -+ -+ /* Enable AFE Mbias */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); -+ rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); -+ mdelay(1); -+ -+ /* Enable LDOA15 block */ -+ tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); -+ rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); -+ -+ /* Set Digital Vdd to Retention isolation Path. */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_ISO_CTRL); -+ rtl_write_word(rtlpriv, SYS_ISO_CTRL, (tmpu2b | BIT(11))); -+ -+ -+ /* For warm reboot NIC disappera bug. */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(13))); -+ -+ rtl_write_byte(rtlpriv, SYS_ISO_CTRL + 1, 0x68); -+ -+ /* Enable AFE PLL Macro Block */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); -+ /* Enable MAC 80MHZ clock */ -+ tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); -+ rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); -+ mdelay(1); -+ -+ /* Release isolation AFE PLL & MD */ -+ rtl_write_byte(rtlpriv, SYS_ISO_CTRL, 0xA6); -+ -+ /* Enable MAC clock */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); -+ rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); -+ -+ /* Enable Core digital and enable IOREG R/W */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); -+ rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11))); -+ /* enable REG_EN */ -+ rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); -+ -+ /* Switch the control path. */ -+ tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); -+ rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); -+ -+ tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); -+ tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); -+ if (!_rtl92s_set_sysclk(hw, tmpu1b)) { -+ rtlpriv->psc.pwrdomain_protect = false; -+ return; -+ } -+ -+ rtl_write_word(rtlpriv, CMDR, 0x37FC); -+ -+ /* After MACIO reset,we must refresh LED state. */ -+ _rtl92se_gen_refreshledstate(hw); -+ -+ rtlpriv->psc.pwrdomain_protect = false; -+} -+ -+void rtl92se_card_disable(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ enum nl80211_iftype opmode; -+ u8 wait = 30; -+ -+ rtlpriv->intf_ops->enable_aspm(hw); -+ -+ if (rtlpci->driver_is_goingto_unload || -+ ppsc->rfoff_reason > RF_CHANGE_BY_PS) -+ rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); -+ -+ /* we should chnge GPIO to input mode -+ * this will drop away current about 25mA*/ -+ rtl8192se_gpiobit3_cfg_inputmode(hw); -+ -+ /* this is very important for ips power save */ -+ while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { -+ if (rtlpriv->psc.pwrdomain_protect) -+ mdelay(20); -+ else -+ break; -+ } -+ -+ mac->link_state = MAC80211_NOLINK; -+ opmode = NL80211_IFTYPE_UNSPECIFIED; -+ _rtl92se_set_media_status(hw, opmode); -+ -+ _rtl92s_phy_set_rfhalt(hw); -+ udelay(100); -+} -+ -+void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta, -+ u32 *p_intb) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; -+ rtl_write_dword(rtlpriv, ISR, *p_inta); -+ -+ *p_intb = rtl_read_dword(rtlpriv, ISR + 4) & rtlpci->irq_mask[1]; -+ rtl_write_dword(rtlpriv, ISR + 4, *p_intb); -+} -+ -+void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ u16 bcntime_cfg = 0; -+ u16 bcn_cw = 6, bcn_ifs = 0xf; -+ u16 atim_window = 2; -+ -+ /* ATIM Window (in unit of TU). */ -+ rtl_write_word(rtlpriv, ATIMWND, atim_window); -+ -+ /* Beacon interval (in unit of TU). */ -+ rtl_write_word(rtlpriv, BCN_INTERVAL, mac->beacon_interval); -+ -+ /* DrvErlyInt (in unit of TU). (Time to send -+ * interrupt to notify driver to change -+ * beacon content) */ -+ rtl_write_word(rtlpriv, BCN_DRV_EARLY_INT, 10 << 4); -+ -+ /* BcnDMATIM(in unit of us). Indicates the -+ * time before TBTT to perform beacon queue DMA */ -+ rtl_write_word(rtlpriv, BCN_DMATIME, 256); -+ -+ /* Force beacon frame transmission even -+ * after receiving beacon frame from -+ * other ad hoc STA */ -+ rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100); -+ -+ /* Beacon Time Configuration */ -+ if (mac->opmode == NL80211_IFTYPE_ADHOC) -+ bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT); -+ -+ /* TODO: bcn_ifs may required to be changed on ASIC */ -+ bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS; -+ -+ /*for beacon changed */ -+ rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval); -+} -+ -+void rtl92se_set_beacon_interval(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ u16 bcn_interval = mac->beacon_interval; -+ -+ /* Beacon interval (in unit of TU). */ -+ rtl_write_word(rtlpriv, BCN_INTERVAL, bcn_interval); -+ /* 2008.10.24 added by tynli for beacon changed. */ -+ rtl92s_phy_set_beacon_hwreg(hw, bcn_interval); -+} -+ -+void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, -+ u32 add_msr, u32 rm_msr) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, -+ ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); -+ -+ if (add_msr) -+ rtlpci->irq_mask[0] |= add_msr; -+ -+ if (rm_msr) -+ rtlpci->irq_mask[0] &= (~rm_msr); -+ -+ rtl92se_disable_interrupt(hw); -+ rtl92se_enable_interrupt(hw); -+} -+ -+static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) -+{ -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u8 efuse_id; -+ -+ rtlhal->ic_class = IC_INFERIORITY_A; -+ -+ /* Only retrieving while using EFUSE. */ -+ if ((rtlefuse->epromtype == EEPROM_BOOT_EFUSE) && -+ !rtlefuse->autoload_failflag) { -+ efuse_id = efuse_read_1byte(hw, EFUSE_IC_ID_OFFSET); -+ -+ if (efuse_id == 0xfe) -+ rtlhal->ic_class = IC_INFERIORITY_B; -+ } -+} -+ -+static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u16 i, usvalue; -+ u16 eeprom_id; -+ u8 tempval; -+ u8 hwinfo[HWSET_MAX_SIZE_92S]; -+ u8 rf_path, index; -+ -+ if (rtlefuse->epromtype == EEPROM_93C46) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("RTL819X Not boot from eeprom, check it !!")); -+ } else if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { -+ rtl_efuse_shadow_map_update(hw); -+ -+ memcpy((void *)hwinfo, (void *) -+ &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], -+ HWSET_MAX_SIZE_92S); -+ } -+ -+ RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), -+ hwinfo, HWSET_MAX_SIZE_92S); -+ -+ eeprom_id = *((u16 *)&hwinfo[0]); -+ if (eeprom_id != RTL8190_EEPROM_ID) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -+ ("EEPROM ID(%#x) is invalid!!\n", eeprom_id)); -+ rtlefuse->autoload_failflag = true; -+ } else { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); -+ rtlefuse->autoload_failflag = false; -+ } -+ -+ if (rtlefuse->autoload_failflag == true) -+ return; -+ -+ _rtl8192se_get_IC_Inferiority(hw); -+ -+ /* Read IC Version && Channel Plan */ -+ /* VID, DID SE 0xA-D */ -+ rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; -+ rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; -+ rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; -+ rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; -+ rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("EEPROMId = 0x%4x\n", eeprom_id)); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid)); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did)); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid)); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid)); -+ -+ for (i = 0; i < 6; i += 2) { -+ usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; -+ *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; -+ } -+ -+ for (i = 0; i < 6; i++) -+ rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, -+ (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); -+ -+ /* Get Tx Power Level by Channel */ -+ /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ -+ /* 92S suupport RF A & B */ -+ for (rf_path = 0; rf_path < 2; rf_path++) { -+ for (i = 0; i < 3; i++) { -+ /* Read CCK RF A & B Tx power */ -+ rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = -+ hwinfo[EEPROM_TXPOWERBASE + rf_path * 3 + i]; -+ -+ /* Read OFDM RF A & B Tx power for 1T */ -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = -+ hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; -+ -+ /* Read OFDM RF A & B Tx power for 2T */ -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i] -+ = hwinfo[EEPROM_TXPOWERBASE + 12 + -+ rf_path * 3 + i]; -+ } -+ } -+ -+ for (rf_path = 0; rf_path < 2; rf_path++) -+ for (i = 0; i < 3; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM, -+ ("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, -+ i, rtlefuse->eeprom_chnlarea_txpwr_cck -+ [rf_path][i])); -+ for (rf_path = 0; rf_path < 2; rf_path++) -+ for (i = 0; i < 3; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM, -+ ("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", -+ rf_path, i, -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s -+ [rf_path][i])); -+ for (rf_path = 0; rf_path < 2; rf_path++) -+ for (i = 0; i < 3; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_EEPROM, -+ ("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", -+ rf_path, i, -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif -+ [rf_path][i])); -+ -+ for (rf_path = 0; rf_path < 2; rf_path++) { -+ -+ /* Assign dedicated channel tx power */ -+ for (i = 0; i < 14; i++) { -+ /* channel 1~3 use the same Tx Power Level. */ -+ if (i < 3) -+ index = 0; -+ /* Channel 4-8 */ -+ else if (i < 8) -+ index = 1; -+ /* Channel 9-14 */ -+ else -+ index = 2; -+ -+ /* Record A & B CCK /OFDM - 1T/2T Channel area -+ * tx power */ -+ rtlefuse->txpwrlevel_cck[rf_path][i] = -+ rtlefuse->eeprom_chnlarea_txpwr_cck -+ [rf_path][index]; -+ rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_1s -+ [rf_path][index]; -+ rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = -+ rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif -+ [rf_path][index]; -+ } -+ -+ for (i = 0; i < 14; i++) { -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " -+ "[0x%x / 0x%x / 0x%x]\n", rf_path, i, -+ rtlefuse->txpwrlevel_cck[rf_path][i], -+ rtlefuse->txpwrlevel_ht40_1s[rf_path][i], -+ rtlefuse->txpwrlevel_ht40_2s[rf_path][i])); -+ } -+ } -+ -+ for (rf_path = 0; rf_path < 2; rf_path++) { -+ for (i = 0; i < 3; i++) { -+ /* Read Power diff limit. */ -+ rtlefuse->eeprom_pwrgroup[rf_path][i] = -+ hwinfo[EEPROM_TXPWRGROUP + rf_path * 3 + i]; -+ } -+ } -+ -+ for (rf_path = 0; rf_path < 2; rf_path++) { -+ /* Fill Pwr group */ -+ for (i = 0; i < 14; i++) { -+ /* Chanel 1-3 */ -+ if (i < 3) -+ index = 0; -+ /* Channel 4-8 */ -+ else if (i < 8) -+ index = 1; -+ /* Channel 9-13 */ -+ else -+ index = 2; -+ -+ rtlefuse->pwrgroup_ht20[rf_path][i] = -+ (rtlefuse->eeprom_pwrgroup[rf_path][index] & -+ 0xf); -+ rtlefuse->pwrgroup_ht40[rf_path][i] = -+ ((rtlefuse->eeprom_pwrgroup[rf_path][index] & -+ 0xf0) >> 4); -+ -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-%d pwrgroup_ht20[%d] = 0x%x\n", -+ rf_path, i, -+ rtlefuse->pwrgroup_ht20[rf_path][i])); -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-%d pwrgroup_ht40[%d] = 0x%x\n", -+ rf_path, i, -+ rtlefuse->pwrgroup_ht40[rf_path][i])); -+ } -+ } -+ -+ for (i = 0; i < 14; i++) { -+ /* Read tx power difference between HT OFDM 20/40 MHZ */ -+ /* channel 1-3 */ -+ if (i < 3) -+ index = 0; -+ /* Channel 4-8 */ -+ else if (i < 8) -+ index = 1; -+ /* Channel 9-14 */ -+ else -+ index = 2; -+ -+ tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_HT20_DIFF + -+ index]) & 0xff; -+ rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); -+ rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = -+ ((tempval >> 4) & 0xF); -+ -+ /* Read OFDM<->HT tx power diff */ -+ /* Channel 1-3 */ -+ if (i < 3) -+ index = 0; -+ /* Channel 4-8 */ -+ else if (i < 8) -+ index = 0x11; -+ /* Channel 9-14 */ -+ else -+ index = 1; -+ -+ tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_OFDM_DIFF + index]) -+ & 0xff; -+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = -+ (tempval & 0xF); -+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = -+ ((tempval >> 4) & 0xF); -+ -+ tempval = (*(u8 *)&hwinfo[TX_PWR_SAFETY_CHK]); -+ rtlefuse->txpwr_safetyflag = (tempval & 0x01); -+ } -+ -+ rtlefuse->eeprom_regulatory = 0; -+ if (rtlefuse->eeprom_version >= 2) { -+ /* BIT(0)~2 */ -+ if (rtlefuse->eeprom_version >= 4) -+ rtlefuse->eeprom_regulatory = -+ (hwinfo[EEPROM_REGULATORY] & 0x7); -+ else /* BIT(0) */ -+ rtlefuse->eeprom_regulatory = -+ (hwinfo[EEPROM_REGULATORY] & 0x1); -+ } -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory)); -+ -+ for (i = 0; i < 14; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, -+ rtlefuse->txpwr_ht20diff[RF90_PATH_A][i])); -+ for (i = 0; i < 14; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, -+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i])); -+ for (i = 0; i < 14; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, -+ rtlefuse->txpwr_ht20diff[RF90_PATH_B][i])); -+ for (i = 0; i < 14; i++) -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, -+ ("RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, -+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i])); -+ -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPwrSafetyFlag = %d\n", -+ rtlefuse->txpwr_safetyflag)); -+ -+ /* Read RF-indication and Tx Power gain -+ * index diff of legacy to HT OFDM rate. */ -+ tempval = (*(u8 *)&hwinfo[EEPROM_RFIND_POWERDIFF]) & 0xff; -+ rtlefuse->eeprom_txpowerdiff = tempval; -+ rtlefuse->legacy_httxpowerdiff = -+ rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; -+ -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPowerDiff = %#x\n", -+ rtlefuse->eeprom_txpowerdiff)); -+ -+ /* Get TSSI value for each path. */ -+ usvalue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; -+ rtlefuse->eeprom_tssi[RF90_PATH_A] = (u8)((usvalue & 0xff00) >> 8); -+ usvalue = *(u8 *)&hwinfo[EEPROM_TSSI_B]; -+ rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); -+ -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TSSI_A = 0x%x, TSSI_B = 0x%x\n", -+ rtlefuse->eeprom_tssi[RF90_PATH_A], -+ rtlefuse->eeprom_tssi[RF90_PATH_B])); -+ -+ /* Read antenna tx power offset of B/C/D to A from EEPROM */ -+ /* and read ThermalMeter from EEPROM */ -+ tempval = *(u8 *)&hwinfo[EEPROM_THERMALMETER]; -+ rtlefuse->eeprom_thermalmeter = tempval; -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("thermalmeter = 0x%x\n", -+ rtlefuse->eeprom_thermalmeter)); -+ -+ /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ -+ rtlefuse->thermalmeter[0] = (rtlefuse->eeprom_thermalmeter & 0x1f); -+ rtlefuse->tssi_13dbm = rtlefuse->eeprom_thermalmeter * 100; -+ -+ /* Read CrystalCap from EEPROM */ -+ tempval = (*(u8 *)&hwinfo[EEPROM_CRYSTALCAP]) >> 4; -+ rtlefuse->eeprom_crystalcap = tempval; -+ /* CrystalCap, BIT(12)~15 */ -+ rtlefuse->crystalcap = rtlefuse->eeprom_crystalcap; -+ -+ /* Read IC Version && Channel Plan */ -+ /* Version ID, Channel plan */ -+ rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; -+ rtlefuse->txpwr_fromeprom = true; -+ RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("EEPROM ChannelPlan = 0x%4x\n", -+ rtlefuse->eeprom_channelplan)); -+ -+ /* Read Customer ID or Board Type!!! */ -+ tempval = *(u8 *)&hwinfo[EEPROM_BOARDTYPE]; -+ /* Change RF type definition */ -+ if (tempval == 0) -+ rtlphy->rf_type = RF_2T2R; -+ else if (tempval == 1) -+ rtlphy->rf_type = RF_1T2R; -+ else if (tempval == 2) -+ rtlphy->rf_type = RF_1T2R; -+ else if (tempval == 3) -+ rtlphy->rf_type = RF_1T1R; -+ -+ /* 1T2R but 1SS (1x1 receive combining) */ -+ rtlefuse->b1x1_recvcombine = false; -+ if (rtlphy->rf_type == RF_1T2R) { -+ tempval = rtl_read_byte(rtlpriv, 0x07); -+ if (!(tempval & BIT(0))) { -+ rtlefuse->b1x1_recvcombine = true; -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("RF_TYPE=1T2R but only 1SS\n")); -+ } -+ } -+ rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine; -+ rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMID]; -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x", -+ rtlefuse->eeprom_oemid)); -+ -+ /* set channel paln to world wide 13 */ -+ rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; -+} -+ -+void rtl92se_read_eeprom_info(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u8 tmp_u1b = 0; -+ -+ tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD); -+ -+ if (tmp_u1b & BIT(4)) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n")); -+ rtlefuse->epromtype = EEPROM_93C46; -+ } else { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n")); -+ rtlefuse->epromtype = EEPROM_BOOT_EFUSE; -+ } -+ -+ if (tmp_u1b & BIT(5)) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); -+ rtlefuse->autoload_failflag = false; -+ _rtl92se_read_adapter_info(hw); -+ } else { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); -+ rtlefuse->autoload_failflag = true; -+ } -+} -+ -+static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u32 ratr_value; -+ u8 ratr_index = 0; -+ u8 nmode = mac->ht_enable; -+ u8 mimo_ps = IEEE80211_SMPS_OFF; -+ u16 shortgi_rate = 0; -+ u32 tmp_ratr_value = 0; -+ u8 curtxbw_40mhz = mac->bw_40; -+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? -+ 1 : 0; -+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? -+ 1 : 0; -+ enum wireless_mode wirelessmode = mac->mode; -+ -+ if (rtlhal->current_bandtype == BAND_ON_5G) -+ ratr_value = sta->supp_rates[1] << 4; -+ else -+ ratr_value = sta->supp_rates[0]; -+ ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | -+ sta->ht_cap.mcs.rx_mask[0] << 12); -+ switch (wirelessmode) { -+ case WIRELESS_MODE_B: -+ ratr_value &= 0x0000000D; -+ break; -+ case WIRELESS_MODE_G: -+ ratr_value &= 0x00000FF5; -+ break; -+ case WIRELESS_MODE_N_24G: -+ case WIRELESS_MODE_N_5G: -+ nmode = 1; -+ if (mimo_ps == IEEE80211_SMPS_STATIC) { -+ ratr_value &= 0x0007F005; -+ } else { -+ u32 ratr_mask; -+ -+ if (get_rf_type(rtlphy) == RF_1T2R || -+ get_rf_type(rtlphy) == RF_1T1R) { -+ if (curtxbw_40mhz) -+ ratr_mask = 0x000ff015; -+ else -+ ratr_mask = 0x000ff005; -+ } else { -+ if (curtxbw_40mhz) -+ ratr_mask = 0x0f0ff015; -+ else -+ ratr_mask = 0x0f0ff005; -+ } -+ -+ ratr_value &= ratr_mask; -+ } -+ break; -+ default: -+ if (rtlphy->rf_type == RF_1T2R) -+ ratr_value &= 0x000ff0ff; -+ else -+ ratr_value &= 0x0f0ff0ff; -+ -+ break; -+ } -+ -+ if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) -+ ratr_value &= 0x0FFFFFFF; -+ else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) -+ ratr_value &= 0x0FFFFFF0; -+ -+ if (nmode && ((curtxbw_40mhz && -+ curshortgi_40mhz) || (!curtxbw_40mhz && -+ curshortgi_20mhz))) { -+ -+ ratr_value |= 0x10000000; -+ tmp_ratr_value = (ratr_value >> 12); -+ -+ for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { -+ if ((1 << shortgi_rate) & tmp_ratr_value) -+ break; -+ } -+ -+ shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | -+ (shortgi_rate << 4) | (shortgi_rate); -+ -+ rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); -+ } -+ -+ rtl_write_dword(rtlpriv, ARFR0 + ratr_index * 4, ratr_value); -+ if (ratr_value & 0xfffff000) -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_N); -+ else -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG); -+ -+ RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, -+ ("%x\n", rtl_read_dword(rtlpriv, ARFR0))); -+} -+ -+static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, -+ u8 rssi_level) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_sta_info *sta_entry = NULL; -+ u32 ratr_bitmap; -+ u8 ratr_index = 0; -+ u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) -+ ? 1 : 0; -+ u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? -+ 1 : 0; -+ u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? -+ 1 : 0; -+ enum wireless_mode wirelessmode = 0; -+ bool shortgi = false; -+ u32 ratr_value = 0; -+ u8 shortgi_rate = 0; -+ u32 mask = 0; -+ u32 band = 0; -+ bool bmulticast = false; -+ u8 macid = 0; -+ u8 mimo_ps = IEEE80211_SMPS_OFF; -+ -+ sta_entry = (struct rtl_sta_info *) sta->drv_priv; -+ wirelessmode = sta_entry->wireless_mode; -+ if (mac->opmode == NL80211_IFTYPE_STATION) -+ curtxbw_40mhz = mac->bw_40; -+ else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) -+ macid = sta->aid + 1; -+ -+ if (rtlhal->current_bandtype == BAND_ON_5G) -+ ratr_bitmap = sta->supp_rates[1] << 4; -+ else -+ ratr_bitmap = sta->supp_rates[0]; -+ ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | -+ sta->ht_cap.mcs.rx_mask[0] << 12); -+ switch (wirelessmode) { -+ case WIRELESS_MODE_B: -+ band |= WIRELESS_11B; -+ ratr_index = RATR_INX_WIRELESS_B; -+ if (ratr_bitmap & 0x0000000c) -+ ratr_bitmap &= 0x0000000d; -+ else -+ ratr_bitmap &= 0x0000000f; -+ break; -+ case WIRELESS_MODE_G: -+ band |= (WIRELESS_11G | WIRELESS_11B); -+ ratr_index = RATR_INX_WIRELESS_GB; -+ -+ if (rssi_level == 1) -+ ratr_bitmap &= 0x00000f00; -+ else if (rssi_level == 2) -+ ratr_bitmap &= 0x00000ff0; -+ else -+ ratr_bitmap &= 0x00000ff5; -+ break; -+ case WIRELESS_MODE_A: -+ band |= WIRELESS_11A; -+ ratr_index = RATR_INX_WIRELESS_A; -+ ratr_bitmap &= 0x00000ff0; -+ break; -+ case WIRELESS_MODE_N_24G: -+ case WIRELESS_MODE_N_5G: -+ band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); -+ ratr_index = RATR_INX_WIRELESS_NGB; -+ -+ if (mimo_ps == IEEE80211_SMPS_STATIC) { -+ if (rssi_level == 1) -+ ratr_bitmap &= 0x00070000; -+ else if (rssi_level == 2) -+ ratr_bitmap &= 0x0007f000; -+ else -+ ratr_bitmap &= 0x0007f005; -+ } else { -+ if (rtlphy->rf_type == RF_1T2R || -+ rtlphy->rf_type == RF_1T1R) { -+ if (rssi_level == 1) { -+ ratr_bitmap &= 0x000f0000; -+ } else if (rssi_level == 3) { -+ ratr_bitmap &= 0x000fc000; -+ } else if (rssi_level == 5) { -+ ratr_bitmap &= 0x000ff000; -+ } else { -+ if (curtxbw_40mhz) -+ ratr_bitmap &= 0x000ff015; -+ else -+ ratr_bitmap &= 0x000ff005; -+ } -+ } else { -+ if (rssi_level == 1) { -+ ratr_bitmap &= 0x0f8f0000; -+ } else if (rssi_level == 3) { -+ ratr_bitmap &= 0x0f8fc000; -+ } else if (rssi_level == 5) { -+ ratr_bitmap &= 0x0f8ff000; -+ } else { -+ if (curtxbw_40mhz) -+ ratr_bitmap &= 0x0f8ff015; -+ else -+ ratr_bitmap &= 0x0f8ff005; -+ } -+ } -+ } -+ -+ if ((curtxbw_40mhz && curshortgi_40mhz) || -+ (!curtxbw_40mhz && curshortgi_20mhz)) { -+ if (macid == 0) -+ shortgi = true; -+ else if (macid == 1) -+ shortgi = false; -+ } -+ break; -+ default: -+ band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); -+ ratr_index = RATR_INX_WIRELESS_NGB; -+ -+ if (rtlphy->rf_type == RF_1T2R) -+ ratr_bitmap &= 0x000ff0ff; -+ else -+ ratr_bitmap &= 0x0f8ff0ff; -+ break; -+ } -+ -+ if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) -+ ratr_bitmap &= 0x0FFFFFFF; -+ else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) -+ ratr_bitmap &= 0x0FFFFFF0; -+ -+ if (shortgi) { -+ ratr_bitmap |= 0x10000000; -+ /* Get MAX MCS available. */ -+ ratr_value = (ratr_bitmap >> 12); -+ for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { -+ if ((1 << shortgi_rate) & ratr_value) -+ break; -+ } -+ -+ shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | -+ (shortgi_rate << 4) | (shortgi_rate); -+ rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); -+ } -+ -+ mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf); -+ -+ RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, ("mask = %x, bitmap = %x\n", -+ mask, ratr_bitmap)); -+ rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap); -+ rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); -+ -+ if (macid != 0) -+ sta_entry->ratr_index = ratr_index; -+} -+ -+void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (rtlpriv->dm.useramask) -+ rtl92se_update_hal_rate_mask(hw, sta, rssi_level); -+ else -+ rtl92se_update_hal_rate_table(hw, sta); -+} -+ -+void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ u16 sifs_timer; -+ -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, -+ (u8 *)&mac->slot_time); -+ sifs_timer = 0x0e0e; -+ rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -+ -+} -+ -+/* this ifunction is for RFKILL, it's different with windows, -+ * because UI will disable wireless when GPIO Radio Off. -+ * And here we not check or Disable/Enable ASPM like windows*/ -+bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ enum rf_pwrstate rfpwr_toset, cur_rfstate; -+ unsigned long flag = 0; -+ bool actuallyset = false; -+ bool turnonbypowerdomain = false; -+ -+ /* just 8191se can check gpio before firstup, 92c/92d have fixed it */ -+ if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) -+ return false; -+ -+ if (ppsc->swrf_processing) -+ return false; -+ -+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -+ if (ppsc->rfchange_inprogress) { -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ return false; -+ } else { -+ ppsc->rfchange_inprogress = true; -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ } -+ -+ cur_rfstate = ppsc->rfpwr_state; -+ -+ /* because after _rtl92s_phy_set_rfhalt, all power -+ * closed, so we must open some power for GPIO check, -+ * or we will always check GPIO RFOFF here, -+ * And we should close power after GPIO check */ -+ if (RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { -+ _rtl92se_power_domain_init(hw); -+ turnonbypowerdomain = true; -+ } -+ -+ rfpwr_toset = _rtl92se_rf_onoff_detect(hw); -+ -+ if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) { -+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, -+ ("RFKILL-HW Radio ON, RF ON\n")); -+ -+ rfpwr_toset = ERFON; -+ ppsc->hwradiooff = false; -+ actuallyset = true; -+ } else if ((ppsc->hwradiooff == false) && (rfpwr_toset == ERFOFF)) { -+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, -+ ("RFKILL-HW Radio OFF, RF OFF\n")); -+ -+ rfpwr_toset = ERFOFF; -+ ppsc->hwradiooff = true; -+ actuallyset = true; -+ } -+ -+ if (actuallyset) { -+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -+ ppsc->rfchange_inprogress = false; -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ -+ /* this not include ifconfig wlan0 down case */ -+ /* } else if (rfpwr_toset == ERFOFF || cur_rfstate == ERFOFF) { */ -+ } else { -+ /* because power_domain_init may be happen when -+ * _rtl92s_phy_set_rfhalt, this will open some powers -+ * and cause current increasing about 40 mA for ips, -+ * rfoff and ifconfig down, so we set -+ * _rtl92s_phy_set_rfhalt again here */ -+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC && -+ turnonbypowerdomain) { -+ _rtl92s_phy_set_rfhalt(hw); -+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); -+ } -+ -+ spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -+ ppsc->rfchange_inprogress = false; -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -+ } -+ -+ *valid = 1; -+ return !ppsc->hwradiooff; -+ -+} -+ -+/* Is_wepkey just used for WEP used as group & pairwise key -+ * if pairwise is AES ang group is WEP Is_wepkey == false.*/ -+void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, -+ bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u8 *macaddr = p_macaddr; -+ -+ u32 entry_id = 0; -+ bool is_pairwise = false; -+ -+ static u8 cam_const_addr[4][6] = { -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} -+ }; -+ static u8 cam_const_broad[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+ }; -+ -+ if (clear_all) { -+ u8 idx = 0; -+ u8 cam_offset = 0; -+ u8 clear_number = 5; -+ -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); -+ -+ for (idx = 0; idx < clear_number; idx++) { -+ rtl_cam_mark_invalid(hw, cam_offset + idx); -+ rtl_cam_empty_entry(hw, cam_offset + idx); -+ -+ if (idx < 5) { -+ memset(rtlpriv->sec.key_buf[idx], 0, -+ MAX_KEY_LEN); -+ rtlpriv->sec.key_len[idx] = 0; -+ } -+ } -+ -+ } else { -+ switch (enc_algo) { -+ case WEP40_ENCRYPTION: -+ enc_algo = CAM_WEP40; -+ break; -+ case WEP104_ENCRYPTION: -+ enc_algo = CAM_WEP104; -+ break; -+ case TKIP_ENCRYPTION: -+ enc_algo = CAM_TKIP; -+ break; -+ case AESCCMP_ENCRYPTION: -+ enc_algo = CAM_AES; -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ enc_algo = CAM_TKIP; -+ break; -+ } -+ -+ if (is_wepkey || rtlpriv->sec.use_defaultkey) { -+ macaddr = cam_const_addr[key_index]; -+ entry_id = key_index; -+ } else { -+ if (is_group) { -+ macaddr = cam_const_broad; -+ entry_id = key_index; -+ } else { -+ if (mac->opmode == NL80211_IFTYPE_AP) { -+ entry_id = rtl_cam_get_free_entry(hw, -+ p_macaddr); -+ if (entry_id >= TOTAL_CAM_ENTRY) { -+ RT_TRACE(rtlpriv, -+ COMP_SEC, DBG_EMERG, -+ ("Can not find free hw" -+ " security cam entry\n")); -+ return; -+ } -+ } else { -+ entry_id = CAM_PAIRWISE_KEY_POSITION; -+ } -+ -+ key_index = PAIRWISE_KEYIDX; -+ is_pairwise = true; -+ } -+ } -+ -+ if (rtlpriv->sec.key_len[key_index] == 0) { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("delete one entry, entry_id is %d\n", -+ entry_id)); -+ if (mac->opmode == NL80211_IFTYPE_AP) -+ rtl_cam_del_entry(hw, p_macaddr); -+ rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); -+ } else { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("The insert KEY length is %d\n", -+ rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, -+ ("The insert KEY is %x %x\n", -+ rtlpriv->sec.key_buf[0][0], -+ rtlpriv->sec.key_buf[0][1])); -+ -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("add one entry\n")); -+ if (is_pairwise) { -+ RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, -+ "Pairwiase Key content :", -+ rtlpriv->sec.pairwise_key, -+ rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); -+ -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("set Pairwiase key\n")); -+ -+ rtl_cam_add_one_entry(hw, macaddr, key_index, -+ entry_id, enc_algo, -+ CAM_CONFIG_NO_USEDK, -+ rtlpriv->sec.key_buf[key_index]); -+ } else { -+ RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, -+ ("set group key\n")); -+ -+ if (mac->opmode == NL80211_IFTYPE_ADHOC) { -+ rtl_cam_add_one_entry(hw, -+ rtlefuse->dev_addr, -+ PAIRWISE_KEYIDX, -+ CAM_PAIRWISE_KEY_POSITION, -+ enc_algo, CAM_CONFIG_NO_USEDK, -+ rtlpriv->sec.key_buf[entry_id]); -+ } -+ -+ rtl_cam_add_one_entry(hw, macaddr, key_index, -+ entry_id, enc_algo, -+ CAM_CONFIG_NO_USEDK, -+ rtlpriv->sec.key_buf[entry_id]); -+ } -+ -+ } -+ } -+} -+ -+void rtl92se_suspend(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ rtlpci->up_first_time = true; -+} -+ -+void rtl92se_resume(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ u32 val; -+ -+ pci_read_config_dword(rtlpci->pdev, 0x40, &val); -+ if ((val & 0x0000ff00) != 0) -+ pci_write_config_dword(rtlpci->pdev, 0x40, -+ val & 0xffff00ff); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/hw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/hw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/hw.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/hw.h 2011-05-05 23:29:49.280487717 +0200 -@@ -0,0 +1,79 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_PCI92SE_HW_H__ -+#define __REALTEK_PCI92SE_HW_H__ -+ -+#define MSR_LINK_MANAGED 2 -+#define MSR_LINK_NONE 0 -+#define MSR_LINK_SHIFT 0 -+#define MSR_LINK_ADHOC 1 -+#define MSR_LINK_MASTER 3 -+ -+enum WIRELESS_NETWORK_TYPE { -+ WIRELESS_11B = 1, -+ WIRELESS_11G = 2, -+ WIRELESS_11A = 4, -+ WIRELESS_11N = 8 -+}; -+ -+void rtl92se_get_hw_reg(struct ieee80211_hw *hw, -+ u8 variable, u8 *val); -+void rtl92se_read_eeprom_info(struct ieee80211_hw *hw); -+void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, -+ u32 *inta, u32 *intb); -+int rtl92se_hw_init(struct ieee80211_hw *hw); -+void rtl92se_card_disable(struct ieee80211_hw *hw); -+void rtl92se_enable_interrupt(struct ieee80211_hw *hw); -+void rtl92se_disable_interrupt(struct ieee80211_hw *hw); -+int rtl92se_set_network_type(struct ieee80211_hw *hw, -+ enum nl80211_iftype type); -+void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -+void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr); -+void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); -+void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); -+void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); -+void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, -+ u32 add_msr, u32 rm_msr); -+void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, -+ u8 *val); -+void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level); -+void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw); -+bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, -+ u8 *valid); -+void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw); -+void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw); -+void rtl92se_set_key(struct ieee80211_hw *hw, -+ u32 key_index, u8 *macaddr, bool is_group, -+ u8 enc_algo, bool is_wepkey, bool clear_all); -+void rtl92se_suspend(struct ieee80211_hw *hw); -+void rtl92se_resume(struct ieee80211_hw *hw); -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/led.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/led.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/led.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/led.c 2011-05-05 23:29:49.281487729 +0200 -@@ -0,0 +1,149 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../pci.h" -+#include "reg.h" -+#include "led.h" -+ -+static void _rtl92se_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 rtl92se_init_sw_leds(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); -+ _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); -+} -+ -+void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -+{ -+ u8 ledcfg; -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, -+ ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); -+ -+ ledcfg = rtl_read_byte(rtlpriv, LEDCFG); -+ -+ switch (pled->ledpin) { -+ case LED_PIN_GPIO0: -+ break; -+ case LED_PIN_LED0: -+ rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0); -+ break; -+ case LED_PIN_LED1: -+ rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ pled->ledon = true; -+} -+ -+void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ u8 ledcfg; -+ -+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, -+ ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); -+ -+ ledcfg = rtl_read_byte(rtlpriv, LEDCFG); -+ -+ switch (pled->ledpin) { -+ case LED_PIN_GPIO0: -+ break; -+ case LED_PIN_LED0: -+ ledcfg &= 0xf0; -+ if (pcipriv->ledctl.led_opendrain == true) -+ rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1))); -+ else -+ rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); -+ break; -+ case LED_PIN_LED1: -+ ledcfg &= 0x0f; -+ rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ pled->ledon = false; -+} -+ -+static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, -+ enum led_ctl_mode ledaction) -+{ -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); -+ switch (ledaction) { -+ case LED_CTL_POWER_ON: -+ case LED_CTL_LINK: -+ case LED_CTL_NO_LINK: -+ rtl92se_sw_led_on(hw, pLed0); -+ break; -+ case LED_CTL_POWER_OFF: -+ rtl92se_sw_led_off(hw, pLed0); -+ break; -+ default: -+ break; -+ } -+} -+ -+void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ -+ if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && -+ (ledaction == LED_CTL_TX || -+ ledaction == LED_CTL_RX || -+ ledaction == LED_CTL_SITE_SURVEY || -+ ledaction == LED_CTL_LINK || -+ ledaction == LED_CTL_NO_LINK || -+ ledaction == LED_CTL_START_TO_LINK || -+ ledaction == LED_CTL_POWER_ON)) { -+ return; -+ } -+ RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", -+ ledaction)); -+ -+ _rtl92se_sw_led_control(hw, ledaction); -+} -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/led.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/led.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/led.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/led.h 2011-05-05 23:29:49.280487717 +0200 -@@ -0,0 +1,37 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_PCI92SE_LED_H__ -+#define __REALTEK_PCI92SE_LED_H__ -+ -+void rtl92se_init_sw_leds(struct ieee80211_hw *hw); -+void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -+void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -+void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); -+ -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/Makefile linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/Makefile ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/Makefile 2011-05-05 23:29:49.279487705 +0200 -@@ -0,0 +1,15 @@ -+rtl8192se-objs := \ -+ dm.o \ -+ fw.o \ -+ hw.o \ -+ led.o \ -+ phy.o \ -+ rf.o \ -+ sw.o \ -+ table.o \ -+ trx.o -+ -+obj-$(CONFIG_RTL8192SE) += rtl8192se.o -+ -+ccflags-y += -D__CHECK_ENDIAN__ -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/phy.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/phy.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/phy.c 2011-05-05 23:29:49.277487681 +0200 -@@ -0,0 +1,1740 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../pci.h" -+#include "../ps.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "rf.h" -+#include "dm.h" -+#include "fw.h" -+#include "hw.h" -+#include "table.h" -+ -+static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask) -+{ -+ u32 i; -+ -+ for (i = 0; i <= 31; i++) { -+ if (((bitmask >> i) & 0x1) == 1) -+ break; -+ } -+ -+ return i; -+} -+ -+u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 returnvalue = 0, originalvalue, bitshift; -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)\n", -+ regaddr, bitmask)); -+ -+ originalvalue = rtl_read_dword(rtlpriv, regaddr); -+ bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); -+ returnvalue = (originalvalue & bitmask) >> bitshift; -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, -+ ("BBR MASK=0x%x Addr[0x%x]=0x%x\n", -+ bitmask, regaddr, originalvalue)); -+ -+ return returnvalue; -+ -+} -+ -+void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, -+ u32 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 originalvalue, bitshift; -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," -+ " data(%#x)\n", regaddr, bitmask, data)); -+ -+ if (bitmask != MASKDWORD) { -+ originalvalue = rtl_read_dword(rtlpriv, regaddr); -+ bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); -+ data = ((originalvalue & (~bitmask)) | (data << bitshift)); -+ } -+ -+ rtl_write_dword(rtlpriv, regaddr, data); -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," -+ " data(%#x)\n", regaddr, bitmask, data)); -+ -+} -+ -+static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset) -+{ -+ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; -+ u32 newoffset; -+ u32 tmplong, tmplong2; -+ u8 rfpi_enable = 0; -+ u32 retvalue = 0; -+ -+ offset &= 0x3f; -+ newoffset = offset; -+ -+ tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); -+ -+ if (rfpath == RF90_PATH_A) -+ tmplong2 = tmplong; -+ else -+ tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); -+ -+ tmplong2 = (tmplong2 & (~BLSSI_READADDRESS)) | (newoffset << 23) | -+ BLSSI_READEDGE; -+ -+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, -+ tmplong & (~BLSSI_READEDGE)); -+ -+ mdelay(1); -+ -+ rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); -+ mdelay(1); -+ -+ rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, tmplong | -+ BLSSI_READEDGE); -+ mdelay(1); -+ -+ if (rfpath == RF90_PATH_A) -+ rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, -+ BIT(8)); -+ else if (rfpath == RF90_PATH_B) -+ rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, -+ BIT(8)); -+ -+ if (rfpi_enable) -+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, -+ BLSSI_READBACK_DATA); -+ else -+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, -+ BLSSI_READBACK_DATA); -+ -+ retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, -+ BLSSI_READBACK_DATA); -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n", -+ rfpath, pphyreg->rflssi_readback, retvalue)); -+ -+ return retvalue; -+ -+} -+ -+static void _rtl92s_phy_rf_serial_write(struct ieee80211_hw *hw, -+ enum radio_path rfpath, u32 offset, -+ u32 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; -+ u32 data_and_addr = 0; -+ u32 newoffset; -+ -+ offset &= 0x3f; -+ newoffset = offset; -+ -+ data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; -+ rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n", -+ rfpath, pphyreg->rf3wire_offset, data_and_addr)); -+} -+ -+ -+u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, -+ u32 regaddr, u32 bitmask) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 original_value, readback_value, bitshift; -+ unsigned long flags; -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " -+ "bitmask(%#x)\n", regaddr, rfpath, bitmask)); -+ -+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); -+ -+ original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr); -+ -+ bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); -+ readback_value = (original_value & bitmask) >> bitshift; -+ -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " -+ "bitmask(%#x), original_value(%#x)\n", regaddr, rfpath, -+ bitmask, original_value)); -+ -+ return readback_value; -+} -+ -+void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, -+ u32 regaddr, u32 bitmask, u32 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u32 original_value, bitshift; -+ unsigned long flags; -+ -+ if (!((rtlphy->rf_pathmap >> rfpath) & 0x1)) -+ return; -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," -+ " data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); -+ -+ spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); -+ -+ if (bitmask != RFREG_OFFSET_MASK) { -+ original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, -+ regaddr); -+ bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); -+ data = ((original_value & (~bitmask)) | (data << bitshift)); -+ } -+ -+ _rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); -+ -+ spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); -+ -+ RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), " -+ "data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); -+ -+} -+ -+void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, -+ u8 operation) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ -+ if (!is_hal_stop(rtlhal)) { -+ switch (operation) { -+ case SCAN_OPT_BACKUP: -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_PAUSE_DM_BY_SCAN); -+ break; -+ case SCAN_OPT_RESTORE: -+ rtl92s_phy_set_fw_cmd(hw, FW_CMD_RESUME_DM_BY_SCAN); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Unknown operation.\n")); -+ break; -+ } -+ } -+} -+ -+void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, -+ enum nl80211_channel_type ch_type) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ u8 reg_bw_opmode; -+ u8 reg_prsr_rsc; -+ -+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n", -+ rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? -+ "20MHz" : "40MHz")); -+ -+ if (rtlphy->set_bwmode_inprogress) -+ return; -+ if (is_hal_stop(rtlhal)) -+ return; -+ -+ rtlphy->set_bwmode_inprogress = true; -+ -+ reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); -+ reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2); -+ -+ switch (rtlphy->current_chan_bw) { -+ case HT_CHANNEL_WIDTH_20: -+ reg_bw_opmode |= BW_OPMODE_20MHZ; -+ rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); -+ break; -+ case HT_CHANNEL_WIDTH_20_40: -+ reg_bw_opmode &= ~BW_OPMODE_20MHZ; -+ rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("unknown bandwidth: %#X\n", -+ rtlphy->current_chan_bw)); -+ break; -+ } -+ -+ switch (rtlphy->current_chan_bw) { -+ case HT_CHANNEL_WIDTH_20: -+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); -+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); -+ -+ if (rtlhal->version >= VERSION_8192S_BCUT) -+ rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x58); -+ break; -+ case HT_CHANNEL_WIDTH_20_40: -+ rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); -+ rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); -+ -+ rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, -+ (mac->cur_40_prime_sc >> 1)); -+ rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); -+ -+ if (rtlhal->version >= VERSION_8192S_BCUT) -+ rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x18); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); -+ break; -+ } -+ -+ rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); -+ rtlphy->set_bwmode_inprogress = false; -+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); -+} -+ -+static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, -+ u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, -+ u32 para1, u32 para2, u32 msdelay) -+{ -+ struct swchnlcmd *pcmd; -+ -+ if (cmdtable == NULL) { -+ RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); -+ return false; -+ } -+ -+ if (cmdtableidx >= cmdtablesz) -+ return false; -+ -+ pcmd = cmdtable + cmdtableidx; -+ pcmd->cmdid = cmdid; -+ pcmd->para1 = para1; -+ pcmd->para2 = para2; -+ pcmd->msdelay = msdelay; -+ -+ return true; -+} -+ -+static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, -+ u8 channel, u8 *stage, u8 *step, u32 *delay) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; -+ u32 precommoncmdcnt; -+ struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; -+ u32 postcommoncmdcnt; -+ struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; -+ u32 rfdependcmdcnt; -+ struct swchnlcmd *currentcmd = NULL; -+ u8 rfpath; -+ u8 num_total_rfpath = rtlphy->num_total_rfpath; -+ -+ precommoncmdcnt = 0; -+ _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, -+ MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); -+ _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, -+ MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); -+ -+ postcommoncmdcnt = 0; -+ -+ _rtl92s_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, -+ MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); -+ -+ rfdependcmdcnt = 0; -+ -+ RT_ASSERT((channel >= 1 && channel <= 14), -+ ("illegal channel for Zebra: %d\n", channel)); -+ -+ _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, -+ MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, -+ RF_CHNLBW, channel, 10); -+ -+ _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, -+ MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0); -+ -+ do { -+ switch (*stage) { -+ case 0: -+ currentcmd = &precommoncmd[*step]; -+ break; -+ case 1: -+ currentcmd = &rfdependcmd[*step]; -+ break; -+ case 2: -+ currentcmd = &postcommoncmd[*step]; -+ break; -+ } -+ -+ if (currentcmd->cmdid == CMDID_END) { -+ if ((*stage) == 2) { -+ return true; -+ } else { -+ (*stage)++; -+ (*step) = 0; -+ continue; -+ } -+ } -+ -+ switch (currentcmd->cmdid) { -+ case CMDID_SET_TXPOWEROWER_LEVEL: -+ rtl92s_phy_set_txpower(hw, channel); -+ break; -+ case CMDID_WRITEPORT_ULONG: -+ rtl_write_dword(rtlpriv, currentcmd->para1, -+ currentcmd->para2); -+ break; -+ case CMDID_WRITEPORT_USHORT: -+ rtl_write_word(rtlpriv, currentcmd->para1, -+ (u16)currentcmd->para2); -+ break; -+ case CMDID_WRITEPORT_UCHAR: -+ rtl_write_byte(rtlpriv, currentcmd->para1, -+ (u8)currentcmd->para2); -+ break; -+ case CMDID_RF_WRITEREG: -+ for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { -+ rtlphy->rfreg_chnlval[rfpath] = -+ ((rtlphy->rfreg_chnlval[rfpath] & -+ 0xfffffc00) | currentcmd->para2); -+ rtl_set_rfreg(hw, (enum radio_path)rfpath, -+ currentcmd->para1, -+ RFREG_OFFSET_MASK, -+ rtlphy->rfreg_chnlval[rfpath]); -+ } -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ break; -+ } -+ -+ break; -+ } while (true); -+ -+ (*delay) = currentcmd->msdelay; -+ (*step)++; -+ return false; -+} -+ -+u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u32 delay; -+ bool ret; -+ -+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, -+ ("switch to channel%d\n", -+ rtlphy->current_channel)); -+ -+ if (rtlphy->sw_chnl_inprogress) -+ return 0; -+ -+ if (rtlphy->set_bwmode_inprogress) -+ return 0; -+ -+ if (is_hal_stop(rtlhal)) -+ return 0; -+ -+ rtlphy->sw_chnl_inprogress = true; -+ rtlphy->sw_chnl_stage = 0; -+ rtlphy->sw_chnl_step = 0; -+ -+ do { -+ if (!rtlphy->sw_chnl_inprogress) -+ break; -+ -+ ret = _rtl92s_phy_sw_chnl_step_by_step(hw, -+ rtlphy->current_channel, -+ &rtlphy->sw_chnl_stage, -+ &rtlphy->sw_chnl_step, &delay); -+ if (!ret) { -+ if (delay > 0) -+ mdelay(delay); -+ else -+ continue; -+ } else { -+ rtlphy->sw_chnl_inprogress = false; -+ } -+ break; -+ } while (true); -+ -+ rtlphy->sw_chnl_inprogress = false; -+ -+ RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); -+ -+ return 1; -+} -+ -+static void _rtl92se_phy_set_rf_sleep(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u8 u1btmp; -+ -+ u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); -+ u1btmp |= BIT(0); -+ -+ rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); -+ rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); -+ rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); -+ rtl_write_word(rtlpriv, CMDR, 0x57FC); -+ udelay(100); -+ -+ rtl_write_word(rtlpriv, CMDR, 0x77FC); -+ rtl_write_byte(rtlpriv, PHY_CCA, 0x0); -+ udelay(10); -+ -+ rtl_write_word(rtlpriv, CMDR, 0x37FC); -+ udelay(10); -+ -+ rtl_write_word(rtlpriv, CMDR, 0x77FC); -+ udelay(10); -+ -+ rtl_write_word(rtlpriv, CMDR, 0x57FC); -+ -+ /* we should chnge GPIO to input mode -+ * this will drop away current about 25mA*/ -+ rtl8192se_gpiobit3_cfg_inputmode(hw); -+} -+ -+bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, -+ enum rf_pwrstate rfpwr_state) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ bool bresult = true; -+ u8 i, queue_id; -+ struct rtl8192_tx_ring *ring = NULL; -+ -+ if (rfpwr_state == ppsc->rfpwr_state) -+ return false; -+ -+ ppsc->set_rfpowerstate_inprogress = true; -+ -+ switch (rfpwr_state) { -+ case ERFON:{ -+ if ((ppsc->rfpwr_state == ERFOFF) && -+ RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { -+ -+ bool rtstatus; -+ u32 InitializeCount = 0; -+ do { -+ InitializeCount++; -+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, -+ ("IPS Set eRf nic enable\n")); -+ rtstatus = rtl_ps_enable_nic(hw); -+ } while ((rtstatus != true) && -+ (InitializeCount < 10)); -+ -+ RT_CLEAR_PS_LEVEL(ppsc, -+ RT_RF_OFF_LEVL_HALT_NIC); -+ } else { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, -+ ("awake, sleeped:%d ms " -+ "state_inap:%x\n", -+ jiffies_to_msecs(jiffies - -+ ppsc->last_sleep_jiffies), -+ rtlpriv->psc.state_inap)); -+ ppsc->last_awake_jiffies = jiffies; -+ rtl_write_word(rtlpriv, CMDR, 0x37FC); -+ rtl_write_byte(rtlpriv, TXPAUSE, 0x00); -+ rtl_write_byte(rtlpriv, PHY_CCA, 0x3); -+ } -+ -+ if (mac->link_state == MAC80211_LINKED) -+ rtlpriv->cfg->ops->led_control(hw, -+ LED_CTL_LINK); -+ else -+ rtlpriv->cfg->ops->led_control(hw, -+ LED_CTL_NO_LINK); -+ break; -+ } -+ case ERFOFF:{ -+ if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { -+ RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, -+ ("IPS Set eRf nic disable\n")); -+ rtl_ps_disable_nic(hw); -+ RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); -+ } else { -+ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) -+ rtlpriv->cfg->ops->led_control(hw, -+ LED_CTL_NO_LINK); -+ else -+ rtlpriv->cfg->ops->led_control(hw, -+ LED_CTL_POWER_OFF); -+ } -+ break; -+ } -+ case ERFSLEEP: -+ if (ppsc->rfpwr_state == ERFOFF) -+ break; -+ -+ for (queue_id = 0, i = 0; -+ queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { -+ ring = &pcipriv->dev.tx_ring[queue_id]; -+ if (skb_queue_len(&ring->queue) == 0 || -+ queue_id == BEACON_QUEUE) { -+ queue_id++; -+ continue; -+ } else { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -+ ("eRf Off/Sleep: " -+ "%d times TcbBusyQueue[%d] = " -+ "%d before doze!\n", -+ (i + 1), queue_id, -+ skb_queue_len(&ring->queue))); -+ -+ udelay(10); -+ i++; -+ } -+ -+ if (i >= MAX_DOZE_WAITING_TIMES_9x) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -+ ("\nERFOFF: %d times" -+ "TcbBusyQueue[%d] = %d !\n", -+ MAX_DOZE_WAITING_TIMES_9x, -+ queue_id, -+ skb_queue_len(&ring->queue))); -+ break; -+ } -+ } -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, -+ ("Set ERFSLEEP awaked:%d ms\n", -+ jiffies_to_msecs(jiffies - -+ ppsc->last_awake_jiffies))); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, -+ ("sleep awaked:%d ms " -+ "state_inap:%x\n", jiffies_to_msecs(jiffies - -+ ppsc->last_awake_jiffies), -+ rtlpriv->psc.state_inap)); -+ ppsc->last_sleep_jiffies = jiffies; -+ _rtl92se_phy_set_rf_sleep(hw); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("switch case not process\n")); -+ bresult = false; -+ break; -+ } -+ -+ if (bresult) -+ ppsc->rfpwr_state = rfpwr_state; -+ -+ ppsc->set_rfpowerstate_inprogress = false; -+ -+ return bresult; -+} -+ -+static bool _rtl92s_phy_config_rfpa_bias_current(struct ieee80211_hw *hw, -+ enum radio_path rfpath) -+{ -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ bool rtstatus = true; -+ u32 tmpval = 0; -+ -+ /* If inferiority IC, we have to increase the PA bias current */ -+ if (rtlhal->ic_class != IC_INFERIORITY_A) { -+ tmpval = rtl92s_phy_query_rf_reg(hw, rfpath, RF_IPA, 0xf); -+ rtl92s_phy_set_rf_reg(hw, rfpath, RF_IPA, 0xf, tmpval + 1); -+ } -+ -+ return rtstatus; -+} -+ -+static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, -+ u32 reg_addr, u32 bitmask, u32 data) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ if (reg_addr == RTXAGC_RATE18_06) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = -+ data; -+ if (reg_addr == RTXAGC_RATE54_24) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = -+ data; -+ if (reg_addr == RTXAGC_CCK_MCS32) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = -+ data; -+ if (reg_addr == RTXAGC_MCS03_MCS00) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = -+ data; -+ if (reg_addr == RTXAGC_MCS07_MCS04) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = -+ data; -+ if (reg_addr == RTXAGC_MCS11_MCS08) -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = -+ data; -+ if (reg_addr == RTXAGC_MCS15_MCS12) { -+ rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = -+ data; -+ rtlphy->pwrgroup_cnt++; -+ } -+} -+ -+static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ /*RF Interface Sowrtware Control */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; -+ rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; -+ rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; -+ rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; -+ -+ /* RF Interface Readback Value */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; -+ rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; -+ rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; -+ rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; -+ -+ /* RF Interface Output (and Enable) */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_C].rfintfo = RFPGA0_XC_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_D].rfintfo = RFPGA0_XD_RFINTERFACEOE; -+ -+ /* RF Interface (Output and) Enable */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_C].rfintfe = RFPGA0_XC_RFINTERFACEOE; -+ rtlphy->phyreg_def[RF90_PATH_D].rfintfe = RFPGA0_XD_RFINTERFACEOE; -+ -+ /* Addr of LSSI. Wirte RF register by driver */ -+ rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = -+ RFPGA0_XA_LSSIPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = -+ RFPGA0_XB_LSSIPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_C].rf3wire_offset = -+ RFPGA0_XC_LSSIPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_D].rf3wire_offset = -+ RFPGA0_XD_LSSIPARAMETER; -+ -+ /* RF parameter */ -+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; -+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; -+ -+ /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ -+ rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; -+ rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; -+ rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; -+ rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; -+ -+ /* Tranceiver A~D HSSI Parameter-1 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; -+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; -+ rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para1 = RFPGA0_XC_HSSIPARAMETER1; -+ rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para1 = RFPGA0_XD_HSSIPARAMETER1; -+ -+ /* Tranceiver A~D HSSI Parameter-2 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; -+ rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; -+ rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para2 = RFPGA0_XC_HSSIPARAMETER2; -+ rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; -+ -+ /* RF switch Control */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = -+ RFPGA0_XAB_SWITCHCONTROL; -+ rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = -+ RFPGA0_XAB_SWITCHCONTROL; -+ rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = -+ RFPGA0_XCD_SWITCHCONTROL; -+ rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = -+ RFPGA0_XCD_SWITCHCONTROL; -+ -+ /* AGC control 1 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; -+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; -+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; -+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; -+ -+ /* AGC control 2 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; -+ rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; -+ rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; -+ rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; -+ -+ /* RX AFE control 1 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = -+ ROFDM0_XARXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = -+ ROFDM0_XBRXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = -+ ROFDM0_XCRXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = -+ ROFDM0_XDRXIQIMBALANCE; -+ -+ /* RX AFE control 1 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; -+ rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; -+ rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; -+ rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; -+ -+ /* Tx AFE control 1 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = -+ ROFDM0_XATXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = -+ ROFDM0_XBTXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = -+ ROFDM0_XCTXIQIMBALANCE; -+ rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = -+ ROFDM0_XDTXIQIMBALANCE; -+ -+ /* Tx AFE control 2 */ -+ rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; -+ rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; -+ rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; -+ rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; -+ -+ /* Tranceiver LSSI Readback */ -+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = -+ RFPGA0_XA_LSSIREADBACK; -+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = -+ RFPGA0_XB_LSSIREADBACK; -+ rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = -+ RFPGA0_XC_LSSIREADBACK; -+ rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = -+ RFPGA0_XD_LSSIREADBACK; -+ -+ /* Tranceiver LSSI Readback PI mode */ -+ rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = -+ TRANSCEIVERA_HSPI_READBACK; -+ rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = -+ TRANSCEIVERB_HSPI_READBACK; -+} -+ -+ -+static bool _rtl92s_phy_config_bb(struct ieee80211_hw *hw, u8 configtype) -+{ -+ int i; -+ u32 *phy_reg_table; -+ u32 *agc_table; -+ u16 phy_reg_len, agc_len; -+ -+ agc_len = AGCTAB_ARRAYLENGTH; -+ agc_table = rtl8192seagctab_array; -+ /* Default RF_type: 2T2R */ -+ phy_reg_len = PHY_REG_2T2RARRAYLENGTH; -+ phy_reg_table = rtl8192sephy_reg_2t2rarray; -+ -+ if (configtype == BASEBAND_CONFIG_PHY_REG) { -+ for (i = 0; i < phy_reg_len; i = i + 2) { -+ if (phy_reg_table[i] == 0xfe) -+ mdelay(50); -+ else if (phy_reg_table[i] == 0xfd) -+ mdelay(5); -+ else if (phy_reg_table[i] == 0xfc) -+ mdelay(1); -+ else if (phy_reg_table[i] == 0xfb) -+ udelay(50); -+ else if (phy_reg_table[i] == 0xfa) -+ udelay(5); -+ else if (phy_reg_table[i] == 0xf9) -+ udelay(1); -+ -+ /* Add delay for ECS T20 & LG malow platform, */ -+ udelay(1); -+ -+ rtl92s_phy_set_bb_reg(hw, phy_reg_table[i], MASKDWORD, -+ phy_reg_table[i + 1]); -+ } -+ } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { -+ for (i = 0; i < agc_len; i = i + 2) { -+ rtl92s_phy_set_bb_reg(hw, agc_table[i], MASKDWORD, -+ agc_table[i + 1]); -+ -+ /* Add delay for ECS T20 & LG malow platform */ -+ udelay(1); -+ } -+ } -+ -+ return true; -+} -+ -+static bool _rtl92s_phy_set_bb_to_diff_rf(struct ieee80211_hw *hw, -+ u8 configtype) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u32 *phy_regarray2xtxr_table; -+ u16 phy_regarray2xtxr_len; -+ int i; -+ -+ if (rtlphy->rf_type == RF_1T1R) { -+ phy_regarray2xtxr_table = rtl8192sephy_changeto_1t1rarray; -+ phy_regarray2xtxr_len = PHY_CHANGETO_1T1RARRAYLENGTH; -+ } else if (rtlphy->rf_type == RF_1T2R) { -+ phy_regarray2xtxr_table = rtl8192sephy_changeto_1t2rarray; -+ phy_regarray2xtxr_len = PHY_CHANGETO_1T2RARRAYLENGTH; -+ } else { -+ return false; -+ } -+ -+ if (configtype == BASEBAND_CONFIG_PHY_REG) { -+ for (i = 0; i < phy_regarray2xtxr_len; i = i + 3) { -+ if (phy_regarray2xtxr_table[i] == 0xfe) -+ mdelay(50); -+ else if (phy_regarray2xtxr_table[i] == 0xfd) -+ mdelay(5); -+ else if (phy_regarray2xtxr_table[i] == 0xfc) -+ mdelay(1); -+ else if (phy_regarray2xtxr_table[i] == 0xfb) -+ udelay(50); -+ else if (phy_regarray2xtxr_table[i] == 0xfa) -+ udelay(5); -+ else if (phy_regarray2xtxr_table[i] == 0xf9) -+ udelay(1); -+ -+ rtl92s_phy_set_bb_reg(hw, phy_regarray2xtxr_table[i], -+ phy_regarray2xtxr_table[i + 1], -+ phy_regarray2xtxr_table[i + 2]); -+ } -+ } -+ -+ return true; -+} -+ -+static bool _rtl92s_phy_config_bb_with_pg(struct ieee80211_hw *hw, -+ u8 configtype) -+{ -+ int i; -+ u32 *phy_table_pg; -+ u16 phy_pg_len; -+ -+ phy_pg_len = PHY_REG_ARRAY_PGLENGTH; -+ phy_table_pg = rtl8192sephy_reg_array_pg; -+ -+ if (configtype == BASEBAND_CONFIG_PHY_REG) { -+ for (i = 0; i < phy_pg_len; i = i + 3) { -+ if (phy_table_pg[i] == 0xfe) -+ mdelay(50); -+ else if (phy_table_pg[i] == 0xfd) -+ mdelay(5); -+ else if (phy_table_pg[i] == 0xfc) -+ mdelay(1); -+ else if (phy_table_pg[i] == 0xfb) -+ udelay(50); -+ else if (phy_table_pg[i] == 0xfa) -+ udelay(5); -+ else if (phy_table_pg[i] == 0xf9) -+ udelay(1); -+ -+ _rtl92s_store_pwrindex_diffrate_offset(hw, -+ phy_table_pg[i], -+ phy_table_pg[i + 1], -+ phy_table_pg[i + 2]); -+ rtl92s_phy_set_bb_reg(hw, phy_table_pg[i], -+ phy_table_pg[i + 1], -+ phy_table_pg[i + 2]); -+ } -+ } -+ -+ return true; -+} -+ -+static bool _rtl92s_phy_bb_config_parafile(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)); -+ bool rtstatus = true; -+ -+ /* 1. Read PHY_REG.TXT BB INIT!! */ -+ /* We will separate as 1T1R/1T2R/1T2R_GREEN/2T2R */ -+ if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_2T2R || -+ rtlphy->rf_type == RF_1T1R || rtlphy->rf_type == RF_2T2R_GREEN) { -+ rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_PHY_REG); -+ -+ if (rtlphy->rf_type != RF_2T2R && -+ rtlphy->rf_type != RF_2T2R_GREEN) -+ /* so we should reconfig BB reg with the right -+ * PHY parameters. */ -+ rtstatus = _rtl92s_phy_set_bb_to_diff_rf(hw, -+ BASEBAND_CONFIG_PHY_REG); -+ } else { -+ rtstatus = false; -+ } -+ -+ if (rtstatus != true) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("Write BB Reg Fail!!")); -+ goto phy_BB8190_Config_ParaFile_Fail; -+ } -+ -+ /* 2. If EEPROM or EFUSE autoload OK, We must config by -+ * PHY_REG_PG.txt */ -+ if (rtlefuse->autoload_failflag == false) { -+ rtlphy->pwrgroup_cnt = 0; -+ -+ rtstatus = _rtl92s_phy_config_bb_with_pg(hw, -+ BASEBAND_CONFIG_PHY_REG); -+ } -+ if (rtstatus != true) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("_rtl92s_phy_bb_config_parafile(): " -+ "BB_PG Reg Fail!!")); -+ goto phy_BB8190_Config_ParaFile_Fail; -+ } -+ -+ /* 3. BB AGC table Initialization */ -+ rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); -+ -+ if (rtstatus != true) { -+ printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): " -+ "AGC Table Fail\n"); -+ goto phy_BB8190_Config_ParaFile_Fail; -+ } -+ -+ /* Check if the CCK HighPower is turned ON. */ -+ /* This is used to calculate PWDB. */ -+ rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, -+ RFPGA0_XA_HSSIPARAMETER2, 0x200)); -+ -+phy_BB8190_Config_ParaFile_Fail: -+ return rtstatus; -+} -+ -+u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ int i; -+ bool rtstatus = true; -+ u32 *radio_a_table; -+ u32 *radio_b_table; -+ u16 radio_a_tblen, radio_b_tblen; -+ -+ radio_a_tblen = RADIOA_1T_ARRAYLENGTH; -+ radio_a_table = rtl8192seradioa_1t_array; -+ -+ /* Using Green mode array table for RF_2T2R_GREEN */ -+ if (rtlphy->rf_type == RF_2T2R_GREEN) { -+ radio_b_table = rtl8192seradiob_gm_array; -+ radio_b_tblen = RADIOB_GM_ARRAYLENGTH; -+ } else { -+ radio_b_table = rtl8192seradiob_array; -+ radio_b_tblen = RADIOB_ARRAYLENGTH; -+ } -+ -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Radio No %x\n", rfpath)); -+ rtstatus = true; -+ -+ switch (rfpath) { -+ case RF90_PATH_A: -+ for (i = 0; i < radio_a_tblen; i = i + 2) { -+ if (radio_a_table[i] == 0xfe) -+ /* Delay specific ms. Only RF configuration -+ * requires delay. */ -+ mdelay(50); -+ else if (radio_a_table[i] == 0xfd) -+ mdelay(5); -+ else if (radio_a_table[i] == 0xfc) -+ mdelay(1); -+ else if (radio_a_table[i] == 0xfb) -+ udelay(50); -+ else if (radio_a_table[i] == 0xfa) -+ udelay(5); -+ else if (radio_a_table[i] == 0xf9) -+ udelay(1); -+ else -+ rtl92s_phy_set_rf_reg(hw, rfpath, -+ radio_a_table[i], -+ MASK20BITS, -+ radio_a_table[i + 1]); -+ -+ /* Add delay for ECS T20 & LG malow platform */ -+ udelay(1); -+ } -+ -+ /* PA Bias current for inferiority IC */ -+ _rtl92s_phy_config_rfpa_bias_current(hw, rfpath); -+ break; -+ case RF90_PATH_B: -+ for (i = 0; i < radio_b_tblen; i = i + 2) { -+ if (radio_b_table[i] == 0xfe) -+ /* Delay specific ms. Only RF configuration -+ * requires delay.*/ -+ mdelay(50); -+ else if (radio_b_table[i] == 0xfd) -+ mdelay(5); -+ else if (radio_b_table[i] == 0xfc) -+ mdelay(1); -+ else if (radio_b_table[i] == 0xfb) -+ udelay(50); -+ else if (radio_b_table[i] == 0xfa) -+ udelay(5); -+ else if (radio_b_table[i] == 0xf9) -+ udelay(1); -+ else -+ rtl92s_phy_set_rf_reg(hw, rfpath, -+ radio_b_table[i], -+ MASK20BITS, -+ radio_b_table[i + 1]); -+ -+ /* Add delay for ECS T20 & LG malow platform */ -+ udelay(1); -+ } -+ break; -+ case RF90_PATH_C: -+ ; -+ break; -+ case RF90_PATH_D: -+ ; -+ break; -+ default: -+ break; -+ } -+ -+ return rtstatus; -+} -+ -+ -+bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 i; -+ u32 arraylength; -+ u32 *ptraArray; -+ -+ arraylength = MAC_2T_ARRAYLENGTH; -+ ptraArray = rtl8192semac_2t_array; -+ -+ for (i = 0; i < arraylength; i = i + 2) -+ rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); -+ -+ return true; -+} -+ -+ -+bool rtl92s_phy_bb_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ bool rtstatus = true; -+ u8 pathmap, index, rf_num = 0; -+ u8 path1, path2; -+ -+ _rtl92s_phy_init_register_definition(hw); -+ -+ /* Config BB and AGC */ -+ rtstatus = _rtl92s_phy_bb_config_parafile(hw); -+ -+ -+ /* Check BB/RF confiuration setting. */ -+ /* We only need to configure RF which is turned on. */ -+ path1 = (u8)(rtl92s_phy_query_bb_reg(hw, RFPGA0_TXINFO, 0xf)); -+ mdelay(10); -+ path2 = (u8)(rtl92s_phy_query_bb_reg(hw, ROFDM0_TRXPATHENABLE, 0xf)); -+ pathmap = path1 | path2; -+ -+ rtlphy->rf_pathmap = pathmap; -+ for (index = 0; index < 4; index++) { -+ if ((pathmap >> index) & 0x1) -+ rf_num++; -+ } -+ -+ if ((rtlphy->rf_type == RF_1T1R && rf_num != 1) || -+ (rtlphy->rf_type == RF_1T2R && rf_num != 2) || -+ (rtlphy->rf_type == RF_2T2R && rf_num != 2) || -+ (rtlphy->rf_type == RF_2T2R_GREEN && rf_num != 2)) { -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("RF_Type(%x) does not match " -+ "RF_Num(%x)!!\n", rtlphy->rf_type, rf_num)); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, -+ ("path1 0x%x, path2 0x%x, pathmap " -+ "0x%x\n", path1, path2, pathmap)); -+ } -+ -+ return rtstatus; -+} -+ -+bool rtl92s_phy_rf_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ /* Initialize general global value */ -+ if (rtlphy->rf_type == RF_1T1R) -+ rtlphy->num_total_rfpath = 1; -+ else -+ rtlphy->num_total_rfpath = 2; -+ -+ /* Config BB and RF */ -+ return rtl92s_phy_rf6052_config(hw); -+} -+ -+void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ /* read rx initial gain */ -+ rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, -+ ROFDM0_XAAGCCORE1, MASKBYTE0); -+ rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, -+ ROFDM0_XBAGCCORE1, MASKBYTE0); -+ rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, -+ ROFDM0_XCAGCCORE1, MASKBYTE0); -+ rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, -+ ROFDM0_XDAGCCORE1, MASKBYTE0); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Default initial gain " -+ "(c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", -+ rtlphy->default_initialgain[0], -+ rtlphy->default_initialgain[1], -+ rtlphy->default_initialgain[2], -+ rtlphy->default_initialgain[3])); -+ -+ /* read framesync */ -+ rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0); -+ rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, -+ MASKDWORD); -+ RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, -+ ("Default framesync (0x%x) = 0x%x\n", -+ ROFDM0_RXDETECTOR3, rtlphy->framesync)); -+ -+} -+ -+static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, -+ u8 *cckpowerlevel, u8 *ofdmpowerLevel) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u8 index = (channel - 1); -+ -+ /* 1. CCK */ -+ /* RF-A */ -+ cckpowerlevel[0] = rtlefuse->txpwrlevel_cck[0][index]; -+ /* RF-B */ -+ cckpowerlevel[1] = rtlefuse->txpwrlevel_cck[1][index]; -+ -+ /* 2. OFDM for 1T or 2T */ -+ if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { -+ /* Read HT 40 OFDM TX power */ -+ ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; -+ ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; -+ } else if (rtlphy->rf_type == RF_2T2R) { -+ /* Read HT 40 OFDM TX power */ -+ ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; -+ ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; -+ } -+} -+ -+static void _rtl92s_phy_ccxpower_indexcheck(struct ieee80211_hw *hw, -+ u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; -+ rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; -+} -+ -+void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ /* [0]:RF-A, [1]:RF-B */ -+ u8 cckpowerlevel[2], ofdmpowerLevel[2]; -+ -+ if (rtlefuse->txpwr_fromeprom == false) -+ return; -+ -+ /* Mainly we use RF-A Tx Power to write the Tx Power registers, -+ * but the RF-B Tx Power must be calculated by the antenna diff. -+ * So we have to rewrite Antenna gain offset register here. -+ * Please refer to BB register 0x80c -+ * 1. For CCK. -+ * 2. For OFDM 1T or 2T */ -+ _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], -+ &ofdmpowerLevel[0]); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Channel-%d, cckPowerLevel (A / B) = " -+ "0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", -+ channel, cckpowerlevel[0], cckpowerlevel[1], -+ ofdmpowerLevel[0], ofdmpowerLevel[1])); -+ -+ _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], -+ &ofdmpowerLevel[0]); -+ -+ rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); -+ rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); -+ -+} -+ -+void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u16 pollingcnt = 10000; -+ u32 tmpvalue; -+ -+ /* Make sure that CMD IO has be accepted by FW. */ -+ do { -+ udelay(10); -+ -+ tmpvalue = rtl_read_dword(rtlpriv, WFM5); -+ if (tmpvalue == 0) -+ break; -+ } while (--pollingcnt); -+ -+ if (pollingcnt == 0) -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Set FW Cmd fail!!\n")); -+} -+ -+ -+static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u32 input, current_aid = 0; -+ -+ if (is_hal_stop(rtlhal)) -+ return; -+ -+ /* We re-map RA related CMD IO to combinational ones */ -+ /* if FW version is v.52 or later. */ -+ switch (rtlhal->current_fwcmd_io) { -+ case FW_CMD_RA_REFRESH_N: -+ rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB; -+ break; -+ case FW_CMD_RA_REFRESH_BG: -+ rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB; -+ break; -+ default: -+ break; -+ } -+ -+ switch (rtlhal->current_fwcmd_io) { -+ case FW_CMD_RA_RESET: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_RESET\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_RA_ACTIVE: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_ACTIVE\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_RA_REFRESH_N: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_REFRESH_N\n")); -+ input = FW_RA_REFRESH; -+ rtl_write_dword(rtlpriv, WFM5, input); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ rtl_write_dword(rtlpriv, WFM5, FW_RA_ENABLE_RSSI_MASK); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_RA_REFRESH_BG: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_REFRESH_BG\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_RA_REFRESH_N_COMB: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_REFRESH_N_COMB\n")); -+ input = FW_RA_IOT_N_COMB; -+ rtl_write_dword(rtlpriv, WFM5, input); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_RA_REFRESH_BG_COMB: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_RA_REFRESH_BG_COMB\n")); -+ input = FW_RA_IOT_BG_COMB; -+ rtl_write_dword(rtlpriv, WFM5, input); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_IQK_ENABLE: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_IQK_ENABLE\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_PAUSE_DM_BY_SCAN: -+ /* Lower initial gain */ -+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); -+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); -+ /* CCA threshold */ -+ rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); -+ break; -+ case FW_CMD_RESUME_DM_BY_SCAN: -+ /* CCA threshold */ -+ rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); -+ rtl92s_phy_set_txpower(hw, rtlphy->current_channel); -+ break; -+ case FW_CMD_HIGH_PWR_DISABLE: -+ if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) -+ break; -+ -+ /* Lower initial gain */ -+ rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); -+ rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); -+ /* CCA threshold */ -+ rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); -+ break; -+ case FW_CMD_HIGH_PWR_ENABLE: -+ if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || -+ (rtlpriv->dm.dynamic_txpower_enable == true)) -+ break; -+ -+ /* CCA threshold */ -+ rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); -+ break; -+ case FW_CMD_LPS_ENTER: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_LPS_ENTER\n")); -+ current_aid = rtlpriv->mac80211.assoc_id; -+ rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER | -+ ((current_aid | 0xc000) << 8))); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ /* FW set TXOP disable here, so disable EDCA -+ * turbo mode until driver leave LPS */ -+ break; -+ case FW_CMD_LPS_LEAVE: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_LPS_LEAVE\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_ADD_A2_ENTRY: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, -+ ("FW_CMD_ADD_A2_ENTRY\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ case FW_CMD_CTRL_DM_BY_DRIVER: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("FW_CMD_CTRL_DM_BY_DRIVER\n")); -+ rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER); -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ break; -+ -+ default: -+ break; -+ } -+ -+ rtl92s_phy_chk_fwcmd_iodone(hw); -+ -+ /* Clear FW CMD operation flag. */ -+ rtlhal->set_fwcmd_inprogress = false; -+} -+ -+bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); -+ u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); -+ bool bPostProcessing = false; -+ -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", -+ fw_cmdio, rtlhal->set_fwcmd_inprogress)); -+ -+ do { -+ /* We re-map to combined FW CMD ones if firmware version */ -+ /* is v.53 or later. */ -+ switch (fw_cmdio) { -+ case FW_CMD_RA_REFRESH_N: -+ fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; -+ break; -+ case FW_CMD_RA_REFRESH_BG: -+ fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; -+ break; -+ default: -+ break; -+ } -+ -+ /* If firmware version is v.62 or later, -+ * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */ -+ if (hal_get_firmwareversion(rtlpriv) >= 0x3E) { -+ if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER) -+ fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW; -+ } -+ -+ -+ /* We shall revise all FW Cmd IO into Reg0x364 -+ * DM map table in the future. */ -+ switch (fw_cmdio) { -+ case FW_CMD_RA_INIT: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("RA init!!\n")); -+ fw_cmdmap |= FW_RA_INIT_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ /* Clear control flag to sync with FW. */ -+ FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL); -+ break; -+ case FW_CMD_DIG_DISABLE: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("Set DIG disable!!\n")); -+ fw_cmdmap &= ~FW_DIG_ENABLE_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ case FW_CMD_DIG_ENABLE: -+ case FW_CMD_DIG_RESUME: -+ if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) { -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("Set DIG enable or resume!!\n")); -+ fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ } -+ break; -+ case FW_CMD_DIG_HALT: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("Set DIG halt!!\n")); -+ fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ case FW_CMD_TXPWR_TRACK_THERMAL: { -+ u8 thermalval = 0; -+ fw_cmdmap |= FW_PWR_TRK_CTL; -+ -+ /* Clear FW parameter in terms of thermal parts. */ -+ fw_param &= FW_PWR_TRK_PARAM_CLR; -+ -+ thermalval = rtlpriv->dm.thermalvalue; -+ fw_param |= ((thermalval << 24) | -+ (rtlefuse->thermalmeter[0] << 16)); -+ -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("Set TxPwr tracking!! " -+ "FwCmdMap(%#x), FwParam(%#x)\n", -+ fw_cmdmap, fw_param)); -+ -+ FW_CMD_PARA_SET(rtlpriv, fw_param); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ -+ /* Clear control flag to sync with FW. */ -+ FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); -+ } -+ break; -+ /* The following FW CMDs are only compatible to -+ * v.53 or later. */ -+ case FW_CMD_RA_REFRESH_N_COMB: -+ fw_cmdmap |= FW_RA_N_CTL; -+ -+ /* Clear RA BG mode control. */ -+ fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL); -+ -+ /* Clear FW parameter in terms of RA parts. */ -+ fw_param &= FW_RA_PARAM_CLR; -+ -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("[FW CMD] [New Version] " -+ "Set RA/IOT Comb in n mode!! FwCmdMap(%#x), " -+ "FwParam(%#x)\n", fw_cmdmap, fw_param)); -+ -+ FW_CMD_PARA_SET(rtlpriv, fw_param); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ -+ /* Clear control flag to sync with FW. */ -+ FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL); -+ break; -+ case FW_CMD_RA_REFRESH_BG_COMB: -+ fw_cmdmap |= FW_RA_BG_CTL; -+ -+ /* Clear RA n-mode control. */ -+ fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL); -+ /* Clear FW parameter in terms of RA parts. */ -+ fw_param &= FW_RA_PARAM_CLR; -+ -+ FW_CMD_PARA_SET(rtlpriv, fw_param); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ -+ /* Clear control flag to sync with FW. */ -+ FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL); -+ break; -+ case FW_CMD_IQK_ENABLE: -+ fw_cmdmap |= FW_IQK_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ /* Clear control flag to sync with FW. */ -+ FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL); -+ break; -+ /* The following FW CMD is compatible to v.62 or later. */ -+ case FW_CMD_CTRL_DM_BY_DRIVER_NEW: -+ fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ /* The followed FW Cmds needs post-processing later. */ -+ case FW_CMD_RESUME_DM_BY_SCAN: -+ fw_cmdmap |= (FW_DIG_ENABLE_CTL | -+ FW_HIGH_PWR_ENABLE_CTL | -+ FW_SS_CTL); -+ -+ if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE || -+ !digtable.dig_enable_flag) -+ fw_cmdmap &= ~FW_DIG_ENABLE_CTL; -+ -+ if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || -+ (rtlpriv->dm.dynamic_txpower_enable == true)) -+ fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; -+ -+ if ((digtable.dig_ext_port_stage == -+ DIG_EXT_PORT_STAGE_0) || -+ (digtable.dig_ext_port_stage == -+ DIG_EXT_PORT_STAGE_1)) -+ fw_cmdmap &= ~FW_DIG_ENABLE_CTL; -+ -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ bPostProcessing = true; -+ break; -+ case FW_CMD_PAUSE_DM_BY_SCAN: -+ fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | -+ FW_HIGH_PWR_ENABLE_CTL | -+ FW_SS_CTL); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ bPostProcessing = true; -+ break; -+ case FW_CMD_HIGH_PWR_DISABLE: -+ fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ bPostProcessing = true; -+ break; -+ case FW_CMD_HIGH_PWR_ENABLE: -+ if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && -+ (rtlpriv->dm.dynamic_txpower_enable != true)) { -+ fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | -+ FW_SS_CTL); -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ bPostProcessing = true; -+ } -+ break; -+ case FW_CMD_DIG_MODE_FA: -+ fw_cmdmap |= FW_FA_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ case FW_CMD_DIG_MODE_SS: -+ fw_cmdmap &= ~FW_FA_CTL; -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ case FW_CMD_PAPE_CONTROL: -+ RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, -+ ("[FW CMD] Set PAPE Control\n")); -+ fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW; -+ -+ FW_CMD_IO_SET(rtlpriv, fw_cmdmap); -+ break; -+ default: -+ /* Pass to original FW CMD processing callback -+ * routine. */ -+ bPostProcessing = true; -+ break; -+ } -+ } while (false); -+ -+ /* We shall post processing these FW CMD if -+ * variable bPostProcessing is set. */ -+ if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) { -+ rtlhal->set_fwcmd_inprogress = true; -+ /* Update current FW Cmd for callback use. */ -+ rtlhal->current_fwcmd_io = fw_cmdio; -+ } else { -+ return false; -+ } -+ -+ _rtl92s_phy_set_fwcmd_io(hw); -+ return true; -+} -+ -+static void _rtl92s_phy_check_ephy_switchready(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 delay = 100; -+ u8 regu1; -+ -+ regu1 = rtl_read_byte(rtlpriv, 0x554); -+ while ((regu1 & BIT(5)) && (delay > 0)) { -+ regu1 = rtl_read_byte(rtlpriv, 0x554); -+ delay--; -+ /* We delay only 50us to prevent -+ * being scheduled out. */ -+ udelay(50); -+ } -+} -+ -+void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -+ -+ /* The way to be capable to switch clock request -+ * when the PG setting does not support clock request. -+ * This is the backdoor solution to switch clock -+ * request before ASPM or D3. */ -+ rtl_write_dword(rtlpriv, 0x540, 0x73c11); -+ rtl_write_dword(rtlpriv, 0x548, 0x2407c); -+ -+ /* Switch EPHY parameter!!!! */ -+ rtl_write_word(rtlpriv, 0x550, 0x1000); -+ rtl_write_byte(rtlpriv, 0x554, 0x20); -+ _rtl92s_phy_check_ephy_switchready(hw); -+ -+ rtl_write_word(rtlpriv, 0x550, 0xa0eb); -+ rtl_write_byte(rtlpriv, 0x554, 0x3e); -+ _rtl92s_phy_check_ephy_switchready(hw); -+ -+ rtl_write_word(rtlpriv, 0x550, 0xff80); -+ rtl_write_byte(rtlpriv, 0x554, 0x39); -+ _rtl92s_phy_check_ephy_switchready(hw); -+ -+ /* Delay L1 enter time */ -+ if (ppsc->support_aspm && !ppsc->support_backdoor) -+ rtl_write_byte(rtlpriv, 0x560, 0x40); -+ else -+ rtl_write_byte(rtlpriv, 0x560, 0x00); -+ -+} -+ -+void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8)); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/phy.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/phy.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/phy.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/phy.h 2011-05-05 23:29:49.278487693 +0200 -@@ -0,0 +1,101 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __RTL92S_PHY_H__ -+#define __RTL92S_PHY_H__ -+ -+#define MAX_TXPWR_IDX_NMODE_92S 63 -+#define MAX_DOZE_WAITING_TIMES_9x 64 -+ -+/* Channel switch:The size of -+ * command tables for switch channel */ -+#define MAX_PRECMD_CNT 16 -+#define MAX_RFDEPENDCMD_CNT 16 -+#define MAX_POSTCMD_CNT 16 -+ -+#define RF90_PATH_MAX 4 -+ -+enum version_8192s { -+ VERSION_8192S_ACUT, -+ VERSION_8192S_BCUT, -+ VERSION_8192S_CCUT -+}; -+ -+enum swchnlcmd_id { -+ CMDID_END, -+ CMDID_SET_TXPOWEROWER_LEVEL, -+ CMDID_BBREGWRITE10, -+ CMDID_WRITEPORT_ULONG, -+ CMDID_WRITEPORT_USHORT, -+ CMDID_WRITEPORT_UCHAR, -+ CMDID_RF_WRITEREG, -+}; -+ -+struct swchnlcmd { -+ enum swchnlcmd_id cmdid; -+ u32 para1; -+ u32 para2; -+ u32 msdelay; -+}; -+ -+enum baseband_config_type { -+ /* Radio Path A */ -+ BASEBAND_CONFIG_PHY_REG = 0, -+ /* Radio Path B */ -+ BASEBAND_CONFIG_AGC_TAB = 1, -+}; -+ -+#define hal_get_firmwareversion(rtlpriv) \ -+ (((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion) -+ -+u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -+void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, -+ u32 data); -+void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -+u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, -+ u32 regaddr, u32 bitmask); -+void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, -+ u32 regaddr, u32 bitmask, u32 data); -+void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, -+ enum nl80211_channel_type ch_type); -+u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw); -+bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, -+ enum rf_pwrstate rfpower_state); -+bool rtl92s_phy_mac_config(struct ieee80211_hw *hw); -+void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw); -+bool rtl92s_phy_bb_config(struct ieee80211_hw *hw); -+bool rtl92s_phy_rf_config(struct ieee80211_hw *hw); -+void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -+void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel); -+bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io); -+void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw); -+void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval); -+u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ; -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/reg.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/reg.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/reg.h 2011-05-05 23:29:49.283487753 +0200 -@@ -0,0 +1,1188 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_92S_REG_H__ -+#define __REALTEK_92S_REG_H__ -+ -+/* 1. System Configuration Registers */ -+#define REG_SYS_ISO_CTRL 0x0000 -+#define REG_SYS_FUNC_EN 0x0002 -+#define PMC_FSM 0x0004 -+#define SYS_CLKR 0x0008 -+#define EPROM_CMD 0x000A -+#define EE_VPD 0x000C -+#define AFE_MISC 0x0010 -+#define SPS0_CTRL 0x0011 -+#define SPS1_CTRL 0x0018 -+#define RF_CTRL 0x001F -+#define LDOA15_CTRL 0x0020 -+#define LDOV12D_CTRL 0x0021 -+#define LDOHCI12_CTRL 0x0022 -+#define LDO_USB_SDIO 0x0023 -+#define LPLDO_CTRL 0x0024 -+#define AFE_XTAL_CTRL 0x0026 -+#define AFE_PLL_CTRL 0x0028 -+#define REG_EFUSE_CTRL 0x0030 -+#define REG_EFUSE_TEST 0x0034 -+#define PWR_DATA 0x0038 -+#define DBG_PORT 0x003A -+#define DPS_TIMER 0x003C -+#define RCLK_MON 0x003E -+ -+/* 2. Command Control Registers */ -+#define CMDR 0x0040 -+#define TXPAUSE 0x0042 -+#define LBKMD_SEL 0x0043 -+#define TCR 0x0044 -+#define RCR 0x0048 -+#define MSR 0x004C -+#define SYSF_CFG 0x004D -+#define RX_PKY_LIMIT 0x004E -+#define MBIDCTRL 0x004F -+ -+/* 3. MACID Setting Registers */ -+#define MACIDR 0x0050 -+#define MACIDR0 0x0050 -+#define MACIDR4 0x0054 -+#define BSSIDR 0x0058 -+#define HWVID 0x005E -+#define MAR 0x0060 -+#define MBIDCAMCONTENT 0x0068 -+#define MBIDCAMCFG 0x0070 -+#define BUILDTIME 0x0074 -+#define BUILDUSER 0x0078 -+ -+#define IDR0 MACIDR0 -+#define IDR4 MACIDR4 -+ -+/* 4. Timing Control Registers */ -+#define TSFR 0x0080 -+#define SLOT_TIME 0x0089 -+#define USTIME 0x008A -+#define SIFS_CCK 0x008C -+#define SIFS_OFDM 0x008E -+#define PIFS_TIME 0x0090 -+#define ACK_TIMEOUT 0x0091 -+#define EIFSTR 0x0092 -+#define BCN_INTERVAL 0x0094 -+#define ATIMWND 0x0096 -+#define BCN_DRV_EARLY_INT 0x0098 -+#define BCN_DMATIME 0x009A -+#define BCN_ERR_THRESH 0x009C -+#define MLT 0x009D -+#define RSVD_MAC_TUNE_US 0x009E -+ -+/* 5. FIFO Control Registers */ -+#define RQPN 0x00A0 -+#define RQPN1 0x00A0 -+#define RQPN2 0x00A1 -+#define RQPN3 0x00A2 -+#define RQPN4 0x00A3 -+#define RQPN5 0x00A4 -+#define RQPN6 0x00A5 -+#define RQPN7 0x00A6 -+#define RQPN8 0x00A7 -+#define RQPN9 0x00A8 -+#define RQPN10 0x00A9 -+#define LD_RQPN 0x00AB -+#define RXFF_BNDY 0x00AC -+#define RXRPT_BNDY 0x00B0 -+#define TXPKTBUF_PGBNDY 0x00B4 -+#define PBP 0x00B5 -+#define RXDRVINFO_SZ 0x00B6 -+#define TXFF_STATUS 0x00B7 -+#define RXFF_STATUS 0x00B8 -+#define TXFF_EMPTY_TH 0x00B9 -+#define SDIO_RX_BLKSZ 0x00BC -+#define RXDMA 0x00BD -+#define RXPKT_NUM 0x00BE -+#define C2HCMD_UDT_SIZE 0x00C0 -+#define C2HCMD_UDT_ADDR 0x00C2 -+#define FIFOPAGE1 0x00C4 -+#define FIFOPAGE2 0x00C8 -+#define FIFOPAGE3 0x00CC -+#define FIFOPAGE4 0x00D0 -+#define FIFOPAGE5 0x00D4 -+#define FW_RSVD_PG_CRTL 0x00D8 -+#define RXDMA_AGG_PG_TH 0x00D9 -+#define TXDESC_MSK 0x00DC -+#define TXRPTFF_RDPTR 0x00E0 -+#define TXRPTFF_WTPTR 0x00E4 -+#define C2HFF_RDPTR 0x00E8 -+#define C2HFF_WTPTR 0x00EC -+#define RXFF0_RDPTR 0x00F0 -+#define RXFF0_WTPTR 0x00F4 -+#define RXFF1_RDPTR 0x00F8 -+#define RXFF1_WTPTR 0x00FC -+#define RXRPT0_RDPTR 0x0100 -+#define RXRPT0_WTPTR 0x0104 -+#define RXRPT1_RDPTR 0x0108 -+#define RXRPT1_WTPTR 0x010C -+#define RX0_UDT_SIZE 0x0110 -+#define RX1PKTNUM 0x0114 -+#define RXFILTERMAP 0x0116 -+#define RXFILTERMAP_GP1 0x0118 -+#define RXFILTERMAP_GP2 0x011A -+#define RXFILTERMAP_GP3 0x011C -+#define BCNQ_CTRL 0x0120 -+#define MGTQ_CTRL 0x0124 -+#define HIQ_CTRL 0x0128 -+#define VOTID7_CTRL 0x012c -+#define VOTID6_CTRL 0x0130 -+#define VITID5_CTRL 0x0134 -+#define VITID4_CTRL 0x0138 -+#define BETID3_CTRL 0x013c -+#define BETID0_CTRL 0x0140 -+#define BKTID2_CTRL 0x0144 -+#define BKTID1_CTRL 0x0148 -+#define CMDQ_CTRL 0x014c -+#define TXPKT_NUM_CTRL 0x0150 -+#define TXQ_PGADD 0x0152 -+#define TXFF_PG_NUM 0x0154 -+#define TRXDMA_STATUS 0x0156 -+ -+/* 6. Adaptive Control Registers */ -+#define INIMCS_SEL 0x0160 -+#define TX_RATE_REG INIMCS_SEL -+#define INIRTSMCS_SEL 0x0180 -+#define RRSR 0x0181 -+#define ARFR0 0x0184 -+#define ARFR1 0x0188 -+#define ARFR2 0x018C -+#define ARFR3 0x0190 -+#define ARFR4 0x0194 -+#define ARFR5 0x0198 -+#define ARFR6 0x019C -+#define ARFR7 0x01A0 -+#define AGGLEN_LMT_H 0x01A7 -+#define AGGLEN_LMT_L 0x01A8 -+#define DARFRC 0x01B0 -+#define RARFRC 0x01B8 -+#define MCS_TXAGC 0x01C0 -+#define CCK_TXAGC 0x01C8 -+ -+/* 7. EDCA Setting Registers */ -+#define EDCAPARA_VO 0x01D0 -+#define EDCAPARA_VI 0x01D4 -+#define EDCAPARA_BE 0x01D8 -+#define EDCAPARA_BK 0x01DC -+#define BCNTCFG 0x01E0 -+#define CWRR 0x01E2 -+#define ACMAVG 0x01E4 -+#define AcmHwCtrl 0x01E7 -+#define VO_ADMTM 0x01E8 -+#define VI_ADMTM 0x01EC -+#define BE_ADMTM 0x01F0 -+#define RETRY_LIMIT 0x01F4 -+#define SG_RATE 0x01F6 -+ -+/* 8. WMAC, BA and CCX related Register. */ -+#define NAV_CTRL 0x0200 -+#define BW_OPMODE 0x0203 -+#define BACAMCMD 0x0204 -+#define BACAMCONTENT 0x0208 -+ -+/* the 0x2xx register WMAC definition */ -+#define LBDLY 0x0210 -+#define FWDLY 0x0211 -+#define HWPC_RX_CTRL 0x0218 -+#define MQIR 0x0220 -+#define MAIR 0x0222 -+#define MSIR 0x0224 -+#define CLM_RESULT 0x0227 -+#define NHM_RPI_CNT 0x0228 -+#define RXERR_RPT 0x0230 -+#define NAV_PROT_LEN 0x0234 -+#define CFEND_TH 0x0236 -+#define AMPDU_MIN_SPACE 0x0237 -+#define TXOP_STALL_CTRL 0x0238 -+ -+/* 9. Security Control Registers */ -+#define REG_RWCAM 0x0240 -+#define REG_WCAMI 0x0244 -+#define REG_RCAMO 0x0248 -+#define REG_CAMDBG 0x024C -+#define REG_SECR 0x0250 -+ -+/* 10. Power Save Control Registers */ -+#define WOW_CTRL 0x0260 -+#define PSSTATUS 0x0261 -+#define PSSWITCH 0x0262 -+#define MIMOPS_WAIT_PERIOD 0x0263 -+#define LPNAV_CTRL 0x0264 -+#define WFM0 0x0270 -+#define WFM1 0x0280 -+#define WFM2 0x0290 -+#define WFM3 0x02A0 -+#define WFM4 0x02B0 -+#define WFM5 0x02C0 -+#define WFCRC 0x02D0 -+#define FW_RPT_REG 0x02c4 -+ -+/* 11. General Purpose Registers */ -+#define PSTIME 0x02E0 -+#define TIMER0 0x02E4 -+#define TIMER1 0x02E8 -+#define GPIO_CTRL 0x02EC -+#define GPIO_IN 0x02EC -+#define GPIO_OUT 0x02ED -+#define GPIO_IO_SEL 0x02EE -+#define GPIO_MOD 0x02EF -+#define GPIO_INTCTRL 0x02F0 -+#define MAC_PINMUX_CFG 0x02F1 -+#define LEDCFG 0x02F2 -+#define PHY_REG 0x02F3 -+#define PHY_REG_DATA 0x02F4 -+#define REG_EFUSE_CLK 0x02F8 -+ -+/* 12. Host Interrupt Status Registers */ -+#define INTA_MASK 0x0300 -+#define ISR 0x0308 -+ -+/* 13. Test Mode and Debug Control Registers */ -+#define DBG_PORT_SWITCH 0x003A -+#define BIST 0x0310 -+#define DBS 0x0314 -+#define CPUINST 0x0318 -+#define CPUCAUSE 0x031C -+#define LBUS_ERR_ADDR 0x0320 -+#define LBUS_ERR_CMD 0x0324 -+#define LBUS_ERR_DATA_L 0x0328 -+#define LBUS_ERR_DATA_H 0x032C -+#define LX_EXCEPTION_ADDR 0x0330 -+#define WDG_CTRL 0x0334 -+#define INTMTU 0x0338 -+#define INTM 0x033A -+#define FDLOCKTURN0 0x033C -+#define FDLOCKTURN1 0x033D -+#define TRXPKTBUF_DBG_DATA 0x0340 -+#define TRXPKTBUF_DBG_CTRL 0x0348 -+#define DPLL 0x034A -+#define CBUS_ERR_ADDR 0x0350 -+#define CBUS_ERR_CMD 0x0354 -+#define CBUS_ERR_DATA_L 0x0358 -+#define CBUS_ERR_DATA_H 0x035C -+#define USB_SIE_INTF_ADDR 0x0360 -+#define USB_SIE_INTF_WD 0x0361 -+#define USB_SIE_INTF_RD 0x0362 -+#define USB_SIE_INTF_CTRL 0x0363 -+#define LBUS_MON_ADDR 0x0364 -+#define LBUS_ADDR_MASK 0x0368 -+ -+/* Boundary is 0x37F */ -+ -+/* 14. PCIE config register */ -+#define TP_POLL 0x0500 -+#define PM_CTRL 0x0502 -+#define PCIF 0x0503 -+ -+#define THPDA 0x0514 -+#define TMDA 0x0518 -+#define TCDA 0x051C -+#define HDA 0x0520 -+#define TVODA 0x0524 -+#define TVIDA 0x0528 -+#define TBEDA 0x052C -+#define TBKDA 0x0530 -+#define TBDA 0x0534 -+#define RCDA 0x0538 -+#define RDQDA 0x053C -+#define DBI_WDATA 0x0540 -+#define DBI_RDATA 0x0544 -+#define DBI_CTRL 0x0548 -+#define MDIO_DATA 0x0550 -+#define MDIO_CTRL 0x0554 -+#define PCI_RPWM 0x0561 -+#define PCI_CPWM 0x0563 -+ -+/* Config register (Offset 0x800-) */ -+#define PHY_CCA 0x803 -+ -+/* Min Spacing related settings. */ -+#define MAX_MSS_DENSITY_2T 0x13 -+#define MAX_MSS_DENSITY_1T 0x0A -+ -+/* Rx DMA Control related settings */ -+#define RXDMA_AGG_EN BIT(7) -+ -+#define RPWM PCI_RPWM -+ -+/* Regsiter Bit and Content definition */ -+ -+#define ISO_MD2PP BIT(0) -+#define ISO_PA2PCIE BIT(3) -+#define ISO_PLL2MD BIT(4) -+#define ISO_PWC_DV2RP BIT(11) -+#define ISO_PWC_RV2RP BIT(12) -+ -+ -+#define FEN_MREGEN BIT(15) -+#define FEN_DCORE BIT(11) -+#define FEN_CPUEN BIT(10) -+ -+#define PAD_HWPD_IDN BIT(22) -+ -+#define SYS_CLKSEL_80M BIT(0) -+#define SYS_PS_CLKSEL BIT(1) -+#define SYS_CPU_CLKSEL BIT(2) -+#define SYS_MAC_CLK_EN BIT(11) -+#define SYS_SWHW_SEL BIT(14) -+#define SYS_FWHW_SEL BIT(15) -+ -+#define CmdEEPROM_En BIT(5) -+#define CmdEERPOMSEL BIT(4) -+#define Cmd9346CR_9356SEL BIT(4) -+ -+#define AFE_MBEN BIT(1) -+#define AFE_BGEN BIT(0) -+ -+#define SPS1_SWEN BIT(1) -+#define SPS1_LDEN BIT(0) -+ -+#define RF_EN BIT(0) -+#define RF_RSTB BIT(1) -+#define RF_SDMRSTB BIT(2) -+ -+#define LDA15_EN BIT(0) -+ -+#define LDV12_EN BIT(0) -+#define LDV12_SDBY BIT(1) -+ -+#define XTAL_GATE_AFE BIT(10) -+ -+#define APLL_EN BIT(0) -+ -+#define AFR_CardBEn BIT(0) -+#define AFR_CLKRUN_SEL BIT(1) -+#define AFR_FuncRegEn BIT(2) -+ -+#define APSDOFF_STATUS BIT(15) -+#define APSDOFF BIT(14) -+#define BBRSTN BIT(13) -+#define BB_GLB_RSTN BIT(12) -+#define SCHEDULE_EN BIT(10) -+#define MACRXEN BIT(9) -+#define MACTXEN BIT(8) -+#define DDMA_EN BIT(7) -+#define FW2HW_EN BIT(6) -+#define RXDMA_EN BIT(5) -+#define TXDMA_EN BIT(4) -+#define HCI_RXDMA_EN BIT(3) -+#define HCI_TXDMA_EN BIT(2) -+ -+#define StopHCCA BIT(6) -+#define StopHigh BIT(5) -+#define StopMgt BIT(4) -+#define StopVO BIT(3) -+#define StopVI BIT(2) -+#define StopBE BIT(1) -+#define StopBK BIT(0) -+ -+#define LBK_NORMAL 0x00 -+#define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) -+#define LBK_MAC_DLB (BIT(0) | BIT(1)) -+#define LBK_DMA_LB (BIT(0) | BIT(1) | BIT(2)) -+ -+#define TCP_OFDL_EN BIT(25) -+#define HWPC_TX_EN BIT(24) -+#define TXDMAPRE2FULL BIT(23) -+#define DISCW BIT(20) -+#define TCRICV BIT(19) -+#define CfendForm BIT(17) -+#define TCRCRC BIT(16) -+#define FAKE_IMEM_EN BIT(15) -+#define TSFRST BIT(9) -+#define TSFEN BIT(8) -+#define FWALLRDY (BIT(0) | BIT(1) | BIT(2) | \ -+ BIT(3) | BIT(4) | BIT(5) | \ -+ BIT(6) | BIT(7)) -+#define FWRDY BIT(7) -+#define BASECHG BIT(6) -+#define IMEM BIT(5) -+#define DMEM_CODE_DONE BIT(4) -+#define EXT_IMEM_CHK_RPT BIT(3) -+#define EXT_IMEM_CODE_DONE BIT(2) -+#define IMEM_CHK_RPT BIT(1) -+#define IMEM_CODE_DONE BIT(0) -+#define IMEM_CODE_DONE BIT(0) -+#define IMEM_CHK_RPT BIT(1) -+#define EMEM_CODE_DONE BIT(2) -+#define EMEM_CHK_RPT BIT(3) -+#define DMEM_CODE_DONE BIT(4) -+#define IMEM_RDY BIT(5) -+#define BASECHG BIT(6) -+#define FWRDY BIT(7) -+#define LOAD_FW_READY (IMEM_CODE_DONE | \ -+ IMEM_CHK_RPT | \ -+ EMEM_CODE_DONE | \ -+ EMEM_CHK_RPT | \ -+ DMEM_CODE_DONE | \ -+ IMEM_RDY | \ -+ BASECHG | \ -+ FWRDY) -+#define TCR_TSFEN BIT(8) -+#define TCR_TSFRST BIT(9) -+#define TCR_FAKE_IMEM_EN BIT(15) -+#define TCR_CRC BIT(16) -+#define TCR_ICV BIT(19) -+#define TCR_DISCW BIT(20) -+#define TCR_HWPC_TX_EN BIT(24) -+#define TCR_TCP_OFDL_EN BIT(25) -+#define TXDMA_INIT_VALUE (IMEM_CHK_RPT | \ -+ EXT_IMEM_CHK_RPT) -+ -+#define RCR_APPFCS BIT(31) -+#define RCR_DIS_ENC_2BYTE BIT(30) -+#define RCR_DIS_AES_2BYTE BIT(29) -+#define RCR_HTC_LOC_CTRL BIT(28) -+#define RCR_ENMBID BIT(27) -+#define RCR_RX_TCPOFDL_EN BIT(26) -+#define RCR_APP_PHYST_RXFF BIT(25) -+#define RCR_APP_PHYST_STAFF BIT(24) -+#define RCR_CBSSID BIT(23) -+#define RCR_APWRMGT BIT(22) -+#define RCR_ADD3 BIT(21) -+#define RCR_AMF BIT(20) -+#define RCR_ACF BIT(19) -+#define RCR_ADF BIT(18) -+#define RCR_APP_MIC BIT(17) -+#define RCR_APP_ICV BIT(16) -+#define RCR_RXFTH BIT(13) -+#define RCR_AICV BIT(12) -+#define RCR_RXDESC_LK_EN BIT(11) -+#define RCR_APP_BA_SSN BIT(6) -+#define RCR_ACRC32 BIT(5) -+#define RCR_RXSHFT_EN BIT(4) -+#define RCR_AB BIT(3) -+#define RCR_AM BIT(2) -+#define RCR_APM BIT(1) -+#define RCR_AAP BIT(0) -+#define RCR_MXDMA_OFFSET 8 -+#define RCR_FIFO_OFFSET 13 -+ -+ -+#define MSR_LINK_MASK ((1 << 0) | (1 << 1)) -+#define MSR_LINK_MANAGED 2 -+#define MSR_LINK_NONE 0 -+#define MSR_LINK_SHIFT 0 -+#define MSR_LINK_ADHOC 1 -+#define MSR_LINK_MASTER 3 -+#define MSR_NOLINK 0x00 -+#define MSR_ADHOC 0x01 -+#define MSR_INFRA 0x02 -+#define MSR_AP 0x03 -+ -+#define ENUART BIT(7) -+#define ENJTAG BIT(3) -+#define BTMODE (BIT(2) | BIT(1)) -+#define ENBT BIT(0) -+ -+#define ENMBID BIT(7) -+#define BCNUM (BIT(6) | BIT(5) | BIT(4)) -+ -+#define USTIME_EDCA 0xFF00 -+#define USTIME_TSF 0x00FF -+ -+#define SIFS_TRX 0xFF00 -+#define SIFS_CTX 0x00FF -+ -+#define ENSWBCN BIT(15) -+#define DRVERLY_TU 0x0FF0 -+#define DRVERLY_US 0x000F -+#define BCN_TCFG_CW_SHIFT 8 -+#define BCN_TCFG_IFS 0 -+ -+#define RRSR_RSC_OFFSET 21 -+#define RRSR_SHORT_OFFSET 23 -+#define RRSR_RSC_BW_40M 0x600000 -+#define RRSR_RSC_UPSUBCHNL 0x400000 -+#define RRSR_RSC_LOWSUBCHNL 0x200000 -+#define RRSR_SHORT 0x800000 -+#define RRSR_1M BIT(0) -+#define RRSR_2M BIT(1) -+#define RRSR_5_5M BIT(2) -+#define RRSR_11M BIT(3) -+#define RRSR_6M BIT(4) -+#define RRSR_9M BIT(5) -+#define RRSR_12M BIT(6) -+#define RRSR_18M BIT(7) -+#define RRSR_24M BIT(8) -+#define RRSR_36M BIT(9) -+#define RRSR_48M BIT(10) -+#define RRSR_54M BIT(11) -+#define RRSR_MCS0 BIT(12) -+#define RRSR_MCS1 BIT(13) -+#define RRSR_MCS2 BIT(14) -+#define RRSR_MCS3 BIT(15) -+#define RRSR_MCS4 BIT(16) -+#define RRSR_MCS5 BIT(17) -+#define RRSR_MCS6 BIT(18) -+#define RRSR_MCS7 BIT(19) -+#define BRSR_AckShortPmb BIT(23) -+ -+#define RATR_1M 0x00000001 -+#define RATR_2M 0x00000002 -+#define RATR_55M 0x00000004 -+#define RATR_11M 0x00000008 -+#define RATR_6M 0x00000010 -+#define RATR_9M 0x00000020 -+#define RATR_12M 0x00000040 -+#define RATR_18M 0x00000080 -+#define RATR_24M 0x00000100 -+#define RATR_36M 0x00000200 -+#define RATR_48M 0x00000400 -+#define RATR_54M 0x00000800 -+#define RATR_MCS0 0x00001000 -+#define RATR_MCS1 0x00002000 -+#define RATR_MCS2 0x00004000 -+#define RATR_MCS3 0x00008000 -+#define RATR_MCS4 0x00010000 -+#define RATR_MCS5 0x00020000 -+#define RATR_MCS6 0x00040000 -+#define RATR_MCS7 0x00080000 -+#define RATR_MCS8 0x00100000 -+#define RATR_MCS9 0x00200000 -+#define RATR_MCS10 0x00400000 -+#define RATR_MCS11 0x00800000 -+#define RATR_MCS12 0x01000000 -+#define RATR_MCS13 0x02000000 -+#define RATR_MCS14 0x04000000 -+#define RATR_MCS15 0x08000000 -+ -+#define RATE_ALL_CCK (RATR_1M | RATR_2M | \ -+ RATR_55M | RATR_11M) -+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | \ -+ RATR_12M | RATR_18M | \ -+ RATR_24M | RATR_36M | \ -+ RATR_48M | RATR_54M) -+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | \ -+ RATR_MCS2 | RATR_MCS3 | \ -+ RATR_MCS4 | RATR_MCS5 | \ -+ RATR_MCS6 | RATR_MCS7) -+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | \ -+ RATR_MCS10 | RATR_MCS11 | \ -+ RATR_MCS12 | RATR_MCS13 | \ -+ RATR_MCS14 | RATR_MCS15) -+ -+#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -+#define AC_PARAM_ECW_MAX_OFFSET 12 -+#define AC_PARAM_ECW_MIN_OFFSET 8 -+#define AC_PARAM_AIFS_OFFSET 0 -+ -+#define AcmHw_HwEn BIT(0) -+#define AcmHw_BeqEn BIT(1) -+#define AcmHw_ViqEn BIT(2) -+#define AcmHw_VoqEn BIT(3) -+#define AcmHw_BeqStatus BIT(4) -+#define AcmHw_ViqStatus BIT(5) -+#define AcmHw_VoqStatus BIT(6) -+ -+#define RETRY_LIMIT_SHORT_SHIFT 8 -+#define RETRY_LIMIT_LONG_SHIFT 0 -+ -+#define NAV_UPPER_EN BIT(16) -+#define NAV_UPPER 0xFF00 -+#define NAV_RTSRST 0xFF -+ -+#define BW_OPMODE_20MHZ BIT(2) -+#define BW_OPMODE_5G BIT(1) -+#define BW_OPMODE_11J BIT(0) -+ -+#define RXERR_RPT_RST BIT(27) -+#define RXERR_OFDM_PPDU 0 -+#define RXERR_OFDM_FALSE_ALARM 1 -+#define RXERR_OFDM_MPDU_OK 2 -+#define RXERR_OFDM_MPDU_FAIL 3 -+#define RXERR_CCK_PPDU 4 -+#define RXERR_CCK_FALSE_ALARM 5 -+#define RXERR_CCK_MPDU_OK 6 -+#define RXERR_CCK_MPDU_FAIL 7 -+#define RXERR_HT_PPDU 8 -+#define RXERR_HT_FALSE_ALARM 9 -+#define RXERR_HT_MPDU_TOTAL 10 -+#define RXERR_HT_MPDU_OK 11 -+#define RXERR_HT_MPDU_FAIL 12 -+#define RXERR_RX_FULL_DROP 15 -+ -+#define SCR_TXUSEDK BIT(0) -+#define SCR_RXUSEDK BIT(1) -+#define SCR_TXENCENABLE BIT(2) -+#define SCR_RXENCENABLE BIT(3) -+#define SCR_SKBYA2 BIT(4) -+#define SCR_NOSKMC BIT(5) -+ -+#define CAM_VALID BIT(15) -+#define CAM_NOTVALID 0x0000 -+#define CAM_USEDK BIT(5) -+ -+#define CAM_NONE 0x0 -+#define CAM_WEP40 0x01 -+#define CAM_TKIP 0x02 -+#define CAM_AES 0x04 -+#define CAM_WEP104 0x05 -+ -+#define TOTAL_CAM_ENTRY 32 -+#define HALF_CAM_ENTRY 16 -+ -+#define CAM_WRITE BIT(16) -+#define CAM_READ 0x00000000 -+#define CAM_POLLINIG BIT(31) -+ -+#define WOW_PMEN BIT(0) -+#define WOW_WOMEN BIT(1) -+#define WOW_MAGIC BIT(2) -+#define WOW_UWF BIT(3) -+ -+#define GPIOMUX_EN BIT(3) -+#define GPIOSEL_GPIO 0 -+#define GPIOSEL_PHYDBG 1 -+#define GPIOSEL_BT 2 -+#define GPIOSEL_WLANDBG 3 -+#define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1))) -+ -+#define HST_RDBUSY BIT(0) -+#define CPU_WTBUSY BIT(1) -+ -+#define IMR8190_DISABLED 0x0 -+#define IMR_CPUERR BIT(5) -+#define IMR_ATIMEND BIT(4) -+#define IMR_TBDOK BIT(3) -+#define IMR_TBDER BIT(2) -+#define IMR_BCNDMAINT8 BIT(1) -+#define IMR_BCNDMAINT7 BIT(0) -+#define IMR_BCNDMAINT6 BIT(31) -+#define IMR_BCNDMAINT5 BIT(30) -+#define IMR_BCNDMAINT4 BIT(29) -+#define IMR_BCNDMAINT3 BIT(28) -+#define IMR_BCNDMAINT2 BIT(27) -+#define IMR_BCNDMAINT1 BIT(26) -+#define IMR_BCNDOK8 BIT(25) -+#define IMR_BCNDOK7 BIT(24) -+#define IMR_BCNDOK6 BIT(23) -+#define IMR_BCNDOK5 BIT(22) -+#define IMR_BCNDOK4 BIT(21) -+#define IMR_BCNDOK3 BIT(20) -+#define IMR_BCNDOK2 BIT(19) -+#define IMR_BCNDOK1 BIT(18) -+#define IMR_TIMEOUT2 BIT(17) -+#define IMR_TIMEOUT1 BIT(16) -+#define IMR_TXFOVW BIT(15) -+#define IMR_PSTIMEOUT BIT(14) -+#define IMR_BCNINT BIT(13) -+#define IMR_RXFOVW BIT(12) -+#define IMR_RDU BIT(11) -+#define IMR_RXCMDOK BIT(10) -+#define IMR_BDOK BIT(9) -+#define IMR_HIGHDOK BIT(8) -+#define IMR_COMDOK BIT(7) -+#define IMR_MGNTDOK BIT(6) -+#define IMR_HCCADOK BIT(5) -+#define IMR_BKDOK BIT(4) -+#define IMR_BEDOK BIT(3) -+#define IMR_VIDOK BIT(2) -+#define IMR_VODOK BIT(1) -+#define IMR_ROK BIT(0) -+ -+#define TPPOLL_BKQ BIT(0) -+#define TPPOLL_BEQ BIT(1) -+#define TPPOLL_VIQ BIT(2) -+#define TPPOLL_VOQ BIT(3) -+#define TPPOLL_BQ BIT(4) -+#define TPPOLL_CQ BIT(5) -+#define TPPOLL_MQ BIT(6) -+#define TPPOLL_HQ BIT(7) -+#define TPPOLL_HCCAQ BIT(8) -+#define TPPOLL_STOPBK BIT(9) -+#define TPPOLL_STOPBE BIT(10) -+#define TPPOLL_STOPVI BIT(11) -+#define TPPOLL_STOPVO BIT(12) -+#define TPPOLL_STOPMGT BIT(13) -+#define TPPOLL_STOPHIGH BIT(14) -+#define TPPOLL_STOPHCCA BIT(15) -+#define TPPOLL_SHIFT 8 -+ -+#define CCX_CMD_CLM_ENABLE BIT(0) -+#define CCX_CMD_NHM_ENABLE BIT(1) -+#define CCX_CMD_FUNCTION_ENABLE BIT(8) -+#define CCX_CMD_IGNORE_CCA BIT(9) -+#define CCX_CMD_IGNORE_TXON BIT(10) -+#define CCX_CLM_RESULT_READY BIT(16) -+#define CCX_NHM_RESULT_READY BIT(16) -+#define CCX_CMD_RESET 0x0 -+ -+ -+#define HWSET_MAX_SIZE_92S 128 -+#define EFUSE_MAX_SECTION 16 -+#define EFUSE_REAL_CONTENT_LEN 512 -+ -+#define RTL8190_EEPROM_ID 0x8129 -+#define EEPROM_HPON 0x02 -+#define EEPROM_CLK 0x06 -+#define EEPROM_TESTR 0x08 -+ -+#define EEPROM_VID 0x0A -+#define EEPROM_DID 0x0C -+#define EEPROM_SVID 0x0E -+#define EEPROM_SMID 0x10 -+ -+#define EEPROM_MAC_ADDR 0x12 -+#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 -+ -+#define EEPROM_PWDIFF 0x54 -+ -+#define EEPROM_TXPOWERBASE 0x50 -+#define EEPROM_TX_PWR_INDEX_RANGE 28 -+ -+#define EEPROM_TX_PWR_HT20_DIFF 0x62 -+#define DEFAULT_HT20_TXPWR_DIFF 2 -+#define EEPROM_TX_PWR_OFDM_DIFF 0x65 -+ -+#define EEPROM_TXPWRGROUP 0x67 -+#define EEPROM_REGULATORY 0x6D -+ -+#define TX_PWR_SAFETY_CHK 0x6D -+#define EEPROM_TXPWINDEX_CCK_24G 0x5D -+#define EEPROM_TXPWINDEX_OFDM_24G 0x6B -+#define EEPROM_HT2T_CH1_A 0x6c -+#define EEPROM_HT2T_CH7_A 0x6d -+#define EEPROM_HT2T_CH13_A 0x6e -+#define EEPROM_HT2T_CH1_B 0x6f -+#define EEPROM_HT2T_CH7_B 0x70 -+#define EEPROM_HT2T_CH13_B 0x71 -+ -+#define EEPROM_TSSI_A 0x74 -+#define EEPROM_TSSI_B 0x75 -+ -+#define EEPROM_RFIND_POWERDIFF 0x76 -+#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -+ -+#define EEPROM_THERMALMETER 0x77 -+#define EEPROM_BLUETOOTH_COEXIST 0x78 -+#define EEPROM_BLUETOOTH_TYPE 0x4f -+ -+#define EEPROM_OPTIONAL 0x78 -+#define EEPROM_WOWLAN 0x78 -+ -+#define EEPROM_CRYSTALCAP 0x79 -+#define EEPROM_CHANNELPLAN 0x7B -+#define EEPROM_VERSION 0x7C -+#define EEPROM_CUSTOMID 0x7A -+#define EEPROM_BOARDTYPE 0x7E -+ -+#define EEPROM_CHANNEL_PLAN_FCC 0x0 -+#define EEPROM_CHANNEL_PLAN_IC 0x1 -+#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -+#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -+#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -+#define EEPROM_CHANNEL_PLAN_MKK 0x5 -+#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -+#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -+#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -+#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -+#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -+#define EEPROM_CHANNEL_PLAN_NCC 0xB -+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 -+ -+#define FW_DIG_DISABLE 0xfd00cc00 -+#define FW_DIG_ENABLE 0xfd000000 -+#define FW_DIG_HALT 0xfd000001 -+#define FW_DIG_RESUME 0xfd000002 -+#define FW_HIGH_PWR_DISABLE 0xfd000008 -+#define FW_HIGH_PWR_ENABLE 0xfd000009 -+#define FW_ADD_A2_ENTRY 0xfd000016 -+#define FW_TXPWR_TRACK_ENABLE 0xfd000017 -+#define FW_TXPWR_TRACK_DISABLE 0xfd000018 -+#define FW_TXPWR_TRACK_THERMAL 0xfd000019 -+#define FW_TXANT_SWITCH_ENABLE 0xfd000023 -+#define FW_TXANT_SWITCH_DISABLE 0xfd000024 -+#define FW_RA_INIT 0xfd000026 -+#define FW_CTRL_DM_BY_DRIVER 0Xfd00002a -+#define FW_RA_IOT_BG_COMB 0xfd000030 -+#define FW_RA_IOT_N_COMB 0xfd000031 -+#define FW_RA_REFRESH 0xfd0000a0 -+#define FW_RA_UPDATE_MASK 0xfd0000a2 -+#define FW_RA_DISABLE 0xfd0000a4 -+#define FW_RA_ACTIVE 0xfd0000a6 -+#define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac -+#define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad -+#define FW_RA_RESET 0xfd0000af -+#define FW_DM_DISABLE 0xfd00aa00 -+#define FW_IQK_ENABLE 0xf0000020 -+#define FW_IQK_SUCCESS 0x0000dddd -+#define FW_IQK_FAIL 0x0000ffff -+#define FW_OP_FAILURE 0xffffffff -+#define FW_TX_FEEDBACK_NONE 0xfb000000 -+#define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) -+#define FW_TX_FEEDBACK_CCX_ENABL (FW_TX_FEEDBACK_NONE | 0x2) -+#define FW_BB_RESET_ENABLE 0xff00000d -+#define FW_BB_RESET_DISABLE 0xff00000e -+#define FW_CCA_CHK_ENABLE 0xff000011 -+#define FW_CCK_RESET_CNT 0xff000013 -+#define FW_LPS_ENTER 0xfe000010 -+#define FW_LPS_LEAVE 0xfe000011 -+#define FW_INDIRECT_READ 0xf2000000 -+#define FW_INDIRECT_WRITE 0xf2000001 -+#define FW_CHAN_SET 0xf3000001 -+ -+#define RFPC 0x5F -+#define RCR_9356SEL BIT(6) -+#define TCR_LRL_OFFSET 0 -+#define TCR_SRL_OFFSET 8 -+#define TCR_MXDMA_OFFSET 21 -+#define TCR_SAT BIT(24) -+#define RCR_MXDMA_OFFSET 8 -+#define RCR_FIFO_OFFSET 13 -+#define RCR_OnlyErlPkt BIT(31) -+#define CWR 0xDC -+#define RETRYCTR 0xDE -+ -+#define CPU_GEN_SYSTEM_RESET 0x00000001 -+ -+#define CCX_COMMAND_REG 0x890 -+#define CLM_PERIOD_REG 0x894 -+#define NHM_PERIOD_REG 0x896 -+ -+#define NHM_THRESHOLD0 0x898 -+#define NHM_THRESHOLD1 0x899 -+#define NHM_THRESHOLD2 0x89A -+#define NHM_THRESHOLD3 0x89B -+#define NHM_THRESHOLD4 0x89C -+#define NHM_THRESHOLD5 0x89D -+#define NHM_THRESHOLD6 0x89E -+#define CLM_RESULT_REG 0x8D0 -+#define NHM_RESULT_REG 0x8D4 -+#define NHM_RPI_COUNTER0 0x8D8 -+#define NHM_RPI_COUNTER1 0x8D9 -+#define NHM_RPI_COUNTER2 0x8DA -+#define NHM_RPI_COUNTER3 0x8DB -+#define NHM_RPI_COUNTER4 0x8DC -+#define NHM_RPI_COUNTER5 0x8DD -+#define NHM_RPI_COUNTER6 0x8DE -+#define NHM_RPI_COUNTER7 0x8DF -+ -+#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) -+#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 -+#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) -+ -+#define RPMAC_RESET 0x100 -+#define RPMAC_TXSTART 0x104 -+#define RPMAC_TXLEGACYSIG 0x108 -+#define RPMAC_TXHTSIG1 0x10c -+#define RPMAC_TXHTSIG2 0x110 -+#define RPMAC_PHYDEBUG 0x114 -+#define RPMAC_TXPACKETNNM 0x118 -+#define RPMAC_TXIDLE 0x11c -+#define RPMAC_TXMACHEADER0 0x120 -+#define RPMAC_TXMACHEADER1 0x124 -+#define RPMAC_TXMACHEADER2 0x128 -+#define RPMAC_TXMACHEADER3 0x12c -+#define RPMAC_TXMACHEADER4 0x130 -+#define RPMAC_TXMACHEADER5 0x134 -+#define RPMAC_TXDATATYPE 0x138 -+#define RPMAC_TXRANDOMSEED 0x13c -+#define RPMAC_CCKPLCPPREAMBLE 0x140 -+#define RPMAC_CCKPLCPHEADER 0x144 -+#define RPMAC_CCKCRC16 0x148 -+#define RPMAC_OFDMRXCRC32OK 0x170 -+#define RPMAC_OFDMRXCRC32ER 0x174 -+#define RPMAC_OFDMRXPARITYER 0x178 -+#define RPMAC_OFDMRXCRC8ER 0x17c -+#define RPMAC_CCKCRXRC16ER 0x180 -+#define RPMAC_CCKCRXRC32ER 0x184 -+#define RPMAC_CCKCRXRC32OK 0x188 -+#define RPMAC_TXSTATUS 0x18c -+ -+#define RF_BB_CMD_ADDR 0x02c0 -+#define RF_BB_CMD_DATA 0x02c4 -+ -+#define RFPGA0_RFMOD 0x800 -+ -+#define RFPGA0_TXINFO 0x804 -+#define RFPGA0_PSDFUNCTION 0x808 -+ -+#define RFPGA0_TXGAINSTAGE 0x80c -+ -+#define RFPGA0_RFTIMING1 0x810 -+#define RFPGA0_RFTIMING2 0x814 -+#define RFPGA0_XA_HSSIPARAMETER1 0x820 -+#define RFPGA0_XA_HSSIPARAMETER2 0x824 -+#define RFPGA0_XB_HSSIPARAMETER1 0x828 -+#define RFPGA0_XB_HSSIPARAMETER2 0x82c -+#define RFPGA0_XC_HSSIPARAMETER1 0x830 -+#define RFPGA0_XC_HSSIPARAMETER2 0x834 -+#define RFPGA0_XD_HSSIPARAMETER1 0x838 -+#define RFPGA0_XD_HSSIPARAMETER2 0x83c -+#define RFPGA0_XA_LSSIPARAMETER 0x840 -+#define RFPGA0_XB_LSSIPARAMETER 0x844 -+#define RFPGA0_XC_LSSIPARAMETER 0x848 -+#define RFPGA0_XD_LSSIPARAMETER 0x84c -+ -+#define RFPGA0_RFWAKEUP_PARAMETER 0x850 -+#define RFPGA0_RFSLEEPUP_PARAMETER 0x854 -+ -+#define RFPGA0_XAB_SWITCHCONTROL 0x858 -+#define RFPGA0_XCD_SWITCHCONTROL 0x85c -+ -+#define RFPGA0_XA_RFINTERFACEOE 0x860 -+#define RFPGA0_XB_RFINTERFACEOE 0x864 -+#define RFPGA0_XC_RFINTERFACEOE 0x868 -+#define RFPGA0_XD_RFINTERFACEOE 0x86c -+ -+#define RFPGA0_XAB_RFINTERFACESW 0x870 -+#define RFPGA0_XCD_RFINTERFACESW 0x874 -+ -+#define RFPGA0_XAB_RFPARAMETER 0x878 -+#define RFPGA0_XCD_RFPARAMETER 0x87c -+ -+#define RFPGA0_ANALOGPARAMETER1 0x880 -+#define RFPGA0_ANALOGPARAMETER2 0x884 -+#define RFPGA0_ANALOGPARAMETER3 0x888 -+#define RFPGA0_ANALOGPARAMETER4 0x88c -+ -+#define RFPGA0_XA_LSSIREADBACK 0x8a0 -+#define RFPGA0_XB_LSSIREADBACK 0x8a4 -+#define RFPGA0_XC_LSSIREADBACK 0x8a8 -+#define RFPGA0_XD_LSSIREADBACK 0x8ac -+ -+#define RFPGA0_PSDREPORT 0x8b4 -+#define TRANSCEIVERA_HSPI_READBACK 0x8b8 -+#define TRANSCEIVERB_HSPI_READBACK 0x8bc -+#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -+#define RFPGA0_XCD_RFINTERFACERB 0x8e4 -+#define RFPGA1_RFMOD 0x900 -+ -+#define RFPGA1_TXBLOCK 0x904 -+#define RFPGA1_DEBUGSELECT 0x908 -+#define RFPGA1_TXINFO 0x90c -+ -+#define RCCK0_SYSTEM 0xa00 -+ -+#define RCCK0_AFESETTING 0xa04 -+#define RCCK0_CCA 0xa08 -+ -+#define RCCK0_RXAGC1 0xa0c -+#define RCCK0_RXAGC2 0xa10 -+ -+#define RCCK0_RXHP 0xa14 -+ -+#define RCCK0_DSPPARAMETER1 0xa18 -+#define RCCK0_DSPPARAMETER2 0xa1c -+ -+#define RCCK0_TXFILTER1 0xa20 -+#define RCCK0_TXFILTER2 0xa24 -+#define RCCK0_DEBUGPORT 0xa28 -+#define RCCK0_FALSEALARMREPORT 0xa2c -+#define RCCK0_TRSSIREPORT 0xa50 -+#define RCCK0_RXREPORT 0xa54 -+#define RCCK0_FACOUNTERLOWER 0xa5c -+#define RCCK0_FACOUNTERUPPER 0xa58 -+ -+#define ROFDM0_LSTF 0xc00 -+ -+#define ROFDM0_TRXPATHENABLE 0xc04 -+#define ROFDM0_TRMUXPAR 0xc08 -+#define ROFDM0_TRSWISOLATION 0xc0c -+ -+#define ROFDM0_XARXAFE 0xc10 -+#define ROFDM0_XARXIQIMBALANCE 0xc14 -+#define ROFDM0_XBRXAFE 0xc18 -+#define ROFDM0_XBRXIQIMBALANCE 0xc1c -+#define ROFDM0_XCRXAFE 0xc20 -+#define ROFDM0_XCRXIQIMBALANCE 0xc24 -+#define ROFDM0_XDRXAFE 0xc28 -+#define ROFDM0_XDRXIQIMBALANCE 0xc2c -+ -+#define ROFDM0_RXDETECTOR1 0xc30 -+#define ROFDM0_RXDETECTOR2 0xc34 -+#define ROFDM0_RXDETECTOR3 0xc38 -+#define ROFDM0_RXDETECTOR4 0xc3c -+ -+#define ROFDM0_RXDSP 0xc40 -+#define ROFDM0_CFO_AND_DAGC 0xc44 -+#define ROFDM0_CCADROP_THRESHOLD 0xc48 -+#define ROFDM0_ECCA_THRESHOLD 0xc4c -+ -+#define ROFDM0_XAAGCCORE1 0xc50 -+#define ROFDM0_XAAGCCORE2 0xc54 -+#define ROFDM0_XBAGCCORE1 0xc58 -+#define ROFDM0_XBAGCCORE2 0xc5c -+#define ROFDM0_XCAGCCORE1 0xc60 -+#define ROFDM0_XCAGCCORE2 0xc64 -+#define ROFDM0_XDAGCCORE1 0xc68 -+#define ROFDM0_XDAGCCORE2 0xc6c -+ -+#define ROFDM0_AGCPARAMETER1 0xc70 -+#define ROFDM0_AGCPARAMETER2 0xc74 -+#define ROFDM0_AGCRSSITABLE 0xc78 -+#define ROFDM0_HTSTFAGC 0xc7c -+ -+#define ROFDM0_XATXIQIMBALANCE 0xc80 -+#define ROFDM0_XATXAFE 0xc84 -+#define ROFDM0_XBTXIQIMBALANCE 0xc88 -+#define ROFDM0_XBTXAFE 0xc8c -+#define ROFDM0_XCTXIQIMBALANCE 0xc90 -+#define ROFDM0_XCTXAFE 0xc94 -+#define ROFDM0_XDTXIQIMBALANCE 0xc98 -+#define ROFDM0_XDTXAFE 0xc9c -+ -+#define ROFDM0_RXHP_PARAMETER 0xce0 -+#define ROFDM0_TXPSEUDO_NOISE_WGT 0xce4 -+#define ROFDM0_FRAME_SYNC 0xcf0 -+#define ROFDM0_DFSREPORT 0xcf4 -+#define ROFDM0_TXCOEFF1 0xca4 -+#define ROFDM0_TXCOEFF2 0xca8 -+#define ROFDM0_TXCOEFF3 0xcac -+#define ROFDM0_TXCOEFF4 0xcb0 -+#define ROFDM0_TXCOEFF5 0xcb4 -+#define ROFDM0_TXCOEFF6 0xcb8 -+ -+ -+#define ROFDM1_LSTF 0xd00 -+#define ROFDM1_TRXPATHENABLE 0xd04 -+ -+#define ROFDM1_CFO 0xd08 -+#define ROFDM1_CSI1 0xd10 -+#define ROFDM1_SBD 0xd14 -+#define ROFDM1_CSI2 0xd18 -+#define ROFDM1_CFOTRACKING 0xd2c -+#define ROFDM1_TRXMESAURE1 0xd34 -+#define ROFDM1_INTF_DET 0xd3c -+#define ROFDM1_PSEUDO_NOISESTATEAB 0xd50 -+#define ROFDM1_PSEUDO_NOISESTATECD 0xd54 -+#define ROFDM1_RX_PSEUDO_NOISE_WGT 0xd58 -+ -+#define ROFDM_PHYCOUNTER1 0xda0 -+#define ROFDM_PHYCOUNTER2 0xda4 -+#define ROFDM_PHYCOUNTER3 0xda8 -+ -+#define ROFDM_SHORT_CFOAB 0xdac -+#define ROFDM_SHORT_CFOCD 0xdb0 -+#define ROFDM_LONG_CFOAB 0xdb4 -+#define ROFDM_LONG_CFOCD 0xdb8 -+#define ROFDM_TAIL_CFOAB 0xdbc -+#define ROFDM_TAIL_CFOCD 0xdc0 -+#define ROFDM_PW_MEASURE1 0xdc4 -+#define ROFDM_PW_MEASURE2 0xdc8 -+#define ROFDM_BW_REPORT 0xdcc -+#define ROFDM_AGC_REPORT 0xdd0 -+#define ROFDM_RXSNR 0xdd4 -+#define ROFDM_RXEVMCSI 0xdd8 -+#define ROFDM_SIG_REPORT 0xddc -+ -+ -+#define RTXAGC_RATE18_06 0xe00 -+#define RTXAGC_RATE54_24 0xe04 -+#define RTXAGC_CCK_MCS32 0xe08 -+#define RTXAGC_MCS03_MCS00 0xe10 -+#define RTXAGC_MCS07_MCS04 0xe14 -+#define RTXAGC_MCS11_MCS08 0xe18 -+#define RTXAGC_MCS15_MCS12 0xe1c -+ -+ -+#define RF_AC 0x00 -+#define RF_IQADJ_G1 0x01 -+#define RF_IQADJ_G2 0x02 -+#define RF_POW_TRSW 0x05 -+#define RF_GAIN_RX 0x06 -+#define RF_GAIN_TX 0x07 -+#define RF_TXM_IDAC 0x08 -+#define RF_BS_IQGEN 0x0F -+ -+#define RF_MODE1 0x10 -+#define RF_MODE2 0x11 -+#define RF_RX_AGC_HP 0x12 -+#define RF_TX_AGC 0x13 -+#define RF_BIAS 0x14 -+#define RF_IPA 0x15 -+#define RF_POW_ABILITY 0x17 -+#define RF_MODE_AG 0x18 -+#define RF_CHANNEL 0x18 -+#define RF_CHNLBW 0x18 -+#define RF_TOP 0x19 -+#define RF_RX_G1 0x1A -+#define RF_RX_G2 0x1B -+#define RF_RX_BB2 0x1C -+#define RF_RX_BB1 0x1D -+#define RF_RCK1 0x1E -+#define RF_RCK2 0x1F -+ -+#define RF_TX_G1 0x20 -+#define RF_TX_G2 0x21 -+#define RF_TX_G3 0x22 -+#define RF_TX_BB1 0x23 -+#define RF_T_METER 0x24 -+#define RF_SYN_G1 0x25 -+#define RF_SYN_G2 0x26 -+#define RF_SYN_G3 0x27 -+#define RF_SYN_G4 0x28 -+#define RF_SYN_G5 0x29 -+#define RF_SYN_G6 0x2A -+#define RF_SYN_G7 0x2B -+#define RF_SYN_G8 0x2C -+ -+#define RF_RCK_OS 0x30 -+#define RF_TXPA_G1 0x31 -+#define RF_TXPA_G2 0x32 -+#define RF_TXPA_G3 0x33 -+ -+#define BRFMOD 0x1 -+#define BCCKEN 0x1000000 -+#define BOFDMEN 0x2000000 -+ -+#define BXBTXAGC 0xf00 -+#define BXCTXAGC 0xf000 -+#define BXDTXAGC 0xf0000 -+ -+#define B3WIRE_DATALENGTH 0x800 -+#define B3WIRE_ADDRESSLENGTH 0x400 -+ -+#define BRFSI_RFENV 0x10 -+ -+#define BLSSI_READADDRESS 0x7f800000 -+#define BLSSI_READEDGE 0x80000000 -+#define BLSSI_READBACK_DATA 0xfffff -+ -+#define BADCLKPHASE 0x4000000 -+ -+#define BCCK_SIDEBAND 0x10 -+ -+#define BTX_AGCRATECCK 0x7f00 -+ -+#define MASKBYTE0 0xff -+#define MASKBYTE1 0xff00 -+#define MASKBYTE2 0xff0000 -+#define MASKBYTE3 0xff000000 -+#define MASKHWORD 0xffff0000 -+#define MASKLWORD 0x0000ffff -+#define MASKDWORD 0xffffffff -+ -+#define MAKS12BITS 0xfffff -+#define MASK20BITS 0xfffff -+#define RFREG_OFFSET_MASK 0xfffff -+ -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/rf.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/rf.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/rf.c 2011-05-05 23:29:49.279487705 +0200 -@@ -0,0 +1,546 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "rf.h" -+#include "dm.h" -+ -+ -+static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel, -+ u8 chnl, u32 *ofdmbase, u32 *mcsbase, -+ u8 *p_final_pwridx) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u32 pwrbase0, pwrbase1; -+ u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; -+ u8 i, pwrlevel[4]; -+ -+ for (i = 0; i < 2; i++) -+ pwrlevel[i] = p_pwrlevel[i]; -+ -+ /* We only care about the path A for legacy. */ -+ if (rtlefuse->eeprom_version < 2) { -+ pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf); -+ } else if (rtlefuse->eeprom_version >= 2) { -+ legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff -+ [RF90_PATH_A][chnl - 1]; -+ -+ /* For legacy OFDM, tx pwr always > HT OFDM pwr. -+ * We do not care Path B -+ * legacy OFDM pwr diff. NO BB register -+ * to notify HW. */ -+ pwrbase0 = pwrlevel[0] + legacy_pwrdiff; -+ } -+ -+ pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) | -+ pwrbase0; -+ *ofdmbase = pwrbase0; -+ -+ /* MCS rates */ -+ if (rtlefuse->eeprom_version >= 2) { -+ /* Check HT20 to HT40 diff */ -+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { -+ for (i = 0; i < 2; i++) { -+ /* rf-A, rf-B */ -+ /* HT 20<->40 pwr diff */ -+ ht20_pwrdiff = rtlefuse->txpwr_ht20diff -+ [i][chnl - 1]; -+ -+ if (ht20_pwrdiff < 8) /* 0~+7 */ -+ pwrlevel[i] += ht20_pwrdiff; -+ else /* index8-15=-8~-1 */ -+ pwrlevel[i] -= (16 - ht20_pwrdiff); -+ } -+ } -+ } -+ -+ /* use index of rf-A */ -+ pwrbase1 = pwrlevel[0]; -+ pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) | -+ pwrbase1; -+ *mcsbase = pwrbase1; -+ -+ /* The following is for Antenna -+ * diff from Ant-B to Ant-A */ -+ p_final_pwridx[0] = pwrlevel[0]; -+ p_final_pwridx[1] = pwrlevel[1]; -+ -+ switch (rtlefuse->eeprom_regulatory) { -+ case 3: -+ /* The following is for calculation -+ * of the power diff for Ant-B to Ant-A. */ -+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { -+ p_final_pwridx[0] += rtlefuse->pwrgroup_ht40 -+ [RF90_PATH_A][ -+ chnl - 1]; -+ p_final_pwridx[1] += rtlefuse->pwrgroup_ht40 -+ [RF90_PATH_B][ -+ chnl - 1]; -+ } else { -+ p_final_pwridx[0] += rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_A][ -+ chnl - 1]; -+ p_final_pwridx[1] += rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_B][ -+ chnl - 1]; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("40MHz finalpwr_idx " -+ "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], -+ p_final_pwridx[1])); -+ } else { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("20MHz finalpwr_idx " -+ "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], -+ p_final_pwridx[1])); -+ } -+} -+ -+static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw, -+ u8 *p_final_pwridx) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ char ant_pwr_diff = 0; -+ u32 u4reg_val = 0; -+ -+ if (rtlphy->rf_type == RF_2T2R) { -+ ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0]; -+ -+ /* range is from 7~-8, -+ * index = 0x0~0xf */ -+ if (ant_pwr_diff > 7) -+ ant_pwr_diff = 7; -+ if (ant_pwr_diff < -8) -+ ant_pwr_diff = -8; -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Antenna Diff from RF-B " -+ "to RF-A = %d (0x%x)\n", ant_pwr_diff, -+ ant_pwr_diff & 0xf)); -+ -+ ant_pwr_diff &= 0xf; -+ } -+ -+ /* Antenna TX power difference */ -+ rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */ -+ rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */ -+ rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */ -+ -+ u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 | -+ rtlefuse->antenna_txpwdiff[1] << 4 | -+ rtlefuse->antenna_txpwdiff[0]; -+ -+ rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC), -+ u4reg_val); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Write BCD-Diff(0x%x) = 0x%x\n", -+ RFPGA0_TXGAINSTAGE, u4reg_val)); -+} -+ -+static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, -+ u8 chnl, u8 index, -+ u32 pwrbase0, -+ u32 pwrbase1, -+ u32 *p_outwrite_val) -+{ -+ 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, pwrdiff_limit[4]; -+ u32 writeval, customer_limit; -+ -+ /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ -+ switch (rtlefuse->eeprom_regulatory) { -+ case 0: -+ /* Realtek better performance increase power diff -+ * defined by Realtek for large power */ -+ chnlgroup = 0; -+ -+ writeval = rtlphy->mcs_txpwrlevel_origoffset -+ [chnlgroup][index] + -+ ((index < 2) ? pwrbase0 : pwrbase1); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("RTK better performance, " -+ "writeval = 0x%x\n", writeval)); -+ break; -+ case 1: -+ /* Realtek regulatory increase power diff defined -+ * by Realtek for regulatory */ -+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { -+ writeval = ((index < 2) ? pwrbase0 : pwrbase1); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Realtek regulatory, " -+ "40MHz, writeval = 0x%x\n", writeval)); -+ } else { -+ if (rtlphy->pwrgroup_cnt == 1) -+ chnlgroup = 0; -+ -+ if (rtlphy->pwrgroup_cnt >= 3) { -+ if (chnl <= 3) -+ chnlgroup = 0; -+ else if (chnl >= 4 && chnl <= 8) -+ chnlgroup = 1; -+ else if (chnl > 8) -+ chnlgroup = 2; -+ if (rtlphy->pwrgroup_cnt == 4) -+ chnlgroup++; -+ } -+ -+ writeval = rtlphy->mcs_txpwrlevel_origoffset -+ [chnlgroup][index] -+ + ((index < 2) ? -+ pwrbase0 : pwrbase1); -+ -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Realtek regulatory, " -+ "20MHz, writeval = 0x%x\n", writeval)); -+ } -+ break; -+ case 2: -+ /* Better regulatory don't increase any power diff */ -+ writeval = ((index < 2) ? pwrbase0 : pwrbase1); -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Better regulatory, " -+ "writeval = 0x%x\n", writeval)); -+ break; -+ case 3: -+ /* Customer defined power diff. increase power diff -+ defined by customer. */ -+ chnlgroup = 0; -+ -+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("customer's limit, 40MHz = 0x%x\n", -+ rtlefuse->pwrgroup_ht40 -+ [RF90_PATH_A][chnl - 1])); -+ } else { -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("customer's limit, 20MHz = 0x%x\n", -+ rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_A][chnl - 1])); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ pwrdiff_limit[i] = -+ (u8)((rtlphy->mcs_txpwrlevel_origoffset -+ [chnlgroup][index] & (0x7f << (i * 8))) -+ >> (i * 8)); -+ -+ if (rtlphy->current_chan_bw == -+ HT_CHANNEL_WIDTH_20_40) { -+ if (pwrdiff_limit[i] > -+ rtlefuse->pwrgroup_ht40 -+ [RF90_PATH_A][chnl - 1]) { -+ pwrdiff_limit[i] = -+ rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_A][chnl - 1]; -+ } -+ } else { -+ if (pwrdiff_limit[i] > -+ rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_A][chnl - 1]) { -+ pwrdiff_limit[i] = -+ rtlefuse->pwrgroup_ht20 -+ [RF90_PATH_A][chnl - 1]; -+ } -+ } -+ } -+ -+ customer_limit = (pwrdiff_limit[3] << 24) | -+ (pwrdiff_limit[2] << 16) | -+ (pwrdiff_limit[1] << 8) | -+ (pwrdiff_limit[0]); -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Customer's limit = 0x%x\n", -+ customer_limit)); -+ -+ writeval = customer_limit + ((index < 2) ? -+ pwrbase0 : pwrbase1); -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("Customer, writeval = " -+ "0x%x\n", writeval)); -+ break; -+ default: -+ chnlgroup = 0; -+ writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] + -+ ((index < 2) ? pwrbase0 : pwrbase1); -+ RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, -+ ("RTK better performance, " -+ "writeval = 0x%x\n", writeval)); -+ break; -+ } -+ -+ if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1) -+ writeval = 0x10101010; -+ else if (rtlpriv->dm.dynamic_txhighpower_lvl == -+ TX_HIGH_PWR_LEVEL_LEVEL2) -+ writeval = 0x0; -+ -+ *p_outwrite_val = writeval; -+ -+} -+ -+static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw, -+ u8 index, u32 val) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; -+ u8 i, rfa_pwr[4]; -+ u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; -+ u32 writeval = val; -+ -+ /* If path A and Path B coexist, we must limit Path A tx power. -+ * Protect Path B pwr over or under flow. We need to calculate -+ * upper and lower bound of path A tx power. */ -+ if (rtlphy->rf_type == RF_2T2R) { -+ rf_pwr_diff = rtlefuse->antenna_txpwdiff[0]; -+ -+ /* Diff=-8~-1 */ -+ if (rf_pwr_diff >= 8) { -+ /* Prevent underflow!! */ -+ rfa_lower_bound = 0x10 - rf_pwr_diff; -+ /* if (rf_pwr_diff >= 0) Diff = 0-7 */ -+ } else { -+ rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff; -+ } -+ } -+ -+ for (i = 0; i < 4; i++) { -+ rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); -+ if (rfa_pwr[i] > RF6052_MAX_TX_PWR) -+ rfa_pwr[i] = RF6052_MAX_TX_PWR; -+ -+ /* If path A and Path B coexist, we must limit Path A tx power. -+ * Protect Path B pwr over or under flow. We need to calculate -+ * upper and lower bound of path A tx power. */ -+ if (rtlphy->rf_type == RF_2T2R) { -+ /* Diff=-8~-1 */ -+ if (rf_pwr_diff >= 8) { -+ /* Prevent underflow!! */ -+ if (rfa_pwr[i] < rfa_lower_bound) -+ rfa_pwr[i] = rfa_lower_bound; -+ /* Diff = 0-7 */ -+ } else if (rf_pwr_diff >= 1) { -+ /* Prevent overflow */ -+ if (rfa_pwr[i] > rfa_upper_bound) -+ rfa_pwr[i] = rfa_upper_bound; -+ } -+ } -+ -+ } -+ -+ writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) | -+ rfa_pwr[0]; -+ -+ rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval); -+} -+ -+void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, -+ u8 *p_pwrlevel, u8 chnl) -+{ -+ u32 writeval, pwrbase0, pwrbase1; -+ u8 index = 0; -+ u8 finalpwr_idx[4]; -+ -+ _rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1, -+ &finalpwr_idx[0]); -+ _rtl92s_set_antennadiff(hw, &finalpwr_idx[0]); -+ -+ for (index = 0; index < 6; index++) { -+ _rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index, -+ pwrbase0, pwrbase1, &writeval); -+ -+ _rtl92s_write_ofdm_powerreg(hw, index, writeval); -+ } -+} -+ -+void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ u32 txagc = 0; -+ bool dont_inc_cck_or_turboscanoff = false; -+ -+ if (((rtlefuse->eeprom_version >= 2) && -+ (rtlefuse->txpwr_safetyflag == 1)) || -+ ((rtlefuse->eeprom_version >= 2) && -+ (rtlefuse->eeprom_regulatory != 0))) -+ dont_inc_cck_or_turboscanoff = true; -+ -+ if (mac->act_scanning == true) { -+ txagc = 0x3f; -+ if (dont_inc_cck_or_turboscanoff) -+ txagc = pwrlevel; -+ } else { -+ txagc = pwrlevel; -+ -+ if (rtlpriv->dm.dynamic_txhighpower_lvl == -+ TX_HIGH_PWR_LEVEL_LEVEL1) -+ txagc = 0x10; -+ else if (rtlpriv->dm.dynamic_txhighpower_lvl == -+ TX_HIGH_PWR_LEVEL_LEVEL2) -+ txagc = 0x0; -+ } -+ -+ if (txagc > RF6052_MAX_TX_PWR) -+ txagc = RF6052_MAX_TX_PWR; -+ -+ rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc); -+ -+} -+ -+bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u32 u4reg_val = 0; -+ u8 rfpath; -+ bool rtstatus = true; -+ struct bb_reg_def *pphyreg; -+ -+ /* Initialize RF */ -+ for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { -+ -+ pphyreg = &rtlphy->phyreg_def[rfpath]; -+ -+ /* Store original RFENV control type */ -+ switch (rfpath) { -+ case RF90_PATH_A: -+ case RF90_PATH_C: -+ u4reg_val = rtl92s_phy_query_bb_reg(hw, -+ pphyreg->rfintfs, -+ BRFSI_RFENV); -+ break; -+ case RF90_PATH_B: -+ case RF90_PATH_D: -+ u4reg_val = rtl92s_phy_query_bb_reg(hw, -+ pphyreg->rfintfs, -+ BRFSI_RFENV << 16); -+ break; -+ } -+ -+ /* Set RF_ENV enable */ -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe, -+ BRFSI_RFENV << 16, 0x1); -+ -+ /* Set RF_ENV output high */ -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); -+ -+ /* Set bit number of Address and Data for RF register */ -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, -+ B3WIRE_ADDRESSLENGTH, 0x0); -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, -+ B3WIRE_DATALENGTH, 0x0); -+ -+ /* Initialize RF fom connfiguration file */ -+ switch (rfpath) { -+ case RF90_PATH_A: -+ rtstatus = rtl92s_phy_config_rf(hw, -+ (enum radio_path)rfpath); -+ break; -+ case RF90_PATH_B: -+ rtstatus = rtl92s_phy_config_rf(hw, -+ (enum radio_path)rfpath); -+ break; -+ case RF90_PATH_C: -+ break; -+ case RF90_PATH_D: -+ break; -+ } -+ -+ /* Restore RFENV control type */ -+ switch (rfpath) { -+ case RF90_PATH_A: -+ case RF90_PATH_C: -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV, -+ u4reg_val); -+ break; -+ case RF90_PATH_B: -+ case RF90_PATH_D: -+ rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, -+ BRFSI_RFENV << 16, -+ u4reg_val); -+ break; -+ } -+ -+ if (rtstatus != true) { -+ printk(KERN_ERR "Radio[%d] Fail!!", rfpath); -+ goto fail; -+ } -+ -+ } -+ -+ return rtstatus; -+ -+fail: -+ return rtstatus; -+} -+ -+void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ -+ switch (bandwidth) { -+ case HT_CHANNEL_WIDTH_20: -+ rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & -+ 0xfffff3ff) | 0x0400); -+ rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, -+ rtlphy->rfreg_chnlval[0]); -+ break; -+ case HT_CHANNEL_WIDTH_20_40: -+ rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & -+ 0xfffff3ff)); -+ rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, -+ rtlphy->rfreg_chnlval[0]); -+ break; -+ default: -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("unknown bandwidth: %#X\n", -+ bandwidth)); -+ break; -+ } -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/rf.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/rf.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/rf.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/rf.h 2011-05-05 23:29:49.280487717 +0200 -@@ -0,0 +1,43 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __INC_RTL92S_RF_H -+#define __INC_RTL92S_RF_H -+ -+#define RF6052_MAX_TX_PWR 0x3F -+ -+void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, -+ u8 bandwidth); -+bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ; -+void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, -+ u8 powerlevel); -+void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, -+ u8 *p_pwrlevel, u8 chnl); -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/sw.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/sw.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/sw.c 2011-05-05 23:29:49.284487765 +0200 -@@ -0,0 +1,421 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include -+ -+#include "../wifi.h" -+#include "../core.h" -+#include "../pci.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "dm.h" -+#include "fw.h" -+#include "hw.h" -+#include "sw.h" -+#include "trx.h" -+#include "led.h" -+ -+static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ -+ /*close ASPM for AMD defaultly */ -+ rtlpci->const_amdpci_aspm = 0; -+ -+ /* -+ * ASPM PS mode. -+ * 0 - Disable ASPM, -+ * 1 - Enable ASPM without Clock Req, -+ * 2 - Enable ASPM with Clock Req, -+ * 3 - Alwyas Enable ASPM with Clock Req, -+ * 4 - Always Enable ASPM without Clock Req. -+ * set defult to RTL8192CE:3 RTL8192E:2 -+ * */ -+ rtlpci->const_pci_aspm = 0; /* changed from 2 due to crashes */ -+ -+ /*Setting for PCI-E device */ -+ rtlpci->const_devicepci_aspm_setting = 0x03; -+ -+ /*Setting for PCI-E bridge */ -+ rtlpci->const_hostpci_aspm_setting = 0x02; -+ -+ /* -+ * In Hw/Sw Radio Off situation. -+ * 0 - Default, -+ * 1 - From ASPM setting without low Mac Pwr, -+ * 2 - From ASPM setting with low Mac Pwr, -+ * 3 - Bus D3 -+ * set default to RTL8192CE:0 RTL8192SE:2 -+ */ -+ rtlpci->const_hwsw_rfoff_d3 = 2; -+ -+ /* -+ * This setting works for those device with -+ * backdoor ASPM setting such as EPHY setting. -+ * 0 - Not support ASPM, -+ * 1 - Support ASPM, -+ * 2 - According to chipset. -+ */ -+ rtlpci->const_support_pciaspm = 2; -+} -+ -+static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ const struct firmware *firmware; -+ struct rt_firmware *pfirmware = NULL; -+ int err = 0; -+ u16 earlyrxthreshold = 7; -+ -+ rtlpriv->dm.dm_initialgain_enable = 1; -+ rtlpriv->dm.dm_flag = 0; -+ rtlpriv->dm.disable_framebursting = 0; -+ rtlpriv->dm.thermalvalue = 0; -+ rtlpriv->dm.useramask = true; -+ -+ /* compatible 5G band 91se just 2.4G band & smsp */ -+ rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; -+ rtlpriv->rtlhal.bandset = BAND_ON_2_4G; -+ rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; -+ -+ rtlpci->transmit_config = 0; -+ -+ rtlpci->receive_config = -+ RCR_APPFCS | -+ RCR_APWRMGT | -+ /*RCR_ADD3 |*/ -+ RCR_AMF | -+ RCR_ADF | -+ RCR_APP_MIC | -+ RCR_APP_ICV | -+ RCR_AICV | -+ /* Accept ICV error, CRC32 Error */ -+ RCR_ACRC32 | -+ RCR_AB | -+ /* Accept Broadcast, Multicast */ -+ RCR_AM | -+ /* Accept Physical match */ -+ RCR_APM | -+ /* Accept Destination Address packets */ -+ /*RCR_AAP |*/ -+ RCR_APP_PHYST_STAFF | -+ /* Accept PHY status */ -+ RCR_APP_PHYST_RXFF | -+ (earlyrxthreshold << RCR_FIFO_OFFSET); -+ -+ rtlpci->irq_mask[0] = (u32) -+ (IMR_ROK | -+ IMR_VODOK | -+ IMR_VIDOK | -+ IMR_BEDOK | -+ IMR_BKDOK | -+ IMR_HCCADOK | -+ IMR_MGNTDOK | -+ IMR_COMDOK | -+ IMR_HIGHDOK | -+ IMR_BDOK | -+ IMR_RXCMDOK | -+ /*IMR_TIMEOUT0 |*/ -+ IMR_RDU | -+ IMR_RXFOVW | -+ IMR_BCNINT -+ /*| IMR_TXFOVW*/ -+ /*| IMR_TBDOK | -+ IMR_TBDER*/); -+ -+ rtlpci->irq_mask[1] = (u32) 0; -+ -+ rtlpci->shortretry_limit = 0x30; -+ rtlpci->longretry_limit = 0x30; -+ -+ rtlpci->first_init = true; -+ -+ /* for LPS & IPS */ -+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; -+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; -+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; -+ rtlpriv->psc.reg_fwctrl_lps = 3; -+ rtlpriv->psc.reg_max_lps_awakeintvl = 5; -+ /* for ASPM, you can close aspm through -+ * set const_support_pciaspm = 0 */ -+ rtl92s_init_aspm_vars(hw); -+ -+ if (rtlpriv->psc.reg_fwctrl_lps == 1) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; -+ else if (rtlpriv->psc.reg_fwctrl_lps == 2) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; -+ else if (rtlpriv->psc.reg_fwctrl_lps == 3) -+ rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; -+ -+ /* for firmware buf */ -+ rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); -+ if (!rtlpriv->rtlhal.pfirmware) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Can't alloc buffer for fw.\n")); -+ return 1; -+ } -+ -+ /* request fw */ -+ err = request_firmware(&firmware, rtlpriv->cfg->fw_name, -+ rtlpriv->io.dev); -+ if (err) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Failed to request firmware!\n")); -+ return 1; -+ } -+ if (firmware->size > sizeof(struct rt_firmware)) { -+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -+ ("Firmware is too big!\n")); -+ release_firmware(firmware); -+ return 1; -+ } -+ -+ pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; -+ memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); -+ pfirmware->sz_fw_tmpbufferlen = firmware->size; -+ release_firmware(firmware); -+ -+ return err; -+} -+ -+static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ -+ if (rtlpriv->rtlhal.pfirmware) { -+ vfree(rtlpriv->rtlhal.pfirmware); -+ rtlpriv->rtlhal.pfirmware = NULL; -+ } -+} -+ -+static struct rtl_hal_ops rtl8192se_hal_ops = { -+ .init_sw_vars = rtl92s_init_sw_vars, -+ .deinit_sw_vars = rtl92s_deinit_sw_vars, -+ .read_eeprom_info = rtl92se_read_eeprom_info, -+ .interrupt_recognized = rtl92se_interrupt_recognized, -+ .hw_init = rtl92se_hw_init, -+ .hw_disable = rtl92se_card_disable, -+ .hw_suspend = rtl92se_suspend, -+ .hw_resume = rtl92se_resume, -+ .enable_interrupt = rtl92se_enable_interrupt, -+ .disable_interrupt = rtl92se_disable_interrupt, -+ .set_network_type = rtl92se_set_network_type, -+ .set_chk_bssid = rtl92se_set_check_bssid, -+ .set_qos = rtl92se_set_qos, -+ .set_bcn_reg = rtl92se_set_beacon_related_registers, -+ .set_bcn_intv = rtl92se_set_beacon_interval, -+ .update_interrupt_mask = rtl92se_update_interrupt_mask, -+ .get_hw_reg = rtl92se_get_hw_reg, -+ .set_hw_reg = rtl92se_set_hw_reg, -+ .update_rate_tbl = rtl92se_update_hal_rate_tbl, -+ .fill_tx_desc = rtl92se_tx_fill_desc, -+ .fill_tx_cmddesc = rtl92se_tx_fill_cmddesc, -+ .query_rx_desc = rtl92se_rx_query_desc, -+ .set_channel_access = rtl92se_update_channel_access_setting, -+ .radio_onoff_checking = rtl92se_gpio_radio_on_off_checking, -+ .set_bw_mode = rtl92s_phy_set_bw_mode, -+ .switch_channel = rtl92s_phy_sw_chnl, -+ .dm_watchdog = rtl92s_dm_watchdog, -+ .scan_operation_backup = rtl92s_phy_scan_operation_backup, -+ .set_rf_power_state = rtl92s_phy_set_rf_power_state, -+ .led_control = rtl92se_led_control, -+ .set_desc = rtl92se_set_desc, -+ .get_desc = rtl92se_get_desc, -+ .tx_polling = rtl92se_tx_polling, -+ .enable_hw_sec = rtl92se_enable_hw_security_config, -+ .set_key = rtl92se_set_key, -+ .init_sw_leds = rtl92se_init_sw_leds, -+ .get_bbreg = rtl92s_phy_query_bb_reg, -+ .set_bbreg = rtl92s_phy_set_bb_reg, -+ .get_rfreg = rtl92s_phy_query_rf_reg, -+ .set_rfreg = rtl92s_phy_set_rf_reg, -+}; -+ -+static struct rtl_mod_params rtl92se_mod_params = { -+ .sw_crypto = false, -+ .inactiveps = true, -+ .swctrl_lps = true, -+ .fwctrl_lps = false, -+}; -+ -+/* Because memory R/W bursting will cause system hang/crash -+ * for 92se, so we don't read back after every write action */ -+static struct rtl_hal_cfg rtl92se_hal_cfg = { -+ .bar_id = 1, -+ .write_readback = false, -+ .name = "rtl92s_pci", -+ .fw_name = "rtlwifi/rtl8192sefw.bin", -+ .ops = &rtl8192se_hal_ops, -+ .mod_params = &rtl92se_mod_params, -+ -+ .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, -+ .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, -+ .maps[SYS_CLK] = SYS_CLKR, -+ .maps[MAC_RCR_AM] = RCR_AM, -+ .maps[MAC_RCR_AB] = RCR_AB, -+ .maps[MAC_RCR_ACRC32] = RCR_ACRC32, -+ .maps[MAC_RCR_ACF] = RCR_ACF, -+ .maps[MAC_RCR_AAP] = RCR_AAP, -+ -+ .maps[EFUSE_TEST] = REG_EFUSE_TEST, -+ .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, -+ .maps[EFUSE_CLK] = REG_EFUSE_CLK, -+ .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, -+ .maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */ -+ .maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */ -+ .maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */ -+ .maps[EFUSE_ANA8M] = EFUSE_ANA8M, -+ .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S, -+ .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, -+ .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, -+ -+ .maps[RWCAM] = REG_RWCAM, -+ .maps[WCAMI] = REG_WCAMI, -+ .maps[RCAMO] = REG_RCAMO, -+ .maps[CAMDBG] = REG_CAMDBG, -+ .maps[SECR] = REG_SECR, -+ .maps[SEC_CAM_NONE] = CAM_NONE, -+ .maps[SEC_CAM_WEP40] = CAM_WEP40, -+ .maps[SEC_CAM_TKIP] = CAM_TKIP, -+ .maps[SEC_CAM_AES] = CAM_AES, -+ .maps[SEC_CAM_WEP104] = CAM_WEP104, -+ -+ .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, -+ .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, -+ .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, -+ .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, -+ .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, -+ .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, -+ .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, -+ .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, -+ .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, -+ .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, -+ .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, -+ .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, -+ .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, -+ .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, -+ .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, -+ .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, -+ -+ .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, -+ .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, -+ .maps[RTL_IMR_BcnInt] = IMR_BCNINT, -+ .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, -+ .maps[RTL_IMR_RDU] = IMR_RDU, -+ .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, -+ .maps[RTL_IMR_BDOK] = IMR_BDOK, -+ .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, -+ .maps[RTL_IMR_TBDER] = IMR_TBDER, -+ .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, -+ .maps[RTL_IMR_COMDOK] = IMR_COMDOK, -+ .maps[RTL_IMR_TBDOK] = IMR_TBDOK, -+ .maps[RTL_IMR_BKDOK] = IMR_BKDOK, -+ .maps[RTL_IMR_BEDOK] = IMR_BEDOK, -+ .maps[RTL_IMR_VIDOK] = IMR_VIDOK, -+ .maps[RTL_IMR_VODOK] = IMR_VODOK, -+ .maps[RTL_IMR_ROK] = IMR_ROK, -+ .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), -+ -+ .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, -+ .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, -+ .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, -+ .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, -+ .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, -+ .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, -+ .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, -+ .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, -+ .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, -+ .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, -+ .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, -+ .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, -+ -+ .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, -+ .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, -+}; -+ -+static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { -+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, -+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, -+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, -+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)}, -+ {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); -+ -+MODULE_AUTHOR("lizhaoming "); -+MODULE_AUTHOR("Realtek WlanFAE "); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); -+MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); -+ -+module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444); -+module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); -+module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); -+module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); -+MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); -+MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); -+MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is " -+ "open)\n"); -+ -+ -+static struct pci_driver rtl92se_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = rtl92se_pci_ids, -+ .probe = rtl_pci_probe, -+ .remove = rtl_pci_disconnect, -+ -+#ifdef CONFIG_PM -+ .suspend = rtl_pci_suspend, -+ .resume = rtl_pci_resume, -+#endif -+ -+}; -+ -+static int __init rtl92se_module_init(void) -+{ -+ int ret = 0; -+ -+ ret = pci_register_driver(&rtl92se_driver); -+ if (ret) -+ RT_ASSERT(false, (": No device found\n")); -+ -+ return ret; -+} -+ -+static void __exit rtl92se_module_exit(void) -+{ -+ pci_unregister_driver(&rtl92se_driver); -+} -+ -+module_init(rtl92se_module_init); -+module_exit(rtl92se_module_exit); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/sw.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/sw.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/sw.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/sw.h 2011-05-05 23:29:49.275487657 +0200 -@@ -0,0 +1,36 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_PCI92SE_SW_H__ -+#define __REALTEK_PCI92SE_SW_H__ -+ -+#define EFUSE_MAX_SECTION 16 -+ -+int rtl92se_init_sw(struct ieee80211_hw *hw); -+void rtl92se_deinit_sw(struct ieee80211_hw *hw); -+void rtl92se_init_var_map(struct ieee80211_hw *hw); -+ -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/table.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/table.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/table.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/table.c 2011-05-05 23:29:49.277487681 +0200 -@@ -0,0 +1,634 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ * Created on 2010/ 5/18, 1:41 -+ *****************************************************************************/ -+ -+#include "table.h" -+ -+u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = { -+ 0x01c, 0x07000000, -+ 0x800, 0x00040000, -+ 0x804, 0x00008003, -+ 0x808, 0x0000fc00, -+ 0x80c, 0x0000000a, -+ 0x810, 0x10005088, -+ 0x814, 0x020c3d10, -+ 0x818, 0x00200185, -+ 0x81c, 0x00000000, -+ 0x820, 0x01000000, -+ 0x824, 0x00390004, -+ 0x828, 0x01000000, -+ 0x82c, 0x00390004, -+ 0x830, 0x00000004, -+ 0x834, 0x00690200, -+ 0x838, 0x00000004, -+ 0x83c, 0x00690200, -+ 0x840, 0x00010000, -+ 0x844, 0x00010000, -+ 0x848, 0x00000000, -+ 0x84c, 0x00000000, -+ 0x850, 0x00000000, -+ 0x854, 0x00000000, -+ 0x858, 0x48484848, -+ 0x85c, 0x65a965a9, -+ 0x860, 0x0f7f0130, -+ 0x864, 0x0f7f0130, -+ 0x868, 0x0f7f0130, -+ 0x86c, 0x0f7f0130, -+ 0x870, 0x03000700, -+ 0x874, 0x03000300, -+ 0x878, 0x00020002, -+ 0x87c, 0x004f0201, -+ 0x880, 0xa8300ac1, -+ 0x884, 0x00000058, -+ 0x888, 0x00000008, -+ 0x88c, 0x00000004, -+ 0x890, 0x00000000, -+ 0x894, 0xfffffffe, -+ 0x898, 0x40302010, -+ 0x89c, 0x00706050, -+ 0x8b0, 0x00000000, -+ 0x8e0, 0x00000000, -+ 0x8e4, 0x00000000, -+ 0xe00, 0x30333333, -+ 0xe04, 0x2a2d2e2f, -+ 0xe08, 0x00003232, -+ 0xe10, 0x30333333, -+ 0xe14, 0x2a2d2e2f, -+ 0xe18, 0x30333333, -+ 0xe1c, 0x2a2d2e2f, -+ 0xe30, 0x01007c00, -+ 0xe34, 0x01004800, -+ 0xe38, 0x1000dc1f, -+ 0xe3c, 0x10008c1f, -+ 0xe40, 0x021400a0, -+ 0xe44, 0x281600a0, -+ 0xe48, 0xf8000001, -+ 0xe4c, 0x00002910, -+ 0xe50, 0x01007c00, -+ 0xe54, 0x01004800, -+ 0xe58, 0x1000dc1f, -+ 0xe5c, 0x10008c1f, -+ 0xe60, 0x021400a0, -+ 0xe64, 0x281600a0, -+ 0xe6c, 0x00002910, -+ 0xe70, 0x31ed92fb, -+ 0xe74, 0x361536fb, -+ 0xe78, 0x361536fb, -+ 0xe7c, 0x361536fb, -+ 0xe80, 0x361536fb, -+ 0xe84, 0x000d92fb, -+ 0xe88, 0x000d92fb, -+ 0xe8c, 0x31ed92fb, -+ 0xed0, 0x31ed92fb, -+ 0xed4, 0x31ed92fb, -+ 0xed8, 0x000d92fb, -+ 0xedc, 0x000d92fb, -+ 0xee0, 0x000d92fb, -+ 0xee4, 0x015e5448, -+ 0xee8, 0x21555448, -+ 0x900, 0x00000000, -+ 0x904, 0x00000023, -+ 0x908, 0x00000000, -+ 0x90c, 0x01121313, -+ 0xa00, 0x00d047c8, -+ 0xa04, 0x80ff0008, -+ 0xa08, 0x8ccd8300, -+ 0xa0c, 0x2e62120f, -+ 0xa10, 0x9500bb78, -+ 0xa14, 0x11144028, -+ 0xa18, 0x00881117, -+ 0xa1c, 0x89140f00, -+ 0xa20, 0x1a1b0000, -+ 0xa24, 0x090e1317, -+ 0xa28, 0x00000204, -+ 0xa2c, 0x10d30000, -+ 0xc00, 0x40071d40, -+ 0xc04, 0x00a05633, -+ 0xc08, 0x000000e4, -+ 0xc0c, 0x6c6c6c6c, -+ 0xc10, 0x08800000, -+ 0xc14, 0x40000100, -+ 0xc18, 0x08000000, -+ 0xc1c, 0x40000100, -+ 0xc20, 0x08000000, -+ 0xc24, 0x40000100, -+ 0xc28, 0x08000000, -+ 0xc2c, 0x40000100, -+ 0xc30, 0x6de9ac44, -+ 0xc34, 0x469652cf, -+ 0xc38, 0x49795994, -+ 0xc3c, 0x0a979764, -+ 0xc40, 0x1f7c403f, -+ 0xc44, 0x000100b7, -+ 0xc48, 0xec020000, -+ 0xc4c, 0x007f037f, -+ 0xc50, 0x69543420, -+ 0xc54, 0x433c0094, -+ 0xc58, 0x69543420, -+ 0xc5c, 0x433c0094, -+ 0xc60, 0x69543420, -+ 0xc64, 0x433c0094, -+ 0xc68, 0x69543420, -+ 0xc6c, 0x433c0094, -+ 0xc70, 0x2c7f000d, -+ 0xc74, 0x0186155b, -+ 0xc78, 0x0000001f, -+ 0xc7c, 0x00b91612, -+ 0xc80, 0x40000100, -+ 0xc84, 0x20f60000, -+ 0xc88, 0x20000080, -+ 0xc8c, 0x20200000, -+ 0xc90, 0x40000100, -+ 0xc94, 0x00000000, -+ 0xc98, 0x40000100, -+ 0xc9c, 0x00000000, -+ 0xca0, 0x00492492, -+ 0xca4, 0x00000000, -+ 0xca8, 0x00000000, -+ 0xcac, 0x00000000, -+ 0xcb0, 0x00000000, -+ 0xcb4, 0x00000000, -+ 0xcb8, 0x00000000, -+ 0xcbc, 0x28000000, -+ 0xcc0, 0x00000000, -+ 0xcc4, 0x00000000, -+ 0xcc8, 0x00000000, -+ 0xccc, 0x00000000, -+ 0xcd0, 0x00000000, -+ 0xcd4, 0x00000000, -+ 0xcd8, 0x64b22427, -+ 0xcdc, 0x00766932, -+ 0xce0, 0x00222222, -+ 0xce4, 0x00000000, -+ 0xce8, 0x37644302, -+ 0xcec, 0x2f97d40c, -+ 0xd00, 0x00000750, -+ 0xd04, 0x00000403, -+ 0xd08, 0x0000907f, -+ 0xd0c, 0x00000001, -+ 0xd10, 0xa0633333, -+ 0xd14, 0x33333c63, -+ 0xd18, 0x6a8f5b6b, -+ 0xd1c, 0x00000000, -+ 0xd20, 0x00000000, -+ 0xd24, 0x00000000, -+ 0xd28, 0x00000000, -+ 0xd2c, 0xcc979975, -+ 0xd30, 0x00000000, -+ 0xd34, 0x00000000, -+ 0xd38, 0x00000000, -+ 0xd3c, 0x00027293, -+ 0xd40, 0x00000000, -+ 0xd44, 0x00000000, -+ 0xd48, 0x00000000, -+ 0xd50, 0x6437140a, -+ 0xd54, 0x024dbd02, -+ 0xd58, 0x00000000, -+ 0xd5c, 0x30032064, -+ 0xd60, 0x4653de68, -+ 0xd64, 0x00518a3c, -+ 0xd68, 0x00002101, -+ 0xf14, 0x00000003, -+ 0xf4c, 0x00000000, -+ 0xf00, 0x00000300, -+}; -+ -+u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = { -+ 0x844, 0xffffffff, 0x00010000, -+ 0x804, 0x0000000f, 0x00000001, -+ 0x824, 0x00f0000f, 0x00300004, -+ 0x82c, 0x00f0000f, 0x00100002, -+ 0x870, 0x04000000, 0x00000001, -+ 0x864, 0x00000400, 0x00000000, -+ 0x878, 0x000f000f, 0x00000002, -+ 0xe74, 0x0f000000, 0x00000002, -+ 0xe78, 0x0f000000, 0x00000002, -+ 0xe7c, 0x0f000000, 0x00000002, -+ 0xe80, 0x0f000000, 0x00000002, -+ 0x90c, 0x000000ff, 0x00000011, -+ 0xc04, 0x000000ff, 0x00000011, -+ 0xd04, 0x0000000f, 0x00000001, -+ 0x1f4, 0xffff0000, 0x00007777, -+ 0x234, 0xf8000000, 0x0000000a, -+}; -+ -+u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = { -+ 0x804, 0x0000000f, 0x00000003, -+ 0x824, 0x00f0000f, 0x00300004, -+ 0x82c, 0x00f0000f, 0x00300002, -+ 0x870, 0x04000000, 0x00000001, -+ 0x864, 0x00000400, 0x00000000, -+ 0x878, 0x000f000f, 0x00000002, -+ 0xe74, 0x0f000000, 0x00000002, -+ 0xe78, 0x0f000000, 0x00000002, -+ 0xe7c, 0x0f000000, 0x00000002, -+ 0xe80, 0x0f000000, 0x00000002, -+ 0x90c, 0x000000ff, 0x00000011, -+ 0xc04, 0x000000ff, 0x00000033, -+ 0xd04, 0x0000000f, 0x00000003, -+ 0x1f4, 0xffff0000, 0x00007777, -+ 0x234, 0xf8000000, 0x0000000a, -+}; -+ -+u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = { -+ 0xe00, 0xffffffff, 0x06090909, -+ 0xe04, 0xffffffff, 0x00030406, -+ 0xe08, 0x0000ff00, 0x00000000, -+ 0xe10, 0xffffffff, 0x0a0c0d0e, -+ 0xe14, 0xffffffff, 0x04070809, -+ 0xe18, 0xffffffff, 0x0a0c0d0e, -+ 0xe1c, 0xffffffff, 0x04070809, -+ 0xe00, 0xffffffff, 0x04040404, -+ 0xe04, 0xffffffff, 0x00020204, -+ 0xe08, 0x0000ff00, 0x00000000, -+ 0xe10, 0xffffffff, 0x02040404, -+ 0xe14, 0xffffffff, 0x00000002, -+ 0xe18, 0xffffffff, 0x02040404, -+ 0xe1c, 0xffffffff, 0x00000002, -+ 0xe00, 0xffffffff, 0x04040404, -+ 0xe04, 0xffffffff, 0x00020204, -+ 0xe08, 0x0000ff00, 0x00000000, -+ 0xe10, 0xffffffff, 0x02040404, -+ 0xe14, 0xffffffff, 0x00000002, -+ 0xe18, 0xffffffff, 0x02040404, -+ 0xe1c, 0xffffffff, 0x00000002, -+ 0xe00, 0xffffffff, 0x02020202, -+ 0xe04, 0xffffffff, 0x00020202, -+ 0xe08, 0x0000ff00, 0x00000000, -+ 0xe10, 0xffffffff, 0x02020202, -+ 0xe14, 0xffffffff, 0x00000002, -+ 0xe18, 0xffffffff, 0x02020202, -+ 0xe1c, 0xffffffff, 0x00000002, -+}; -+ -+u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = { -+ 0x000, 0x00030159, -+ 0x001, 0x00030250, -+ 0x002, 0x00010000, -+ 0x010, 0x0008000f, -+ 0x011, 0x000231fc, -+ 0x010, 0x000c000f, -+ 0x011, 0x0003f9f8, -+ 0x010, 0x0002000f, -+ 0x011, 0x00020101, -+ 0x014, 0x0001093e, -+ 0x014, 0x0009093e, -+ 0x015, 0x0000f8f4, -+ 0x017, 0x000f6500, -+ 0x01a, 0x00013056, -+ 0x01b, 0x00060000, -+ 0x01c, 0x00000300, -+ 0x01e, 0x00031059, -+ 0x021, 0x00054000, -+ 0x022, 0x0000083c, -+ 0x023, 0x00001558, -+ 0x024, 0x00000060, -+ 0x025, 0x00022583, -+ 0x026, 0x0000f200, -+ 0x027, 0x000eacf1, -+ 0x028, 0x0009bd54, -+ 0x029, 0x00004582, -+ 0x02a, 0x00000001, -+ 0x02b, 0x00021334, -+ 0x02a, 0x00000000, -+ 0x02b, 0x0000000a, -+ 0x02a, 0x00000001, -+ 0x02b, 0x00000808, -+ 0x02b, 0x00053333, -+ 0x02c, 0x0000000c, -+ 0x02a, 0x00000002, -+ 0x02b, 0x00000808, -+ 0x02b, 0x0005b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000003, -+ 0x02b, 0x00000808, -+ 0x02b, 0x00063333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000004, -+ 0x02b, 0x00000808, -+ 0x02b, 0x0006b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000005, -+ 0x02b, 0x00000709, -+ 0x02b, 0x00053333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000006, -+ 0x02b, 0x00000709, -+ 0x02b, 0x0005b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000007, -+ 0x02b, 0x00000709, -+ 0x02b, 0x00063333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000008, -+ 0x02b, 0x00000709, -+ 0x02b, 0x0006b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x00000009, -+ 0x02b, 0x0000060a, -+ 0x02b, 0x00053333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x0000000a, -+ 0x02b, 0x0000060a, -+ 0x02b, 0x0005b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x0000000b, -+ 0x02b, 0x0000060a, -+ 0x02b, 0x00063333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x0000000c, -+ 0x02b, 0x0000060a, -+ 0x02b, 0x0006b333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x0000000d, -+ 0x02b, 0x0000050b, -+ 0x02b, 0x00053333, -+ 0x02c, 0x0000000d, -+ 0x02a, 0x0000000e, -+ 0x02b, 0x0000050b, -+ 0x02b, 0x00066623, -+ 0x02c, 0x0000001a, -+ 0x02a, 0x000e4000, -+ 0x030, 0x00020000, -+ 0x031, 0x000b9631, -+ 0x032, 0x0000130d, -+ 0x033, 0x00000187, -+ 0x013, 0x00019e6c, -+ 0x013, 0x00015e94, -+ 0x000, 0x00010159, -+ 0x018, 0x0000f401, -+ 0x0fe, 0x00000000, -+ 0x01e, 0x0003105b, -+ 0x0fe, 0x00000000, -+ 0x000, 0x00030159, -+ 0x010, 0x0004000f, -+ 0x011, 0x000203f9, -+}; -+ -+u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = { -+ 0x000, 0x00030159, -+ 0x001, 0x00001041, -+ 0x002, 0x00011000, -+ 0x005, 0x00080fc0, -+ 0x007, 0x000fc803, -+ 0x013, 0x00017cb0, -+ 0x013, 0x00011cc0, -+ 0x013, 0x0000dc60, -+ 0x013, 0x00008c60, -+ 0x013, 0x00004450, -+ 0x013, 0x00000020, -+}; -+ -+u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = { -+ 0x000, 0x00030159, -+ 0x001, 0x00001041, -+ 0x002, 0x00011000, -+ 0x005, 0x00080fc0, -+ 0x007, 0x000fc803, -+}; -+ -+u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = { -+ 0x020, 0x00000035, -+ 0x048, 0x0000000e, -+ 0x049, 0x000000f0, -+ 0x04a, 0x00000077, -+ 0x04b, 0x00000083, -+ 0x0b5, 0x00000021, -+ 0x0dc, 0x000000ff, -+ 0x0dd, 0x000000ff, -+ 0x0de, 0x000000ff, -+ 0x0df, 0x000000ff, -+ 0x116, 0x00000000, -+ 0x117, 0x00000000, -+ 0x118, 0x00000000, -+ 0x119, 0x00000000, -+ 0x11a, 0x00000000, -+ 0x11b, 0x00000000, -+ 0x11c, 0x00000000, -+ 0x11d, 0x00000000, -+ 0x160, 0x0000000b, -+ 0x161, 0x0000000b, -+ 0x162, 0x0000000b, -+ 0x163, 0x0000000b, -+ 0x164, 0x0000000b, -+ 0x165, 0x0000000b, -+ 0x166, 0x0000000b, -+ 0x167, 0x0000000b, -+ 0x168, 0x0000000b, -+ 0x169, 0x0000000b, -+ 0x16a, 0x0000000b, -+ 0x16b, 0x0000000b, -+ 0x16c, 0x0000000b, -+ 0x16d, 0x0000000b, -+ 0x16e, 0x0000000b, -+ 0x16f, 0x0000000b, -+ 0x170, 0x0000000b, -+ 0x171, 0x0000000b, -+ 0x172, 0x0000000b, -+ 0x173, 0x0000000b, -+ 0x174, 0x0000000b, -+ 0x175, 0x0000000b, -+ 0x176, 0x0000000b, -+ 0x177, 0x0000000b, -+ 0x178, 0x0000000b, -+ 0x179, 0x0000000b, -+ 0x17a, 0x0000000b, -+ 0x17b, 0x0000000b, -+ 0x17c, 0x0000000b, -+ 0x17d, 0x0000000b, -+ 0x17e, 0x0000000b, -+ 0x17f, 0x0000000b, -+ 0x236, 0x0000000c, -+ 0x503, 0x00000022, -+ 0x560, 0x00000000, -+}; -+ -+u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = { -+ 0xc78, 0x7f000001, -+ 0xc78, 0x7f010001, -+ 0xc78, 0x7e020001, -+ 0xc78, 0x7d030001, -+ 0xc78, 0x7c040001, -+ 0xc78, 0x7b050001, -+ 0xc78, 0x7a060001, -+ 0xc78, 0x79070001, -+ 0xc78, 0x78080001, -+ 0xc78, 0x77090001, -+ 0xc78, 0x760a0001, -+ 0xc78, 0x750b0001, -+ 0xc78, 0x740c0001, -+ 0xc78, 0x730d0001, -+ 0xc78, 0x720e0001, -+ 0xc78, 0x710f0001, -+ 0xc78, 0x70100001, -+ 0xc78, 0x6f110001, -+ 0xc78, 0x6f120001, -+ 0xc78, 0x6e130001, -+ 0xc78, 0x6d140001, -+ 0xc78, 0x6d150001, -+ 0xc78, 0x6c160001, -+ 0xc78, 0x6b170001, -+ 0xc78, 0x6a180001, -+ 0xc78, 0x6a190001, -+ 0xc78, 0x691a0001, -+ 0xc78, 0x681b0001, -+ 0xc78, 0x671c0001, -+ 0xc78, 0x661d0001, -+ 0xc78, 0x651e0001, -+ 0xc78, 0x641f0001, -+ 0xc78, 0x63200001, -+ 0xc78, 0x4c210001, -+ 0xc78, 0x4b220001, -+ 0xc78, 0x4a230001, -+ 0xc78, 0x49240001, -+ 0xc78, 0x48250001, -+ 0xc78, 0x47260001, -+ 0xc78, 0x46270001, -+ 0xc78, 0x45280001, -+ 0xc78, 0x44290001, -+ 0xc78, 0x2c2a0001, -+ 0xc78, 0x2b2b0001, -+ 0xc78, 0x2a2c0001, -+ 0xc78, 0x292d0001, -+ 0xc78, 0x282e0001, -+ 0xc78, 0x272f0001, -+ 0xc78, 0x26300001, -+ 0xc78, 0x25310001, -+ 0xc78, 0x24320001, -+ 0xc78, 0x23330001, -+ 0xc78, 0x22340001, -+ 0xc78, 0x09350001, -+ 0xc78, 0x08360001, -+ 0xc78, 0x07370001, -+ 0xc78, 0x06380001, -+ 0xc78, 0x05390001, -+ 0xc78, 0x043a0001, -+ 0xc78, 0x033b0001, -+ 0xc78, 0x023c0001, -+ 0xc78, 0x013d0001, -+ 0xc78, 0x003e0001, -+ 0xc78, 0x003f0001, -+ 0xc78, 0x7f400001, -+ 0xc78, 0x7f410001, -+ 0xc78, 0x7e420001, -+ 0xc78, 0x7d430001, -+ 0xc78, 0x7c440001, -+ 0xc78, 0x7b450001, -+ 0xc78, 0x7a460001, -+ 0xc78, 0x79470001, -+ 0xc78, 0x78480001, -+ 0xc78, 0x77490001, -+ 0xc78, 0x764a0001, -+ 0xc78, 0x754b0001, -+ 0xc78, 0x744c0001, -+ 0xc78, 0x734d0001, -+ 0xc78, 0x724e0001, -+ 0xc78, 0x714f0001, -+ 0xc78, 0x70500001, -+ 0xc78, 0x6f510001, -+ 0xc78, 0x6f520001, -+ 0xc78, 0x6e530001, -+ 0xc78, 0x6d540001, -+ 0xc78, 0x6d550001, -+ 0xc78, 0x6c560001, -+ 0xc78, 0x6b570001, -+ 0xc78, 0x6a580001, -+ 0xc78, 0x6a590001, -+ 0xc78, 0x695a0001, -+ 0xc78, 0x685b0001, -+ 0xc78, 0x675c0001, -+ 0xc78, 0x665d0001, -+ 0xc78, 0x655e0001, -+ 0xc78, 0x645f0001, -+ 0xc78, 0x63600001, -+ 0xc78, 0x4c610001, -+ 0xc78, 0x4b620001, -+ 0xc78, 0x4a630001, -+ 0xc78, 0x49640001, -+ 0xc78, 0x48650001, -+ 0xc78, 0x47660001, -+ 0xc78, 0x46670001, -+ 0xc78, 0x45680001, -+ 0xc78, 0x44690001, -+ 0xc78, 0x2c6a0001, -+ 0xc78, 0x2b6b0001, -+ 0xc78, 0x2a6c0001, -+ 0xc78, 0x296d0001, -+ 0xc78, 0x286e0001, -+ 0xc78, 0x276f0001, -+ 0xc78, 0x26700001, -+ 0xc78, 0x25710001, -+ 0xc78, 0x24720001, -+ 0xc78, 0x23730001, -+ 0xc78, 0x22740001, -+ 0xc78, 0x09750001, -+ 0xc78, 0x08760001, -+ 0xc78, 0x07770001, -+ 0xc78, 0x06780001, -+ 0xc78, 0x05790001, -+ 0xc78, 0x047a0001, -+ 0xc78, 0x037b0001, -+ 0xc78, 0x027c0001, -+ 0xc78, 0x017d0001, -+ 0xc78, 0x007e0001, -+ 0xc78, 0x007f0001, -+ 0xc78, 0x3000001e, -+ 0xc78, 0x3001001e, -+ 0xc78, 0x3002001e, -+ 0xc78, 0x3003001e, -+ 0xc78, 0x3004001e, -+ 0xc78, 0x3405001e, -+ 0xc78, 0x3806001e, -+ 0xc78, 0x3e07001e, -+ 0xc78, 0x3e08001e, -+ 0xc78, 0x4409001e, -+ 0xc78, 0x460a001e, -+ 0xc78, 0x480b001e, -+ 0xc78, 0x480c001e, -+ 0xc78, 0x4e0d001e, -+ 0xc78, 0x560e001e, -+ 0xc78, 0x5a0f001e, -+ 0xc78, 0x5e10001e, -+ 0xc78, 0x6211001e, -+ 0xc78, 0x6c12001e, -+ 0xc78, 0x7213001e, -+ 0xc78, 0x7214001e, -+ 0xc78, 0x7215001e, -+ 0xc78, 0x7216001e, -+ 0xc78, 0x7217001e, -+ 0xc78, 0x7218001e, -+ 0xc78, 0x7219001e, -+ 0xc78, 0x721a001e, -+ 0xc78, 0x721b001e, -+ 0xc78, 0x721c001e, -+ 0xc78, 0x721d001e, -+ 0xc78, 0x721e001e, -+ 0xc78, 0x721f001e, -+}; -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/table.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/table.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/table.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/table.h 2011-05-05 23:29:49.276487669 +0200 -@@ -0,0 +1,49 @@ -+/****************************************************************************** -+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. -+ * -+ * 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: -+ * wlanfae -+ * -+ * Larry Finger -+ * -+ ******************************************************************************/ -+#ifndef __INC_HAL8192SE_FW_IMG_H -+#define __INC_HAL8192SE_FW_IMG_H -+ -+#include -+ -+/*Created on 2010/ 4/12, 5:56*/ -+ -+#define PHY_REG_2T2RARRAYLENGTH 372 -+extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH]; -+#define PHY_CHANGETO_1T1RARRAYLENGTH 48 -+extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH]; -+#define PHY_CHANGETO_1T2RARRAYLENGTH 45 -+extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH]; -+#define PHY_REG_ARRAY_PGLENGTH 84 -+extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH]; -+#define RADIOA_1T_ARRAYLENGTH 202 -+extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH]; -+#define RADIOB_ARRAYLENGTH 22 -+extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH]; -+#define RADIOB_GM_ARRAYLENGTH 10 -+extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH]; -+#define MAC_2T_ARRAYLENGTH 106 -+extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH]; -+#define AGCTAB_ARRAYLENGTH 320 -+extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH]; -+ -+#endif -+ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/trx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/trx.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/trx.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/trx.c 2011-05-05 23:29:49.278487693 +0200 -@@ -0,0 +1,976 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+ -+#include "../wifi.h" -+#include "../pci.h" -+#include "../base.h" -+#include "reg.h" -+#include "def.h" -+#include "phy.h" -+#include "fw.h" -+#include "trx.h" -+#include "led.h" -+ -+static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) -+{ -+ __le16 fc = rtl_get_fc(skb); -+ -+ if (unlikely(ieee80211_is_beacon(fc))) -+ return QSLT_BEACON; -+ if (ieee80211_is_mgmt(fc)) -+ return QSLT_MGNT; -+ if (ieee80211_is_nullfunc(fc)) -+ return QSLT_HIGH; -+ -+ return skb->priority; -+} -+ -+static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -+{ -+ int rate_idx = 0; -+ -+ if (first_ampdu) { -+ if (false == isht) { -+ switch (desc_rate) { -+ case DESC92S_RATE1M: -+ rate_idx = 0; -+ break; -+ case DESC92S_RATE2M: -+ rate_idx = 1; -+ break; -+ case DESC92S_RATE5_5M: -+ rate_idx = 2; -+ break; -+ case DESC92S_RATE11M: -+ rate_idx = 3; -+ break; -+ case DESC92S_RATE6M: -+ rate_idx = 4; -+ break; -+ case DESC92S_RATE9M: -+ rate_idx = 5; -+ break; -+ case DESC92S_RATE12M: -+ rate_idx = 6; -+ break; -+ case DESC92S_RATE18M: -+ rate_idx = 7; -+ break; -+ case DESC92S_RATE24M: -+ rate_idx = 8; -+ break; -+ case DESC92S_RATE36M: -+ rate_idx = 9; -+ break; -+ case DESC92S_RATE48M: -+ rate_idx = 10; -+ break; -+ case DESC92S_RATE54M: -+ rate_idx = 11; -+ break; -+ default: -+ rate_idx = 0; -+ break; -+ } -+ } else { -+ rate_idx = 11; -+ } -+ -+ return rate_idx; -+ } -+ -+ switch (desc_rate) { -+ case DESC92S_RATE1M: -+ rate_idx = 0; -+ break; -+ case DESC92S_RATE2M: -+ rate_idx = 1; -+ break; -+ case DESC92S_RATE5_5M: -+ rate_idx = 2; -+ break; -+ case DESC92S_RATE11M: -+ rate_idx = 3; -+ break; -+ case DESC92S_RATE6M: -+ rate_idx = 4; -+ break; -+ case DESC92S_RATE9M: -+ rate_idx = 5; -+ break; -+ case DESC92S_RATE12M: -+ rate_idx = 6; -+ break; -+ case DESC92S_RATE18M: -+ rate_idx = 7; -+ break; -+ case DESC92S_RATE24M: -+ rate_idx = 8; -+ break; -+ case DESC92S_RATE36M: -+ rate_idx = 9; -+ break; -+ case DESC92S_RATE48M: -+ rate_idx = 10; -+ break; -+ case DESC92S_RATE54M: -+ rate_idx = 11; -+ break; -+ default: -+ rate_idx = 11; -+ break; -+ } -+ return rate_idx; -+} -+ -+static u8 _rtl92s_query_rxpwrpercentage(char antpower) -+{ -+ if ((antpower <= -100) || (antpower >= 20)) -+ return 0; -+ else if (antpower >= 0) -+ return 100; -+ else -+ return 100 + antpower; -+} -+ -+static u8 _rtl92s_evm_db_to_percentage(char value) -+{ -+ char ret_val; -+ ret_val = value; -+ -+ if (ret_val >= 0) -+ ret_val = 0; -+ -+ if (ret_val <= -33) -+ ret_val = -33; -+ -+ ret_val = 0 - ret_val; -+ ret_val *= 3; -+ -+ if (ret_val == 99) -+ ret_val = 100; -+ -+ return ret_val; -+} -+ -+static long _rtl92se_translate_todbm(struct ieee80211_hw *hw, -+ u8 signal_strength_index) -+{ -+ long signal_power; -+ -+ signal_power = (long)((signal_strength_index + 1) >> 1); -+ signal_power -= 95; -+ return signal_power; -+} -+ -+static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw, -+ long currsig) -+{ -+ long retsig = 0; -+ -+ /* Step 1. Scale mapping. */ -+ if (currsig > 47) -+ retsig = 100; -+ else if (currsig > 14 && currsig <= 47) -+ retsig = 100 - ((47 - currsig) * 3) / 2; -+ else if (currsig > 2 && currsig <= 14) -+ retsig = 48 - ((14 - currsig) * 15) / 7; -+ else if (currsig >= 0) -+ retsig = currsig * 9 + 1; -+ -+ return retsig; -+} -+ -+ -+static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats, u8 *pdesc, -+ struct rx_fwinfo *p_drvinfo, -+ bool packet_match_bssid, -+ bool packet_toself, -+ bool packet_beacon) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct phy_sts_cck_8192s_t *cck_buf; -+ s8 rx_pwr_all = 0, rx_pwr[4]; -+ u8 rf_rx_num = 0, evm, pwdb_all; -+ u8 i, max_spatial_stream; -+ u32 rssi, total_rssi = 0; -+ bool in_powersavemode = false; -+ bool is_cck_rate; -+ -+ is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); -+ pstats->packet_matchbssid = packet_match_bssid; -+ pstats->packet_toself = packet_toself; -+ pstats->is_cck = is_cck_rate; -+ pstats->packet_beacon = packet_beacon; -+ pstats->is_cck = is_cck_rate; -+ pstats->rx_mimo_signalquality[0] = -1; -+ pstats->rx_mimo_signalquality[1] = -1; -+ -+ if (is_cck_rate) { -+ u8 report, cck_highpwr; -+ cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; -+ -+ if (!in_powersavemode) -+ cck_highpwr = (u8) rtl_get_bbreg(hw, -+ RFPGA0_XA_HSSIPARAMETER2, -+ 0x200); -+ else -+ cck_highpwr = false; -+ -+ if (!cck_highpwr) { -+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt; -+ report = cck_buf->cck_agc_rpt & 0xc0; -+ report = report >> 6; -+ switch (report) { -+ case 0x3: -+ rx_pwr_all = -40 - (cck_agc_rpt & 0x3e); -+ break; -+ case 0x2: -+ rx_pwr_all = -20 - (cck_agc_rpt & 0x3e); -+ break; -+ case 0x1: -+ rx_pwr_all = -2 - (cck_agc_rpt & 0x3e); -+ break; -+ case 0x0: -+ rx_pwr_all = 14 - (cck_agc_rpt & 0x3e); -+ break; -+ } -+ } else { -+ u8 cck_agc_rpt = cck_buf->cck_agc_rpt; -+ report = p_drvinfo->cfosho[0] & 0x60; -+ report = report >> 5; -+ switch (report) { -+ case 0x3: -+ rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1); -+ break; -+ case 0x2: -+ rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1); -+ break; -+ case 0x1: -+ rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1); -+ break; -+ case 0x0: -+ rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1); -+ break; -+ } -+ } -+ -+ pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); -+ -+ /* CCK gain is smaller than OFDM/MCS gain, */ -+ /* so we add gain diff by experiences, the val is 6 */ -+ pwdb_all += 6; -+ if (pwdb_all > 100) -+ pwdb_all = 100; -+ /* modify the offset to make the same gain index with OFDM. */ -+ if (pwdb_all > 34 && pwdb_all <= 42) -+ pwdb_all -= 2; -+ else if (pwdb_all > 26 && pwdb_all <= 34) -+ pwdb_all -= 6; -+ else if (pwdb_all > 14 && pwdb_all <= 26) -+ pwdb_all -= 8; -+ else if (pwdb_all > 4 && pwdb_all <= 14) -+ pwdb_all -= 4; -+ -+ pstats->rx_pwdb_all = pwdb_all; -+ pstats->recvsignalpower = rx_pwr_all; -+ -+ if (packet_match_bssid) { -+ u8 sq; -+ if (pstats->rx_pwdb_all > 40) { -+ sq = 100; -+ } else { -+ sq = cck_buf->sq_rpt; -+ if (sq > 64) -+ sq = 0; -+ else if (sq < 20) -+ sq = 100; -+ else -+ sq = ((64 - sq) * 100) / 44; -+ } -+ -+ pstats->signalquality = sq; -+ pstats->rx_mimo_signalquality[0] = sq; -+ pstats->rx_mimo_signalquality[1] = -1; -+ } -+ } else { -+ rtlpriv->dm.rfpath_rxenable[0] = -+ rtlpriv->dm.rfpath_rxenable[1] = true; -+ for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { -+ if (rtlpriv->dm.rfpath_rxenable[i]) -+ rf_rx_num++; -+ -+ rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & -+ 0x3f) * 2) - 110; -+ rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]); -+ total_rssi += rssi; -+ rtlpriv->stats.rx_snr_db[i] = -+ (long)(p_drvinfo->rxsnr[i] / 2); -+ -+ if (packet_match_bssid) -+ pstats->rx_mimo_signalstrength[i] = (u8) rssi; -+ } -+ -+ rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; -+ pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); -+ pstats->rx_pwdb_all = pwdb_all; -+ pstats->rxpower = rx_pwr_all; -+ pstats->recvsignalpower = rx_pwr_all; -+ -+ if (GET_RX_STATUS_DESC_RX_HT(pdesc) && -+ GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && -+ GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) -+ max_spatial_stream = 2; -+ else -+ max_spatial_stream = 1; -+ -+ for (i = 0; i < max_spatial_stream; i++) { -+ evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]); -+ -+ if (packet_match_bssid) { -+ if (i == 0) -+ pstats->signalquality = (u8)(evm & -+ 0xff); -+ pstats->rx_mimo_signalquality[i] = -+ (u8) (evm & 0xff); -+ } -+ } -+ } -+ -+ if (is_cck_rate) -+ pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw, -+ pwdb_all)); -+ else if (rf_rx_num != 0) -+ pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw, -+ total_rssi /= rf_rx_num)); -+} -+ -+static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_phy *rtlphy = &(rtlpriv->phy); -+ u8 rfpath; -+ u32 last_rssi, tmpval; -+ -+ if (pstats->packet_toself || pstats->packet_beacon) { -+ rtlpriv->stats.rssi_calculate_cnt++; -+ -+ if (rtlpriv->stats.ui_rssi.total_num++ >= -+ PHY_RSSI_SLID_WIN_MAX) { -+ rtlpriv->stats.ui_rssi.total_num = -+ PHY_RSSI_SLID_WIN_MAX; -+ last_rssi = rtlpriv->stats.ui_rssi.elements[ -+ rtlpriv->stats.ui_rssi.index]; -+ rtlpriv->stats.ui_rssi.total_val -= last_rssi; -+ } -+ -+ rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; -+ rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] -+ = pstats->signalstrength; -+ -+ if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) -+ rtlpriv->stats.ui_rssi.index = 0; -+ -+ tmpval = rtlpriv->stats.ui_rssi.total_val / -+ rtlpriv->stats.ui_rssi.total_num; -+ rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw, -+ (u8) tmpval); -+ pstats->rssi = rtlpriv->stats.signal_strength; -+ } -+ -+ if (!pstats->is_cck && pstats->packet_toself) { -+ for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; -+ rfpath++) { -+ if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { -+ rtlpriv->stats.rx_rssi_percentage[rfpath] = -+ pstats->rx_mimo_signalstrength[rfpath]; -+ -+ } -+ -+ if (pstats->rx_mimo_signalstrength[rfpath] > -+ rtlpriv->stats.rx_rssi_percentage[rfpath]) { -+ rtlpriv->stats.rx_rssi_percentage[rfpath] = -+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] -+ * (RX_SMOOTH_FACTOR - 1)) + -+ (pstats->rx_mimo_signalstrength[rfpath])) / -+ (RX_SMOOTH_FACTOR); -+ -+ rtlpriv->stats.rx_rssi_percentage[rfpath] = -+ rtlpriv->stats.rx_rssi_percentage[rfpath] -+ + 1; -+ } else { -+ rtlpriv->stats.rx_rssi_percentage[rfpath] = -+ ((rtlpriv->stats.rx_rssi_percentage[rfpath] -+ * (RX_SMOOTH_FACTOR - 1)) + -+ (pstats->rx_mimo_signalstrength[rfpath])) / -+ (RX_SMOOTH_FACTOR); -+ } -+ -+ } -+ } -+} -+ -+static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ int weighting = 0; -+ -+ if (rtlpriv->stats.recv_signal_power == 0) -+ rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; -+ -+ if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) -+ weighting = 5; -+ else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) -+ weighting = (-5); -+ -+ rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5 -+ + pstats->recvsignalpower + -+ weighting) / 6; -+} -+ -+static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ long undec_sm_pwdb = 0; -+ -+ if (mac->opmode == NL80211_IFTYPE_ADHOC) { -+ return; -+ } else { -+ undec_sm_pwdb = -+ rtlpriv->dm.undecorated_smoothed_pwdb; -+ } -+ -+ if (pstats->packet_toself || pstats->packet_beacon) { -+ if (undec_sm_pwdb < 0) -+ undec_sm_pwdb = pstats->rx_pwdb_all; -+ -+ if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { -+ undec_sm_pwdb = -+ (((undec_sm_pwdb) * -+ (RX_SMOOTH_FACTOR - 1)) + -+ (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); -+ -+ undec_sm_pwdb = undec_sm_pwdb + 1; -+ } else { -+ undec_sm_pwdb = (((undec_sm_pwdb) * -+ (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) / -+ (RX_SMOOTH_FACTOR); -+ } -+ -+ rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb; -+ _rtl92se_update_rxsignalstatistics(hw, pstats); -+ } -+} -+ -+static void rtl_92s_process_streams(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 stream; -+ -+ for (stream = 0; stream < 2; stream++) { -+ if (pstats->rx_mimo_signalquality[stream] != -1) { -+ if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { -+ rtlpriv->stats.rx_evm_percentage[stream] = -+ pstats->rx_mimo_signalquality[stream]; -+ } -+ -+ rtlpriv->stats.rx_evm_percentage[stream] = -+ ((rtlpriv->stats.rx_evm_percentage[stream] * -+ (RX_SMOOTH_FACTOR - 1)) + -+ (pstats->rx_mimo_signalquality[stream] * -+ 1)) / (RX_SMOOTH_FACTOR); -+ } -+ } -+} -+ -+static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw, -+ struct rtl_stats *pstats) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ u32 last_evm = 0, tmpval; -+ -+ if (pstats->signalquality != 0) { -+ if (pstats->packet_toself || pstats->packet_beacon) { -+ -+ if (rtlpriv->stats.ui_link_quality.total_num++ >= -+ PHY_LINKQUALITY_SLID_WIN_MAX) { -+ rtlpriv->stats.ui_link_quality.total_num = -+ PHY_LINKQUALITY_SLID_WIN_MAX; -+ last_evm = -+ rtlpriv->stats.ui_link_quality.elements[ -+ rtlpriv->stats.ui_link_quality.index]; -+ rtlpriv->stats.ui_link_quality.total_val -= -+ last_evm; -+ } -+ -+ rtlpriv->stats.ui_link_quality.total_val += -+ pstats->signalquality; -+ rtlpriv->stats.ui_link_quality.elements[ -+ rtlpriv->stats.ui_link_quality.index++] = -+ pstats->signalquality; -+ -+ if (rtlpriv->stats.ui_link_quality.index >= -+ PHY_LINKQUALITY_SLID_WIN_MAX) -+ rtlpriv->stats.ui_link_quality.index = 0; -+ -+ tmpval = rtlpriv->stats.ui_link_quality.total_val / -+ rtlpriv->stats.ui_link_quality.total_num; -+ rtlpriv->stats.signal_quality = tmpval; -+ -+ rtlpriv->stats.last_sigstrength_inpercent = tmpval; -+ -+ rtl_92s_process_streams(hw, pstats); -+ -+ } -+ } -+} -+ -+static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw, -+ u8 *buffer, -+ struct rtl_stats *pcurrent_stats) -+{ -+ -+ if (!pcurrent_stats->packet_matchbssid && -+ !pcurrent_stats->packet_beacon) -+ return; -+ -+ _rtl92se_process_ui_rssi(hw, pcurrent_stats); -+ _rtl92se_process_pwdb(hw, pcurrent_stats); -+ _rtl92se_process_ui_link_quality(hw, pcurrent_stats); -+} -+ -+static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, -+ struct sk_buff *skb, struct rtl_stats *pstats, -+ u8 *pdesc, struct rx_fwinfo *p_drvinfo) -+{ -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -+ -+ struct ieee80211_hdr *hdr; -+ u8 *tmp_buf; -+ u8 *praddr; -+ u8 *psaddr; -+ __le16 fc; -+ u16 type, cfc; -+ bool packet_matchbssid, packet_toself, packet_beacon; -+ -+ tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; -+ -+ hdr = (struct ieee80211_hdr *)tmp_buf; -+ fc = hdr->frame_control; -+ cfc = le16_to_cpu(fc); -+ type = WLAN_FC_GET_TYPE(fc); -+ praddr = hdr->addr1; -+ psaddr = hdr->addr2; -+ -+ packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && -+ (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ? -+ hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ? -+ hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) && -+ (!pstats->crc) && (!pstats->icv)); -+ -+ packet_toself = packet_matchbssid && -+ (!compare_ether_addr(praddr, rtlefuse->dev_addr)); -+ -+ if (ieee80211_is_beacon(fc)) -+ packet_beacon = true; -+ -+ _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, -+ packet_matchbssid, packet_toself, packet_beacon); -+ _rtl92se_process_phyinfo(hw, tmp_buf, pstats); -+} -+ -+bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, -+ struct ieee80211_rx_status *rx_status, u8 *pdesc, -+ struct sk_buff *skb) -+{ -+ struct rx_fwinfo *p_drvinfo; -+ u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc); -+ -+ stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc); -+ stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8; -+ stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03); -+ stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc); -+ stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc); -+ stats->hwerror = (u16)(stats->crc | stats->icv); -+ stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc); -+ -+ stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc); -+ stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc); -+ stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1); -+ stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); -+ stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); -+ -+ if (stats->hwerror) -+ return false; -+ -+ rx_status->freq = hw->conf.channel->center_freq; -+ rx_status->band = hw->conf.channel->band; -+ -+ if (GET_RX_STATUS_DESC_CRC32(pdesc)) -+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; -+ -+ if (!GET_RX_STATUS_DESC_SWDEC(pdesc)) -+ rx_status->flag |= RX_FLAG_DECRYPTED; -+ -+ if (GET_RX_STATUS_DESC_BW(pdesc)) -+ rx_status->flag |= RX_FLAG_40MHZ; -+ -+ if (GET_RX_STATUS_DESC_RX_HT(pdesc)) -+ rx_status->flag |= RX_FLAG_HT; -+ -+ rx_status->flag |= RX_FLAG_MACTIME_MPDU; -+ -+ if (stats->decrypted) -+ rx_status->flag |= RX_FLAG_DECRYPTED; -+ -+ rx_status->rate_idx = _rtl92se_rate_mapping((bool) -+ GET_RX_STATUS_DESC_RX_HT(pdesc), -+ (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), -+ (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); -+ -+ -+ rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); -+ if (phystatus == true) { -+ p_drvinfo = (struct rx_fwinfo *)(skb->data + -+ stats->rx_bufshift); -+ _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, -+ p_drvinfo); -+ } -+ -+ /*rx_status->qual = stats->signal; */ -+ rx_status->signal = stats->rssi + 10; -+ /*rx_status->noise = -stats->noise; */ -+ -+ return true; -+} -+ -+void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, -+ struct ieee80211_hdr *hdr, u8 *pdesc_tx, -+ struct ieee80211_tx_info *info, struct sk_buff *skb, -+ u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct ieee80211_sta *sta = info->control.sta; -+ u8 *pdesc = (u8 *) pdesc_tx; -+ u16 seq_number; -+ __le16 fc = hdr->frame_control; -+ u8 reserved_macid = 0; -+ u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue); -+ bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); -+ bool lastseg = (!(hdr->frame_control & -+ cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); -+ dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, -+ PCI_DMA_TODEVICE); -+ u8 bw_40 = 0; -+ -+ if (mac->opmode == NL80211_IFTYPE_STATION) { -+ bw_40 = mac->bw_40; -+ } else if (mac->opmode == NL80211_IFTYPE_AP || -+ mac->opmode == NL80211_IFTYPE_ADHOC) { -+ if (sta) -+ bw_40 = sta->ht_cap.cap & -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ } -+ -+ seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; -+ -+ rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); -+ -+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); -+ -+ if (firstseg) { -+ if (rtlpriv->dm.useramask) { -+ /* set txdesc macId */ -+ if (ptcb_desc->mac_id < 32) { -+ SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); -+ reserved_macid |= ptcb_desc->mac_id; -+ } -+ } -+ SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); -+ -+ SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= -+ DESC92S_RATEMCS0) ? 1 : 0)); -+ -+ if (rtlhal->version == VERSION_8192S_ACUT) { -+ if (ptcb_desc->hw_rate == DESC92S_RATE1M || -+ ptcb_desc->hw_rate == DESC92S_RATE2M || -+ ptcb_desc->hw_rate == DESC92S_RATE5_5M || -+ ptcb_desc->hw_rate == DESC92S_RATE11M) { -+ ptcb_desc->hw_rate = DESC92S_RATE12M; -+ } -+ } -+ -+ SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); -+ -+ if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) -+ SET_TX_DESC_TX_SHORT(pdesc, 0); -+ -+ /* Aggregation related */ -+ if (info->flags & IEEE80211_TX_CTL_AMPDU) -+ SET_TX_DESC_AGG_ENABLE(pdesc, 1); -+ -+ /* For AMPDU, we must insert SSN into TX_DESC */ -+ SET_TX_DESC_SEQ(pdesc, seq_number); -+ -+ /* Protection mode related */ -+ /* For 92S, if RTS/CTS are set, HW will execute RTS. */ -+ /* We choose only one protection mode to execute */ -+ SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && -+ !ptcb_desc->cts_enable) ? 1 : 0)); -+ SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? -+ 1 : 0)); -+ SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); -+ -+ SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); -+ SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); -+ SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); -+ SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= -+ DESC92S_RATE54M) ? -+ (ptcb_desc->rts_use_shortpreamble ? 1 : 0) -+ : (ptcb_desc->rts_use_shortgi ? 1 : 0))); -+ -+ -+ /* Set Bandwidth and sub-channel settings. */ -+ if (bw_40) { -+ if (ptcb_desc->packet_bw) { -+ SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); -+ /* use duplicated mode */ -+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); -+ } else { -+ SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); -+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, -+ mac->cur_40_prime_sc); -+ } -+ } else { -+ SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); -+ SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); -+ } -+ -+ /* 3 Fill necessary field in First Descriptor */ -+ /*DWORD 0*/ -+ SET_TX_DESC_LINIP(pdesc, 0); -+ SET_TX_DESC_OFFSET(pdesc, 32); -+ SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); -+ -+ /*DWORD 1*/ -+ SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); -+ -+ /* Fill security related */ -+ if (info->control.hw_key) { -+ struct ieee80211_key_conf *keyconf; -+ -+ keyconf = info->control.hw_key; -+ switch (keyconf->cipher) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ case WLAN_CIPHER_SUITE_WEP104: -+ SET_TX_DESC_SEC_TYPE(pdesc, 0x1); -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ SET_TX_DESC_SEC_TYPE(pdesc, 0x2); -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ SET_TX_DESC_SEC_TYPE(pdesc, 0x3); -+ break; -+ default: -+ SET_TX_DESC_SEC_TYPE(pdesc, 0x0); -+ break; -+ -+ } -+ } -+ -+ /* Set Packet ID */ -+ SET_TX_DESC_PACKET_ID(pdesc, 0); -+ -+ /* We will assign magement queue to BK. */ -+ SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); -+ -+ /* Alwasy enable all rate fallback range */ -+ SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); -+ -+ /* Fix: I don't kown why hw use 6.5M to tx when set it */ -+ SET_TX_DESC_USER_RATE(pdesc, -+ ptcb_desc->use_driver_rate ? 1 : 0); -+ -+ /* Set NON_QOS bit. */ -+ if (!ieee80211_is_data_qos(fc)) -+ SET_TX_DESC_NON_QOS(pdesc, 1); -+ -+ } -+ -+ /* Fill fields that are required to be initialized -+ * in all of the descriptors */ -+ /*DWORD 0 */ -+ SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); -+ SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); -+ -+ /* DWORD 7 */ -+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); -+ -+ /* DOWRD 8 */ -+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); -+ -+ RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); -+} -+ -+void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, -+ bool firstseg, bool lastseg, struct sk_buff *skb) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); -+ -+ dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, -+ PCI_DMA_TODEVICE); -+ -+ /* Clear all status */ -+ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); -+ -+ /* This bit indicate this packet is used for FW download. */ -+ if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { -+ /* For firmware downlaod we only need to set LINIP */ -+ SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); -+ -+ /* 92SE must set as 1 for firmware download HW DMA error */ -+ SET_TX_DESC_FIRST_SEG(pdesc, 1); -+ SET_TX_DESC_LAST_SEG(pdesc, 1); -+ -+ /* 92SE need not to set TX packet size when firmware download */ -+ SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); -+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); -+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); -+ -+ SET_TX_DESC_OWN(pdesc, 1); -+ } else { /* H2C Command Desc format (Host TXCMD) */ -+ /* 92SE must set as 1 for firmware download HW DMA error */ -+ SET_TX_DESC_FIRST_SEG(pdesc, 1); -+ SET_TX_DESC_LAST_SEG(pdesc, 1); -+ -+ SET_TX_DESC_OFFSET(pdesc, 0x20); -+ -+ /* Buffer size + command header */ -+ SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); -+ /* Fixed queue of H2C command */ -+ SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); -+ -+ SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); -+ -+ SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); -+ SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); -+ -+ SET_TX_DESC_OWN(pdesc, 1); -+ -+ } -+} -+ -+void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) -+{ -+ if (istx == true) { -+ switch (desc_name) { -+ case HW_DESC_OWN: -+ SET_TX_DESC_OWN(pdesc, 1); -+ break; -+ case HW_DESC_TX_NEXTDESC_ADDR: -+ SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); -+ break; -+ default: -+ RT_ASSERT(false, ("ERR txdesc :%d not process\n", -+ desc_name)); -+ break; -+ } -+ } else { -+ switch (desc_name) { -+ case HW_DESC_RXOWN: -+ SET_RX_STATUS_DESC_OWN(pdesc, 1); -+ break; -+ case HW_DESC_RXBUFF_ADDR: -+ SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val); -+ break; -+ case HW_DESC_RXPKT_LEN: -+ SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val); -+ break; -+ case HW_DESC_RXERO: -+ SET_RX_STATUS_DESC_EOR(pdesc, 1); -+ break; -+ default: -+ RT_ASSERT(false, ("ERR rxdesc :%d not process\n", -+ desc_name)); -+ break; -+ } -+ } -+} -+ -+u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) -+{ -+ u32 ret = 0; -+ -+ if (istx == true) { -+ switch (desc_name) { -+ case HW_DESC_OWN: -+ ret = GET_TX_DESC_OWN(desc); -+ break; -+ case HW_DESC_TXBUFF_ADDR: -+ ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc); -+ break; -+ default: -+ RT_ASSERT(false, ("ERR txdesc :%d not process\n", -+ desc_name)); -+ break; -+ } -+ } else { -+ switch (desc_name) { -+ case HW_DESC_OWN: -+ ret = GET_RX_STATUS_DESC_OWN(desc); -+ break; -+ case HW_DESC_RXPKT_LEN: -+ ret = GET_RX_STATUS_DESC_PKT_LEN(desc); -+ break; -+ default: -+ RT_ASSERT(false, ("ERR rxdesc :%d not process\n", -+ desc_name)); -+ break; -+ } -+ } -+ return ret; -+} -+ -+void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue)); -+} -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/trx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/trx.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/rtl8192se/trx.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/rtl8192se/trx.h 2011-05-05 23:29:49.282487741 +0200 -@@ -0,0 +1,45 @@ -+/****************************************************************************** -+ * -+ * Copyright(c) 2009-2010 Realtek Corporation. -+ * -+ * 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: -+ * wlanfae -+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, -+ * Hsinchu 300, Taiwan. -+ * -+ * Larry Finger -+ * -+ *****************************************************************************/ -+#ifndef __REALTEK_PCI92SE_TRX_H__ -+#define __REALTEK_PCI92SE_TRX_H__ -+ -+void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, -+ u8 *pdesc, struct ieee80211_tx_info *info, -+ struct sk_buff *skb, u8 hw_queue, -+ struct rtl_tcb_desc *ptcb_desc); -+void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, -+ bool lastseg, struct sk_buff *skb); -+bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, -+ struct ieee80211_rx_status *rx_status, u8 *pdesc, -+ struct sk_buff *skb); -+void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); -+u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name); -+void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -+ -+#endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/usb.c 2011-05-05 23:29:49.302487983 +0200 -@@ -852,6 +852,7 @@ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_tx_desc *pdesc = NULL; -+ struct rtl_tcb_desc tcb_desc; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - u8 *pda_addr = hdr->addr1; -@@ -860,8 +861,17 @@ - u8 tid = 0; - u16 seq_number = 0; - -- if (ieee80211_is_mgmt(fc)) -- rtl_tx_mgmt_proc(hw, skb); -+ if (ieee80211_is_auth(fc)) { -+ RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); -+ rtl_ips_nic_on(hw); -+ } -+ -+ if (rtlpriv->psc.sw_ps_enabled) { -+ if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && -+ !ieee80211_has_pm(fc)) -+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); -+ } -+ - rtl_action_proc(hw, skb, true); - if (is_multicast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesmulticast += skb->len; -@@ -878,7 +888,7 @@ - seq_number <<= 4; - } - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, -- hw_queue); -+ hw_queue, &tcb_desc); - if (!ieee80211_has_morefrags(hdr->frame_control)) { - if (qc) - mac->tids[tid].seq_number = seq_number; -@@ -887,7 +897,8 @@ - rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - } - --static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -+static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, -+ struct rtl_tcb_desc *dummy) - { - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/usb.h 2011-05-05 23:29:49.301487971 +0200 -@@ -31,6 +31,8 @@ - #include - #include - -+#define RTL_RX_DESC_SIZE 24 -+ - #define RTL_USB_DEVICE(vend, prod, cfg) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ - .idVendor = (vend), \ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/wifi.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/wifi.h ---- linux-2.6.39-rc6/drivers/net/wireless/rtlwifi/wifi.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/rtlwifi/wifi.h 2011-05-05 23:29:49.309488067 +0200 -@@ -68,6 +68,8 @@ - #define QBSS_LOAD_SIZE 5 - #define MAX_WMMELE_LENGTH 64 - -+#define TOTAL_CAM_ENTRY 32 -+ - /*slot time for 11g. */ - #define RTL_SLOT_TIME_9 9 - #define RTL_SLOT_TIME_20 20 -@@ -94,8 +96,10 @@ - #define CHANNEL_GROUP_MAX_5G 9 - #define CHANNEL_MAX_NUMBER_2G 14 - #define AVG_THERMAL_NUM 8 -+#define MAX_TID_COUNT 9 - - /* for early mode */ -+#define FCS_LEN 4 - #define EM_HDR_LEN 8 - enum intf_type { - INTF_PCI = 0, -@@ -159,6 +163,8 @@ - (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) - #define IS_HARDWARE_TYPE_8723(rtlhal) \ - (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) -+#define IS_HARDWARE_TYPE_8723U(rtlhal) \ -+ (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) - - enum scan_operation_backup_opt { - SCAN_OPT_BACKUP = 0, -@@ -297,6 +303,9 @@ - HW_VAR_DATA_FILTER, - }; - -+#define HWSET_MAX_SIZE 128 -+#define EFUSE_MAX_SECTION 16 -+ - enum _RT_MEDIA_STATUS { - RT_MEDIA_DISCONNECT = 0, - RT_MEDIA_CONNECT = 1 -@@ -766,7 +775,7 @@ - #define IQK_MATRIX_REG_NUM 8 - #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) - struct iqk_matrix_regs { -- bool b_iqk_done; -+ bool iqk_done; - long value[1][IQK_MATRIX_REG_NUM]; - }; - -@@ -843,6 +852,7 @@ - bool apk_done; - u32 reg_rf3c[2]; /* pathA / pathB */ - -+ /* bfsync */ - u8 framesync; - u32 framesync_c34; - -@@ -852,6 +862,10 @@ - }; - - #define MAX_TID_COUNT 9 -+#define RTL_AGG_STOP 0 -+#define RTL_AGG_PROGRESS 1 -+#define RTL_AGG_START 2 -+#define RTL_AGG_OPERATIONAL 3 - #define RTL_AGG_OFF 0 - #define RTL_AGG_ON 1 - #define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 -@@ -871,6 +885,13 @@ - struct rtl_ht_agg agg; - }; - -+struct rtl_sta_info { -+ u8 ratr_index; -+ u8 wireless_mode; -+ u8 mimo_ps; -+ struct rtl_tid_data tids[MAX_TID_COUNT]; -+} __packed; -+ - struct rtl_priv; - struct rtl_io { - struct device *dev; -@@ -894,6 +915,7 @@ - u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); - int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len, - u8 *pdata); -+ - }; - - struct rtl_mac { -@@ -916,6 +938,8 @@ - int n_channels; - int n_bitrates; - -+ bool offchan_deley; -+ - /*filters */ - u32 rx_conf; - u16 rx_mgt_filter; -@@ -1032,7 +1056,9 @@ - enum rt_enc_alg pairwise_enc_algorithm; - /*Encryption Algorithm for Brocast/Multicast */ - enum rt_enc_alg group_enc_algorithm; -- -+ /*Cam Entry Bitmap */ -+ u32 hwsec_cam_bitmap; -+ u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; - /*local Key buffer, indx 0 is for - pairwise key 1-4 is for agoup key. */ - u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; -@@ -1053,7 +1079,7 @@ - bool current_turbo_edca; - bool is_any_nonbepkts; /*out dm */ - bool is_cur_rdlstate; -- bool txpower_trackingInit; -+ bool txpower_trackinginit; - bool disable_framebursting; - bool cck_inch14; - bool txpower_tracking; -@@ -1079,7 +1105,6 @@ - bool disable_tx_int; - char ofdm_index[2]; - char cck_index; -- u8 power_index_backup[6]; - }; - - #define EFUSE_MAX_LOGICAL_SIZE 256 -@@ -1175,6 +1200,7 @@ - * otherwise Offset[560h] = 0x00. - * */ - bool support_aspm; -+ - bool support_backdoor; - - /*for LPS */ -@@ -1201,7 +1227,6 @@ - - /*just for PCIE ASPM */ - u8 const_amdpci_aspm; -- - bool pwrdown_mode; - - enum rf_pwrstate inactive_pwrstate; -@@ -1282,6 +1307,10 @@ - bool busytraffic; - bool higher_busytraffic; - bool higher_busyrxtraffic; -+ -+ u32 tidtx_in4period[MAX_TID_COUNT][4]; -+ u32 tidtx_inperiod[MAX_TID_COUNT]; -+ bool higher_busytxtraffic[MAX_TID_COUNT]; - }; - - struct rtl_tcb_desc { -@@ -1344,13 +1373,15 @@ - u32 add_msr, u32 rm_msr); - void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); -- void (*update_rate_table) (struct ieee80211_hw *hw); -+ void (*update_rate_tbl) (struct ieee80211_hw *hw, -+ struct ieee80211_sta *sta, u8 rssi_level); - void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); - void (*fill_tx_desc) (struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, -- struct sk_buff *skb, unsigned int queue_index); -- void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc, -+ struct sk_buff *skb, u8 hw_queue, -+ struct rtl_tcb_desc *ptcb_desc); -+ void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, - u32 buffer_len, bool bIsPsPoll); - void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, -@@ -1370,10 +1401,10 @@ - enum led_ctl_mode ledaction); - void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val); - u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); -- void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue); -+ void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); - void (*enable_hw_sec) (struct ieee80211_hw *hw); - void (*set_key) (struct ieee80211_hw *hw, u32 key_index, -- u8 *p_macaddr, bool is_group, u8 enc_algo, -+ u8 *macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - void (*init_sw_leds) (struct ieee80211_hw *hw); - void (*deinit_sw_leds) (struct ieee80211_hw *hw); -@@ -1384,6 +1415,7 @@ - u32 regaddr, u32 bitmask); - void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -+ void (*linked_set_reg) (struct ieee80211_hw *hw); - bool (*phy_rf6052_config) (struct ieee80211_hw *hw); - void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, - u8 *powerlevel); -@@ -1404,7 +1436,9 @@ - int (*adapter_start) (struct ieee80211_hw *hw); - void (*adapter_stop) (struct ieee80211_hw *hw); - -- int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb); -+ int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, -+ struct rtl_tcb_desc *ptcb_desc); -+ void (*flush)(struct ieee80211_hw *hw, bool drop); - int (*reset_trx_ring) (struct ieee80211_hw *hw); - bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); - -@@ -1418,6 +1452,15 @@ - struct rtl_mod_params { - /* default: 0 = using hardware encryption */ - int sw_crypto; -+ -+ /* default: 1 = using no linked power save */ -+ bool inactiveps; -+ -+ /* default: 1 = using linked sw power save */ -+ bool swctrl_lps; -+ -+ /* default: 1 = using linked fw power save */ -+ bool fwctrl_lps; - }; - - struct rtl_hal_usbint_cfg { -@@ -1445,6 +1488,7 @@ - - struct rtl_hal_cfg { - u8 bar_id; -+ bool write_readback; - char *name; - char *fw_name; - struct rtl_hal_ops *ops; -@@ -1469,7 +1513,6 @@ - spinlock_t rf_lock; - spinlock_t lps_lock; - spinlock_t waitq_lock; -- spinlock_t tx_urb_lock; - - /*Dual mac*/ - spinlock_t cck_and_rw_pagea_lock; -@@ -1621,19 +1664,19 @@ - u32 bt_edca_ul; - u32 bt_edca_dl; - -- bool b_init_set; -- bool b_bt_busy_traffic; -- bool b_bt_traffic_mode_set; -- bool b_bt_non_traffic_mode_set; -+ bool init_set; -+ bool bt_busy_traffic; -+ bool bt_traffic_mode_set; -+ bool bt_non_traffic_mode_set; - -- bool b_fw_coexist_all_off; -- bool b_sw_coexist_all_off; -+ bool fw_coexist_all_off; -+ bool sw_coexist_all_off; - u32 current_state; - u32 previous_state; - u8 bt_pre_rssi_state; - -- u8 b_reg_bt_iso; -- u8 b_reg_bt_sco; -+ u8 reg_bt_iso; -+ u8 reg_bt_sco; - - }; - -@@ -1653,13 +1696,23 @@ - #define EF4BYTE(_val) \ - (le32_to_cpu(_val)) - -+/* Read data from memory */ -+#define READEF1BYTE(_ptr) \ -+ EF1BYTE(*((u8 *)(_ptr))) - /* Read le16 data from memory and convert to host ordering */ - #define READEF2BYTE(_ptr) \ - EF2BYTE(*((u16 *)(_ptr))) -+#define READEF4BYTE(_ptr) \ -+ EF4BYTE(*((u32 *)(_ptr))) - -+/* Write data to memory */ -+#define WRITEEF1BYTE(_ptr, _val) \ -+ (*((u8 *)(_ptr))) = EF1BYTE(_val) - /* Write le16 data to memory in host ordering */ - #define WRITEEF2BYTE(_ptr, _val) \ - (*((u16 *)(_ptr))) = EF2BYTE(_val) -+#define WRITEEF4BYTE(_ptr, _val) \ -+ (*((u16 *)(_ptr))) = EF2BYTE(_val) - - /* Create a bit mask - * Examples: -@@ -1698,6 +1751,25 @@ - #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ - (EF1BYTE(*((u8 *)(__pstart)))) - -+/*Description: -+Translate subfield (continuous bits in little-endian) of 4-byte -+value to host byte ordering.*/ -+#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ -+ ( \ -+ (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ -+ BIT_LEN_MASK_32(__bitlen) \ -+ ) -+#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ -+ ( \ -+ (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ -+ BIT_LEN_MASK_16(__bitlen) \ -+ ) -+#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ -+ ( \ -+ (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ -+ BIT_LEN_MASK_8(__bitlen) \ -+ ) -+ - /* Description: - * Mask subfield (continuous bits in little-endian) of 4-byte value - * and return the result in 4-byte value in host byte ordering. -@@ -1721,6 +1793,18 @@ - /* Description: - * Set subfield of little-endian 4-byte value to specified value. - */ -+#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ -+ *((u32 *)(__pstart)) = EF4BYTE \ -+ ( \ -+ LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \ -+ ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \ -+ ); -+#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \ -+ *((u16 *)(__pstart)) = EF2BYTE \ -+ ( \ -+ LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ -+ ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ -+ ); - #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u8 *)(__pstart)) = EF1BYTE \ - ( \ -@@ -1728,12 +1812,16 @@ - ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ - ); - -+#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ -+ (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) -+ - /**************************************** - mem access macro define end - ****************************************/ - - #define byte(x, n) ((x >> (8 * n)) & 0xff) - -+#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) - #define RTL_WATCH_DOG_TIME 2000 - #define MSECS(t) msecs_to_jiffies(t) - #define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) -@@ -1768,6 +1856,15 @@ - #define container_of_dwork_rtl(x, y, z) \ - container_of(container_of(x, struct delayed_work, work), y, z) - -+#define FILL_OCTET_STRING(_os, _octet, _len) \ -+ (_os).octet = (u8 *)(_octet); \ -+ (_os).length = (_len); -+ -+#define CP_MACADDR(des, src) \ -+ ((des)[0] = (src)[0], (des)[1] = (src)[1],\ -+ (des)[2] = (src)[2], (des)[3] = (src)[3],\ -+ (des)[4] = (src)[4], (des)[5] = (src)[5]) -+ - static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) - { - return rtlpriv->io.read8_sync(rtlpriv, addr); -@@ -1786,17 +1883,26 @@ - static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) - { - rtlpriv->io.write8_async(rtlpriv, addr, val8); -+ -+ if (rtlpriv->cfg->write_readback) -+ rtlpriv->io.read8_sync(rtlpriv, addr); - } - - static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) - { - rtlpriv->io.write16_async(rtlpriv, addr, val16); -+ -+ if (rtlpriv->cfg->write_readback) -+ rtlpriv->io.read16_sync(rtlpriv, addr); - } - - static inline void rtl_write_dword(struct rtl_priv *rtlpriv, - u32 addr, u32 val32) - { - rtlpriv->io.write32_async(rtlpriv, addr, val32); -+ -+ if (rtlpriv->cfg->write_readback) -+ rtlpriv->io.read32_sync(rtlpriv, addr); - } - - static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, -@@ -1855,4 +1961,31 @@ - return rtlphy->rf_type; - } - -+static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) -+{ -+ return (struct ieee80211_hdr *)(skb->data); -+} -+ -+static inline __le16 rtl_get_fc(struct sk_buff *skb) -+{ -+ return rtl_get_hdr(skb)->frame_control; -+} -+ -+static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) -+{ -+ return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -+} -+ -+static inline u16 rtl_get_tid(struct sk_buff *skb) -+{ -+ return rtl_get_tid_h(rtl_get_hdr(skb)); -+} -+ -+static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ u8 *bssid) -+{ -+ return ieee80211_find_sta(vif, bssid); -+} -+ - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/cmd.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/cmd.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/cmd.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/cmd.h 2011-05-05 23:29:46.501454141 +0200 -@@ -313,8 +313,8 @@ - } __packed; - - enum wl1251_cmd_ps_mode { -- STATION_ACTIVE_MODE, -- STATION_POWER_SAVE_MODE -+ CHIP_ACTIVE_MODE, -+ CHIP_POWER_SAVE_MODE - }; - - struct wl1251_cmd_ps_params { -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/event.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/event.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/event.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/event.c 2011-05-05 23:29:46.341452207 +0200 -@@ -68,14 +68,16 @@ - if (vector & BSS_LOSE_EVENT_ID) { - wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); - -- if (wl->psm_requested && wl->psm) { -+ if (wl->psm_requested && -+ wl->station_mode != STATION_ACTIVE_MODE) { - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - return ret; - } - } - -- if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) { -+ if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && -+ wl->station_mode != STATION_ACTIVE_MODE) { - wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); - - /* indicate to the stack, that beacons have been lost */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/main.c 2011-05-05 23:29:46.498454104 +0200 -@@ -497,7 +497,7 @@ - wl->rx_last_id = 0; - wl->next_tx_complete = 0; - wl->elp = false; -- wl->psm = 0; -+ wl->station_mode = STATION_ACTIVE_MODE; - wl->tx_queue_stopped = false; - wl->power_level = WL1251_DEFAULT_POWER_LEVEL; - wl->rssi_thold = 0; -@@ -632,13 +632,29 @@ - - wl->psm_requested = false; - -- if (wl->psm) { -+ if (wl->station_mode != STATION_ACTIVE_MODE) { - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - goto out_sleep; - } - } - -+ if (changed & IEEE80211_CONF_CHANGE_IDLE) { -+ if (conf->flags & IEEE80211_CONF_IDLE) { -+ ret = wl1251_ps_set_mode(wl, STATION_IDLE); -+ if (ret < 0) -+ goto out_sleep; -+ } else { -+ ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); -+ if (ret < 0) -+ goto out_sleep; -+ ret = wl1251_join(wl, wl->bss_type, wl->channel, -+ wl->beacon_int, wl->dtim_period); -+ if (ret < 0) -+ goto out_sleep; -+ } -+ } -+ - if (conf->power_level != wl->power_level) { - ret = wl1251_acx_tx_power(wl, conf->power_level); - if (ret < 0) -@@ -1384,7 +1400,7 @@ - wl->rx_config = WL1251_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1251_DEFAULT_RX_FILTER; - wl->elp = false; -- wl->psm = 0; -+ wl->station_mode = STATION_ACTIVE_MODE; - wl->psm_requested = false; - wl->tx_queue_stopped = false; - wl->power_level = WL1251_DEFAULT_POWER_LEVEL; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/ps.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/ps.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/ps.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/ps.c 2011-05-05 23:29:46.498454104 +0200 -@@ -39,7 +39,7 @@ - - mutex_lock(&wl->mutex); - -- if (wl->elp || !wl->psm) -+ if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE) - goto out; - - wl1251_debug(DEBUG_PSM, "chip to elp"); -@@ -57,7 +57,7 @@ - { - unsigned long delay; - -- if (wl->psm) { -+ if (wl->station_mode != STATION_ACTIVE_MODE) { - delay = msecs_to_jiffies(ELP_ENTRY_DELAY); - ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); - } -@@ -104,7 +104,7 @@ - return 0; - } - --int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) -+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode) - { - int ret; - -@@ -128,15 +128,24 @@ - if (ret < 0) - return ret; - -- ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); -+ ret = wl1251_cmd_ps_mode(wl, CHIP_POWER_SAVE_MODE); - if (ret < 0) - return ret; - - ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); - if (ret < 0) - return ret; -+ break; -+ case STATION_IDLE: -+ wl1251_debug(DEBUG_PSM, "entering idle"); - -- wl->psm = 1; -+ ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); -+ if (ret < 0) -+ return ret; -+ -+ ret = wl1251_cmd_template_set(wl, CMD_DISCONNECT, NULL, 0); -+ if (ret < 0) -+ return ret; - break; - case STATION_ACTIVE_MODE: - default: -@@ -163,13 +172,13 @@ - if (ret < 0) - return ret; - -- ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); -+ ret = wl1251_cmd_ps_mode(wl, CHIP_ACTIVE_MODE); - if (ret < 0) - return ret; - -- wl->psm = 0; - break; - } -+ wl->station_mode = mode; - - return ret; - } -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/ps.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/ps.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/ps.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/ps.h 2011-05-05 23:29:46.352452339 +0200 -@@ -26,7 +26,7 @@ - #include "wl1251.h" - #include "acx.h" - --int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); -+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode); - void wl1251_ps_elp_sleep(struct wl1251 *wl); - int wl1251_ps_elp_wakeup(struct wl1251 *wl); - void wl1251_elp_work(struct work_struct *work); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl1251/wl1251.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/wl1251.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl1251/wl1251.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl1251/wl1251.h 2011-05-05 23:29:46.341452207 +0200 -@@ -129,6 +129,12 @@ - PART_TABLE_LEN - }; - -+enum wl1251_station_mode { -+ STATION_ACTIVE_MODE, -+ STATION_POWER_SAVE_MODE, -+ STATION_IDLE, -+}; -+ - struct wl1251_partition { - u32 size; - u32 start; -@@ -358,8 +364,7 @@ - - struct delayed_work elp_work; - -- /* we can be in psm, but not in elp, we have to differentiate */ -- bool psm; -+ enum wl1251_station_mode station_mode; - - /* PSM mode requested */ - bool psm_requested; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/acx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/acx.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/acx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/acx.c 2011-05-05 23:29:45.984447893 +0200 -@@ -965,10 +965,13 @@ - } - - /* memory config */ -- mem_conf->num_stations = wl->conf.mem.num_stations; -- mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; -- mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; -- mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; -+ /* FIXME: for now we always use mem_wl127x for AP, because it -+ * doesn't support dynamic memory and we don't have the -+ * optimal values for wl128x without dynamic memory yet */ -+ mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; -+ mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; -+ mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; -+ mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; - mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); - - ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, -@@ -986,6 +989,7 @@ - int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) - { - struct wl1271_acx_sta_config_memory *mem_conf; -+ struct conf_memory_settings *mem; - int ret; - - wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); -@@ -996,16 +1000,21 @@ - goto out; - } - -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ mem = &wl->conf.mem_wl128x; -+ else -+ mem = &wl->conf.mem_wl127x; -+ - /* memory config */ -- mem_conf->num_stations = wl->conf.mem.num_stations; -- mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num; -- mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num; -- mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles; -+ mem_conf->num_stations = mem->num_stations; -+ mem_conf->rx_mem_block_num = mem->rx_block_num; -+ mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; -+ mem_conf->num_ssid_profiles = mem->ssid_profiles; - mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); -- mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory; -- mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks; -- mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks; -- mem_conf->tx_min = wl->conf.mem.tx_min; -+ mem_conf->dyn_mem_enable = mem->dynamic_memory; -+ mem_conf->tx_free_req = mem->min_req_tx_blocks; -+ mem_conf->rx_free_req = mem->min_req_rx_blocks; -+ mem_conf->tx_min = mem->tx_min; - - ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, - sizeof(*mem_conf)); -@@ -1019,6 +1028,32 @@ - return ret; - } - -+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) -+{ -+ struct wl1271_acx_host_config_bitmap *bitmap_conf; -+ int ret; -+ -+ bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); -+ if (!bitmap_conf) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); -+ -+ ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, -+ bitmap_conf, sizeof(*bitmap_conf)); -+ if (ret < 0) { -+ wl1271_warning("wl1271 bitmap config opt failed: %d", ret); -+ goto out; -+ } -+ -+out: -+ kfree(bitmap_conf); -+ -+ return ret; -+} -+ - int wl1271_acx_init_mem_config(struct wl1271 *wl) - { - int ret; -@@ -1489,22 +1524,46 @@ - return ret; - } - --int wl1271_acx_max_tx_retry(struct wl1271 *wl) -+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) - { -- struct wl1271_acx_max_tx_retry *acx = NULL; -+ struct wl1271_acx_ap_max_tx_retry *acx = NULL; - int ret; - -- wl1271_debug(DEBUG_ACX, "acx max tx retry"); -+ wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) - return -ENOMEM; - -- acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); -+ acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); - - ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); - if (ret < 0) { -- wl1271_warning("acx max tx retry failed: %d", ret); -+ wl1271_warning("acx ap max tx retry failed: %d", ret); -+ goto out; -+ } -+ -+out: -+ kfree(acx); -+ return ret; -+} -+ -+int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) -+{ -+ struct wl1271_acx_sta_max_tx_retry *acx = NULL; -+ int ret; -+ -+ wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); -+ -+ acx = kzalloc(sizeof(*acx), GFP_KERNEL); -+ if (!acx) -+ return -ENOMEM; -+ -+ acx->max_tx_retry = wl->conf.tx.max_tx_retries; -+ -+ ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); -+ if (ret < 0) { -+ wl1271_warning("acx sta max tx retry failed: %d", ret); - goto out; - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/acx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/acx.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/acx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/acx.h 2011-05-05 23:29:45.887446721 +0200 -@@ -939,6 +939,16 @@ - u8 padding; - } __packed; - -+#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) -+#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) -+#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) -+ -+struct wl1271_acx_host_config_bitmap { -+ struct acx_header header; -+ -+ __le32 host_cfg_bitmap; -+} __packed; -+ - enum { - WL1271_ACX_TRIG_TYPE_LEVEL = 0, - WL1271_ACX_TRIG_TYPE_EDGE, -@@ -1135,7 +1145,7 @@ - u8 padding[3]; - } __packed; - --struct wl1271_acx_max_tx_retry { -+struct wl1271_acx_ap_max_tx_retry { - struct acx_header header; - - /* -@@ -1146,6 +1156,13 @@ - u8 padding_1[2]; - } __packed; - -+struct wl1271_acx_sta_max_tx_retry { -+ struct acx_header header; -+ -+ u8 max_tx_retry; -+ u8 padding_1[3]; -+} __packed; -+ - struct wl1271_acx_config_ps { - struct acx_header header; - -@@ -1275,6 +1292,7 @@ - int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); - int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); - int wl1271_acx_init_mem_config(struct wl1271 *wl); -+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); - int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); - int wl1271_acx_smart_reflex(struct wl1271 *wl); - int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); -@@ -1296,7 +1314,8 @@ - int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, - bool enable); - int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); --int wl1271_acx_max_tx_retry(struct wl1271 *wl); -+int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); -+int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); - int wl1271_acx_config_ps(struct wl1271 *wl); - int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/boot.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/boot.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/boot.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/boot.c 2011-05-05 23:29:45.879446625 +0200 -@@ -22,6 +22,7 @@ - */ - - #include -+#include - - #include "acx.h" - #include "reg.h" -@@ -243,33 +244,57 @@ - if (wl->nvs == NULL) - return -ENODEV; - -- /* -- * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band -- * configurations) can be removed when those NVS files stop floating -- * around. -- */ -- if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || -- wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { -- /* for now 11a is unsupported in AP mode */ -- if (wl->bss_type != BSS_TYPE_AP_BSS && -- wl->nvs->general_params.dual_mode_select) -- wl->enable_11a = true; -- } -- -- if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && -- (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || -- wl->enable_11a)) { -- wl1271_error("nvs size is not as expected: %zu != %zu", -- wl->nvs_len, sizeof(struct wl1271_nvs_file)); -- kfree(wl->nvs); -- wl->nvs = NULL; -- wl->nvs_len = 0; -- return -EILSEQ; -- } -- -- /* only the first part of the NVS needs to be uploaded */ -- nvs_len = sizeof(wl->nvs->nvs); -- nvs_ptr = (u8 *)wl->nvs->nvs; -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; -+ -+ if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) { -+ if (nvs->general_params.dual_mode_select) -+ wl->enable_11a = true; -+ } else { -+ wl1271_error("nvs size is not as expected: %zu != %zu", -+ wl->nvs_len, -+ sizeof(struct wl128x_nvs_file)); -+ kfree(wl->nvs); -+ wl->nvs = NULL; -+ wl->nvs_len = 0; -+ return -EILSEQ; -+ } -+ -+ /* only the first part of the NVS needs to be uploaded */ -+ nvs_len = sizeof(nvs->nvs); -+ nvs_ptr = (u8 *)nvs->nvs; -+ -+ } else { -+ struct wl1271_nvs_file *nvs = -+ (struct wl1271_nvs_file *)wl->nvs; -+ /* -+ * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz -+ * band configurations) can be removed when those NVS files stop -+ * floating around. -+ */ -+ if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || -+ wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { -+ /* for now 11a is unsupported in AP mode */ -+ if (wl->bss_type != BSS_TYPE_AP_BSS && -+ nvs->general_params.dual_mode_select) -+ wl->enable_11a = true; -+ } -+ -+ if (wl->nvs_len != sizeof(struct wl1271_nvs_file) && -+ (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE || -+ wl->enable_11a)) { -+ wl1271_error("nvs size is not as expected: %zu != %zu", -+ wl->nvs_len, sizeof(struct wl1271_nvs_file)); -+ kfree(wl->nvs); -+ wl->nvs = NULL; -+ wl->nvs_len = 0; -+ return -EILSEQ; -+ } -+ -+ /* only the first part of the NVS needs to be uploaded */ -+ nvs_len = sizeof(nvs->nvs); -+ nvs_ptr = (u8 *) nvs->nvs; -+ } - - /* update current MAC address to NVS */ - nvs_ptr[11] = wl->mac_addr[0]; -@@ -319,10 +344,13 @@ - /* - * We've reached the first zero length, the first NVS table - * is located at an aligned offset which is at least 7 bytes further. -+ * NOTE: The wl->nvs->nvs element must be first, in order to -+ * simplify the casting, we assume it is at the beginning of -+ * the wl->nvs structure. - */ -- nvs_ptr = (u8 *)wl->nvs->nvs + -- ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4); -- nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; -+ nvs_ptr = (u8 *)wl->nvs + -+ ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); -+ nvs_len -= nvs_ptr - (u8 *)wl->nvs; - - /* Now we must set the partition correctly */ - wl1271_set_partition(wl, &part_table[PART_WORK]); -@@ -450,10 +478,14 @@ - DISCONNECT_EVENT_COMPLETE_ID | - RSSI_SNR_TRIGGER_0_EVENT_ID | - PSPOLL_DELIVERY_FAILURE_EVENT_ID | -- SOFT_GEMINI_SENSE_EVENT_ID; -+ SOFT_GEMINI_SENSE_EVENT_ID | -+ MAX_TX_RETRY_EVENT_ID; - - if (wl->bss_type == BSS_TYPE_AP_BSS) -- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; -+ wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | -+ INACTIVE_STA_EVENT_ID; -+ else -+ wl->event_mask |= DUMMY_PACKET_EVENT_ID; - - ret = wl1271_event_unmask(wl); - if (ret < 0) { -@@ -493,24 +525,159 @@ - wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; - } - --/* uploads NVS and firmware */ --int wl1271_load_firmware(struct wl1271 *wl) -+static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) - { -- int ret = 0; -- u32 tmp, clk, pause; -+ u16 spare_reg; -+ -+ /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ -+ spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); -+ if (spare_reg == 0xFFFF) -+ return -EFAULT; -+ spare_reg |= (BIT(3) | BIT(5) | BIT(6)); -+ wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); -+ -+ /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ -+ wl1271_top_reg_write(wl, SYS_CLK_CFG_REG, -+ WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); -+ -+ /* Delay execution for 15msec, to let the HW settle */ -+ mdelay(15); -+ -+ return 0; -+} -+ -+static bool wl128x_is_tcxo_valid(struct wl1271 *wl) -+{ -+ u16 tcxo_detection; -+ -+ tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG); -+ if (tcxo_detection & TCXO_DET_FAILED) -+ return false; -+ -+ return true; -+} -+ -+static bool wl128x_is_fref_valid(struct wl1271 *wl) -+{ -+ u16 fref_detection; -+ -+ fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG); -+ if (fref_detection & FREF_CLK_DETECT_FAIL) -+ return false; -+ -+ return true; -+} -+ -+static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) -+{ -+ wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); -+ wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); -+ wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); -+ -+ return 0; -+} -+ -+static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) -+{ -+ u16 spare_reg; -+ u16 pll_config; -+ u8 input_freq; -+ -+ /* Mask bits [3:1] in the sys_clk_cfg register */ -+ spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG); -+ if (spare_reg == 0xFFFF) -+ return -EFAULT; -+ spare_reg |= BIT(2); -+ wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg); -+ -+ /* Handle special cases of the TCXO clock */ -+ if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || -+ wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) -+ return wl128x_manually_configure_mcs_pll(wl); -+ -+ /* Set the input frequency according to the selected clock source */ -+ input_freq = (clk & 1) + 1; -+ -+ pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG); -+ if (pll_config == 0xFFFF) -+ return -EFAULT; -+ pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); -+ pll_config |= MCS_PLL_ENABLE_HP; -+ wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); -+ -+ return 0; -+} -+ -+/* -+ * WL128x has two clocks input - TCXO and FREF. -+ * TCXO is the main clock of the device, while FREF is used to sync -+ * between the GPS and the cellular modem. -+ * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used -+ * as the WLAN/BT main clock. -+ */ -+static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) -+{ -+ u16 sys_clk_cfg; -+ -+ /* For XTAL-only modes, FREF will be used after switching from TCXO */ -+ if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || -+ wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { -+ if (!wl128x_switch_tcxo_to_fref(wl)) -+ return -EINVAL; -+ goto fref_clk; -+ } -+ -+ /* Query the HW, to determine which clock source we should use */ -+ sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG); -+ if (sys_clk_cfg == 0xFFFF) -+ return -EINVAL; -+ if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) -+ goto fref_clk; -+ -+ /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ -+ if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || -+ wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { -+ if (!wl128x_switch_tcxo_to_fref(wl)) -+ return -EINVAL; -+ goto fref_clk; -+ } -+ -+ /* TCXO clock is selected */ -+ if (!wl128x_is_tcxo_valid(wl)) -+ return -EINVAL; -+ *selected_clock = wl->tcxo_clock; -+ goto config_mcs_pll; -+ -+fref_clk: -+ /* FREF clock is selected */ -+ if (!wl128x_is_fref_valid(wl)) -+ return -EINVAL; -+ *selected_clock = wl->ref_clock; -+ -+config_mcs_pll: -+ return wl128x_configure_mcs_pll(wl, *selected_clock); -+} -+ -+static int wl127x_boot_clk(struct wl1271 *wl) -+{ -+ u32 pause; -+ u32 clk; - - wl1271_boot_hw_version(wl); - -- if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4) -+ if (wl->ref_clock == CONF_REF_CLK_19_2_E || -+ wl->ref_clock == CONF_REF_CLK_38_4_E || -+ wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) - /* ref clk: 19.2/38.4/38.4-XTAL */ - clk = 0x3; -- else if (wl->ref_clock == 1 || wl->ref_clock == 3) -+ else if (wl->ref_clock == CONF_REF_CLK_26_E || -+ wl->ref_clock == CONF_REF_CLK_52_E) - /* ref clk: 26/52 */ - clk = 0x5; - else - return -EINVAL; - -- if (wl->ref_clock != 0) { -+ if (wl->ref_clock != CONF_REF_CLK_19_2_E) { - u16 val; - /* Set clock type (open drain) */ - val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); -@@ -540,6 +707,26 @@ - pause |= WU_COUNTER_PAUSE_VAL; - wl1271_write32(wl, WU_COUNTER_PAUSE, pause); - -+ return 0; -+} -+ -+/* uploads NVS and firmware */ -+int wl1271_load_firmware(struct wl1271 *wl) -+{ -+ int ret = 0; -+ u32 tmp, clk; -+ int selected_clock = -1; -+ -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ ret = wl128x_boot_clk(wl, &selected_clock); -+ if (ret < 0) -+ goto out; -+ } else { -+ ret = wl127x_boot_clk(wl); -+ if (ret < 0) -+ goto out; -+ } -+ - /* Continue the ELP wake up sequence */ - wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); - udelay(500); -@@ -555,7 +742,12 @@ - - wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - -- clk |= (wl->ref_clock << 1) << 4; -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ clk |= ((selected_clock & 0x3) << 1) << 4; -+ } else { -+ clk |= (wl->ref_clock << 1) << 4; -+ } -+ - wl1271_write32(wl, DRPW_SCRATCH_START, clk); - - wl1271_set_partition(wl, &part_table[PART_WORK]); -@@ -585,16 +777,12 @@ - /* 6. read the EEPROM parameters */ - tmp = wl1271_read32(wl, SCR_PAD2); - -- ret = wl1271_boot_write_irq_polarity(wl); -- if (ret < 0) -- goto out; -- -- wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, -- WL1271_ACX_ALL_EVENTS_VECTOR); -- - /* WL1271: The reference driver skips steps 7 to 10 (jumps directly - * to upload_fw) */ - -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); -+ - ret = wl1271_boot_upload_firmware(wl); - if (ret < 0) - goto out; -@@ -618,6 +806,13 @@ - if (ret < 0) - goto out; - -+ ret = wl1271_boot_write_irq_polarity(wl); -+ if (ret < 0) -+ goto out; -+ -+ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, -+ WL1271_ACX_ALL_EVENTS_VECTOR); -+ - /* Enable firmware interrupts now */ - wl1271_boot_enable_interrupts(wl); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/boot.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/boot.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/boot.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/boot.h 2011-05-05 23:29:45.968447701 +0200 -@@ -74,4 +74,56 @@ - #define FREF_CLK_POLARITY_BITS 0xfffff8ff - #define CLK_REQ_OUTN_SEL 0x700 - -+/* PLL configuration algorithm for wl128x */ -+#define SYS_CLK_CFG_REG 0x2200 -+/* Bit[0] - 0-TCXO, 1-FREF */ -+#define MCS_PLL_CLK_SEL_FREF BIT(0) -+/* Bit[3:2] - 01-TCXO, 10-FREF */ -+#define WL_CLK_REQ_TYPE_FREF BIT(3) -+#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) -+/* Bit[4] - 0-TCXO, 1-FREF */ -+#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) -+ -+#define TCXO_ILOAD_INT_REG 0x2264 -+#define TCXO_CLK_DETECT_REG 0x2266 -+ -+#define TCXO_DET_FAILED BIT(4) -+ -+#define FREF_ILOAD_INT_REG 0x2084 -+#define FREF_CLK_DETECT_REG 0x2086 -+#define FREF_CLK_DETECT_FAIL BIT(4) -+ -+/* Use this reg for masking during driver access */ -+#define WL_SPARE_REG 0x2320 -+#define WL_SPARE_VAL BIT(2) -+/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ -+#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) -+ -+#define PLL_LOCK_COUNTERS_REG 0xD8C -+#define PLL_LOCK_COUNTERS_COEX 0x0F -+#define PLL_LOCK_COUNTERS_MCS 0xF0 -+#define MCS_PLL_OVERRIDE_REG 0xD90 -+#define MCS_PLL_CONFIG_REG 0xD92 -+#define MCS_SEL_IN_FREQ_MASK 0x0070 -+#define MCS_SEL_IN_FREQ_SHIFT 4 -+#define MCS_PLL_CONFIG_REG_VAL 0x73 -+#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) -+ -+#define MCS_PLL_M_REG 0xD94 -+#define MCS_PLL_N_REG 0xD96 -+#define MCS_PLL_M_REG_VAL 0xC8 -+#define MCS_PLL_N_REG_VAL 0x07 -+ -+#define SDIO_IO_DS 0xd14 -+ -+/* SDIO/wSPI DS configuration values */ -+enum { -+ HCI_IO_DS_8MA = 0, -+ HCI_IO_DS_4MA = 1, /* default */ -+ HCI_IO_DS_6MA = 2, -+ HCI_IO_DS_2MA = 3, -+}; -+ -+/* end PLL configuration algorithm for wl128x */ -+ - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/cmd.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/cmd.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/cmd.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/cmd.c 2011-05-05 23:29:45.918447097 +0200 -@@ -110,7 +110,47 @@ - int wl1271_cmd_general_parms(struct wl1271 *wl) - { - struct wl1271_general_parms_cmd *gen_parms; -- struct wl1271_ini_general_params *gp = &wl->nvs->general_params; -+ struct wl1271_ini_general_params *gp = -+ &((struct wl1271_nvs_file *)wl->nvs)->general_params; -+ bool answer = false; -+ int ret; -+ -+ if (!wl->nvs) -+ return -ENODEV; -+ -+ gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); -+ if (!gen_parms) -+ return -ENOMEM; -+ -+ gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; -+ -+ memcpy(&gen_parms->general_params, gp, sizeof(*gp)); -+ -+ if (gp->tx_bip_fem_auto_detect) -+ answer = true; -+ -+ ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); -+ if (ret < 0) { -+ wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); -+ goto out; -+ } -+ -+ gp->tx_bip_fem_manufacturer = -+ gen_parms->general_params.tx_bip_fem_manufacturer; -+ -+ wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", -+ answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); -+ -+out: -+ kfree(gen_parms); -+ return ret; -+} -+ -+int wl128x_cmd_general_parms(struct wl1271 *wl) -+{ -+ struct wl128x_general_parms_cmd *gen_parms; -+ struct wl128x_ini_general_params *gp = -+ &((struct wl128x_nvs_file *)wl->nvs)->general_params; - bool answer = false; - int ret; - -@@ -147,8 +187,9 @@ - - int wl1271_cmd_radio_parms(struct wl1271 *wl) - { -+ struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; - struct wl1271_radio_parms_cmd *radio_parms; -- struct wl1271_ini_general_params *gp = &wl->nvs->general_params; -+ struct wl1271_ini_general_params *gp = &nvs->general_params; - int ret; - - if (!wl->nvs) -@@ -161,18 +202,18 @@ - radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - - /* 2.4GHz parameters */ -- memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2, -+ memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, - sizeof(struct wl1271_ini_band_params_2)); - memcpy(&radio_parms->dyn_params_2, -- &wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, -+ &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl1271_ini_fem_params_2)); - - /* 5GHz parameters */ - memcpy(&radio_parms->static_params_5, -- &wl->nvs->stat_radio_params_5, -+ &nvs->stat_radio_params_5, - sizeof(struct wl1271_ini_band_params_5)); - memcpy(&radio_parms->dyn_params_5, -- &wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, -+ &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl1271_ini_fem_params_5)); - - wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", -@@ -186,6 +227,50 @@ - return ret; - } - -+int wl128x_cmd_radio_parms(struct wl1271 *wl) -+{ -+ struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; -+ struct wl128x_radio_parms_cmd *radio_parms; -+ struct wl128x_ini_general_params *gp = &nvs->general_params; -+ int ret; -+ -+ if (!wl->nvs) -+ return -ENODEV; -+ -+ radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); -+ if (!radio_parms) -+ return -ENOMEM; -+ -+ radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; -+ -+ /* 2.4GHz parameters */ -+ memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, -+ sizeof(struct wl128x_ini_band_params_2)); -+ memcpy(&radio_parms->dyn_params_2, -+ &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, -+ sizeof(struct wl128x_ini_fem_params_2)); -+ -+ /* 5GHz parameters */ -+ memcpy(&radio_parms->static_params_5, -+ &nvs->stat_radio_params_5, -+ sizeof(struct wl128x_ini_band_params_5)); -+ memcpy(&radio_parms->dyn_params_5, -+ &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, -+ sizeof(struct wl128x_ini_fem_params_5)); -+ -+ radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; -+ -+ wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", -+ radio_parms, sizeof(*radio_parms)); -+ -+ ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); -+ if (ret < 0) -+ wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); -+ -+ kfree(radio_parms); -+ return ret; -+} -+ - int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) - { - struct wl1271_ext_radio_parms_cmd *ext_radio_parms; -@@ -985,7 +1070,7 @@ - - memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); - -- cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); -+ cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); - cmd->bss_index = WL1271_AP_BSS_INDEX; - cmd->global_hlid = WL1271_AP_GLOBAL_HLID; - cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/cmd.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/cmd.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/cmd.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/cmd.h 2011-05-05 23:29:45.998448063 +0200 -@@ -32,7 +32,9 @@ - int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, - size_t res_len); - int wl1271_cmd_general_parms(struct wl1271 *wl); -+int wl128x_cmd_general_parms(struct wl1271 *wl); - int wl1271_cmd_radio_parms(struct wl1271 *wl); -+int wl128x_cmd_radio_parms(struct wl1271 *wl); - int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); - int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); - int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); -@@ -415,6 +417,21 @@ - u8 padding[3]; - } __packed; - -+struct wl128x_general_parms_cmd { -+ struct wl1271_cmd_header header; -+ -+ struct wl1271_cmd_test_header test; -+ -+ struct wl128x_ini_general_params general_params; -+ -+ u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; -+ u8 sr_sen_n_p; -+ u8 sr_sen_n_p_gain; -+ u8 sr_sen_nrn; -+ u8 sr_sen_prn; -+ u8 padding[3]; -+} __packed; -+ - struct wl1271_radio_parms_cmd { - struct wl1271_cmd_header header; - -@@ -431,6 +448,23 @@ - u8 padding3[2]; - } __packed; - -+struct wl128x_radio_parms_cmd { -+ struct wl1271_cmd_header header; -+ -+ struct wl1271_cmd_test_header test; -+ -+ /* Static radio parameters */ -+ struct wl128x_ini_band_params_2 static_params_2; -+ struct wl128x_ini_band_params_5 static_params_5; -+ -+ u8 fem_vendor_and_options; -+ -+ /* Dynamic radio parameters */ -+ struct wl128x_ini_fem_params_2 dyn_params_2; -+ u8 padding2; -+ struct wl128x_ini_fem_params_5 dyn_params_5; -+} __packed; -+ - struct wl1271_ext_radio_parms_cmd { - struct wl1271_cmd_header header; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/conf.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/conf.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/conf.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/conf.h 2011-05-05 23:29:46.005448147 +0200 -@@ -683,10 +683,18 @@ - struct conf_tx_rate_class ap_bcst_conf; - - /* -- * AP-mode - allow this number of TX retries to a station before an -+ * Allow this number of TX retries to a connected station/AP before an - * event is triggered from FW. -+ * In AP-mode the hlids of unreachable stations are given in the -+ * "sta_tx_retry_exceeded" member in the event mailbox. - */ -- u16 ap_max_tx_retries; -+ u8 max_tx_retries; -+ -+ /* -+ * AP-mode - after this number of seconds a connected station is -+ * considered inactive. -+ */ -+ u16 ap_aging_period; - - /* - * Configuration for TID parameters. -@@ -1004,7 +1012,9 @@ - CONF_REF_CLK_19_2_E, - CONF_REF_CLK_26_E, - CONF_REF_CLK_38_4_E, -- CONF_REF_CLK_52_E -+ CONF_REF_CLK_52_E, -+ CONF_REF_CLK_38_4_M_XTAL, -+ CONF_REF_CLK_26_M_XTAL, - }; - - enum single_dual_band_enum { -@@ -1018,15 +1028,6 @@ - #define CONF_NUMBER_OF_CHANNELS_2_4 14 - #define CONF_NUMBER_OF_CHANNELS_5 35 - --struct conf_radio_parms { -- /* -- * FEM parameter set to use -- * -- * Range: 0 or 1 -- */ -- u8 fem; --}; -- - struct conf_itrim_settings { - /* enable dco itrim */ - u8 enable; -@@ -1202,7 +1203,9 @@ - struct conf_scan_settings scan; - struct conf_rf_settings rf; - struct conf_ht_setting ht; -- struct conf_memory_settings mem; -+ struct conf_memory_settings mem_wl127x; -+ struct conf_memory_settings mem_wl128x; -+ u8 hci_io_ds; - }; - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/debugfs.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/debugfs.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/debugfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/debugfs.c 2011-05-05 23:29:45.977447809 +0200 -@@ -267,7 +267,7 @@ - } - buf[len] = '\0'; - -- ret = strict_strtoul(buf, 0, &value); -+ ret = kstrtoul(buf, 0, &value); - if (ret < 0) { - wl1271_warning("illegal value in gpio_power"); - return -EINVAL; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/event.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/event.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/event.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/event.c 2011-05-05 23:29:45.901446891 +0200 -@@ -33,6 +33,7 @@ - { - struct delayed_work *dwork; - struct wl1271 *wl; -+ int ret; - - dwork = container_of(work, struct delayed_work, work); - wl = container_of(dwork, struct wl1271, pspoll_work); -@@ -55,8 +56,13 @@ - * delivery failure occurred, and no-one changed state since, so - * we should go back to powersave. - */ -+ ret = wl1271_ps_elp_wakeup(wl); -+ if (ret < 0) -+ goto out; -+ - wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); - -+ wl1271_ps_elp_sleep(wl); - out: - mutex_unlock(&wl->mutex); - }; -@@ -129,11 +135,6 @@ - - /* enable beacon early termination */ - ret = wl1271_acx_bet_enable(wl, true); -- if (ret < 0) -- break; -- -- /* go to extremely low power mode */ -- wl1271_ps_elp_sleep(wl); - break; - default: - break; -@@ -173,6 +174,8 @@ - u32 vector; - bool beacon_loss = false; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); -+ bool disconnect_sta = false; -+ unsigned long sta_bitmap = 0; - - wl1271_event_mbox_dump(mbox); - -@@ -228,9 +231,60 @@ - wl1271_event_rssi_trigger(wl, mbox); - } - -+ if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { -+ wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); -+ if (wl->vif) -+ wl1271_tx_dummy_packet(wl); -+ } -+ -+ /* -+ * "TX retries exceeded" has a different meaning according to mode. -+ * In AP mode the offending station is disconnected. In STA mode we -+ * report connection loss. -+ */ -+ if (vector & MAX_TX_RETRY_EVENT_ID) { -+ wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); -+ if (is_ap) { -+ sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); -+ disconnect_sta = true; -+ } else { -+ beacon_loss = true; -+ } -+ } -+ -+ if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { -+ wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); -+ sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); -+ disconnect_sta = true; -+ } -+ - if (wl->vif && beacon_loss) - ieee80211_connection_loss(wl->vif); - -+ if (is_ap && disconnect_sta) { -+ u32 num_packets = wl->conf.tx.max_tx_retries; -+ struct ieee80211_sta *sta; -+ const u8 *addr; -+ int h; -+ -+ for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); -+ h < AP_MAX_LINKS; -+ h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { -+ if (!wl1271_is_active_sta(wl, h)) -+ continue; -+ -+ addr = wl->links[h].addr; -+ -+ rcu_read_lock(); -+ sta = ieee80211_find_sta(wl->vif, addr); -+ if (sta) { -+ wl1271_debug(DEBUG_EVENT, "remove sta %d", h); -+ ieee80211_report_low_ack(sta, num_packets); -+ } -+ rcu_read_unlock(); -+ } -+ } -+ - return 0; - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/event.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/event.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/event.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/event.h 2011-05-05 23:29:45.970447725 +0200 -@@ -58,10 +58,16 @@ - CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), - BSS_LOSE_EVENT_ID = BIT(18), - REGAINED_BSS_EVENT_ID = BIT(19), -- ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), -- STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */ -+ MAX_TX_RETRY_EVENT_ID = BIT(20), -+ /* STA: dummy paket for dynamic mem blocks */ -+ DUMMY_PACKET_EVENT_ID = BIT(21), -+ /* AP: STA remove complete */ -+ STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), - SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), -+ /* STA: SG prediction */ - SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), -+ /* AP: Inactive STA */ -+ INACTIVE_STA_EVENT_ID = BIT(23), - SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), - PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), - DBG_EVENT_ID = BIT(26), -@@ -116,7 +122,11 @@ - - /* AP FW only */ - u8 hlid_removed; -+ -+ /* a bitmap of hlids for stations that have been inactive too long */ - __le16 sta_aging_status; -+ -+ /* a bitmap of hlids for stations which didn't respond to TX */ - __le16 sta_tx_retry_exceeded; - - u8 reserved_5[24]; -@@ -127,4 +137,7 @@ - int wl1271_event_handle(struct wl1271 *wl, u8 mbox); - void wl1271_pspoll_work(struct work_struct *work); - -+/* Functions from main.c */ -+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); -+ - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/ini.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/ini.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/ini.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/ini.h 2011-05-05 23:29:45.978447821 +0200 -@@ -41,6 +41,28 @@ - u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - } __packed; - -+#define WL128X_INI_MAX_SETTINGS_PARAM 4 -+ -+struct wl128x_ini_general_params { -+ u8 ref_clock; -+ u8 settling_time; -+ u8 clk_valid_on_wakeup; -+ u8 tcxo_ref_clock; -+ u8 tcxo_settling_time; -+ u8 tcxo_valid_on_wakeup; -+ u8 tcxo_ldo_voltage; -+ u8 xtal_itrim_val; -+ u8 platform_conf; -+ u8 dual_mode_select; -+ u8 tx_bip_fem_auto_detect; -+ u8 tx_bip_fem_manufacturer; -+ u8 general_settings[WL128X_INI_MAX_SETTINGS_PARAM]; -+ u8 sr_state; -+ u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM]; -+ u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM]; -+ u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM]; -+} __packed; -+ - #define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15 - - struct wl1271_ini_band_params_2 { -@@ -49,9 +71,16 @@ - u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; - } __packed; - --#define WL1271_INI_RATE_GROUP_COUNT 6 - #define WL1271_INI_CHANNEL_COUNT_2 14 - -+struct wl128x_ini_band_params_2 { -+ u8 rx_trace_insertion_loss; -+ u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_2]; -+ u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; -+} __packed; -+ -+#define WL1271_INI_RATE_GROUP_COUNT 6 -+ - struct wl1271_ini_fem_params_2 { - __le16 tx_bip_ref_pd_voltage; - u8 tx_bip_ref_power; -@@ -68,6 +97,28 @@ - u8 normal_to_degraded_high_thr; - } __packed; - -+#define WL128X_INI_RATE_GROUP_COUNT 7 -+/* low and high temperatures */ -+#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2 -+ -+struct wl128x_ini_fem_params_2 { -+ __le16 tx_bip_ref_pd_voltage; -+ u8 tx_bip_ref_power; -+ u8 tx_bip_ref_offset; -+ u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2]; -+ u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2]; -+ u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT + 1]; -+ u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_2]; -+ u8 tx_pd_vs_temperature[WL128X_INI_PD_VS_TEMPERATURE_RANGES]; -+ u8 rx_fem_insertion_loss; -+ u8 degraded_low_to_normal_thr; -+ u8 normal_to_degraded_high_thr; -+} __packed; -+ - #define WL1271_INI_CHANNEL_COUNT_5 35 - #define WL1271_INI_SUB_BAND_COUNT_5 7 - -@@ -77,6 +128,12 @@ - u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; - } __packed; - -+struct wl128x_ini_band_params_5 { -+ u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; -+ u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_5]; -+ u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE]; -+} __packed; -+ - struct wl1271_ini_fem_params_5 { - __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; - u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; -@@ -92,6 +149,23 @@ - u8 normal_to_degraded_high_thr; - } __packed; - -+struct wl128x_ini_fem_params_5 { -+ __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5]; -+ u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5]; -+ u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5]; -+ u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5]; -+ u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT]; -+ u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_5]; -+ u8 tx_pd_vs_temperature[WL1271_INI_SUB_BAND_COUNT_5 * -+ WL128X_INI_PD_VS_TEMPERATURE_RANGES]; -+ u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5]; -+ u8 degraded_low_to_normal_thr; -+ u8 normal_to_degraded_high_thr; -+} __packed; - - /* NVS data structure */ - #define WL1271_INI_NVS_SECTION_SIZE 468 -@@ -100,7 +174,7 @@ - #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 - - struct wl1271_nvs_file { -- /* NVS section */ -+ /* NVS section - must be first! */ - u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; - - /* INI section */ -@@ -120,4 +194,24 @@ - } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; - } __packed; - -+struct wl128x_nvs_file { -+ /* NVS section - must be first! */ -+ u8 nvs[WL1271_INI_NVS_SECTION_SIZE]; -+ -+ /* INI section */ -+ struct wl128x_ini_general_params general_params; -+ u8 fem_vendor_and_options; -+ struct wl128x_ini_band_params_2 stat_radio_params_2; -+ u8 padding2; -+ struct { -+ struct wl128x_ini_fem_params_2 params; -+ u8 padding; -+ } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; -+ struct wl128x_ini_band_params_5 stat_radio_params_5; -+ u8 padding3; -+ struct { -+ struct wl128x_ini_fem_params_5 params; -+ u8 padding; -+ } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; -+} __packed; - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/init.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/init.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/init.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/init.c 2011-05-05 23:29:45.970447725 +0200 -@@ -31,6 +31,7 @@ - #include "cmd.h" - #include "reg.h" - #include "tx.h" -+#include "io.h" - - int wl1271_sta_init_templates_config(struct wl1271 *wl) - { -@@ -321,9 +322,11 @@ - { - int ret; - -- ret = wl1271_cmd_ext_radio_parms(wl); -- if (ret < 0) -- return ret; -+ if (wl->chip.id != CHIP_ID_1283_PG20) { -+ ret = wl1271_cmd_ext_radio_parms(wl); -+ if (ret < 0) -+ return ret; -+ } - - /* PS config */ - ret = wl1271_acx_config_ps(wl); -@@ -372,6 +375,10 @@ - if (ret < 0) - return ret; - -+ ret = wl1271_acx_sta_max_tx_retry(wl); -+ if (ret < 0) -+ return ret; -+ - ret = wl1271_acx_sta_mem_cfg(wl); - if (ret < 0) - return ret; -@@ -438,7 +445,7 @@ - if (ret < 0) - return ret; - -- ret = wl1271_acx_max_tx_retry(wl); -+ ret = wl1271_acx_ap_max_tx_retry(wl); - if (ret < 0) - return ret; - -@@ -504,6 +511,27 @@ - return ret; - } - -+int wl1271_chip_specific_init(struct wl1271 *wl) -+{ -+ int ret = 0; -+ -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; -+ -+ if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) -+ /* Enable SDIO padding */ -+ host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; -+ -+ /* Must be before wl1271_acx_init_mem_config() */ -+ ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); -+ if (ret < 0) -+ goto out; -+ } -+out: -+ return ret; -+} -+ -+ - int wl1271_hw_init(struct wl1271 *wl) - { - struct conf_tx_ac_category *conf_ac; -@@ -511,11 +539,22 @@ - int ret, i; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - -- ret = wl1271_cmd_general_parms(wl); -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ ret = wl128x_cmd_general_parms(wl); -+ else -+ ret = wl1271_cmd_general_parms(wl); -+ if (ret < 0) -+ return ret; -+ -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ ret = wl128x_cmd_radio_parms(wl); -+ else -+ ret = wl1271_cmd_radio_parms(wl); - if (ret < 0) - return ret; - -- ret = wl1271_cmd_radio_parms(wl); -+ /* Chip-specific init */ -+ ret = wl1271_chip_specific_init(wl); - if (ret < 0) - return ret; - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/init.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/init.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/init.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/init.h 2011-05-05 23:29:45.969447713 +0200 -@@ -31,6 +31,7 @@ - int wl1271_init_phy_config(struct wl1271 *wl); - int wl1271_init_pta(struct wl1271 *wl); - int wl1271_init_energy_detection(struct wl1271 *wl); -+int wl1271_chip_specific_init(struct wl1271 *wl); - int wl1271_hw_init(struct wl1271 *wl); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/io.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/io.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/io.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/io.c 2011-05-05 23:29:45.917447084 +0200 -@@ -29,6 +29,7 @@ - #include "wl12xx.h" - #include "wl12xx_80211.h" - #include "io.h" -+#include "tx.h" - - #define OCP_CMD_LOOP 32 - -@@ -43,6 +44,16 @@ - #define OCP_STATUS_REQ_FAILED 0x20000 - #define OCP_STATUS_RESP_ERROR 0x30000 - -+bool wl1271_set_block_size(struct wl1271 *wl) -+{ -+ if (wl->if_ops->set_block_size) { -+ wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); -+ return true; -+ } -+ -+ return false; -+} -+ - void wl1271_disable_interrupts(struct wl1271 *wl) - { - wl->if_ops->disable_irq(wl); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/io.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/io.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/io.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/io.h 2011-05-05 23:29:45.952447507 +0200 -@@ -169,5 +169,8 @@ - struct ieee80211_hw *wl1271_alloc_hw(void); - int wl1271_free_hw(struct wl1271 *wl); - irqreturn_t wl1271_irq(int irq, void *data); -+bool wl1271_set_block_size(struct wl1271 *wl); -+int wl1271_tx_dummy_packet(struct wl1271 *wl); -+void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters); - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/Kconfig linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/Kconfig ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/Kconfig 2011-05-05 23:29:46.010448207 +0200 -@@ -3,7 +3,7 @@ - depends on MAC80211 && EXPERIMENTAL - ---help--- - This will enable TI wl12xx driver support for the following chips: -- wl1271 and wl1273. -+ wl1271, wl1273, wl1281 and wl1283. - The drivers make use of the mac80211 stack. - - config WL12XX -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/main.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/main.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/main.c 2011-05-05 23:29:45.982447869 +0200 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include "wl12xx.h" - #include "wl12xx_80211.h" -@@ -54,7 +55,7 @@ - [CONF_SG_BT_PER_THRESHOLD] = 7500, - [CONF_SG_HV3_MAX_OVERRIDE] = 0, - [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, -- [CONF_SG_BT_LOAD_RATIO] = 50, -+ [CONF_SG_BT_LOAD_RATIO] = 200, - [CONF_SG_AUTO_PS_MODE] = 1, - [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, -@@ -191,7 +192,8 @@ - .long_retry_limit = 10, - .aflags = 0, - }, -- .ap_max_tx_retries = 100, -+ .max_tx_retries = 100, -+ .ap_aging_period = 300, - .tid_conf_count = 4, - .tid_conf = { - [CONF_TX_AC_BE] = { -@@ -254,7 +256,7 @@ - .ps_poll_threshold = 10, - .ps_poll_recovery_period = 700, - .bet_enable = CONF_BET_MODE_ENABLE, -- .bet_max_consecutive = 10, -+ .bet_max_consecutive = 50, - .psm_entry_retries = 5, - .psm_exit_retries = 255, - .psm_entry_nullfunc_retries = 3, -@@ -298,7 +300,7 @@ - .tx_ba_win_size = 64, - .inactivity_timeout = 10000, - }, -- .mem = { -+ .mem_wl127x = { - .num_stations = 1, - .ssid_profiles = 1, - .rx_block_num = 70, -@@ -307,7 +309,18 @@ - .min_req_tx_blocks = 100, - .min_req_rx_blocks = 22, - .tx_min = 27, -- } -+ }, -+ .mem_wl128x = { -+ .num_stations = 1, -+ .ssid_profiles = 1, -+ .rx_block_num = 40, -+ .tx_min_block_num = 40, -+ .dynamic_memory = 1, -+ .min_req_tx_blocks = 45, -+ .min_req_rx_blocks = 22, -+ .tx_min = 27, -+ }, -+ .hci_io_ds = HCI_IO_DS_6MA, - }; - - static void __wl1271_op_remove_interface(struct wl1271 *wl); -@@ -329,6 +342,7 @@ - }, - }; - -+static DEFINE_MUTEX(wl_list_mutex); - static LIST_HEAD(wl_list); - - static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, -@@ -359,10 +373,12 @@ - return NOTIFY_DONE; - - wl_temp = hw->priv; -+ mutex_lock(&wl_list_mutex); - list_for_each_entry(wl, &wl_list, list) { - if (wl == wl_temp) - break; - } -+ mutex_unlock(&wl_list_mutex); - if (wl != wl_temp) - return NOTIFY_DONE; - -@@ -438,15 +454,30 @@ - struct conf_tx_tid *conf_tid; - int ret, i; - -- ret = wl1271_cmd_general_parms(wl); -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ ret = wl128x_cmd_general_parms(wl); -+ else -+ ret = wl1271_cmd_general_parms(wl); - if (ret < 0) - return ret; - -- ret = wl1271_cmd_radio_parms(wl); -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ ret = wl128x_cmd_radio_parms(wl); -+ else -+ ret = wl1271_cmd_radio_parms(wl); -+ if (ret < 0) -+ return ret; -+ -+ if (wl->chip.id != CHIP_ID_1283_PG20) { -+ ret = wl1271_cmd_ext_radio_parms(wl); -+ if (ret < 0) -+ return ret; -+ } - if (ret < 0) - return ret; - -- ret = wl1271_cmd_ext_radio_parms(wl); -+ /* Chip-specific initializations */ -+ ret = wl1271_chip_specific_init(wl); - if (ret < 0) - return ret; - -@@ -593,15 +624,17 @@ - { - struct wl1271_fw_common_status *status = &full_status->common; - struct timespec ts; -- u32 total = 0; -+ u32 old_tx_blk_count = wl->tx_blocks_available; -+ u32 freed_blocks = 0; - int i; - -- if (wl->bss_type == BSS_TYPE_AP_BSS) -+ if (wl->bss_type == BSS_TYPE_AP_BSS) { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_ap_status), false); -- else -+ } else { - wl1271_raw_read(wl, FW_STATUS_ADDR, status, - sizeof(struct wl1271_fw_sta_status), false); -+ } - - wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " - "drv_rx_counter = %d, tx_results_counter = %d)", -@@ -612,22 +645,37 @@ - - /* update number of available TX blocks */ - for (i = 0; i < NUM_TX_QUEUES; i++) { -- u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - -- wl->tx_blocks_freed[i]; -+ freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - -+ wl->tx_blocks_freed[i]; - - wl->tx_blocks_freed[i] = - le32_to_cpu(status->tx_released_blks[i]); -- wl->tx_blocks_available += cnt; -- total += cnt; - } - -- /* if more blocks are available now, tx work can be scheduled */ -- if (total) -- clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); -+ wl->tx_allocated_blocks -= freed_blocks; - -- /* for AP update num of allocated TX blocks per link and ps status */ -- if (wl->bss_type == BSS_TYPE_AP_BSS) -+ if (wl->bss_type == BSS_TYPE_AP_BSS) { -+ /* Update num of allocated TX blocks per link and ps status */ - wl1271_irq_update_links_status(wl, &full_status->ap); -+ wl->tx_blocks_available += freed_blocks; -+ } else { -+ int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; -+ -+ /* -+ * The FW might change the total number of TX memblocks before -+ * we get a notification about blocks being released. Thus, the -+ * available blocks calculation might yield a temporary result -+ * which is lower than the actual available blocks. Keeping in -+ * mind that only blocks that were allocated can be moved from -+ * TX to RX, tx_blocks_available should never decrease here. -+ */ -+ wl->tx_blocks_available = max((int)wl->tx_blocks_available, -+ avail); -+ } -+ -+ /* if more blocks are available now, tx work can be scheduled */ -+ if (wl->tx_blocks_available > old_tx_blk_count) -+ clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); - - /* update the host-chipset time offset */ - getnstimeofday(&ts); -@@ -674,6 +722,13 @@ - set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); - cancel_work_sync(&wl->tx_work); - -+ /* -+ * In case edge triggered interrupt must be used, we cannot iterate -+ * more than once without introducing race conditions with the hardirq. -+ */ -+ if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) -+ loopcount = 1; -+ - mutex_lock(&wl->mutex); - - wl1271_debug(DEBUG_IRQ, "IRQ work"); -@@ -785,11 +840,17 @@ - - switch (wl->bss_type) { - case BSS_TYPE_AP_BSS: -- fw_name = WL1271_AP_FW_NAME; -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ fw_name = WL128X_AP_FW_NAME; -+ else -+ fw_name = WL127X_AP_FW_NAME; - break; - case BSS_TYPE_IBSS: - case BSS_TYPE_STA_BSS: -- fw_name = WL1271_FW_NAME; -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ fw_name = WL128X_FW_NAME; -+ else -+ fw_name = WL1271_FW_NAME; - break; - default: - wl1271_error("no compatible firmware for bss_type %d", -@@ -838,14 +899,14 @@ - const struct firmware *fw; - int ret; - -- ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); -+ ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); - - if (ret < 0) { - wl1271_error("could not get nvs file: %d", ret); - return ret; - } - -- wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); -+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); - - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); -@@ -954,6 +1015,17 @@ - if (ret < 0) - goto out; - break; -+ case CHIP_ID_1283_PG20: -+ wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", -+ wl->chip.id); -+ -+ ret = wl1271_setup(wl); -+ if (ret < 0) -+ goto out; -+ if (wl1271_set_block_size(wl)) -+ wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; -+ break; -+ case CHIP_ID_1283_PG10: - default: - wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); - ret = -ENODEV; -@@ -978,6 +1050,24 @@ - return ret; - } - -+static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) -+{ -+ unsigned int quirks = 0; -+ unsigned int *fw_ver = wl->chip.fw_ver; -+ -+ /* Only for wl127x */ -+ if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && -+ /* Check STA version */ -+ (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && -+ (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || -+ /* Check AP version */ -+ ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && -+ (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) -+ quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; -+ -+ return quirks; -+} -+ - int wl1271_plt_start(struct wl1271 *wl) - { - int retries = WL1271_BOOT_RETRIES; -@@ -1013,6 +1103,9 @@ - wl->state = WL1271_STATE_PLT; - wl1271_notice("firmware booted in PLT mode (%s)", - wl->chip.fw_ver_str); -+ -+ /* Check if any quirks are needed with older fw versions */ -+ wl->quirks |= wl1271_get_fw_ver_quirks(wl); - goto out; - - irq_disable: -@@ -1040,7 +1133,7 @@ - return ret; - } - --int __wl1271_plt_stop(struct wl1271 *wl) -+static int __wl1271_plt_stop(struct wl1271 *wl) - { - int ret = 0; - -@@ -1124,6 +1217,69 @@ - spin_unlock_irqrestore(&wl->wl_lock, flags); - } - -+int wl1271_tx_dummy_packet(struct wl1271 *wl) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&wl->wl_lock, flags); -+ set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); -+ wl->tx_queue_count++; -+ spin_unlock_irqrestore(&wl->wl_lock, flags); -+ -+ /* The FW is low on RX memory blocks, so send the dummy packet asap */ -+ if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) -+ wl1271_tx_work_locked(wl); -+ -+ /* -+ * If the FW TX is busy, TX work will be scheduled by the threaded -+ * interrupt handler function -+ */ -+ return 0; -+} -+ -+/* -+ * The size of the dummy packet should be at least 1400 bytes. However, in -+ * order to minimize the number of bus transactions, aligning it to 512 bytes -+ * boundaries could be beneficial, performance wise -+ */ -+#define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) -+ -+static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) -+{ -+ struct sk_buff *skb; -+ struct ieee80211_hdr_3addr *hdr; -+ unsigned int dummy_packet_size; -+ -+ dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE - -+ sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr); -+ -+ skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE); -+ if (!skb) { -+ wl1271_warning("Failed to allocate a dummy packet skb"); -+ return NULL; -+ } -+ -+ skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); -+ -+ hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); -+ memset(hdr, 0, sizeof(*hdr)); -+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | -+ IEEE80211_STYPE_NULLFUNC | -+ IEEE80211_FCTL_TODS); -+ -+ memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size); -+ -+ /* Dummy packets require the TID to be management */ -+ skb->priority = WL1271_TID_MGMT; -+ -+ /* Initialize all fields that might be used */ -+ skb->queue_mapping = 0; -+ memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); -+ -+ return skb; -+} -+ -+ - static struct notifier_block wl1271_dev_notifier = { - .notifier_call = wl1271_dev_notify, - }; -@@ -1174,6 +1330,16 @@ - goto out; - } - -+ /* -+ * in some very corner case HW recovery scenarios its possible to -+ * get here before __wl1271_op_remove_interface is complete, so -+ * opt out if that is the case. -+ */ -+ if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { -+ ret = -EBUSY; -+ goto out; -+ } -+ - switch (vif->type) { - case NL80211_IFTYPE_STATION: - wl->bss_type = BSS_TYPE_STA_BSS; -@@ -1242,6 +1408,7 @@ - - wl->vif = vif; - wl->state = WL1271_STATE_ON; -+ set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); - wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); - - /* update hw/fw version info in wiphy struct */ -@@ -1249,6 +1416,9 @@ - strncpy(wiphy->fw_version, wl->chip.fw_ver_str, - sizeof(wiphy->fw_version)); - -+ /* Check if any quirks are needed with older fw versions */ -+ wl->quirks |= wl1271_get_fw_ver_quirks(wl); -+ - /* - * Now we know if 11a is supported (info from the NVS), so disable - * 11a channels if not supported -@@ -1262,8 +1432,10 @@ - out: - mutex_unlock(&wl->mutex); - -+ mutex_lock(&wl_list_mutex); - if (!ret) - list_add(&wl->list, &wl_list); -+ mutex_unlock(&wl_list_mutex); - - return ret; - } -@@ -1274,11 +1446,15 @@ - - wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); - -+ /* because of hardware recovery, we may get here twice */ -+ if (wl->state != WL1271_STATE_ON) -+ return; -+ - wl1271_info("down"); - -+ mutex_lock(&wl_list_mutex); - list_del(&wl->list); -- -- WARN_ON(wl->state != WL1271_STATE_ON); -+ mutex_unlock(&wl_list_mutex); - - /* enable dyn ps just in case (if left on due to fw crash etc) */ - if (wl->bss_type == BSS_TYPE_STA_BSS) -@@ -1286,12 +1462,15 @@ - - if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { - wl->scan.state = WL1271_SCAN_STATE_IDLE; -- kfree(wl->scan.scanned_ch); -- wl->scan.scanned_ch = NULL; -+ memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - wl->scan.req = NULL; - ieee80211_scan_completed(wl->hw, true); - } - -+ /* -+ * this must be before the cancel_work calls below, so that the work -+ * functions don't perform further work. -+ */ - wl->state = WL1271_STATE_OFF; - - mutex_unlock(&wl->mutex); -@@ -1321,6 +1500,7 @@ - wl->psm_entry_retry = 0; - wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->tx_blocks_available = 0; -+ wl->tx_allocated_blocks = 0; - wl->tx_results_count = 0; - wl->tx_packets_count = 0; - wl->tx_security_last_seq = 0; -@@ -1328,7 +1508,6 @@ - wl->time_offset = 0; - wl->session_counter = 0; - wl->rate_set = CONF_TX_RATE_MASK_BASIC; -- wl->flags = 0; - wl->vif = NULL; - wl->filters = 0; - wl1271_free_ap_keys(wl); -@@ -1336,6 +1515,13 @@ - wl->ap_fw_ps_map = 0; - wl->ap_ps_map = 0; - -+ /* -+ * this is performed after the cancel_work calls and the associated -+ * mutex_lock, so that wl1271_op_add_interface does not accidentally -+ * get executed before all these vars have been reset. -+ */ -+ wl->flags = 0; -+ - for (i = 0; i < NUM_TX_QUEUES; i++) - wl->tx_blocks_freed[i] = 0; - -@@ -1368,7 +1554,7 @@ - cancel_work_sync(&wl->recovery_work); - } - --static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) -+void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) - { - wl1271_set_default_filters(wl); - -@@ -1431,10 +1617,10 @@ - * One of the side effects of the JOIN command is that is clears - * WPA/WPA2 keys from the chipset. Performing a JOIN while associated - * to a WPA/WPA2 access point will therefore kill the data-path. -- * Currently there is no supported scenario for JOIN during -- * association - if it becomes a supported scenario, the WPA/WPA2 keys -- * must be handled somehow. -- * -+ * Currently the only valid scenario for JOIN during association -+ * is on roaming, in which case we will also be given new keys. -+ * Keep the below message for now, unless it starts bothering -+ * users who really like to roam a lot :) - */ - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) - wl1271_info("JOIN while associated."); -@@ -1490,7 +1676,7 @@ - clear_bit(WL1271_FLAG_JOINED, &wl->flags); - memset(wl->bssid, 0, ETH_ALEN); - -- /* stop filterting packets based on bssid */ -+ /* stop filtering packets based on bssid */ - wl1271_configure_filters(wl, FIF_OTHER_BSS); - - out: -@@ -1569,7 +1755,12 @@ - mutex_lock(&wl->mutex); - - if (unlikely(wl->state == WL1271_STATE_OFF)) { -- ret = -EAGAIN; -+ /* we support configuring the channel and band while off */ -+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { -+ wl->band = conf->channel->band; -+ wl->channel = channel; -+ } -+ - goto out; - } - -@@ -2650,32 +2841,31 @@ - conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; - conf_tid->apsd_conf[0] = 0; - conf_tid->apsd_conf[1] = 0; -- } else { -- ret = wl1271_ps_elp_wakeup(wl); -- if (ret < 0) -- goto out; -+ goto out; -+ } - -- /* -- * the txop is confed in units of 32us by the mac80211, -- * we need us -- */ -- ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), -- params->cw_min, params->cw_max, -- params->aifs, params->txop << 5); -- if (ret < 0) -- goto out_sleep; -+ ret = wl1271_ps_elp_wakeup(wl); -+ if (ret < 0) -+ goto out; - -- ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), -- CONF_CHANNEL_TYPE_EDCF, -- wl1271_tx_get_queue(queue), -- ps_scheme, CONF_ACK_POLICY_LEGACY, -- 0, 0); -- if (ret < 0) -- goto out_sleep; -+ /* -+ * the txop is confed in units of 32us by the mac80211, -+ * we need us -+ */ -+ ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), -+ params->cw_min, params->cw_max, -+ params->aifs, params->txop << 5); -+ if (ret < 0) -+ goto out_sleep; -+ -+ ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), -+ CONF_CHANNEL_TYPE_EDCF, -+ wl1271_tx_get_queue(queue), -+ ps_scheme, CONF_ACK_POLICY_LEGACY, -+ 0, 0); - - out_sleep: -- wl1271_ps_elp_sleep(wl); -- } -+ wl1271_ps_elp_sleep(wl); - - out: - mutex_unlock(&wl->mutex); -@@ -2764,6 +2954,12 @@ - __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); - } - -+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -+{ -+ int id = hlid - WL1271_AP_STA_HLID_START; -+ return test_bit(id, wl->ap_hlid_map); -+} -+ - static int wl1271_op_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -@@ -2847,10 +3043,11 @@ - return ret; - } - --int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -- enum ieee80211_ampdu_mlme_action action, -- struct ieee80211_sta *sta, u16 tid, u16 *ssn, -- u8 buf_size) -+static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ enum ieee80211_ampdu_mlme_action action, -+ struct ieee80211_sta *sta, u16 tid, u16 *ssn, -+ u8 buf_size) - { - struct wl1271 *wl = hw->priv; - int ret; -@@ -3003,7 +3200,8 @@ - - #ifdef CONFIG_WL12XX_HT - #define WL12XX_HT_CAP { \ -- .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ -+ .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ -+ (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ - .ht_supported = true, \ - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ -@@ -3207,8 +3405,7 @@ - unsigned long res; - int ret; - -- ret = strict_strtoul(buf, 10, &res); -- -+ ret = kstrtoul(buf, 10, &res); - if (ret < 0) { - wl1271_warning("incorrect value written to bt_coex_mode"); - return count; -@@ -3273,7 +3470,11 @@ - - ret = wl1271_fetch_nvs(wl); - if (ret == 0) { -- u8 *nvs_ptr = (u8 *)wl->nvs->nvs; -+ /* NOTE: The wl->nvs->nvs element must be first, in -+ * order to simplify the casting, we assume it is at -+ * the beginning of the wl->nvs structure. -+ */ -+ u8 *nvs_ptr = (u8 *)wl->nvs; - - wl->mac_addr[0] = nvs_ptr[11]; - wl->mac_addr[1] = nvs_ptr[10]; -@@ -3341,7 +3542,6 @@ - IEEE80211_HW_HAS_RATE_CONTROL | - IEEE80211_HW_CONNECTION_MONITOR | - IEEE80211_HW_SUPPORTS_CQM_RSSI | -- IEEE80211_HW_REPORTS_TX_ACK_STATUS | - IEEE80211_HW_AP_LINK_PS; - - wl->hw->wiphy->cipher_suites = cipher_suites; -@@ -3358,6 +3558,10 @@ - wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - - sizeof(struct ieee80211_header); - -+ /* make sure all our channels fit in the scanned_ch bitmask */ -+ BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + -+ ARRAY_SIZE(wl1271_channels_5ghz) > -+ WL1271_MAX_CHANNELS); - /* - * We keep local copies of the band structs because we need to - * modify them on a per-device basis. -@@ -3458,6 +3662,7 @@ - wl->ap_ps_map = 0; - wl->ap_fw_ps_map = 0; - wl->quirks = 0; -+ wl->platform_quirks = 0; - - memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); - for (i = 0; i < ACX_TX_DESCRIPTORS; i++) -@@ -3478,11 +3683,17 @@ - goto err_hw; - } - -+ wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); -+ if (!wl->dummy_packet) { -+ ret = -ENOMEM; -+ goto err_aggr; -+ } -+ - /* Register platform device */ - ret = platform_device_register(wl->plat_dev); - if (ret) { - wl1271_error("couldn't register platform device"); -- goto err_aggr; -+ goto err_dummy_packet; - } - dev_set_drvdata(&wl->plat_dev->dev, wl); - -@@ -3508,6 +3719,9 @@ - err_platform: - platform_device_unregister(wl->plat_dev); - -+err_dummy_packet: -+ dev_kfree_skb(wl->dummy_packet); -+ - err_aggr: - free_pages((unsigned long)wl->aggr_buf, order); - -@@ -3527,6 +3741,7 @@ - int wl1271_free_hw(struct wl1271 *wl) - { - platform_device_unregister(wl->plat_dev); -+ dev_kfree_skb(wl->dummy_packet); - free_pages((unsigned long)wl->aggr_buf, - get_order(WL1271_AGGR_BUFFER_SIZE)); - kfree(wl->plat_dev); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/ps.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/ps.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/ps.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/ps.c 2011-05-05 23:29:45.983447881 +0200 -@@ -149,9 +149,6 @@ - case STATION_ACTIVE_MODE: - default: - wl1271_debug(DEBUG_PSM, "leaving psm"); -- ret = wl1271_ps_elp_wakeup(wl); -- if (ret < 0) -- return ret; - - /* disable beacon early termination */ - ret = wl1271_acx_bet_enable(wl, false); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/reg.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/reg.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/reg.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/reg.h 2011-05-05 23:29:46.009448195 +0200 -@@ -207,6 +207,8 @@ - - #define CHIP_ID_1271_PG10 (0x4030101) - #define CHIP_ID_1271_PG20 (0x4030111) -+#define CHIP_ID_1283_PG10 (0x05030101) -+#define CHIP_ID_1283_PG20 (0x05030111) - - #define ENABLE (REGISTERS_BASE + 0x5450) - -@@ -452,24 +454,11 @@ - #define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 - #define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 - --/* -- * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile -- * for platforms using active high interrupt level -- */ --#ifdef USE_ACTIVE_HIGH - #define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) --#else --#define HI_CFG_DEF_VAL \ -- (HI_CFG_UART_ENABLE | \ -- HI_CFG_RST232_ENABLE | \ -- HI_CFG_CLOCK_REQ_SELECT | \ -- HI_CFG_HOST_INT_ENABLE) -- --#endif - - #define REF_FREQ_19_2 0 - #define REF_FREQ_26_0 1 -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/rx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/rx.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/rx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/rx.c 2011-05-05 23:29:45.942447386 +0200 -@@ -48,18 +48,14 @@ - struct ieee80211_rx_status *status, - u8 beacon) - { -- enum ieee80211_band desc_band; -- - memset(status, 0, sizeof(struct ieee80211_rx_status)); - -- status->band = wl->band; -- - if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) -- desc_band = IEEE80211_BAND_2GHZ; -+ status->band = IEEE80211_BAND_2GHZ; - else -- desc_band = IEEE80211_BAND_5GHZ; -+ status->band = IEEE80211_BAND_5GHZ; - -- status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band); -+ status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); - - #ifdef CONFIG_WL12XX_HT - /* 11n support */ -@@ -76,7 +72,8 @@ - */ - wl->noise = desc->rssi - (desc->snr >> 1); - -- status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band); -+ status->freq = ieee80211_channel_to_frequency(desc->channel, -+ status->band); - - if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { - status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; -@@ -163,18 +160,25 @@ - break; - } - -- /* -- * Choose the block we want to read -- * For aggregated packets, only the first memory block should -- * be retrieved. The FW takes care of the rest. -- */ -- mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); -- wl->rx_mem_pool_addr.addr = (mem_block << 8) + -- le32_to_cpu(wl_mem_map->packet_memory_pool_start); -- wl->rx_mem_pool_addr.addr_extra = -- wl->rx_mem_pool_addr.addr + 4; -- wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, -- sizeof(wl->rx_mem_pool_addr), false); -+ if (wl->chip.id != CHIP_ID_1283_PG20) { -+ /* -+ * Choose the block we want to read -+ * For aggregated packets, only the first memory block -+ * should be retrieved. The FW takes care of the rest. -+ */ -+ mem_block = wl1271_rx_get_mem_block(status, -+ drv_rx_counter); -+ -+ wl->rx_mem_pool_addr.addr = (mem_block << 8) + -+ le32_to_cpu(wl_mem_map->packet_memory_pool_start); -+ -+ wl->rx_mem_pool_addr.addr_extra = -+ wl->rx_mem_pool_addr.addr + 4; -+ -+ wl1271_write(wl, WL1271_SLV_REG_DATA, -+ &wl->rx_mem_pool_addr, -+ sizeof(wl->rx_mem_pool_addr), false); -+ } - - /* Read all available packets at once */ - wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/scan.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/scan.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/scan.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/scan.c 2011-05-05 23:29:45.913447035 +0200 -@@ -48,8 +48,7 @@ - goto out; - - wl->scan.state = WL1271_SCAN_STATE_IDLE; -- kfree(wl->scan.scanned_ch); -- wl->scan.scanned_ch = NULL; -+ memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - wl->scan.req = NULL; - ieee80211_scan_completed(wl->hw, false); - -@@ -87,7 +86,7 @@ - - flags = req->channels[i]->flags; - -- if (!wl->scan.scanned_ch[i] && -+ if (!test_bit(i, wl->scan.scanned_ch) && - !(flags & IEEE80211_CHAN_DISABLED) && - ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && - (req->channels[i]->band == band)) { -@@ -124,7 +123,7 @@ - memset(&channels[j].bssid_msb, 0xff, 2); - - /* Mark the channels we already used */ -- wl->scan.scanned_ch[i] = true; -+ set_bit(i, wl->scan.scanned_ch); - - j++; - } -@@ -291,6 +290,12 @@ - int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, - struct cfg80211_scan_request *req) - { -+ /* -+ * cfg80211 should guarantee that we don't get more channels -+ * than what we have registered. -+ */ -+ BUG_ON(req->n_channels > WL1271_MAX_CHANNELS); -+ - if (wl->scan.state != WL1271_SCAN_STATE_IDLE) - return -EBUSY; - -@@ -304,10 +309,8 @@ - } - - wl->scan.req = req; -+ memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - -- wl->scan.scanned_ch = kcalloc(req->n_channels, -- sizeof(*wl->scan.scanned_ch), -- GFP_KERNEL); - /* we assume failure so that timeout scenarios are handled correctly */ - wl->scan.failed = true; - ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/sdio.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/sdio.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/sdio.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/sdio.c 2011-05-05 23:29:46.011448219 +0200 -@@ -51,6 +51,13 @@ - }; - MODULE_DEVICE_TABLE(sdio, wl1271_devices); - -+static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) -+{ -+ sdio_claim_host(wl->if_priv); -+ sdio_set_block_size(wl->if_priv, blksz); -+ sdio_release_host(wl->if_priv); -+} -+ - static inline struct sdio_func *wl_to_func(struct wl1271 *wl) - { - return wl->if_priv; -@@ -203,7 +210,8 @@ - .power = wl1271_sdio_set_power, - .dev = wl1271_sdio_wl_to_dev, - .enable_irq = wl1271_sdio_enable_interrupts, -- .disable_irq = wl1271_sdio_disable_interrupts -+ .disable_irq = wl1271_sdio_disable_interrupts, -+ .set_block_size = wl1271_sdio_set_block_size, - }; - - static int __devinit wl1271_probe(struct sdio_func *func, -@@ -212,6 +220,7 @@ - struct ieee80211_hw *hw; - const struct wl12xx_platform_data *wlan_data; - struct wl1271 *wl; -+ unsigned long irqflags; - int ret; - - /* We are only able to handle the wlan function */ -@@ -230,6 +239,9 @@ - /* Grab access to FN0 for ELP reg. */ - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - -+ /* Use block mode for transferring over one block size of data */ -+ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; -+ - wlan_data = wl12xx_get_platform_data(); - if (IS_ERR(wlan_data)) { - ret = PTR_ERR(wlan_data); -@@ -239,9 +251,16 @@ - - wl->irq = wlan_data->irq; - wl->ref_clock = wlan_data->board_ref_clock; -+ wl->tcxo_clock = wlan_data->board_tcxo_clock; -+ wl->platform_quirks = wlan_data->platform_quirks; -+ -+ if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) -+ irqflags = IRQF_TRIGGER_RISING; -+ else -+ irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; - - ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, -- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -+ irqflags, - DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); -@@ -343,4 +362,6 @@ - MODULE_AUTHOR("Luciano Coelho "); - MODULE_AUTHOR("Juuso Oikarinen "); - MODULE_FIRMWARE(WL1271_FW_NAME); --MODULE_FIRMWARE(WL1271_AP_FW_NAME); -+MODULE_FIRMWARE(WL128X_FW_NAME); -+MODULE_FIRMWARE(WL127X_AP_FW_NAME); -+MODULE_FIRMWARE(WL128X_AP_FW_NAME); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/sdio_test.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/sdio_test.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/sdio_test.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/sdio_test.c 2011-05-05 23:29:45.942447386 +0200 -@@ -189,7 +189,12 @@ - const struct firmware *fw; - int ret; - -- ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); -+ if (wl->chip.id == CHIP_ID_1283_PG20) -+ ret = request_firmware(&fw, WL128X_FW_NAME, -+ wl1271_wl_to_dev(wl)); -+ else -+ ret = request_firmware(&fw, WL1271_FW_NAME, -+ wl1271_wl_to_dev(wl)); - - if (ret < 0) { - wl1271_error("could not get firmware: %d", ret); -@@ -227,14 +232,14 @@ - const struct firmware *fw; - int ret; - -- ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); -+ ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); - - if (ret < 0) { - wl1271_error("could not get nvs file: %d", ret); - return ret; - } - -- wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); -+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); - - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); -@@ -288,6 +293,11 @@ - wl1271_notice("chip id 0x%x (1271 PG20)", - wl->chip.id); - break; -+ case CHIP_ID_1283_PG20: -+ wl1271_notice("chip id 0x%x (1283 PG20)", -+ wl->chip.id); -+ break; -+ case CHIP_ID_1283_PG10: - default: - wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); - return -ENODEV; -@@ -407,6 +417,9 @@ - /* Grab access to FN0 for ELP reg. */ - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - -+ /* Use block mode for transferring over one block size of data */ -+ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; -+ - wlan_data = wl12xx_get_platform_data(); - if (IS_ERR(wlan_data)) { - ret = PTR_ERR(wlan_data); -@@ -416,6 +429,7 @@ - - wl->irq = wlan_data->irq; - wl->ref_clock = wlan_data->board_ref_clock; -+ wl->tcxo_clock = wlan_data->board_tcxo_clock; - - sdio_set_drvdata(func, wl_test); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/spi.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/spi.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/spi.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/spi.c 2011-05-05 23:29:46.010448207 +0200 -@@ -355,7 +355,8 @@ - .power = wl1271_spi_set_power, - .dev = wl1271_spi_wl_to_dev, - .enable_irq = wl1271_spi_enable_interrupts, -- .disable_irq = wl1271_spi_disable_interrupts -+ .disable_irq = wl1271_spi_disable_interrupts, -+ .set_block_size = NULL, - }; - - static int __devinit wl1271_probe(struct spi_device *spi) -@@ -363,6 +364,7 @@ - struct wl12xx_platform_data *pdata; - struct ieee80211_hw *hw; - struct wl1271 *wl; -+ unsigned long irqflags; - int ret; - - pdata = spi->dev.platform_data; -@@ -400,6 +402,13 @@ - } - - wl->ref_clock = pdata->board_ref_clock; -+ wl->tcxo_clock = pdata->board_tcxo_clock; -+ wl->platform_quirks = pdata->platform_quirks; -+ -+ if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) -+ irqflags = IRQF_TRIGGER_RISING; -+ else -+ irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; - - wl->irq = spi->irq; - if (wl->irq < 0) { -@@ -409,7 +418,7 @@ - } - - ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, -- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -+ irqflags, - DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); -@@ -490,5 +499,7 @@ - MODULE_AUTHOR("Luciano Coelho "); - MODULE_AUTHOR("Juuso Oikarinen "); - MODULE_FIRMWARE(WL1271_FW_NAME); --MODULE_FIRMWARE(WL1271_AP_FW_NAME); -+MODULE_FIRMWARE(WL128X_FW_NAME); -+MODULE_FIRMWARE(WL127X_AP_FW_NAME); -+MODULE_FIRMWARE(WL128X_AP_FW_NAME); - MODULE_ALIAS("spi:wl1271"); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/testmode.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/testmode.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/testmode.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/testmode.c 2011-05-05 23:29:45.983447881 +0200 -@@ -27,6 +27,7 @@ - - #include "wl12xx.h" - #include "acx.h" -+#include "reg.h" - - #define WL1271_TM_MAX_DATA_LENGTH 1024 - -@@ -204,7 +205,10 @@ - - kfree(wl->nvs); - -- if (len != sizeof(struct wl1271_nvs_file)) -+ if ((wl->chip.id == CHIP_ID_1283_PG20) && -+ (len != sizeof(struct wl128x_nvs_file))) -+ return -EINVAL; -+ else if (len != sizeof(struct wl1271_nvs_file)) - return -EINVAL; - - wl->nvs = kzalloc(len, GFP_KERNEL); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/tx.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/tx.c ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/tx.c 2011-05-05 23:29:45.893446794 +0200 -@@ -70,6 +70,28 @@ - } - } - -+static int wl1271_tx_update_filters(struct wl1271 *wl, -+ struct sk_buff *skb) -+{ -+ struct ieee80211_hdr *hdr; -+ -+ hdr = (struct ieee80211_hdr *)(skb->data + -+ sizeof(struct wl1271_tx_hw_descr)); -+ -+ /* -+ * stop bssid-based filtering before transmitting authentication -+ * requests. this way the hw will never drop authentication -+ * responses coming from BSSIDs it isn't familiar with (e.g. on -+ * roaming) -+ */ -+ if (!ieee80211_is_auth(hdr->frame_control)) -+ return 0; -+ -+ wl1271_configure_filters(wl, FIF_OTHER_BSS); -+ -+ return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); -+} -+ - static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, - struct sk_buff *skb) - { -@@ -127,13 +149,29 @@ - } - } - -+static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, -+ unsigned int packet_length) -+{ -+ if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) -+ return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); -+ else -+ return ALIGN(packet_length, WL1271_TX_ALIGN_TO); -+} -+ - static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, - u32 buf_offset, u8 hlid) - { - struct wl1271_tx_hw_descr *desc; - u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; -+ u32 len; - u32 total_blocks; - int id, ret = -EBUSY; -+ u32 spare_blocks; -+ -+ if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) -+ spare_blocks = 2; -+ else -+ spare_blocks = 1; - - if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) - return -EAGAIN; -@@ -145,17 +183,27 @@ - - /* approximate the number of blocks required for this packet - in the firmware */ -- total_blocks = total_len + TX_HW_BLOCK_SIZE - 1; -- total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE; -+ len = wl12xx_calc_packet_alignment(wl, total_len); -+ -+ total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + -+ spare_blocks; -+ - if (total_blocks <= wl->tx_blocks_available) { - desc = (struct wl1271_tx_hw_descr *)skb_push( - skb, total_len - skb->len); - -- desc->extra_mem_blocks = TX_HW_BLOCK_SPARE; -- desc->total_mem_blocks = total_blocks; -+ /* HW descriptor fields change between wl127x and wl128x */ -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ desc->wl128x_mem.total_mem_blocks = total_blocks; -+ } else { -+ desc->wl127x_mem.extra_blocks = spare_blocks; -+ desc->wl127x_mem.total_mem_blocks = total_blocks; -+ } -+ - desc->id = id; - - wl->tx_blocks_available -= total_blocks; -+ wl->tx_allocated_blocks += total_blocks; - - if (wl->bss_type == BSS_TYPE_AP_BSS) - wl->links[hlid].allocated_blks += total_blocks; -@@ -172,13 +220,18 @@ - return ret; - } - -+static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) -+{ -+ return wl->dummy_packet == skb; -+} -+ - static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, - u32 extra, struct ieee80211_tx_info *control, - u8 hlid) - { - struct timespec ts; - struct wl1271_tx_hw_descr *desc; -- int pad, ac, rate_idx; -+ int aligned_len, ac, rate_idx; - s64 hosttime; - u16 tx_attr; - -@@ -202,12 +255,25 @@ - else - desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); - -- /* configure the tx attributes */ -- tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; -- -- /* queue (we use same identifiers for tid's and ac's */ -+ /* queue */ - ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); -- desc->tid = ac; -+ desc->tid = skb->priority; -+ -+ if (wl12xx_is_dummy_packet(wl, skb)) { -+ /* -+ * FW expects the dummy packet to have an invalid session id - -+ * any session id that is different than the one set in the join -+ */ -+ tx_attr = ((~wl->session_counter) << -+ TX_HW_ATTR_OFST_SESSION_COUNTER) & -+ TX_HW_ATTR_SESSION_COUNTER; -+ -+ tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; -+ } else { -+ /* configure the tx attributes */ -+ tx_attr = -+ wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; -+ } - - if (wl->bss_type != BSS_TYPE_AP_BSS) { - desc->aid = hlid; -@@ -237,20 +303,37 @@ - tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; - desc->reserved = 0; - -- /* align the length (and store in terms of words) */ -- pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO); -- desc->length = cpu_to_le16(pad >> 2); -- -- /* calculate number of padding bytes */ -- pad = pad - skb->len; -- tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; -+ aligned_len = wl12xx_calc_packet_alignment(wl, skb->len); - -- desc->tx_attr = cpu_to_le16(tx_attr); -+ if (wl->chip.id == CHIP_ID_1283_PG20) { -+ desc->wl128x_mem.extra_bytes = aligned_len - skb->len; -+ desc->length = cpu_to_le16(aligned_len >> 2); -+ -+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " -+ "tx_attr: 0x%x len: %d life: %d mem: %d", -+ desc->hlid, tx_attr, -+ le16_to_cpu(desc->length), -+ le16_to_cpu(desc->life_time), -+ desc->wl128x_mem.total_mem_blocks); -+ } else { -+ int pad; -+ -+ /* Store the aligned length in terms of words */ -+ desc->length = cpu_to_le16(aligned_len >> 2); - -- wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " -- "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid, -- le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length), -- le16_to_cpu(desc->life_time), desc->total_mem_blocks); -+ /* calculate number of padding bytes */ -+ pad = aligned_len - skb->len; -+ tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; -+ -+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " -+ "tx_attr: 0x%x len: %d life: %d mem: %d", pad, -+ desc->hlid, tx_attr, -+ le16_to_cpu(desc->length), -+ le16_to_cpu(desc->life_time), -+ desc->wl127x_mem.total_mem_blocks); -+ } -+ -+ desc->tx_attr = cpu_to_le16(tx_attr); - } - - /* caller must hold wl->mutex */ -@@ -300,19 +383,29 @@ - if (wl->bss_type == BSS_TYPE_AP_BSS) { - wl1271_tx_ap_update_inconnection_sta(wl, skb); - wl1271_tx_regulate_link(wl, hlid); -+ } else { -+ wl1271_tx_update_filters(wl, skb); - } - - wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); - - /* -- * The length of each packet is stored in terms of words. Thus, we must -- * pad the skb data to make sure its length is aligned. -- * The number of padding bytes is computed and set in wl1271_tx_fill_hdr -+ * The length of each packet is stored in terms of -+ * words. Thus, we must pad the skb data to make sure its -+ * length is aligned. The number of padding bytes is computed -+ * and set in wl1271_tx_fill_hdr. -+ * In special cases, we want to align to a specific block size -+ * (eg. for wl128x with SDIO we align to 256). - */ -- total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO); -+ total_len = wl12xx_calc_packet_alignment(wl, skb->len); -+ - memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len); - memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); - -+ /* Revert side effects in the dummy packet skb, so it can be reused */ -+ if (wl12xx_is_dummy_packet(wl, skb)) -+ skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); -+ - return total_len; - } - -@@ -425,10 +518,23 @@ - - static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) - { -+ unsigned long flags; -+ struct sk_buff *skb = NULL; -+ - if (wl->bss_type == BSS_TYPE_AP_BSS) -- return wl1271_ap_skb_dequeue(wl); -+ skb = wl1271_ap_skb_dequeue(wl); -+ else -+ skb = wl1271_sta_skb_dequeue(wl); -+ -+ if (!skb && -+ test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { -+ skb = wl->dummy_packet; -+ spin_lock_irqsave(&wl->wl_lock, flags); -+ wl->tx_queue_count--; -+ spin_unlock_irqrestore(&wl->wl_lock, flags); -+ } - -- return wl1271_sta_skb_dequeue(wl); -+ return skb; - } - - static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) -@@ -436,7 +542,9 @@ - unsigned long flags; - int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - -- if (wl->bss_type == BSS_TYPE_AP_BSS) { -+ if (wl12xx_is_dummy_packet(wl, skb)) { -+ set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); -+ } else if (wl->bss_type == BSS_TYPE_AP_BSS) { - u8 hlid = wl1271_tx_get_hlid(skb); - skb_queue_head(&wl->links[hlid].tx_queue[q], skb); - -@@ -454,22 +562,14 @@ - void wl1271_tx_work_locked(struct wl1271 *wl) - { - struct sk_buff *skb; -- bool woken_up = false; - u32 buf_offset = 0; - bool sent_packets = false; - int ret; - - if (unlikely(wl->state == WL1271_STATE_OFF)) -- goto out; -+ return; - - while ((skb = wl1271_skb_dequeue(wl))) { -- if (!woken_up) { -- ret = wl1271_ps_elp_wakeup(wl); -- if (ret < 0) -- goto out_ack; -- woken_up = true; -- } -- - ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); - if (ret == -EAGAIN) { - /* -@@ -516,18 +616,22 @@ - - wl1271_handle_tx_low_watermark(wl); - } -- --out: -- if (woken_up) -- wl1271_ps_elp_sleep(wl); - } - - void wl1271_tx_work(struct work_struct *work) - { - struct wl1271 *wl = container_of(work, struct wl1271, tx_work); -+ int ret; - - mutex_lock(&wl->mutex); -+ ret = wl1271_ps_elp_wakeup(wl); -+ if (ret < 0) -+ goto out; -+ - wl1271_tx_work_locked(wl); -+ -+ wl1271_ps_elp_wakeup(wl); -+out: - mutex_unlock(&wl->mutex); - } - -@@ -549,6 +653,11 @@ - skb = wl->tx_frames[id]; - info = IEEE80211_SKB_CB(skb); - -+ if (wl12xx_is_dummy_packet(wl, skb)) { -+ wl1271_free_tx_id(wl, id); -+ return; -+ } -+ - /* update the TX status info */ - if (result->status == TX_SUCCESS) { - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) -@@ -678,10 +787,13 @@ - while ((skb = skb_dequeue(&wl->tx_queue[i]))) { - wl1271_debug(DEBUG_TX, "freeing skb 0x%p", - skb); -- info = IEEE80211_SKB_CB(skb); -- info->status.rates[0].idx = -1; -- info->status.rates[0].count = 0; -- ieee80211_tx_status(wl->hw, skb); -+ -+ if (!wl12xx_is_dummy_packet(wl, skb)) { -+ info = IEEE80211_SKB_CB(skb); -+ info->status.rates[0].idx = -1; -+ info->status.rates[0].count = 0; -+ ieee80211_tx_status(wl->hw, skb); -+ } - } - } - } -@@ -702,21 +814,27 @@ - wl1271_free_tx_id(wl, i); - wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); - -- /* Remove private headers before passing the skb to mac80211 */ -- info = IEEE80211_SKB_CB(skb); -- skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); -- if (info->control.hw_key && -- info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { -- int hdrlen = ieee80211_get_hdrlen_from_skb(skb); -- memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, -- hdrlen); -- skb_pull(skb, WL1271_TKIP_IV_SPACE); -- } -+ if (!wl12xx_is_dummy_packet(wl, skb)) { -+ /* -+ * Remove private headers before passing the skb to -+ * mac80211 -+ */ -+ info = IEEE80211_SKB_CB(skb); -+ skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); -+ if (info->control.hw_key && -+ info->control.hw_key->cipher == -+ WLAN_CIPHER_SUITE_TKIP) { -+ int hdrlen = ieee80211_get_hdrlen_from_skb(skb); -+ memmove(skb->data + WL1271_TKIP_IV_SPACE, -+ skb->data, hdrlen); -+ skb_pull(skb, WL1271_TKIP_IV_SPACE); -+ } - -- info->status.rates[0].idx = -1; -- info->status.rates[0].count = 0; -+ info->status.rates[0].idx = -1; -+ info->status.rates[0].count = 0; - -- ieee80211_tx_status(wl->hw, skb); -+ ieee80211_tx_status(wl->hw, skb); -+ } - } - } - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/tx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/tx.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/tx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/tx.h 2011-05-05 23:29:45.953447519 +0200 -@@ -25,7 +25,6 @@ - #ifndef __TX_H__ - #define __TX_H__ - --#define TX_HW_BLOCK_SPARE 2 - #define TX_HW_BLOCK_SIZE 252 - - #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 -@@ -41,6 +40,7 @@ - BIT(8) | BIT(9)) - #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) - #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) -+#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) - - #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 - #define TX_HW_ATTR_OFST_HEADER_PAD 1 -@@ -55,20 +55,60 @@ - #define WL1271_TX_ALIGN_TO 4 - #define WL1271_TKIP_IV_SPACE 4 - -+/* Used for management frames and dummy packets */ -+#define WL1271_TID_MGMT 7 -+ -+struct wl127x_tx_mem { -+ /* -+ * Number of extra memory blocks to allocate for this packet -+ * in addition to the number of blocks derived from the packet -+ * length. -+ */ -+ u8 extra_blocks; -+ /* -+ * Total number of memory blocks allocated by the host for -+ * this packet. Must be equal or greater than the actual -+ * blocks number allocated by HW. -+ */ -+ u8 total_mem_blocks; -+} __packed; -+ -+struct wl128x_tx_mem { -+ /* -+ * Total number of memory blocks allocated by the host for -+ * this packet. -+ */ -+ u8 total_mem_blocks; -+ /* -+ * Number of extra bytes, at the end of the frame. the host -+ * uses this padding to complete each frame to integer number -+ * of SDIO blocks. -+ */ -+ u8 extra_bytes; -+} __packed; -+ -+/* -+ * On wl128x based devices, when TX packets are aggregated, each packet -+ * size must be aligned to the SDIO block size. The maximum block size -+ * is bounded by the type of the padded bytes field that is sent to the -+ * FW. Currently the type is u8, so the maximum block size is 256 bytes. -+ */ -+#define WL12XX_BUS_BLOCK_SIZE min(512u, \ -+ (1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes)))) -+ - struct wl1271_tx_hw_descr { - /* Length of packet in words, including descriptor+header+data */ - __le16 length; -- /* Number of extra memory blocks to allocate for this packet in -- addition to the number of blocks derived from the packet length */ -- u8 extra_mem_blocks; -- /* Total number of memory blocks allocated by the host for this packet. -- Must be equal or greater than the actual blocks number allocated by -- HW!! */ -- u8 total_mem_blocks; -+ union { -+ struct wl127x_tx_mem wl127x_mem; -+ struct wl128x_tx_mem wl128x_mem; -+ } __packed; - /* Device time (in us) when the packet arrived to the driver */ - __le32 start_time; -- /* Max delay in TUs until transmission. The last device time the -- packet can be transmitted is: startTime+(1024*LifeTime) */ -+ /* -+ * Max delay in TUs until transmission. The last device time the -+ * packet can be transmitted is: start_time + (1024 * life_time) -+ */ - __le16 life_time; - /* Bitwise fields - see TX_ATTR... definitions above. */ - __le16 tx_attr; -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/wl12xx/wl12xx.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/wl12xx.h ---- linux-2.6.39-rc6/drivers/net/wireless/wl12xx/wl12xx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/wl12xx/wl12xx.h 2011-05-05 23:29:45.977447809 +0200 -@@ -131,9 +131,16 @@ - - - #define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" --#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -+#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" -+#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" -+#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" - --#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin" -+/* -+ * wl127x and wl128x are using the same NVS file name. However, the -+ * ini parameters between them are different. The driver validates -+ * the correct NVS size in wl1271_boot_upload_nvs(). -+ */ -+#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin" - - #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) - #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) -@@ -165,7 +172,6 @@ - #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) - - #define WL1271_AP_BSS_INDEX 0 --#define WL1271_AP_DEF_INACTIV_SEC 300 - #define WL1271_AP_DEF_BEACON_EXP 20 - - #define ACX_TX_DESCRIPTORS 32 -@@ -200,13 +206,29 @@ - - struct wl1271; - --#define WL12XX_NUM_FW_VER 5 -+enum { -+ FW_VER_CHIP, -+ FW_VER_IF_TYPE, -+ FW_VER_MAJOR, -+ FW_VER_SUBTYPE, -+ FW_VER_MINOR, -+ -+ NUM_FW_VER -+}; -+ -+#define FW_VER_CHIP_WL127X 6 -+#define FW_VER_CHIP_WL128X 7 -+ -+#define FW_VER_IF_TYPE_STA 1 -+#define FW_VER_IF_TYPE_AP 2 -+ -+#define FW_VER_MINOR_1_SPARE_STA_MIN 58 -+#define FW_VER_MINOR_1_SPARE_AP_MIN 47 - --/* FIXME: I'm not sure about this structure name */ - struct wl1271_chip { - u32 id; - char fw_ver_str[ETHTOOL_BUSINFO_LEN]; -- unsigned int fw_ver[WL12XX_NUM_FW_VER]; -+ unsigned int fw_ver[NUM_FW_VER]; - }; - - struct wl1271_stats { -@@ -261,6 +283,8 @@ - u8 tx_total; - u8 reserved1; - __le16 reserved2; -+ /* Total structure size is 68 bytes */ -+ u32 padding; - } __packed; - - struct wl1271_fw_full_status { -@@ -277,9 +301,10 @@ - u32 addr_extra; - }; - -+#define WL1271_MAX_CHANNELS 64 - struct wl1271_scan { - struct cfg80211_scan_request *req; -- bool *scanned_ch; -+ unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)]; - bool failed; - u8 state; - u8 ssid[IW_ESSID_MAX_SIZE+1]; -@@ -297,6 +322,7 @@ - struct device* (*dev)(struct wl1271 *wl); - void (*enable_irq)(struct wl1271 *wl); - void (*disable_irq)(struct wl1271 *wl); -+ void (*set_block_size) (struct wl1271 *wl, unsigned int blksz); - }; - - #define MAX_NUM_KEYS 14 -@@ -327,7 +353,9 @@ - WL1271_FLAG_PSPOLL_FAILURE, - WL1271_FLAG_STA_STATE_SENT, - WL1271_FLAG_FW_TX_BUSY, -- WL1271_FLAG_AP_STARTED -+ WL1271_FLAG_AP_STARTED, -+ WL1271_FLAG_IF_INITIALIZED, -+ WL1271_FLAG_DUMMY_PACKET_PENDING, - }; - - struct wl1271_link { -@@ -371,7 +399,7 @@ - u8 *fw; - size_t fw_len; - u8 fw_bss_type; -- struct wl1271_nvs_file *nvs; -+ void *nvs; - size_t nvs_len; - - s8 hw_pg_ver; -@@ -389,6 +417,7 @@ - /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed[NUM_TX_QUEUES]; - u32 tx_blocks_available; -+ u32 tx_allocated_blocks; - u32 tx_results_count; - - /* Transmitted TX packets counter for chipset interface */ -@@ -430,6 +459,9 @@ - /* Intermediate buffer, used for packet aggregation */ - u8 *aggr_buf; - -+ /* Reusable dummy packet template */ -+ struct sk_buff *dummy_packet; -+ - /* Network stack work */ - struct work_struct netstack_work; - -@@ -527,6 +559,8 @@ - bool ba_support; - u8 ba_rx_bitmap; - -+ int tcxo_clock; -+ - /* - * AP-mode - links indexed by HLID. The global and broadcast links - * are always active. -@@ -544,6 +578,9 @@ - - /* Quirks of specific hardware revisions */ - unsigned int quirks; -+ -+ /* Platform limitations */ -+ unsigned int platform_quirks; - }; - - struct wl1271_station { -@@ -576,6 +613,15 @@ - /* Quirks */ - - /* Each RX/TX transaction requires an end-of-transaction transfer */ --#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) -+#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) -+ -+/* -+ * Older firmwares use 2 spare TX blocks -+ * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) -+ */ -+#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) -+ -+/* WL128X requires aggregated packets to be aligned to the SDIO block size */ -+#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) - - #endif -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_chip.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_chip.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_chip.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_chip.c 2011-05-05 23:29:45.554442697 +0200 -@@ -557,7 +557,7 @@ - return r; - } - --/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ -+/* ZD_CR157 can be optionally patched by the EEPROM for original ZD1211 */ - static int patch_cr157(struct zd_chip *chip) - { - int r; -@@ -571,7 +571,7 @@ - return r; - - dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); -- return zd_iowrite32_locked(chip, value >> 8, CR157); -+ return zd_iowrite32_locked(chip, value >> 8, ZD_CR157); - } - - /* -@@ -593,8 +593,8 @@ - int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) - { - struct zd_ioreq16 ioreqs[] = { -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -- { CR47, 0x1e }, -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, -+ { ZD_CR47, 0x1e }, - }; - - /* FIXME: Channel 11 is not the edge for all regulatory domains. */ -@@ -608,69 +608,69 @@ - static int zd1211_hw_reset_phy(struct zd_chip *chip) - { - static const struct zd_ioreq16 ioreqs[] = { -- { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, -- { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, -- { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, -- { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, -- { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, -- { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, -- { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, -- { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, -- { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, -- { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, -- { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, -- { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, -- { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, -- { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, -- { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, -- { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, -- { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, -- { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, -- { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, -- { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, -- { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, -- { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, -- { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, -- { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, -- { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, -- { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, -- { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, -- { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, -- { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, -- { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, -- { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, -- { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, -- { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, -+ { ZD_CR0, 0x0a }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, -+ { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xa0 }, -+ { ZD_CR10, 0x81 }, { ZD_CR11, 0x00 }, { ZD_CR12, 0x7f }, -+ { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, { ZD_CR15, 0x3d }, -+ { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, { ZD_CR18, 0x0a }, -+ { ZD_CR19, 0x48 }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0c }, -+ { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, { ZD_CR24, 0x14 }, -+ { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, { ZD_CR27, 0x19 }, -+ { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, { ZD_CR30, 0x4b }, -+ { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, -+ { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, -+ { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, -+ { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, -+ { ZD_CR43, 0x10 }, { ZD_CR44, 0x12 }, { ZD_CR46, 0xff }, -+ { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, -+ { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, -+ { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, -+ { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, -+ { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, -+ { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, -+ { ZD_CR79, 0x68 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, -+ { ZD_CR82, 0x00 }, { ZD_CR83, 0x00 }, { ZD_CR84, 0x00 }, -+ { ZD_CR85, 0x02 }, { ZD_CR86, 0x00 }, { ZD_CR87, 0x00 }, -+ { ZD_CR88, 0xff }, { ZD_CR89, 0xfc }, { ZD_CR90, 0x00 }, -+ { ZD_CR91, 0x00 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x08 }, -+ { ZD_CR94, 0x00 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0xff }, -+ { ZD_CR97, 0xe7 }, { ZD_CR98, 0x00 }, { ZD_CR99, 0x00 }, -+ { ZD_CR100, 0x00 }, { ZD_CR101, 0xae }, { ZD_CR102, 0x02 }, -+ { ZD_CR103, 0x00 }, { ZD_CR104, 0x03 }, { ZD_CR105, 0x65 }, -+ { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, { ZD_CR108, 0x0a }, -+ { ZD_CR109, 0xaa }, { ZD_CR110, 0xaa }, { ZD_CR111, 0x25 }, -+ { ZD_CR112, 0x25 }, { ZD_CR113, 0x00 }, { ZD_CR119, 0x1e }, -+ { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, - { }, -- { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, -- { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, -- { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, -- { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, -- { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, -- { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, -- { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, -- { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, -- { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, -- { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, -- { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, -- { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, -- { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, -- { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, -- { CR125, 0xaa }, { CR127, 0x03 }, { CR128, 0x14 }, -- { CR129, 0x12 }, { CR130, 0x10 }, { CR131, 0x0C }, -- { CR136, 0xdf }, { CR137, 0x40 }, { CR138, 0xa0 }, -- { CR139, 0xb0 }, { CR140, 0x99 }, { CR141, 0x82 }, -- { CR142, 0x54 }, { CR143, 0x1c }, { CR144, 0x6c }, -- { CR147, 0x07 }, { CR148, 0x4c }, { CR149, 0x50 }, -- { CR150, 0x0e }, { CR151, 0x18 }, { CR160, 0xfe }, -- { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, -- { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, -- { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, -- { CR170, 0xba }, { CR171, 0xba }, -- /* Note: CR204 must lead the CR203 */ -- { CR204, 0x7d }, -+ { ZD_CR5, 0x00 }, { ZD_CR6, 0x00 }, { ZD_CR7, 0x00 }, -+ { ZD_CR8, 0x00 }, { ZD_CR9, 0x20 }, { ZD_CR12, 0xf0 }, -+ { ZD_CR20, 0x0e }, { ZD_CR21, 0x0e }, { ZD_CR27, 0x10 }, -+ { ZD_CR44, 0x33 }, { ZD_CR47, 0x1E }, { ZD_CR83, 0x24 }, -+ { ZD_CR84, 0x04 }, { ZD_CR85, 0x00 }, { ZD_CR86, 0x0C }, -+ { ZD_CR87, 0x12 }, { ZD_CR88, 0x0C }, { ZD_CR89, 0x00 }, -+ { ZD_CR90, 0x10 }, { ZD_CR91, 0x08 }, { ZD_CR93, 0x00 }, -+ { ZD_CR94, 0x01 }, { ZD_CR95, 0x00 }, { ZD_CR96, 0x50 }, -+ { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, { ZD_CR101, 0x13 }, -+ { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, -+ { ZD_CR105, 0x12 }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, -+ { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, -+ { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR120, 0x4f }, -+ { ZD_CR125, 0xaa }, { ZD_CR127, 0x03 }, { ZD_CR128, 0x14 }, -+ { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, { ZD_CR131, 0x0C }, -+ { ZD_CR136, 0xdf }, { ZD_CR137, 0x40 }, { ZD_CR138, 0xa0 }, -+ { ZD_CR139, 0xb0 }, { ZD_CR140, 0x99 }, { ZD_CR141, 0x82 }, -+ { ZD_CR142, 0x54 }, { ZD_CR143, 0x1c }, { ZD_CR144, 0x6c }, -+ { ZD_CR147, 0x07 }, { ZD_CR148, 0x4c }, { ZD_CR149, 0x50 }, -+ { ZD_CR150, 0x0e }, { ZD_CR151, 0x18 }, { ZD_CR160, 0xfe }, -+ { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, -+ { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, -+ { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, -+ { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, -+ /* Note: ZD_CR204 must lead the ZD_CR203 */ -+ { ZD_CR204, 0x7d }, - { }, -- { CR203, 0x30 }, -+ { ZD_CR203, 0x30 }, - }; - - int r, t; -@@ -697,62 +697,62 @@ - static int zd1211b_hw_reset_phy(struct zd_chip *chip) - { - static const struct zd_ioreq16 ioreqs[] = { -- { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, -- { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, -- { CR10, 0x81 }, -- /* power control { { CR11, 1 << 6 }, */ -- { CR11, 0x00 }, -- { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, -- { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, -- { CR18, 0x0a }, { CR19, 0x48 }, -- { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ -- { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, -- { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, -- { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, -- { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ -- { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, -- { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, -- { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, -- { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, -- { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, -- { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, -- { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, -- { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, -- { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, -- { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, -- { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, -- { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, -- { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, -- { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, -- { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, -- { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, -- { CR94, 0x01 }, -- { CR95, 0x20 }, /* ZD1211B */ -- { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, -- { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, -- { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, -- { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, -- { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, -- { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, -- { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, -- { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, -- { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -- { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, -- { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, -- { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, -- { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, -- { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ -- { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ -- { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, -- { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, -- { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, -- { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, -- { CR170, 0xba }, { CR171, 0xba }, -- /* Note: CR204 must lead the CR203 */ -- { CR204, 0x7d }, -+ { ZD_CR0, 0x14 }, { ZD_CR1, 0x06 }, { ZD_CR2, 0x26 }, -+ { ZD_CR3, 0x38 }, { ZD_CR4, 0x80 }, { ZD_CR9, 0xe0 }, -+ { ZD_CR10, 0x81 }, -+ /* power control { { ZD_CR11, 1 << 6 }, */ -+ { ZD_CR11, 0x00 }, -+ { ZD_CR12, 0xf0 }, { ZD_CR13, 0x8c }, { ZD_CR14, 0x80 }, -+ { ZD_CR15, 0x3d }, { ZD_CR16, 0x20 }, { ZD_CR17, 0x1e }, -+ { ZD_CR18, 0x0a }, { ZD_CR19, 0x48 }, -+ { ZD_CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ -+ { ZD_CR21, 0x0e }, { ZD_CR22, 0x23 }, { ZD_CR23, 0x90 }, -+ { ZD_CR24, 0x14 }, { ZD_CR25, 0x40 }, { ZD_CR26, 0x10 }, -+ { ZD_CR27, 0x10 }, { ZD_CR28, 0x7f }, { ZD_CR29, 0x80 }, -+ { ZD_CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ -+ { ZD_CR31, 0x60 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x08 }, -+ { ZD_CR34, 0x06 }, { ZD_CR35, 0x0a }, { ZD_CR36, 0x00 }, -+ { ZD_CR37, 0x00 }, { ZD_CR38, 0x38 }, { ZD_CR39, 0x0c }, -+ { ZD_CR40, 0x84 }, { ZD_CR41, 0x2a }, { ZD_CR42, 0x80 }, -+ { ZD_CR43, 0x10 }, { ZD_CR44, 0x33 }, { ZD_CR46, 0xff }, -+ { ZD_CR47, 0x1E }, { ZD_CR48, 0x26 }, { ZD_CR49, 0x5b }, -+ { ZD_CR64, 0xd0 }, { ZD_CR65, 0x04 }, { ZD_CR66, 0x58 }, -+ { ZD_CR67, 0xc9 }, { ZD_CR68, 0x88 }, { ZD_CR69, 0x41 }, -+ { ZD_CR70, 0x23 }, { ZD_CR71, 0x10 }, { ZD_CR72, 0xff }, -+ { ZD_CR73, 0x32 }, { ZD_CR74, 0x30 }, { ZD_CR75, 0x65 }, -+ { ZD_CR76, 0x41 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x30 }, -+ { ZD_CR79, 0xf0 }, { ZD_CR80, 0x64 }, { ZD_CR81, 0x64 }, -+ { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, -+ { ZD_CR85, 0x00 }, { ZD_CR86, 0x0c }, { ZD_CR87, 0x12 }, -+ { ZD_CR88, 0x0c }, { ZD_CR89, 0x00 }, { ZD_CR90, 0x58 }, -+ { ZD_CR91, 0x04 }, { ZD_CR92, 0x00 }, { ZD_CR93, 0x00 }, -+ { ZD_CR94, 0x01 }, -+ { ZD_CR95, 0x20 }, /* ZD1211B */ -+ { ZD_CR96, 0x50 }, { ZD_CR97, 0x37 }, { ZD_CR98, 0x35 }, -+ { ZD_CR99, 0x00 }, { ZD_CR100, 0x01 }, { ZD_CR101, 0x13 }, -+ { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 }, -+ { ZD_CR105, 0x12 }, { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, -+ { ZD_CR108, 0x0a }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 }, -+ { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 }, -+ { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x1e }, -+ { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 }, -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, -+ { ZD_CR131, 0x0c }, { ZD_CR136, 0xdf }, { ZD_CR137, 0xa0 }, -+ { ZD_CR138, 0xa8 }, { ZD_CR139, 0xb4 }, { ZD_CR140, 0x98 }, -+ { ZD_CR141, 0x82 }, { ZD_CR142, 0x53 }, { ZD_CR143, 0x1c }, -+ { ZD_CR144, 0x6c }, { ZD_CR147, 0x07 }, { ZD_CR148, 0x40 }, -+ { ZD_CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ -+ { ZD_CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ -+ { ZD_CR151, 0x18 }, { ZD_CR159, 0x70 }, { ZD_CR160, 0xfe }, -+ { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa }, -+ { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe }, -+ { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba }, -+ { ZD_CR170, 0xba }, { ZD_CR171, 0xba }, -+ /* Note: ZD_CR204 must lead the ZD_CR203 */ -+ { ZD_CR204, 0x7d }, - {}, -- { CR203, 0x30 }, -+ { ZD_CR203, 0x30 }, - }; - - int r, t; -@@ -1200,24 +1200,24 @@ - static int update_pwr_int(struct zd_chip *chip, u8 channel) - { - u8 value = chip->pwr_int_values[channel - 1]; -- return zd_iowrite16_locked(chip, value, CR31); -+ return zd_iowrite16_locked(chip, value, ZD_CR31); - } - - static int update_pwr_cal(struct zd_chip *chip, u8 channel) - { - u8 value = chip->pwr_cal_values[channel-1]; -- return zd_iowrite16_locked(chip, value, CR68); -+ return zd_iowrite16_locked(chip, value, ZD_CR68); - } - - static int update_ofdm_cal(struct zd_chip *chip, u8 channel) - { - struct zd_ioreq16 ioreqs[3]; - -- ioreqs[0].addr = CR67; -+ ioreqs[0].addr = ZD_CR67; - ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; -- ioreqs[1].addr = CR66; -+ ioreqs[1].addr = ZD_CR66; - ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; -- ioreqs[2].addr = CR65; -+ ioreqs[2].addr = ZD_CR65; - ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -1236,9 +1236,9 @@ - return r; - if (zd_chip_is_zd1211b(chip)) { - static const struct zd_ioreq16 ioreqs[] = { -- { CR69, 0x28 }, -+ { ZD_CR69, 0x28 }, - {}, -- { CR69, 0x2a }, -+ { ZD_CR69, 0x2a }, - }; - - r = update_ofdm_cal(chip, channel); -@@ -1269,7 +1269,7 @@ - if (r) - return r; - dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); -- return zd_iowrite16_locked(chip, value & 0xff, CR47); -+ return zd_iowrite16_locked(chip, value & 0xff, ZD_CR47); - } - - int zd_chip_set_channel(struct zd_chip *chip, u8 channel) -@@ -1505,9 +1505,9 @@ - int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) - { - const struct zd_ioreq16 ioreqs[] = { -- { CR244, (value >> 16) & 0xff }, -- { CR243, (value >> 8) & 0xff }, -- { CR242, value & 0xff }, -+ { ZD_CR244, (value >> 16) & 0xff }, -+ { ZD_CR243, (value >> 8) & 0xff }, -+ { ZD_CR242, value & 0xff }, - }; - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_chip.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_chip.h ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_chip.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_chip.h 2011-05-05 23:29:45.534442457 +0200 -@@ -61,277 +61,288 @@ - #define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset))) - - /* 8-bit hardware registers */ --#define CR0 CTL_REG(0x0000) --#define CR1 CTL_REG(0x0004) --#define CR2 CTL_REG(0x0008) --#define CR3 CTL_REG(0x000C) -+#define ZD_CR0 CTL_REG(0x0000) -+#define ZD_CR1 CTL_REG(0x0004) -+#define ZD_CR2 CTL_REG(0x0008) -+#define ZD_CR3 CTL_REG(0x000C) - --#define CR5 CTL_REG(0x0010) -+#define ZD_CR5 CTL_REG(0x0010) - /* bit 5: if set short preamble used - * bit 6: filter band - Japan channel 14 on, else off - */ --#define CR6 CTL_REG(0x0014) --#define CR7 CTL_REG(0x0018) --#define CR8 CTL_REG(0x001C) -- --#define CR4 CTL_REG(0x0020) -- --#define CR9 CTL_REG(0x0024) --/* bit 2: antenna switch (together with CR10) */ --#define CR10 CTL_REG(0x0028) --/* bit 1: antenna switch (together with CR9) -- * RF2959 controls with CR11 radion on and off -+#define ZD_CR6 CTL_REG(0x0014) -+#define ZD_CR7 CTL_REG(0x0018) -+#define ZD_CR8 CTL_REG(0x001C) -+ -+#define ZD_CR4 CTL_REG(0x0020) -+ -+#define ZD_CR9 CTL_REG(0x0024) -+/* bit 2: antenna switch (together with ZD_CR10) */ -+#define ZD_CR10 CTL_REG(0x0028) -+/* bit 1: antenna switch (together with ZD_CR9) -+ * RF2959 controls with ZD_CR11 radion on and off - */ --#define CR11 CTL_REG(0x002C) -+#define ZD_CR11 CTL_REG(0x002C) - /* bit 6: TX power control for OFDM -- * RF2959 controls with CR10 radio on and off -+ * RF2959 controls with ZD_CR10 radio on and off - */ --#define CR12 CTL_REG(0x0030) --#define CR13 CTL_REG(0x0034) --#define CR14 CTL_REG(0x0038) --#define CR15 CTL_REG(0x003C) --#define CR16 CTL_REG(0x0040) --#define CR17 CTL_REG(0x0044) --#define CR18 CTL_REG(0x0048) --#define CR19 CTL_REG(0x004C) --#define CR20 CTL_REG(0x0050) --#define CR21 CTL_REG(0x0054) --#define CR22 CTL_REG(0x0058) --#define CR23 CTL_REG(0x005C) --#define CR24 CTL_REG(0x0060) /* CCA threshold */ --#define CR25 CTL_REG(0x0064) --#define CR26 CTL_REG(0x0068) --#define CR27 CTL_REG(0x006C) --#define CR28 CTL_REG(0x0070) --#define CR29 CTL_REG(0x0074) --#define CR30 CTL_REG(0x0078) --#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ --#define CR32 CTL_REG(0x0080) --#define CR33 CTL_REG(0x0084) --#define CR34 CTL_REG(0x0088) --#define CR35 CTL_REG(0x008C) --#define CR36 CTL_REG(0x0090) --#define CR37 CTL_REG(0x0094) --#define CR38 CTL_REG(0x0098) --#define CR39 CTL_REG(0x009C) --#define CR40 CTL_REG(0x00A0) --#define CR41 CTL_REG(0x00A4) --#define CR42 CTL_REG(0x00A8) --#define CR43 CTL_REG(0x00AC) --#define CR44 CTL_REG(0x00B0) --#define CR45 CTL_REG(0x00B4) --#define CR46 CTL_REG(0x00B8) --#define CR47 CTL_REG(0x00BC) /* CCK baseband gain -- * (patch value might be in EEPROM) -- */ --#define CR48 CTL_REG(0x00C0) --#define CR49 CTL_REG(0x00C4) --#define CR50 CTL_REG(0x00C8) --#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ --#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ --#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ --#define CR54 CTL_REG(0x00D8) --#define CR55 CTL_REG(0x00DC) --#define CR56 CTL_REG(0x00E0) --#define CR57 CTL_REG(0x00E4) --#define CR58 CTL_REG(0x00E8) --#define CR59 CTL_REG(0x00EC) --#define CR60 CTL_REG(0x00F0) --#define CR61 CTL_REG(0x00F4) --#define CR62 CTL_REG(0x00F8) --#define CR63 CTL_REG(0x00FC) --#define CR64 CTL_REG(0x0100) --#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ --#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ --#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ --#define CR68 CTL_REG(0x0110) /* CCK calibration */ --#define CR69 CTL_REG(0x0114) --#define CR70 CTL_REG(0x0118) --#define CR71 CTL_REG(0x011C) --#define CR72 CTL_REG(0x0120) --#define CR73 CTL_REG(0x0124) --#define CR74 CTL_REG(0x0128) --#define CR75 CTL_REG(0x012C) --#define CR76 CTL_REG(0x0130) --#define CR77 CTL_REG(0x0134) --#define CR78 CTL_REG(0x0138) --#define CR79 CTL_REG(0x013C) --#define CR80 CTL_REG(0x0140) --#define CR81 CTL_REG(0x0144) --#define CR82 CTL_REG(0x0148) --#define CR83 CTL_REG(0x014C) --#define CR84 CTL_REG(0x0150) --#define CR85 CTL_REG(0x0154) --#define CR86 CTL_REG(0x0158) --#define CR87 CTL_REG(0x015C) --#define CR88 CTL_REG(0x0160) --#define CR89 CTL_REG(0x0164) --#define CR90 CTL_REG(0x0168) --#define CR91 CTL_REG(0x016C) --#define CR92 CTL_REG(0x0170) --#define CR93 CTL_REG(0x0174) --#define CR94 CTL_REG(0x0178) --#define CR95 CTL_REG(0x017C) --#define CR96 CTL_REG(0x0180) --#define CR97 CTL_REG(0x0184) --#define CR98 CTL_REG(0x0188) --#define CR99 CTL_REG(0x018C) --#define CR100 CTL_REG(0x0190) --#define CR101 CTL_REG(0x0194) --#define CR102 CTL_REG(0x0198) --#define CR103 CTL_REG(0x019C) --#define CR104 CTL_REG(0x01A0) --#define CR105 CTL_REG(0x01A4) --#define CR106 CTL_REG(0x01A8) --#define CR107 CTL_REG(0x01AC) --#define CR108 CTL_REG(0x01B0) --#define CR109 CTL_REG(0x01B4) --#define CR110 CTL_REG(0x01B8) --#define CR111 CTL_REG(0x01BC) --#define CR112 CTL_REG(0x01C0) --#define CR113 CTL_REG(0x01C4) --#define CR114 CTL_REG(0x01C8) --#define CR115 CTL_REG(0x01CC) --#define CR116 CTL_REG(0x01D0) --#define CR117 CTL_REG(0x01D4) --#define CR118 CTL_REG(0x01D8) --#define CR119 CTL_REG(0x01DC) --#define CR120 CTL_REG(0x01E0) --#define CR121 CTL_REG(0x01E4) --#define CR122 CTL_REG(0x01E8) --#define CR123 CTL_REG(0x01EC) --#define CR124 CTL_REG(0x01F0) --#define CR125 CTL_REG(0x01F4) --#define CR126 CTL_REG(0x01F8) --#define CR127 CTL_REG(0x01FC) --#define CR128 CTL_REG(0x0200) --#define CR129 CTL_REG(0x0204) --#define CR130 CTL_REG(0x0208) --#define CR131 CTL_REG(0x020C) --#define CR132 CTL_REG(0x0210) --#define CR133 CTL_REG(0x0214) --#define CR134 CTL_REG(0x0218) --#define CR135 CTL_REG(0x021C) --#define CR136 CTL_REG(0x0220) --#define CR137 CTL_REG(0x0224) --#define CR138 CTL_REG(0x0228) --#define CR139 CTL_REG(0x022C) --#define CR140 CTL_REG(0x0230) --#define CR141 CTL_REG(0x0234) --#define CR142 CTL_REG(0x0238) --#define CR143 CTL_REG(0x023C) --#define CR144 CTL_REG(0x0240) --#define CR145 CTL_REG(0x0244) --#define CR146 CTL_REG(0x0248) --#define CR147 CTL_REG(0x024C) --#define CR148 CTL_REG(0x0250) --#define CR149 CTL_REG(0x0254) --#define CR150 CTL_REG(0x0258) --#define CR151 CTL_REG(0x025C) --#define CR152 CTL_REG(0x0260) --#define CR153 CTL_REG(0x0264) --#define CR154 CTL_REG(0x0268) --#define CR155 CTL_REG(0x026C) --#define CR156 CTL_REG(0x0270) --#define CR157 CTL_REG(0x0274) --#define CR158 CTL_REG(0x0278) --#define CR159 CTL_REG(0x027C) --#define CR160 CTL_REG(0x0280) --#define CR161 CTL_REG(0x0284) --#define CR162 CTL_REG(0x0288) --#define CR163 CTL_REG(0x028C) --#define CR164 CTL_REG(0x0290) --#define CR165 CTL_REG(0x0294) --#define CR166 CTL_REG(0x0298) --#define CR167 CTL_REG(0x029C) --#define CR168 CTL_REG(0x02A0) --#define CR169 CTL_REG(0x02A4) --#define CR170 CTL_REG(0x02A8) --#define CR171 CTL_REG(0x02AC) --#define CR172 CTL_REG(0x02B0) --#define CR173 CTL_REG(0x02B4) --#define CR174 CTL_REG(0x02B8) --#define CR175 CTL_REG(0x02BC) --#define CR176 CTL_REG(0x02C0) --#define CR177 CTL_REG(0x02C4) --#define CR178 CTL_REG(0x02C8) --#define CR179 CTL_REG(0x02CC) --#define CR180 CTL_REG(0x02D0) --#define CR181 CTL_REG(0x02D4) --#define CR182 CTL_REG(0x02D8) --#define CR183 CTL_REG(0x02DC) --#define CR184 CTL_REG(0x02E0) --#define CR185 CTL_REG(0x02E4) --#define CR186 CTL_REG(0x02E8) --#define CR187 CTL_REG(0x02EC) --#define CR188 CTL_REG(0x02F0) --#define CR189 CTL_REG(0x02F4) --#define CR190 CTL_REG(0x02F8) --#define CR191 CTL_REG(0x02FC) --#define CR192 CTL_REG(0x0300) --#define CR193 CTL_REG(0x0304) --#define CR194 CTL_REG(0x0308) --#define CR195 CTL_REG(0x030C) --#define CR196 CTL_REG(0x0310) --#define CR197 CTL_REG(0x0314) --#define CR198 CTL_REG(0x0318) --#define CR199 CTL_REG(0x031C) --#define CR200 CTL_REG(0x0320) --#define CR201 CTL_REG(0x0324) --#define CR202 CTL_REG(0x0328) --#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ --#define CR204 CTL_REG(0x0330) --#define CR205 CTL_REG(0x0334) --#define CR206 CTL_REG(0x0338) --#define CR207 CTL_REG(0x033C) --#define CR208 CTL_REG(0x0340) --#define CR209 CTL_REG(0x0344) --#define CR210 CTL_REG(0x0348) --#define CR211 CTL_REG(0x034C) --#define CR212 CTL_REG(0x0350) --#define CR213 CTL_REG(0x0354) --#define CR214 CTL_REG(0x0358) --#define CR215 CTL_REG(0x035C) --#define CR216 CTL_REG(0x0360) --#define CR217 CTL_REG(0x0364) --#define CR218 CTL_REG(0x0368) --#define CR219 CTL_REG(0x036C) --#define CR220 CTL_REG(0x0370) --#define CR221 CTL_REG(0x0374) --#define CR222 CTL_REG(0x0378) --#define CR223 CTL_REG(0x037C) --#define CR224 CTL_REG(0x0380) --#define CR225 CTL_REG(0x0384) --#define CR226 CTL_REG(0x0388) --#define CR227 CTL_REG(0x038C) --#define CR228 CTL_REG(0x0390) --#define CR229 CTL_REG(0x0394) --#define CR230 CTL_REG(0x0398) --#define CR231 CTL_REG(0x039C) --#define CR232 CTL_REG(0x03A0) --#define CR233 CTL_REG(0x03A4) --#define CR234 CTL_REG(0x03A8) --#define CR235 CTL_REG(0x03AC) --#define CR236 CTL_REG(0x03B0) -- --#define CR240 CTL_REG(0x03C0) --/* bit 7: host-controlled RF register writes -- * CR241-CR245: for hardware controlled writing of RF bits, not needed for -- * USB -- */ --#define CR241 CTL_REG(0x03C4) --#define CR242 CTL_REG(0x03C8) --#define CR243 CTL_REG(0x03CC) --#define CR244 CTL_REG(0x03D0) --#define CR245 CTL_REG(0x03D4) -- --#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of -- * Airoha RFs AL2230 and AL7230B -- */ --#define CR252 CTL_REG(0x03F0) --#define CR253 CTL_REG(0x03F4) --#define CR254 CTL_REG(0x03F8) --#define CR255 CTL_REG(0x03FC) -+#define ZD_CR12 CTL_REG(0x0030) -+#define ZD_CR13 CTL_REG(0x0034) -+#define ZD_CR14 CTL_REG(0x0038) -+#define ZD_CR15 CTL_REG(0x003C) -+#define ZD_CR16 CTL_REG(0x0040) -+#define ZD_CR17 CTL_REG(0x0044) -+#define ZD_CR18 CTL_REG(0x0048) -+#define ZD_CR19 CTL_REG(0x004C) -+#define ZD_CR20 CTL_REG(0x0050) -+#define ZD_CR21 CTL_REG(0x0054) -+#define ZD_CR22 CTL_REG(0x0058) -+#define ZD_CR23 CTL_REG(0x005C) -+#define ZD_CR24 CTL_REG(0x0060) /* CCA threshold */ -+#define ZD_CR25 CTL_REG(0x0064) -+#define ZD_CR26 CTL_REG(0x0068) -+#define ZD_CR27 CTL_REG(0x006C) -+#define ZD_CR28 CTL_REG(0x0070) -+#define ZD_CR29 CTL_REG(0x0074) -+#define ZD_CR30 CTL_REG(0x0078) -+#define ZD_CR31 CTL_REG(0x007C) /* TX power control for RF in -+ * CCK mode -+ */ -+#define ZD_CR32 CTL_REG(0x0080) -+#define ZD_CR33 CTL_REG(0x0084) -+#define ZD_CR34 CTL_REG(0x0088) -+#define ZD_CR35 CTL_REG(0x008C) -+#define ZD_CR36 CTL_REG(0x0090) -+#define ZD_CR37 CTL_REG(0x0094) -+#define ZD_CR38 CTL_REG(0x0098) -+#define ZD_CR39 CTL_REG(0x009C) -+#define ZD_CR40 CTL_REG(0x00A0) -+#define ZD_CR41 CTL_REG(0x00A4) -+#define ZD_CR42 CTL_REG(0x00A8) -+#define ZD_CR43 CTL_REG(0x00AC) -+#define ZD_CR44 CTL_REG(0x00B0) -+#define ZD_CR45 CTL_REG(0x00B4) -+#define ZD_CR46 CTL_REG(0x00B8) -+#define ZD_CR47 CTL_REG(0x00BC) /* CCK baseband gain -+ * (patch value might be in EEPROM) -+ */ -+#define ZD_CR48 CTL_REG(0x00C0) -+#define ZD_CR49 CTL_REG(0x00C4) -+#define ZD_CR50 CTL_REG(0x00C8) -+#define ZD_CR51 CTL_REG(0x00CC) /* TX power control for RF in -+ * 6-36M modes -+ */ -+#define ZD_CR52 CTL_REG(0x00D0) /* TX power control for RF in -+ * 48M mode -+ */ -+#define ZD_CR53 CTL_REG(0x00D4) /* TX power control for RF in -+ * 54M mode -+ */ -+#define ZD_CR54 CTL_REG(0x00D8) -+#define ZD_CR55 CTL_REG(0x00DC) -+#define ZD_CR56 CTL_REG(0x00E0) -+#define ZD_CR57 CTL_REG(0x00E4) -+#define ZD_CR58 CTL_REG(0x00E8) -+#define ZD_CR59 CTL_REG(0x00EC) -+#define ZD_CR60 CTL_REG(0x00F0) -+#define ZD_CR61 CTL_REG(0x00F4) -+#define ZD_CR62 CTL_REG(0x00F8) -+#define ZD_CR63 CTL_REG(0x00FC) -+#define ZD_CR64 CTL_REG(0x0100) -+#define ZD_CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ -+#define ZD_CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ -+#define ZD_CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ -+#define ZD_CR68 CTL_REG(0x0110) /* CCK calibration */ -+#define ZD_CR69 CTL_REG(0x0114) -+#define ZD_CR70 CTL_REG(0x0118) -+#define ZD_CR71 CTL_REG(0x011C) -+#define ZD_CR72 CTL_REG(0x0120) -+#define ZD_CR73 CTL_REG(0x0124) -+#define ZD_CR74 CTL_REG(0x0128) -+#define ZD_CR75 CTL_REG(0x012C) -+#define ZD_CR76 CTL_REG(0x0130) -+#define ZD_CR77 CTL_REG(0x0134) -+#define ZD_CR78 CTL_REG(0x0138) -+#define ZD_CR79 CTL_REG(0x013C) -+#define ZD_CR80 CTL_REG(0x0140) -+#define ZD_CR81 CTL_REG(0x0144) -+#define ZD_CR82 CTL_REG(0x0148) -+#define ZD_CR83 CTL_REG(0x014C) -+#define ZD_CR84 CTL_REG(0x0150) -+#define ZD_CR85 CTL_REG(0x0154) -+#define ZD_CR86 CTL_REG(0x0158) -+#define ZD_CR87 CTL_REG(0x015C) -+#define ZD_CR88 CTL_REG(0x0160) -+#define ZD_CR89 CTL_REG(0x0164) -+#define ZD_CR90 CTL_REG(0x0168) -+#define ZD_CR91 CTL_REG(0x016C) -+#define ZD_CR92 CTL_REG(0x0170) -+#define ZD_CR93 CTL_REG(0x0174) -+#define ZD_CR94 CTL_REG(0x0178) -+#define ZD_CR95 CTL_REG(0x017C) -+#define ZD_CR96 CTL_REG(0x0180) -+#define ZD_CR97 CTL_REG(0x0184) -+#define ZD_CR98 CTL_REG(0x0188) -+#define ZD_CR99 CTL_REG(0x018C) -+#define ZD_CR100 CTL_REG(0x0190) -+#define ZD_CR101 CTL_REG(0x0194) -+#define ZD_CR102 CTL_REG(0x0198) -+#define ZD_CR103 CTL_REG(0x019C) -+#define ZD_CR104 CTL_REG(0x01A0) -+#define ZD_CR105 CTL_REG(0x01A4) -+#define ZD_CR106 CTL_REG(0x01A8) -+#define ZD_CR107 CTL_REG(0x01AC) -+#define ZD_CR108 CTL_REG(0x01B0) -+#define ZD_CR109 CTL_REG(0x01B4) -+#define ZD_CR110 CTL_REG(0x01B8) -+#define ZD_CR111 CTL_REG(0x01BC) -+#define ZD_CR112 CTL_REG(0x01C0) -+#define ZD_CR113 CTL_REG(0x01C4) -+#define ZD_CR114 CTL_REG(0x01C8) -+#define ZD_CR115 CTL_REG(0x01CC) -+#define ZD_CR116 CTL_REG(0x01D0) -+#define ZD_CR117 CTL_REG(0x01D4) -+#define ZD_CR118 CTL_REG(0x01D8) -+#define ZD_CR119 CTL_REG(0x01DC) -+#define ZD_CR120 CTL_REG(0x01E0) -+#define ZD_CR121 CTL_REG(0x01E4) -+#define ZD_CR122 CTL_REG(0x01E8) -+#define ZD_CR123 CTL_REG(0x01EC) -+#define ZD_CR124 CTL_REG(0x01F0) -+#define ZD_CR125 CTL_REG(0x01F4) -+#define ZD_CR126 CTL_REG(0x01F8) -+#define ZD_CR127 CTL_REG(0x01FC) -+#define ZD_CR128 CTL_REG(0x0200) -+#define ZD_CR129 CTL_REG(0x0204) -+#define ZD_CR130 CTL_REG(0x0208) -+#define ZD_CR131 CTL_REG(0x020C) -+#define ZD_CR132 CTL_REG(0x0210) -+#define ZD_CR133 CTL_REG(0x0214) -+#define ZD_CR134 CTL_REG(0x0218) -+#define ZD_CR135 CTL_REG(0x021C) -+#define ZD_CR136 CTL_REG(0x0220) -+#define ZD_CR137 CTL_REG(0x0224) -+#define ZD_CR138 CTL_REG(0x0228) -+#define ZD_CR139 CTL_REG(0x022C) -+#define ZD_CR140 CTL_REG(0x0230) -+#define ZD_CR141 CTL_REG(0x0234) -+#define ZD_CR142 CTL_REG(0x0238) -+#define ZD_CR143 CTL_REG(0x023C) -+#define ZD_CR144 CTL_REG(0x0240) -+#define ZD_CR145 CTL_REG(0x0244) -+#define ZD_CR146 CTL_REG(0x0248) -+#define ZD_CR147 CTL_REG(0x024C) -+#define ZD_CR148 CTL_REG(0x0250) -+#define ZD_CR149 CTL_REG(0x0254) -+#define ZD_CR150 CTL_REG(0x0258) -+#define ZD_CR151 CTL_REG(0x025C) -+#define ZD_CR152 CTL_REG(0x0260) -+#define ZD_CR153 CTL_REG(0x0264) -+#define ZD_CR154 CTL_REG(0x0268) -+#define ZD_CR155 CTL_REG(0x026C) -+#define ZD_CR156 CTL_REG(0x0270) -+#define ZD_CR157 CTL_REG(0x0274) -+#define ZD_CR158 CTL_REG(0x0278) -+#define ZD_CR159 CTL_REG(0x027C) -+#define ZD_CR160 CTL_REG(0x0280) -+#define ZD_CR161 CTL_REG(0x0284) -+#define ZD_CR162 CTL_REG(0x0288) -+#define ZD_CR163 CTL_REG(0x028C) -+#define ZD_CR164 CTL_REG(0x0290) -+#define ZD_CR165 CTL_REG(0x0294) -+#define ZD_CR166 CTL_REG(0x0298) -+#define ZD_CR167 CTL_REG(0x029C) -+#define ZD_CR168 CTL_REG(0x02A0) -+#define ZD_CR169 CTL_REG(0x02A4) -+#define ZD_CR170 CTL_REG(0x02A8) -+#define ZD_CR171 CTL_REG(0x02AC) -+#define ZD_CR172 CTL_REG(0x02B0) -+#define ZD_CR173 CTL_REG(0x02B4) -+#define ZD_CR174 CTL_REG(0x02B8) -+#define ZD_CR175 CTL_REG(0x02BC) -+#define ZD_CR176 CTL_REG(0x02C0) -+#define ZD_CR177 CTL_REG(0x02C4) -+#define ZD_CR178 CTL_REG(0x02C8) -+#define ZD_CR179 CTL_REG(0x02CC) -+#define ZD_CR180 CTL_REG(0x02D0) -+#define ZD_CR181 CTL_REG(0x02D4) -+#define ZD_CR182 CTL_REG(0x02D8) -+#define ZD_CR183 CTL_REG(0x02DC) -+#define ZD_CR184 CTL_REG(0x02E0) -+#define ZD_CR185 CTL_REG(0x02E4) -+#define ZD_CR186 CTL_REG(0x02E8) -+#define ZD_CR187 CTL_REG(0x02EC) -+#define ZD_CR188 CTL_REG(0x02F0) -+#define ZD_CR189 CTL_REG(0x02F4) -+#define ZD_CR190 CTL_REG(0x02F8) -+#define ZD_CR191 CTL_REG(0x02FC) -+#define ZD_CR192 CTL_REG(0x0300) -+#define ZD_CR193 CTL_REG(0x0304) -+#define ZD_CR194 CTL_REG(0x0308) -+#define ZD_CR195 CTL_REG(0x030C) -+#define ZD_CR196 CTL_REG(0x0310) -+#define ZD_CR197 CTL_REG(0x0314) -+#define ZD_CR198 CTL_REG(0x0318) -+#define ZD_CR199 CTL_REG(0x031C) -+#define ZD_CR200 CTL_REG(0x0320) -+#define ZD_CR201 CTL_REG(0x0324) -+#define ZD_CR202 CTL_REG(0x0328) -+#define ZD_CR203 CTL_REG(0x032C) /* I2C bus template value & flash -+ * control -+ */ -+#define ZD_CR204 CTL_REG(0x0330) -+#define ZD_CR205 CTL_REG(0x0334) -+#define ZD_CR206 CTL_REG(0x0338) -+#define ZD_CR207 CTL_REG(0x033C) -+#define ZD_CR208 CTL_REG(0x0340) -+#define ZD_CR209 CTL_REG(0x0344) -+#define ZD_CR210 CTL_REG(0x0348) -+#define ZD_CR211 CTL_REG(0x034C) -+#define ZD_CR212 CTL_REG(0x0350) -+#define ZD_CR213 CTL_REG(0x0354) -+#define ZD_CR214 CTL_REG(0x0358) -+#define ZD_CR215 CTL_REG(0x035C) -+#define ZD_CR216 CTL_REG(0x0360) -+#define ZD_CR217 CTL_REG(0x0364) -+#define ZD_CR218 CTL_REG(0x0368) -+#define ZD_CR219 CTL_REG(0x036C) -+#define ZD_CR220 CTL_REG(0x0370) -+#define ZD_CR221 CTL_REG(0x0374) -+#define ZD_CR222 CTL_REG(0x0378) -+#define ZD_CR223 CTL_REG(0x037C) -+#define ZD_CR224 CTL_REG(0x0380) -+#define ZD_CR225 CTL_REG(0x0384) -+#define ZD_CR226 CTL_REG(0x0388) -+#define ZD_CR227 CTL_REG(0x038C) -+#define ZD_CR228 CTL_REG(0x0390) -+#define ZD_CR229 CTL_REG(0x0394) -+#define ZD_CR230 CTL_REG(0x0398) -+#define ZD_CR231 CTL_REG(0x039C) -+#define ZD_CR232 CTL_REG(0x03A0) -+#define ZD_CR233 CTL_REG(0x03A4) -+#define ZD_CR234 CTL_REG(0x03A8) -+#define ZD_CR235 CTL_REG(0x03AC) -+#define ZD_CR236 CTL_REG(0x03B0) -+ -+#define ZD_CR240 CTL_REG(0x03C0) -+/* bit 7: host-controlled RF register writes -+ * ZD_CR241-ZD_CR245: for hardware controlled writing of RF bits, not needed for -+ * USB -+ */ -+#define ZD_CR241 CTL_REG(0x03C4) -+#define ZD_CR242 CTL_REG(0x03C8) -+#define ZD_CR243 CTL_REG(0x03CC) -+#define ZD_CR244 CTL_REG(0x03D0) -+#define ZD_CR245 CTL_REG(0x03D4) -+ -+#define ZD_CR251 CTL_REG(0x03EC) /* only used for activation and -+ * deactivation of Airoha RFs AL2230 -+ * and AL7230B -+ */ -+#define ZD_CR252 CTL_REG(0x03F0) -+#define ZD_CR253 CTL_REG(0x03F4) -+#define ZD_CR254 CTL_REG(0x03F8) -+#define ZD_CR255 CTL_REG(0x03FC) - - #define CR_MAX_PHY_REG 255 - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_al2230.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_al2230.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_al2230.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_al2230.c 2011-05-05 23:29:45.535442469 +0200 -@@ -61,31 +61,31 @@ - }; - - static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { -- { CR240, 0x57 }, { CR9, 0xe0 }, -+ { ZD_CR240, 0x57 }, { ZD_CR9, 0xe0 }, - }; - - static const struct zd_ioreq16 ioreqs_init_al2230s[] = { -- { CR47, 0x1e }, /* MARK_002 */ -- { CR106, 0x22 }, -- { CR107, 0x2a }, /* MARK_002 */ -- { CR109, 0x13 }, /* MARK_002 */ -- { CR118, 0xf8 }, /* MARK_002 */ -- { CR119, 0x12 }, { CR122, 0xe0 }, -- { CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ -- { CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ -- { CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ -+ { ZD_CR47, 0x1e }, /* MARK_002 */ -+ { ZD_CR106, 0x22 }, -+ { ZD_CR107, 0x2a }, /* MARK_002 */ -+ { ZD_CR109, 0x13 }, /* MARK_002 */ -+ { ZD_CR118, 0xf8 }, /* MARK_002 */ -+ { ZD_CR119, 0x12 }, { ZD_CR122, 0xe0 }, -+ { ZD_CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ -+ { ZD_CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ -+ { ZD_CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ - }; - - static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) - { - int r; - static const struct zd_ioreq16 ioreqs[] = { -- { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, -- { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, -- { CR203, 0x06 }, -+ { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, -+ { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, -+ { ZD_CR203, 0x06 }, - { }, - -- { CR240, 0x80 }, -+ { ZD_CR240, 0x80 }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -94,12 +94,12 @@ - - /* related to antenna selection? */ - if (chip->new_phy_layout) { -- r = zd_iowrite16_locked(chip, 0xe1, CR9); -+ r = zd_iowrite16_locked(chip, 0xe1, ZD_CR9); - if (r) - return r; - } - -- return zd_iowrite16_locked(chip, 0x06, CR203); -+ return zd_iowrite16_locked(chip, 0x06, ZD_CR203); - } - - static int zd1211_al2230_init_hw(struct zd_rf *rf) -@@ -108,40 +108,40 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs_init[] = { -- { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, -- { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, -- { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, -- { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, -- { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, -+ { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, -+ { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, -+ { ZD_CR44, 0x33 }, { ZD_CR106, 0x2a }, { ZD_CR107, 0x1a }, -+ { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, { ZD_CR111, 0x2b }, -+ { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, { ZD_CR10, 0x89 }, - /* for newest (3rd cut) AL2300 */ -- { CR17, 0x28 }, -- { CR26, 0x93 }, { CR34, 0x30 }, -+ { ZD_CR17, 0x28 }, -+ { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, - /* for newest (3rd cut) AL2300 */ -- { CR35, 0x3e }, -- { CR41, 0x24 }, { CR44, 0x32 }, -+ { ZD_CR35, 0x3e }, -+ { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, - /* for newest (3rd cut) AL2300 */ -- { CR46, 0x96 }, -- { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, -- { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, -- { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, -- { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, -- { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, -- { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, -- { CR114, 0x27 }, -+ { ZD_CR46, 0x96 }, -+ { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, -+ { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, -+ { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, -+ { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR106, 0x24 }, -+ { ZD_CR107, 0x2a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x13 }, -+ { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x27 }, - /* for newest (3rd cut) AL2300 */ -- { CR115, 0x24 }, -- { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, -- { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, -- { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, -- { CR253, 0xff }, -+ { ZD_CR115, 0x24 }, -+ { ZD_CR116, 0x24 }, { ZD_CR117, 0xf4 }, { ZD_CR118, 0xfc }, -+ { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, { ZD_CR121, 0x77 }, -+ { ZD_CR122, 0xe0 }, { ZD_CR137, 0x88 }, { ZD_CR252, 0xff }, -+ { ZD_CR253, 0xff }, - }; - - static const struct zd_ioreq16 ioreqs_pll[] = { - /* shdnb(PLL_ON)=0 */ -- { CR251, 0x2f }, -+ { ZD_CR251, 0x2f }, - /* shdnb(PLL_ON)=1 */ -- { CR251, 0x3f }, -- { CR138, 0x28 }, { CR203, 0x06 }, -+ { ZD_CR251, 0x3f }, -+ { ZD_CR138, 0x28 }, { ZD_CR203, 0x06 }, - }; - - static const u32 rv1[] = { -@@ -161,7 +161,7 @@ - 0x0805b6, - 0x011687, - 0x000688, -- 0x0403b9, /* external control TX power (CR31) */ -+ 0x0403b9, /* external control TX power (ZD_CR31) */ - 0x00dbba, - 0x00099b, - 0x0bdffc, -@@ -221,52 +221,54 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs1[] = { -- { CR10, 0x89 }, { CR15, 0x20 }, -- { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ -- { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, -- { CR28, 0x3e }, { CR29, 0x00 }, -- { CR33, 0x28 }, /* 5621 */ -- { CR34, 0x30 }, -- { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ -- { CR41, 0x24 }, { CR44, 0x32 }, -- { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ -- { CR47, 0x1e }, -+ { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, -+ { ZD_CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ -+ { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, -+ { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, -+ { ZD_CR33, 0x28 }, /* 5621 */ -+ { ZD_CR34, 0x30 }, -+ { ZD_CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ -+ { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, -+ { ZD_CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ -+ { ZD_CR47, 0x1e }, - - /* ZD1211B 05.06.10 */ -- { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, -- { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, -- { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, -- { CR69, 0x28 }, -- -- { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, -- { CR87, 0x0a }, { CR89, 0x04 }, -- { CR91, 0x00 }, /* 5621 */ -- { CR92, 0x0a }, -- { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ -- { CR99, 0x00 }, /* 5621 */ -- { CR101, 0x13 }, { CR102, 0x27 }, -- { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ -- { CR107, 0x2a }, -- { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ -- { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ -- { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, -- { CR114, 0x27 }, -- { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ -- { CR116, 0x24 }, -- { CR117, 0xfa }, /* for 1211b */ -- { CR118, 0xfa }, /* for 1211b */ -- { CR119, 0x10 }, -- { CR120, 0x4f }, -- { CR121, 0x6c }, /* for 1211b */ -- { CR122, 0xfc }, /* E0->FC at 4902 */ -- { CR123, 0x57 }, /* 5623 */ -- { CR125, 0xad }, /* 4804, for 1212 new algorithm */ -- { CR126, 0x6c }, /* 5614 */ -- { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ -- { CR137, 0x50 }, /* 5614 */ -- { CR138, 0xa8 }, -- { CR144, 0xac }, /* 5621 */ -- { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, -+ { ZD_CR48, 0x06 }, { ZD_CR49, 0xf9 }, { ZD_CR51, 0x01 }, -+ { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, -+ { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, -+ { ZD_CR69, 0x28 }, -+ -+ { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, -+ { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, -+ { ZD_CR91, 0x00 }, /* 5621 */ -+ { ZD_CR92, 0x0a }, -+ { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR99, 0x00 }, /* 5621 */ -+ { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, -+ { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ -+ { ZD_CR107, 0x2a }, -+ { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x27 }, -+ { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) -+ * AL2230 -+ */ -+ { ZD_CR116, 0x24 }, -+ { ZD_CR117, 0xfa }, /* for 1211b */ -+ { ZD_CR118, 0xfa }, /* for 1211b */ -+ { ZD_CR119, 0x10 }, -+ { ZD_CR120, 0x4f }, -+ { ZD_CR121, 0x6c }, /* for 1211b */ -+ { ZD_CR122, 0xfc }, /* E0->FC at 4902 */ -+ { ZD_CR123, 0x57 }, /* 5623 */ -+ { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR126, 0x6c }, /* 5614 */ -+ { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR137, 0x50 }, /* 5614 */ -+ { ZD_CR138, 0xa8 }, -+ { ZD_CR144, 0xac }, /* 5621 */ -+ { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, - }; - - static const u32 rv1[] = { -@@ -284,7 +286,7 @@ - 0x6da010, /* Reg6 update for MP versio */ - 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ - 0x116000, -- 0x9dc020, /* External control TX power (CR31) */ -+ 0x9dc020, /* External control TX power (ZD_CR31) */ - 0x5ddb00, /* RegA update for MP version */ - 0xd99000, /* RegB update for MP version */ - 0x3ffbd0, /* RegC update for MP version */ -@@ -295,8 +297,8 @@ - }; - - static const struct zd_ioreq16 ioreqs2[] = { -- { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ -- { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ -+ { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ -+ { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ - }; - - static const u32 rv3[] = { -@@ -308,7 +310,7 @@ - - static const struct zd_ioreq16 ioreqs3[] = { - /* related to 6M band edge patching, happens unconditionally */ -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, - }; - - r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, -@@ -361,8 +363,8 @@ - const u32 *rv = zd1211_al2230_table[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR138, 0x28 }, -- { CR203, 0x06 }, -+ { ZD_CR138, 0x28 }, -+ { ZD_CR203, 0x06 }, - }; - - r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); -@@ -393,8 +395,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x00 }, -- { CR251, 0x3f }, -+ { ZD_CR11, 0x00 }, -+ { ZD_CR251, 0x3f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -404,8 +406,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x00 }, -- { CR251, 0x7f }, -+ { ZD_CR11, 0x00 }, -+ { ZD_CR251, 0x7f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -415,8 +417,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x04 }, -- { CR251, 0x2f }, -+ { ZD_CR11, 0x04 }, -+ { ZD_CR251, 0x2f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c 2011-05-05 23:29:45.553442685 +0200 -@@ -68,19 +68,19 @@ - }; - - static const struct zd_ioreq16 ioreqs_sw[] = { -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -- { CR38, 0x38 }, { CR136, 0xdf }, -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, -+ { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, - }; - - static int zd1211b_al7230b_finalize(struct zd_chip *chip) - { - int r; - static const struct zd_ioreq16 ioreqs[] = { -- { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, -- { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, -- { CR203, 0x04 }, -+ { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, -+ { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, -+ { ZD_CR203, 0x04 }, - { }, -- { CR240, 0x80 }, -+ { ZD_CR240, 0x80 }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -89,12 +89,12 @@ - - if (chip->new_phy_layout) { - /* antenna selection? */ -- r = zd_iowrite16_locked(chip, 0xe5, CR9); -+ r = zd_iowrite16_locked(chip, 0xe5, ZD_CR9); - if (r) - return r; - } - -- return zd_iowrite16_locked(chip, 0x04, CR203); -+ return zd_iowrite16_locked(chip, 0x04, ZD_CR203); - } - - static int zd1211_al7230b_init_hw(struct zd_rf *rf) -@@ -106,66 +106,66 @@ - * specified */ - static const struct zd_ioreq16 ioreqs_1[] = { - /* This one is 7230-specific, and happens before the rest */ -- { CR240, 0x57 }, -+ { ZD_CR240, 0x57 }, - { }, - -- { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, -- { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, -- { CR44, 0x33 }, -+ { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, -+ { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, -+ { ZD_CR44, 0x33 }, - /* This value is different for 7230 (was: 0x2a) */ -- { CR106, 0x22 }, -- { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, -- { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, -+ { ZD_CR106, 0x22 }, -+ { ZD_CR107, 0x1a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, -+ { ZD_CR111, 0x2b }, { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, - /* This happened further down in AL2230, - * and the value changed (was: 0xe0) */ -- { CR122, 0xfc }, -- { CR10, 0x89 }, -+ { ZD_CR122, 0xfc }, -+ { ZD_CR10, 0x89 }, - /* for newest (3rd cut) AL2300 */ -- { CR17, 0x28 }, -- { CR26, 0x93 }, { CR34, 0x30 }, -+ { ZD_CR17, 0x28 }, -+ { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 }, - /* for newest (3rd cut) AL2300 */ -- { CR35, 0x3e }, -- { CR41, 0x24 }, { CR44, 0x32 }, -+ { ZD_CR35, 0x3e }, -+ { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, - /* for newest (3rd cut) AL2300 */ -- { CR46, 0x96 }, -- { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, -- { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, -- { CR92, 0x0a }, { CR99, 0x28 }, -+ { ZD_CR46, 0x96 }, -+ { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, -+ { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, -+ { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, - /* This value is different for 7230 (was: 0x00) */ -- { CR100, 0x02 }, -- { CR101, 0x13 }, { CR102, 0x27 }, -+ { ZD_CR100, 0x02 }, -+ { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, - /* This value is different for 7230 (was: 0x24) */ -- { CR106, 0x22 }, -+ { ZD_CR106, 0x22 }, - /* This value is different for 7230 (was: 0x2a) */ -- { CR107, 0x3f }, -- { CR109, 0x09 }, -+ { ZD_CR107, 0x3f }, -+ { ZD_CR109, 0x09 }, - /* This value is different for 7230 (was: 0x13) */ -- { CR110, 0x1f }, -- { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, -- { CR114, 0x27 }, -+ { ZD_CR110, 0x1f }, -+ { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x27 }, - /* for newest (3rd cut) AL2300 */ -- { CR115, 0x24 }, -+ { ZD_CR115, 0x24 }, - /* This value is different for 7230 (was: 0x24) */ -- { CR116, 0x3f }, -+ { ZD_CR116, 0x3f }, - /* This value is different for 7230 (was: 0xf4) */ -- { CR117, 0xfa }, -- { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, -- { CR121, 0x77 }, { CR137, 0x88 }, -+ { ZD_CR117, 0xfa }, -+ { ZD_CR118, 0xfc }, { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, -+ { ZD_CR121, 0x77 }, { ZD_CR137, 0x88 }, - /* This one is 7230-specific */ -- { CR138, 0xa8 }, -+ { ZD_CR138, 0xa8 }, - /* This value is different for 7230 (was: 0xff) */ -- { CR252, 0x34 }, -+ { ZD_CR252, 0x34 }, - /* This value is different for 7230 (was: 0xff) */ -- { CR253, 0x34 }, -+ { ZD_CR253, 0x34 }, - - /* PLL_OFF */ -- { CR251, 0x2f }, -+ { ZD_CR251, 0x2f }, - }; - - static const struct zd_ioreq16 ioreqs_2[] = { -- { CR251, 0x3f }, /* PLL_ON */ -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -- { CR38, 0x38 }, { CR136, 0xdf }, -+ { ZD_CR251, 0x3f }, /* PLL_ON */ -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, -+ { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); -@@ -192,10 +192,10 @@ - if (r) - return r; - -- r = zd_iowrite16_locked(chip, 0x06, CR203); -+ r = zd_iowrite16_locked(chip, 0x06, ZD_CR203); - if (r) - return r; -- r = zd_iowrite16_locked(chip, 0x80, CR240); -+ r = zd_iowrite16_locked(chip, 0x80, ZD_CR240); - if (r) - return r; - -@@ -208,79 +208,79 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs_1[] = { -- { CR240, 0x57 }, { CR9, 0x9 }, -+ { ZD_CR240, 0x57 }, { ZD_CR9, 0x9 }, - { }, -- { CR10, 0x8b }, { CR15, 0x20 }, -- { CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ -- { CR20, 0x10 }, /* 4N25->Stone Request */ -- { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, -- { CR28, 0x3e }, { CR29, 0x00 }, -- { CR33, 0x28 }, /* 5613 */ -- { CR34, 0x30 }, -- { CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ -- { CR41, 0x24 }, { CR44, 0x32 }, -- { CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ -- { CR47, 0x1e }, -+ { ZD_CR10, 0x8b }, { ZD_CR15, 0x20 }, -+ { ZD_CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ -+ { ZD_CR20, 0x10 }, /* 4N25->Stone Request */ -+ { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, -+ { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, -+ { ZD_CR33, 0x28 }, /* 5613 */ -+ { ZD_CR34, 0x30 }, -+ { ZD_CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ -+ { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, -+ { ZD_CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ -+ { ZD_CR47, 0x1e }, - - /* ZD1215 5610 */ -- { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, -- { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, -- { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, -- { CR69, 0x28 }, -- -- { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, -- { CR87, 0x0A }, { CR89, 0x04 }, -- { CR90, 0x58 }, /* 5112 */ -- { CR91, 0x00 }, /* 5613 */ -- { CR92, 0x0a }, -- { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ -- { CR99, 0x00 }, { CR100, 0x02 }, { CR101, 0x13 }, -- { CR102, 0x27 }, -- { CR106, 0x20 }, /* change to 0x24 for AL7230B */ -- { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ -- { CR112, 0x1f }, -+ { ZD_CR48, 0x00 }, { ZD_CR49, 0x00 }, { ZD_CR51, 0x01 }, -+ { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 }, -+ { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 }, -+ { ZD_CR69, 0x28 }, -+ -+ { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, -+ { ZD_CR87, 0x0A }, { ZD_CR89, 0x04 }, -+ { ZD_CR90, 0x58 }, /* 5112 */ -+ { ZD_CR91, 0x00 }, /* 5613 */ -+ { ZD_CR92, 0x0a }, -+ { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR99, 0x00 }, { ZD_CR100, 0x02 }, { ZD_CR101, 0x13 }, -+ { ZD_CR102, 0x27 }, -+ { ZD_CR106, 0x20 }, /* change to 0x24 for AL7230B */ -+ { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR112, 0x1f }, - }; - - static const struct zd_ioreq16 ioreqs_new_phy[] = { -- { CR107, 0x28 }, -- { CR110, 0x1f }, /* 5127, 0x13->0x1f */ -- { CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ -- { CR116, 0x2a }, { CR118, 0xfa }, { CR119, 0x12 }, -- { CR121, 0x6c }, /* 5613 */ -+ { ZD_CR107, 0x28 }, -+ { ZD_CR110, 0x1f }, /* 5127, 0x13->0x1f */ -+ { ZD_CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ -+ { ZD_CR116, 0x2a }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x12 }, -+ { ZD_CR121, 0x6c }, /* 5613 */ - }; - - static const struct zd_ioreq16 ioreqs_old_phy[] = { -- { CR107, 0x24 }, -- { CR110, 0x13 }, /* 5127, 0x13->0x1f */ -- { CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ -- { CR116, 0x24 }, { CR118, 0xfc }, { CR119, 0x11 }, -- { CR121, 0x6a }, /* 5613 */ -+ { ZD_CR107, 0x24 }, -+ { ZD_CR110, 0x13 }, /* 5127, 0x13->0x1f */ -+ { ZD_CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ -+ { ZD_CR116, 0x24 }, { ZD_CR118, 0xfc }, { ZD_CR119, 0x11 }, -+ { ZD_CR121, 0x6a }, /* 5613 */ - }; - - static const struct zd_ioreq16 ioreqs_2[] = { -- { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x24 }, -- { CR117, 0xfa }, { CR120, 0x4f }, -- { CR122, 0xfc }, /* E0->FCh at 4901 */ -- { CR123, 0x57 }, /* 5613 */ -- { CR125, 0xad }, /* 4804, for 1212 new algorithm */ -- { CR126, 0x6c }, /* 5613 */ -- { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ -- { CR130, 0x10 }, -- { CR131, 0x00 }, /* 5112 */ -- { CR137, 0x50 }, /* 5613 */ -- { CR138, 0xa8 }, /* 5112 */ -- { CR144, 0xac }, /* 5613 */ -- { CR148, 0x40 }, /* 5112 */ -- { CR149, 0x40 }, /* 4O07, 50->40 */ -- { CR150, 0x1a }, /* 5112, 0C->1A */ -- { CR252, 0x34 }, { CR253, 0x34 }, -- { CR251, 0x2f }, /* PLL_OFF */ -+ { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x24 }, -+ { ZD_CR117, 0xfa }, { ZD_CR120, 0x4f }, -+ { ZD_CR122, 0xfc }, /* E0->FCh at 4901 */ -+ { ZD_CR123, 0x57 }, /* 5613 */ -+ { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR126, 0x6c }, /* 5613 */ -+ { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */ -+ { ZD_CR130, 0x10 }, -+ { ZD_CR131, 0x00 }, /* 5112 */ -+ { ZD_CR137, 0x50 }, /* 5613 */ -+ { ZD_CR138, 0xa8 }, /* 5112 */ -+ { ZD_CR144, 0xac }, /* 5613 */ -+ { ZD_CR148, 0x40 }, /* 5112 */ -+ { ZD_CR149, 0x40 }, /* 4O07, 50->40 */ -+ { ZD_CR150, 0x1a }, /* 5112, 0C->1A */ -+ { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 }, -+ { ZD_CR251, 0x2f }, /* PLL_OFF */ - }; - - static const struct zd_ioreq16 ioreqs_3[] = { -- { CR251, 0x7f }, /* PLL_ON */ -- { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, -- { CR38, 0x38 }, { CR136, 0xdf }, -+ { ZD_CR251, 0x7f }, /* PLL_ON */ -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, -+ { ZD_CR38, 0x38 }, { ZD_CR136, 0xdf }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); -@@ -331,16 +331,16 @@ - - static const struct zd_ioreq16 ioreqs[] = { - /* PLL_ON */ -- { CR251, 0x3f }, -- { CR203, 0x06 }, { CR240, 0x08 }, -+ { ZD_CR251, 0x3f }, -+ { ZD_CR203, 0x06 }, { ZD_CR240, 0x08 }, - }; - -- r = zd_iowrite16_locked(chip, 0x57, CR240); -+ r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); - if (r) - return r; - - /* PLL_OFF */ -- r = zd_iowrite16_locked(chip, 0x2f, CR251); -+ r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); - if (r) - return r; - -@@ -376,15 +376,15 @@ - const u32 *rv = chan_rv[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - -- r = zd_iowrite16_locked(chip, 0x57, CR240); -+ r = zd_iowrite16_locked(chip, 0x57, ZD_CR240); - if (r) - return r; -- r = zd_iowrite16_locked(chip, 0xe4, CR9); -+ r = zd_iowrite16_locked(chip, 0xe4, ZD_CR9); - if (r) - return r; - - /* PLL_OFF */ -- r = zd_iowrite16_locked(chip, 0x2f, CR251); -+ r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251); - if (r) - return r; - r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); -@@ -410,7 +410,7 @@ - if (r) - return r; - -- r = zd_iowrite16_locked(chip, 0x7f, CR251); -+ r = zd_iowrite16_locked(chip, 0x7f, ZD_CR251); - if (r) - return r; - -@@ -421,8 +421,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x00 }, -- { CR251, 0x3f }, -+ { ZD_CR11, 0x00 }, -+ { ZD_CR251, 0x3f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -432,8 +432,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x00 }, -- { CR251, 0x7f }, -+ { ZD_CR11, 0x00 }, -+ { ZD_CR251, 0x7f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -443,8 +443,8 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x04 }, -- { CR251, 0x2f }, -+ { ZD_CR11, 0x04 }, -+ { ZD_CR251, 0x2f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -@@ -456,7 +456,7 @@ - { - struct zd_chip *chip = zd_rf_to_chip(rf); - struct zd_ioreq16 ioreqs[] = { -- { CR128, 0x14 }, { CR129, 0x12 }, -+ { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, - }; - - /* FIXME: Channel 11 is not the edge for all regulatory domains. */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf.h ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf.h 2011-05-05 23:29:45.546442601 +0200 -@@ -55,7 +55,7 @@ - * defaults to 1 (yes) */ - u8 update_channel_int:1; - -- /* whether CR47 should be patched from the EEPROM, if the appropriate -+ /* whether ZD_CR47 should be patched from the EEPROM, if the appropriate - * flag is set in the POD. The vendor driver suggests that this should - * be done for all RF's, but a bug in their code prevents but their - * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c 2011-05-05 23:29:45.544442577 +0200 -@@ -152,44 +152,44 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { -- { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, -- { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, -- { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, -- { CR23, 0x48 }, -+ { ZD_CR2, 0x1E }, { ZD_CR9, 0x20 }, { ZD_CR10, 0x89 }, -+ { ZD_CR11, 0x00 }, { ZD_CR15, 0xD0 }, { ZD_CR17, 0x68 }, -+ { ZD_CR19, 0x4a }, { ZD_CR20, 0x0c }, { ZD_CR21, 0x0E }, -+ { ZD_CR23, 0x48 }, - /* normal size for cca threshold */ -- { CR24, 0x14 }, -- /* { CR24, 0x20 }, */ -- { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, -- { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, -- { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, -- { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, -- { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, -- { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, -- { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, -- { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, -- { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, -- /* { CR91, 0x18 }, */ -+ { ZD_CR24, 0x14 }, -+ /* { ZD_CR24, 0x20 }, */ -+ { ZD_CR26, 0x90 }, { ZD_CR27, 0x30 }, { ZD_CR29, 0x20 }, -+ { ZD_CR31, 0xb2 }, { ZD_CR32, 0x43 }, { ZD_CR33, 0x28 }, -+ { ZD_CR38, 0x30 }, { ZD_CR34, 0x0f }, { ZD_CR35, 0xF0 }, -+ { ZD_CR41, 0x2a }, { ZD_CR46, 0x7F }, { ZD_CR47, 0x1E }, -+ { ZD_CR51, 0xc5 }, { ZD_CR52, 0xc5 }, { ZD_CR53, 0xc5 }, -+ { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, -+ { ZD_CR82, 0x00 }, { ZD_CR83, 0x24 }, { ZD_CR84, 0x04 }, -+ { ZD_CR85, 0x00 }, { ZD_CR86, 0x10 }, { ZD_CR87, 0x2A }, -+ { ZD_CR88, 0x10 }, { ZD_CR89, 0x24 }, { ZD_CR90, 0x18 }, -+ /* { ZD_CR91, 0x18 }, */ - /* should solve continuous CTS frame problems */ -- { CR91, 0x00 }, -- { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, -- { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, -- { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, -- { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, -- { CR104, 0x18 }, { CR105, 0x12 }, -+ { ZD_CR91, 0x00 }, -+ { ZD_CR92, 0x0a }, { ZD_CR93, 0x00 }, { ZD_CR94, 0x01 }, -+ { ZD_CR95, 0x00 }, { ZD_CR96, 0x40 }, { ZD_CR97, 0x37 }, -+ { ZD_CR98, 0x05 }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 }, -+ { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, -+ { ZD_CR104, 0x18 }, { ZD_CR105, 0x12 }, - /* normal size */ -- { CR106, 0x1a }, -- /* { CR106, 0x22 }, */ -- { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, -- { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, -- { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, -- { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, -- { CR119, 0x16 }, -+ { ZD_CR106, 0x1a }, -+ /* { ZD_CR106, 0x22 }, */ -+ { ZD_CR107, 0x24 }, { ZD_CR108, 0x0a }, { ZD_CR109, 0x13 }, -+ { ZD_CR110, 0x2F }, { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, -+ { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x40 }, -+ { ZD_CR116, 0x40 }, { ZD_CR117, 0xF0 }, { ZD_CR118, 0xF0 }, -+ { ZD_CR119, 0x16 }, - /* no TX continuation */ -- { CR122, 0x00 }, -- /* { CR122, 0xff }, */ -- { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, -- { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, -- { CR170, 0xBB }, -+ { ZD_CR122, 0x00 }, -+ /* { ZD_CR122, 0xff }, */ -+ { ZD_CR127, 0x03 }, { ZD_CR131, 0x08 }, { ZD_CR138, 0x28 }, -+ { ZD_CR148, 0x44 }, { ZD_CR150, 0x10 }, { ZD_CR169, 0xBB }, -+ { ZD_CR170, 0xBB }, - }; - - static const u32 rv[] = { -@@ -210,7 +210,7 @@ - */ - 0x294128, /* internal power */ - /* 0x28252c, */ /* External control TX power */ -- /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ -+ /* ZD_CR31_CCK, ZD_CR51_6-36M, ZD_CR52_48M, ZD_CR53_54M */ - 0x2c0000, - 0x300000, - 0x340000, /* REG13(0xD) */ -@@ -245,8 +245,8 @@ - static int rf2959_switch_radio_on(struct zd_rf *rf) - { - static const struct zd_ioreq16 ioreqs[] = { -- { CR10, 0x89 }, -- { CR11, 0x00 }, -+ { ZD_CR10, 0x89 }, -+ { ZD_CR11, 0x00 }, - }; - struct zd_chip *chip = zd_rf_to_chip(rf); - -@@ -256,8 +256,8 @@ - static int rf2959_switch_radio_off(struct zd_rf *rf) - { - static const struct zd_ioreq16 ioreqs[] = { -- { CR10, 0x15 }, -- { CR11, 0x81 }, -+ { ZD_CR10, 0x15 }, -+ { ZD_CR11, 0x81 }, - }; - struct zd_chip *chip = zd_rf_to_chip(rf); - -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c 2011-05-05 23:29:45.552442673 +0200 -@@ -314,42 +314,44 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { -- { CR10, 0x89 }, { CR15, 0x20 }, -- { CR17, 0x28 }, /* 6112 no change */ -- { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 }, -- { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 }, -- { CR33, 0x28 }, { CR34, 0x30 }, -- { CR35, 0x43 }, /* 6112 3e->43 */ -- { CR41, 0x24 }, { CR44, 0x32 }, -- { CR46, 0x92 }, /* 6112 96->92 */ -- { CR47, 0x1e }, -- { CR48, 0x04 }, /* 5602 Roger */ -- { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 }, -- { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, -- { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d }, -- { CR99, 0x28 }, { CR100, 0x02 }, -- { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ -- { CR102, 0x27 }, -- { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */ -- { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ -- { CR109, 0x13 }, -- { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ -- { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 }, -- { CR114, 0x23 }, /* 6221 27->23 */ -- { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ -- { CR116, 0x24 }, /* 6220 1c->24 */ -- { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ -- { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ -- { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ -- { CR120, 0x4f }, -- { CR121, 0x1f }, /* 6220 4f->1f */ -- { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad }, -- { CR126, 0x6c }, { CR127, 0x03 }, -- { CR128, 0x14 }, /* 6302 12->11 */ -- { CR129, 0x12 }, /* 6301 10->0f */ -- { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 }, -- { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff }, -- { CR253, 0xff }, -+ { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, -+ { ZD_CR17, 0x28 }, /* 6112 no change */ -+ { ZD_CR23, 0x38 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, -+ { ZD_CR27, 0x15 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, -+ { ZD_CR33, 0x28 }, { ZD_CR34, 0x30 }, -+ { ZD_CR35, 0x43 }, /* 6112 3e->43 */ -+ { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, -+ { ZD_CR46, 0x92 }, /* 6112 96->92 */ -+ { ZD_CR47, 0x1e }, -+ { ZD_CR48, 0x04 }, /* 5602 Roger */ -+ { ZD_CR49, 0xfa }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, -+ { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, -+ { ZD_CR91, 0x00 }, { ZD_CR92, 0x0a }, { ZD_CR98, 0x8d }, -+ { ZD_CR99, 0x28 }, { ZD_CR100, 0x02 }, -+ { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ -+ { ZD_CR102, 0x27 }, -+ { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f -+ * 6221 1f->1c -+ */ -+ { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ -+ { ZD_CR109, 0x13 }, -+ { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ -+ { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, -+ { ZD_CR114, 0x23 }, /* 6221 27->23 */ -+ { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ -+ { ZD_CR116, 0x24 }, /* 6220 1c->24 */ -+ { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ -+ { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ -+ { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ -+ { ZD_CR120, 0x4f }, -+ { ZD_CR121, 0x1f }, /* 6220 4f->1f */ -+ { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad }, -+ { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 }, -+ { ZD_CR128, 0x14 }, /* 6302 12->11 */ -+ { ZD_CR129, 0x12 }, /* 6301 10->0f */ -+ { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 }, -+ { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff }, -+ { ZD_CR253, 0xff }, - }; - - static const u32 rv[] = { -@@ -433,7 +435,7 @@ - * the one that produced a lock. */ - UW2453_PRIV(rf)->config = found_config + 1; - -- return zd_iowrite16_locked(chip, 0x06, CR203); -+ return zd_iowrite16_locked(chip, 0x06, ZD_CR203); - } - - static int uw2453_set_channel(struct zd_rf *rf, u8 channel) -@@ -445,8 +447,8 @@ - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { -- { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, -- { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, -+ { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, -+ { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, - }; - - r = uw2453_synth_set_channel(chip, channel, autocal); -@@ -474,7 +476,7 @@ - if (r) - return r; - -- return zd_iowrite16_locked(chip, 0x06, CR203); -+ return zd_iowrite16_locked(chip, 0x06, ZD_CR203); - } - - static int uw2453_switch_radio_on(struct zd_rf *rf) -@@ -482,7 +484,7 @@ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x00 }, { CR251, 0x3f }, -+ { ZD_CR11, 0x00 }, { ZD_CR251, 0x3f }, - }; - - /* enter RXTX mode */ -@@ -501,7 +503,7 @@ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { -- { CR11, 0x04 }, { CR251, 0x2f }, -+ { ZD_CR11, 0x04 }, { ZD_CR251, 0x2f }, - }; - - /* enter IDLE mode */ -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_usb.c linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_usb.c ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_usb.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_usb.c 2011-05-05 23:29:45.552442673 +0200 -@@ -1893,10 +1893,10 @@ - - dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); - -- r = zd_usb_ioread16(usb, &bit_value_template, CR203); -+ r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203); - if (r) { - dev_dbg_f(zd_usb_dev(usb), -- "error %d: Couldn't read CR203\n", r); -+ "error %d: Couldn't read ZD_CR203\n", r); - return r; - } - bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); -diff -Naur linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_usb.h linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_usb.h ---- linux-2.6.39-rc6/drivers/net/wireless/zd1211rw/zd_usb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/net/wireless/zd1211rw/zd_usb.h 2011-05-05 23:29:45.509442155 +0200 -@@ -109,7 +109,7 @@ - __le16 bits; - /* RF2595: 24 */ - __le16 bit_values[0]; -- /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ -+ /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ - } __packed; - - /* USB interrupt */ -diff -Naur linux-2.6.39-rc6/drivers/ssb/driver_chipcommon.c linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_chipcommon.c ---- linux-2.6.39-rc6/drivers/ssb/driver_chipcommon.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_chipcommon.c 2011-05-05 23:29:49.743493311 +0200 -@@ -46,40 +46,66 @@ - if (!ccdev) - return; - bus = ccdev->bus; -+ -+ /* We support SLOW only on 6..9 */ -+ if (ccdev->id.revision >= 10 && mode == SSB_CLKMODE_SLOW) -+ mode = SSB_CLKMODE_DYNAMIC; -+ -+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) -+ return; /* PMU controls clockmode, separated function needed */ -+ SSB_WARN_ON(ccdev->id.revision >= 20); -+ - /* chipcommon cores prior to rev6 don't support dynamic clock control */ - if (ccdev->id.revision < 6) - return; -- /* chipcommon cores rev10 are a whole new ball game */ -+ -+ /* ChipCommon cores rev10+ need testing */ - if (ccdev->id.revision >= 10) - return; -+ - if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) - return; - - switch (mode) { -- case SSB_CLKMODE_SLOW: -+ case SSB_CLKMODE_SLOW: /* For revs 6..9 only */ - tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); - tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW; - chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); - break; - case SSB_CLKMODE_FAST: -- ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ -- tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); -- tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; -- tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; -- chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); -+ if (ccdev->id.revision < 10) { -+ ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ -+ tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); -+ tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; -+ tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; -+ chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); -+ } else { -+ chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, -+ (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) | -+ SSB_CHIPCO_SYSCLKCTL_FORCEHT)); -+ /* udelay(150); TODO: not available in early init */ -+ } - break; - case SSB_CLKMODE_DYNAMIC: -- tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); -- tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; -- tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; -- tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; -- if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) -- tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; -- chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); -- -- /* for dynamic control, we have to release our xtal_pu "force on" */ -- if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) -- ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); -+ if (ccdev->id.revision < 10) { -+ tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); -+ tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; -+ tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; -+ tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; -+ if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != -+ SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) -+ tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; -+ chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); -+ -+ /* For dynamic control, we have to release our xtal_pu -+ * "force on" */ -+ if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) -+ ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); -+ } else { -+ chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, -+ (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) & -+ ~SSB_CHIPCO_SYSCLKCTL_FORCEHT)); -+ } - break; - default: - SSB_WARN_ON(1); -@@ -260,6 +286,12 @@ - if (cc->dev->id.revision >= 11) - cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); - ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); -+ -+ if (cc->dev->id.revision >= 20) { -+ chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); -+ chipco_write32(cc, SSB_CHIPCO_GPIOPULLDOWN, 0); -+ } -+ - ssb_pmu_init(cc); - chipco_powercontrol_init(cc); - ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); -diff -Naur linux-2.6.39-rc6/drivers/ssb/driver_chipcommon_pmu.c linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_chipcommon_pmu.c ---- linux-2.6.39-rc6/drivers/ssb/driver_chipcommon_pmu.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_chipcommon_pmu.c 2011-05-05 23:29:49.742493299 +0200 -@@ -423,6 +423,8 @@ - - switch (bus->chip_id) { - case 0x4312: -+ min_msk = 0xCBB; -+ break; - case 0x4322: - /* We keep the default settings: - * min_msk = 0xCBB -diff -Naur linux-2.6.39-rc6/drivers/ssb/driver_pcicore.c linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_pcicore.c ---- linux-2.6.39-rc6/drivers/ssb/driver_pcicore.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/ssb/driver_pcicore.c 2011-05-05 23:29:49.767493601 +0200 -@@ -15,6 +15,13 @@ - - #include "ssb_private.h" - -+static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address); -+static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data); -+static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); -+static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, -+ u8 address, u16 data); -+ -+static void ssb_commit_settings(struct ssb_bus *bus); - - static inline - u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) -@@ -403,6 +410,107 @@ - } - #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ - -+/************************************************** -+ * Workarounds. -+ **************************************************/ -+ -+static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) -+{ -+ u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); -+ if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { -+ tmp &= ~0xF000; -+ tmp |= (pc->dev->core_index << 12); -+ pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp); -+ } -+} -+ -+static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) -+{ -+ return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; -+} -+ -+static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) -+{ -+ const u8 serdes_pll_device = 0x1D; -+ const u8 serdes_rx_device = 0x1F; -+ u16 tmp; -+ -+ ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, -+ ssb_pcicore_polarity_workaround(pc)); -+ tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); -+ if (tmp & 0x4000) -+ ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); -+} -+ -+static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc) -+{ -+ struct ssb_device *pdev = pc->dev; -+ struct ssb_bus *bus = pdev->bus; -+ u32 tmp; -+ -+ tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); -+ tmp |= SSB_PCICORE_SBTOPCI_PREF; -+ tmp |= SSB_PCICORE_SBTOPCI_BURST; -+ pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); -+ -+ if (pdev->id.revision < 5) { -+ tmp = ssb_read32(pdev, SSB_IMCFGLO); -+ tmp &= ~SSB_IMCFGLO_SERTO; -+ tmp |= 2; -+ tmp &= ~SSB_IMCFGLO_REQTO; -+ tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; -+ ssb_write32(pdev, SSB_IMCFGLO, tmp); -+ ssb_commit_settings(bus); -+ } else if (pdev->id.revision >= 11) { -+ tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); -+ tmp |= SSB_PCICORE_SBTOPCI_MRM; -+ pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); -+ } -+} -+ -+static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) -+{ -+ u32 tmp; -+ u8 rev = pc->dev->id.revision; -+ -+ if (rev == 0 || rev == 1) { -+ /* TLP Workaround register. */ -+ tmp = ssb_pcie_read(pc, 0x4); -+ tmp |= 0x8; -+ ssb_pcie_write(pc, 0x4, tmp); -+ } -+ if (rev == 1) { -+ /* DLLP Link Control register. */ -+ tmp = ssb_pcie_read(pc, 0x100); -+ tmp |= 0x40; -+ ssb_pcie_write(pc, 0x100, tmp); -+ } -+ -+ if (rev == 0) { -+ const u8 serdes_rx_device = 0x1F; -+ -+ ssb_pcie_mdio_write(pc, serdes_rx_device, -+ 2 /* Timer */, 0x8128); -+ ssb_pcie_mdio_write(pc, serdes_rx_device, -+ 6 /* CDR */, 0x0100); -+ ssb_pcie_mdio_write(pc, serdes_rx_device, -+ 7 /* CDR BW */, 0x1466); -+ } else if (rev == 3 || rev == 4 || rev == 5) { -+ /* TODO: DLLP Power Management Threshold */ -+ ssb_pcicore_serdes_workaround(pc); -+ /* TODO: ASPM */ -+ } else if (rev == 7) { -+ /* TODO: No PLL down */ -+ } -+ -+ if (rev >= 6) { -+ /* Miscellaneous Configuration Fixup */ -+ tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5)); -+ if (!(tmp & 0x8000)) -+ pcicore_write16(pc, SSB_PCICORE_SPROM(5), -+ tmp | 0x8000); -+ } -+} - - /************************************************** - * Generic and Clientmode operation code. -@@ -417,14 +525,14 @@ - void ssb_pcicore_init(struct ssb_pcicore *pc) - { - struct ssb_device *dev = pc->dev; -- struct ssb_bus *bus; - - if (!dev) - return; -- bus = dev->bus; - if (!ssb_device_is_enabled(dev)) - ssb_device_enable(dev, 0); - -+ ssb_pcicore_fix_sprom_core_index(pc); -+ - #ifdef CONFIG_SSB_PCICORE_HOSTMODE - pc->hostmode = pcicore_is_in_hostmode(pc); - if (pc->hostmode) -@@ -432,6 +540,11 @@ - #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ - if (!pc->hostmode) - ssb_pcicore_init_clientmode(pc); -+ -+ /* Additional always once-executed workarounds */ -+ ssb_pcicore_serdes_workaround(pc); -+ /* TODO: ASPM */ -+ /* TODO: Clock Request Update */ - } - - static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) -@@ -446,11 +559,75 @@ - pcicore_write32(pc, 0x134, data); - } - -+static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) -+{ -+ const u16 mdio_control = 0x128; -+ const u16 mdio_data = 0x12C; -+ u32 v; -+ int i; -+ -+ v = (1 << 30); /* Start of Transaction */ -+ v |= (1 << 28); /* Write Transaction */ -+ v |= (1 << 17); /* Turnaround */ -+ v |= (0x1F << 18); -+ v |= (phy << 4); -+ pcicore_write32(pc, mdio_data, v); -+ -+ udelay(10); -+ for (i = 0; i < 200; i++) { -+ v = pcicore_read32(pc, mdio_control); -+ if (v & 0x100 /* Trans complete */) -+ break; -+ msleep(1); -+ } -+} -+ -+static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) -+{ -+ const u16 mdio_control = 0x128; -+ const u16 mdio_data = 0x12C; -+ int max_retries = 10; -+ u16 ret = 0; -+ u32 v; -+ int i; -+ -+ v = 0x80; /* Enable Preamble Sequence */ -+ v |= 0x2; /* MDIO Clock Divisor */ -+ pcicore_write32(pc, mdio_control, v); -+ -+ if (pc->dev->id.revision >= 10) { -+ max_retries = 200; -+ ssb_pcie_mdio_set_phy(pc, device); -+ } -+ -+ v = (1 << 30); /* Start of Transaction */ -+ v |= (1 << 29); /* Read Transaction */ -+ v |= (1 << 17); /* Turnaround */ -+ if (pc->dev->id.revision < 10) -+ v |= (u32)device << 22; -+ v |= (u32)address << 18; -+ pcicore_write32(pc, mdio_data, v); -+ /* Wait for the device to complete the transaction */ -+ udelay(10); -+ for (i = 0; i < max_retries; i++) { -+ v = pcicore_read32(pc, mdio_control); -+ if (v & 0x100 /* Trans complete */) { -+ udelay(10); -+ ret = pcicore_read32(pc, mdio_data); -+ break; -+ } -+ msleep(1); -+ } -+ pcicore_write32(pc, mdio_control, 0); -+ return ret; -+} -+ - static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, - u8 address, u16 data) - { - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; -+ int max_retries = 10; - u32 v; - int i; - -@@ -458,16 +635,22 @@ - v |= 0x2; /* MDIO Clock Divisor */ - pcicore_write32(pc, mdio_control, v); - -+ if (pc->dev->id.revision >= 10) { -+ max_retries = 200; -+ ssb_pcie_mdio_set_phy(pc, device); -+ } -+ - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 28); /* Write Transaction */ - v |= (1 << 17); /* Turnaround */ -- v |= (u32)device << 22; -+ if (pc->dev->id.revision < 10) -+ v |= (u32)device << 22; - v |= (u32)address << 18; - v |= data; - pcicore_write32(pc, mdio_data, v); - /* Wait for the device to complete the transaction */ - udelay(10); -- for (i = 0; i < 10; i++) { -+ for (i = 0; i < max_retries; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) - break; -@@ -550,48 +733,10 @@ - if (pc->setup_done) - goto out; - if (pdev->id.coreid == SSB_DEV_PCI) { -- tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); -- tmp |= SSB_PCICORE_SBTOPCI_PREF; -- tmp |= SSB_PCICORE_SBTOPCI_BURST; -- pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); -- -- if (pdev->id.revision < 5) { -- tmp = ssb_read32(pdev, SSB_IMCFGLO); -- tmp &= ~SSB_IMCFGLO_SERTO; -- tmp |= 2; -- tmp &= ~SSB_IMCFGLO_REQTO; -- tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; -- ssb_write32(pdev, SSB_IMCFGLO, tmp); -- ssb_commit_settings(bus); -- } else if (pdev->id.revision >= 11) { -- tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); -- tmp |= SSB_PCICORE_SBTOPCI_MRM; -- pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); -- } -+ ssb_pcicore_pci_setup_workarounds(pc); - } else { - WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); -- //TODO: Better make defines for all these magic PCIE values. -- if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { -- /* TLP Workaround register. */ -- tmp = ssb_pcie_read(pc, 0x4); -- tmp |= 0x8; -- ssb_pcie_write(pc, 0x4, tmp); -- } -- if (pdev->id.revision == 0) { -- const u8 serdes_rx_device = 0x1F; -- -- ssb_pcie_mdio_write(pc, serdes_rx_device, -- 2 /* Timer */, 0x8128); -- ssb_pcie_mdio_write(pc, serdes_rx_device, -- 6 /* CDR */, 0x0100); -- ssb_pcie_mdio_write(pc, serdes_rx_device, -- 7 /* CDR BW */, 0x1466); -- } else if (pdev->id.revision == 1) { -- /* DLLP Link Control register. */ -- tmp = ssb_pcie_read(pc, 0x100); -- tmp |= 0x40; -- ssb_pcie_write(pc, 0x100, tmp); -- } -+ ssb_pcicore_pcie_setup_workarounds(pc); - } - pc->setup_done = 1; - out: -diff -Naur linux-2.6.39-rc6/drivers/ssb/main.c linux-2.6.39-rc6.rtl8192se/drivers/ssb/main.c ---- linux-2.6.39-rc6/drivers/ssb/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/ssb/main.c 2011-05-05 23:29:49.766493589 +0200 -@@ -1117,23 +1117,22 @@ - { - u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV; - -- /* The REJECT bit changed position in TMSLOW between -- * Backplane revisions. */ -+ /* The REJECT bit seems to be different for Backplane rev 2.3 */ - switch (rev) { - case SSB_IDLOW_SSBREV_22: -- return SSB_TMSLOW_REJECT_22; -+ case SSB_IDLOW_SSBREV_24: -+ case SSB_IDLOW_SSBREV_26: -+ return SSB_TMSLOW_REJECT; - case SSB_IDLOW_SSBREV_23: - return SSB_TMSLOW_REJECT_23; -- case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */ -- case SSB_IDLOW_SSBREV_25: /* same here */ -- case SSB_IDLOW_SSBREV_26: /* same here */ -+ case SSB_IDLOW_SSBREV_25: /* TODO - find the proper REJECT bit */ - case SSB_IDLOW_SSBREV_27: /* same here */ -- return SSB_TMSLOW_REJECT_23; /* this is a guess */ -+ return SSB_TMSLOW_REJECT; /* this is a guess */ - default: - printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); - WARN_ON(1); - } -- return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); -+ return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); - } - - int ssb_device_is_enabled(struct ssb_device *dev) -@@ -1309,20 +1308,20 @@ - - int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) - { -- struct ssb_chipcommon *cc; - int err; - enum ssb_clkmode mode; - - err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); - if (err) - goto error; -- cc = &bus->chipco; -- mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; -- ssb_chipco_set_clockmode(cc, mode); - - #ifdef CONFIG_SSB_DEBUG - bus->powered_up = 1; - #endif -+ -+ mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; -+ ssb_chipco_set_clockmode(&bus->chipco, mode); -+ - return 0; - error: - ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); -diff -Naur linux-2.6.39-rc6/drivers/ssb/scan.c linux-2.6.39-rc6.rtl8192se/drivers/ssb/scan.c ---- linux-2.6.39-rc6/drivers/ssb/scan.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/drivers/ssb/scan.c 2011-05-05 23:29:49.742493299 +0200 -@@ -307,7 +307,7 @@ - } else { - if (bus->bustype == SSB_BUSTYPE_PCI) { - bus->chip_id = pcidev_to_chipid(bus->host_pci); -- pci_read_config_word(bus->host_pci, PCI_REVISION_ID, -+ pci_read_config_byte(bus->host_pci, PCI_REVISION_ID, - &bus->chip_rev); - bus->chip_package = 0; - } else { -diff -Naur linux-2.6.39-rc6/include/linux/ath9k_platform.h linux-2.6.39-rc6.rtl8192se/include/linux/ath9k_platform.h ---- linux-2.6.39-rc6/include/linux/ath9k_platform.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/ath9k_platform.h 2011-05-05 23:30:06.514695895 +0200 -@@ -23,6 +23,13 @@ - - struct ath9k_platform_data { - u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; -+ u8 *macaddr; -+ -+ int led_pin; -+ u32 gpio_mask; -+ u32 gpio_val; -+ -+ bool is_clk_25mhz; - }; - - #endif /* _LINUX_ATH9K_PLATFORM_H */ -diff -Naur linux-2.6.39-rc6/include/linux/ieee80211.h linux-2.6.39-rc6.rtl8192se/include/linux/ieee80211.h ---- linux-2.6.39-rc6/include/linux/ieee80211.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/ieee80211.h 2011-05-05 23:30:10.326741933 +0200 -@@ -884,6 +884,15 @@ - #define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 - #define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 - -+/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ -+#define IEEE80211_HT_EXT_CAP_PCO 0x0001 -+#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 -+#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 -+#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 -+#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 -+#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 -+#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 -+ - /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ - #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 - #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C -diff -Naur linux-2.6.39-rc6/include/linux/nl80211.h linux-2.6.39-rc6.rtl8192se/include/linux/nl80211.h ---- linux-2.6.39-rc6/include/linux/nl80211.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/nl80211.h 2011-05-05 23:30:06.699698129 +0200 -@@ -410,6 +410,16 @@ - * 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 @@ - 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 @@ - /* 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 @@ - * 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 @@ - 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 @@ - * 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 @@ - NL80211_STA_FLAG_SHORT_PREAMBLE, - NL80211_STA_FLAG_WME, - NL80211_STA_FLAG_MFP, -+ NL80211_STA_FLAG_AUTHENTICATED, - - /* keep last */ - __NL80211_STA_FLAG_AFTER_LAST, -@@ -1222,6 +1242,36 @@ - }; - - /** -+ * enum nl80211_sta_bss_param - BSS information collected by STA -+ * -+ * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM -+ * when getting information about the bitrate of a station. -+ * -+ * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved -+ * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) -+ * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled -+ * (flag) -+ * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled -+ * (flag) -+ * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) -+ * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) -+ * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined -+ * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use -+ */ -+enum nl80211_sta_bss_param { -+ __NL80211_STA_BSS_PARAM_INVALID, -+ NL80211_STA_BSS_PARAM_CTS_PROT, -+ NL80211_STA_BSS_PARAM_SHORT_PREAMBLE, -+ NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME, -+ NL80211_STA_BSS_PARAM_DTIM_PERIOD, -+ NL80211_STA_BSS_PARAM_BEACON_INTERVAL, -+ -+ /* keep last */ -+ __NL80211_STA_BSS_PARAM_AFTER_LAST, -+ NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 -+}; -+ -+/** - * enum nl80211_sta_info - station information - * - * These attribute types are used with %NL80211_ATTR_STA_INFO -@@ -1233,7 +1283,7 @@ - * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) - * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute -- * containing info as possible, see &enum nl80211_sta_info_txrate. -+ * containing info as possible, see &enum nl80211_rate_info - * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) - * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this - * station) -@@ -1245,6 +1295,9 @@ - * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station - * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested - * 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 - */ -@@ -1264,6 +1317,8 @@ - NL80211_STA_INFO_TX_FAILED, - 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, -@@ -1686,9 +1741,12 @@ - * 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 -@@ -1697,7 +1755,8 @@ - __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 -Naur linux-2.6.39-rc6/include/linux/rfkill-regulator.h linux-2.6.39-rc6.rtl8192se/include/linux/rfkill-regulator.h ---- linux-2.6.39-rc6/include/linux/rfkill-regulator.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/rfkill-regulator.h 2011-05-05 23:30:05.771686923 +0200 -@@ -0,0 +1,48 @@ -+/* -+ * rfkill-regulator.c - Regulator consumer driver for rfkill -+ * -+ * Copyright (C) 2009 Guiming Zhuo -+ * Copyright (C) 2011 Antonio Ospite -+ * -+ * 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 -+ -+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 */ -diff -Naur linux-2.6.39-rc6/include/linux/ssb/ssb_driver_chipcommon.h linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb_driver_chipcommon.h ---- linux-2.6.39-rc6/include/linux/ssb/ssb_driver_chipcommon.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb_driver_chipcommon.h 2011-05-05 23:30:10.166740001 +0200 -@@ -123,6 +123,8 @@ - #define SSB_CHIPCO_FLASHDATA 0x0048 - #define SSB_CHIPCO_BCAST_ADDR 0x0050 - #define SSB_CHIPCO_BCAST_DATA 0x0054 -+#define SSB_CHIPCO_GPIOPULLUP 0x0058 /* Rev >= 20 only */ -+#define SSB_CHIPCO_GPIOPULLDOWN 0x005C /* Rev >= 20 only */ - #define SSB_CHIPCO_GPIOIN 0x0060 - #define SSB_CHIPCO_GPIOOUT 0x0064 - #define SSB_CHIPCO_GPIOOUTEN 0x0068 -@@ -131,6 +133,9 @@ - #define SSB_CHIPCO_GPIOIRQ 0x0074 - #define SSB_CHIPCO_WATCHDOG 0x0080 - #define SSB_CHIPCO_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ -+#define SSB_CHIPCO_GPIOTIMER_OFFTIME 0x0000FFFF -+#define SSB_CHIPCO_GPIOTIMER_OFFTIME_SHIFT 0 -+#define SSB_CHIPCO_GPIOTIMER_ONTIME 0xFFFF0000 - #define SSB_CHIPCO_GPIOTIMER_ONTIME_SHIFT 16 - #define SSB_CHIPCO_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ - #define SSB_CHIPCO_CLOCK_N 0x0090 -@@ -189,8 +194,10 @@ - #define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ - #define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ - #define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ --#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ --#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ -+#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ -+#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00020000 /* HT available */ -+#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ -+#define SSB_CHIPCO_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ - #define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ - #define SSB_CHIPCO_UART0_DATA 0x0300 - #define SSB_CHIPCO_UART0_IMR 0x0304 -diff -Naur linux-2.6.39-rc6/include/linux/ssb/ssb.h linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb.h ---- linux-2.6.39-rc6/include/linux/ssb/ssb.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb.h 2011-05-05 23:30:10.164739976 +0200 -@@ -308,7 +308,7 @@ - - /* ID information about the Chip. */ - u16 chip_id; -- u16 chip_rev; -+ u8 chip_rev; - u16 sprom_offset; - u16 sprom_size; /* number of words in sprom */ - u8 chip_package; -diff -Naur linux-2.6.39-rc6/include/linux/ssb/ssb_regs.h linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb_regs.h ---- linux-2.6.39-rc6/include/linux/ssb/ssb_regs.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/ssb/ssb_regs.h 2011-05-05 23:30:10.163739963 +0200 -@@ -97,7 +97,7 @@ - #define SSB_INTVEC_ENET1 0x00000040 /* Enable interrupts for enet 1 */ - #define SSB_TMSLOW 0x0F98 /* SB Target State Low */ - #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ --#define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ -+#define SSB_TMSLOW_REJECT 0x00000002 /* Reject (Standard Backplane) */ - #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ - #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ - #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ -diff -Naur linux-2.6.39-rc6/include/linux/wl12xx.h linux-2.6.39-rc6.rtl8192se/include/linux/wl12xx.h ---- linux-2.6.39-rc6/include/linux/wl12xx.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/linux/wl12xx.h 2011-05-05 23:30:08.273717139 +0200 -@@ -24,12 +24,26 @@ - #ifndef _LINUX_WL12XX_H - #define _LINUX_WL12XX_H - --/* The board reference clock values */ -+/* Reference clock values */ - enum { -- WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ -- WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ -- WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ -- WL12XX_REFCLOCK_54 = 3, /* 54 MHz */ -+ WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ -+ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ -+ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ -+ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */ -+ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */ -+ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */ -+}; -+ -+/* TCXO clock values */ -+enum { -+ WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */ -+ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */ -+ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */ -+ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */ -+ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */ -+ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */ -+ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */ -+ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */ - }; - - struct wl12xx_platform_data { -@@ -38,8 +52,13 @@ - int irq; - bool use_eeprom; - int board_ref_clock; -+ int board_tcxo_clock; -+ unsigned long platform_quirks; - }; - -+/* Platform does not support level trigger interrupts */ -+#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0) -+ - #ifdef CONFIG_WL12XX_PLATFORM_DATA - - int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); -diff -Naur linux-2.6.39-rc6/include/net/bluetooth/hci_core.h linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/hci_core.h ---- linux-2.6.39-rc6/include/net/bluetooth/hci_core.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/hci_core.h 2011-05-05 23:30:11.206752559 +0200 -@@ -82,6 +82,13 @@ - u8 pin_len; - }; - -+struct oob_data { -+ struct list_head list; -+ bdaddr_t bdaddr; -+ u8 hash[16]; -+ u8 randomizer[16]; -+}; -+ - #define NUM_REASSEMBLY 4 - struct hci_dev { - struct list_head list; -@@ -94,7 +101,8 @@ - __u8 bus; - __u8 dev_type; - bdaddr_t bdaddr; -- __u8 dev_name[248]; -+ __u8 dev_name[HCI_MAX_NAME_LENGTH]; -+ __u8 eir[HCI_MAX_EIR_LENGTH]; - __u8 dev_class[3]; - __u8 major_class; - __u8 minor_class; -@@ -118,6 +126,8 @@ - __u16 sniff_min_interval; - __u16 sniff_max_interval; - -+ unsigned int auto_accept_delay; -+ - unsigned long quirks; - - atomic_t cmd_cnt; -@@ -169,6 +179,8 @@ - - struct list_head link_keys; - -+ struct list_head remote_oob_data; -+ - struct hci_dev_stats stat; - - struct sk_buff_head driver_init; -@@ -216,6 +228,7 @@ - __u16 pkt_type; - __u16 link_policy; - __u32 link_mode; -+ __u8 key_type; - __u8 auth_type; - __u8 sec_level; - __u8 pending_sec_level; -@@ -235,6 +248,7 @@ - - struct timer_list disc_timer; - struct timer_list idle_timer; -+ struct timer_list auto_accept_timer; - - struct work_struct work_add; - struct work_struct work_del; -@@ -501,10 +515,17 @@ - - int hci_link_keys_clear(struct hci_dev *hdev); - struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); --int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, -- u8 *key, u8 type, u8 pin_len); -+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, -+ bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); - int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); - -+int hci_remote_oob_data_clear(struct hci_dev *hdev); -+struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, -+ bdaddr_t *bdaddr); -+int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, -+ u8 *randomizer); -+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); -+ - void hci_del_off_timer(struct hci_dev *hdev); - - void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); -@@ -754,19 +775,27 @@ - int mgmt_powered(u16 index, u8 powered); - int mgmt_discoverable(u16 index, u8 discoverable); - int mgmt_connectable(u16 index, u8 connectable); --int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type); -+int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); - int mgmt_connected(u16 index, bdaddr_t *bdaddr); - int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); - int mgmt_disconnect_failed(u16 index); - int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); --int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr); -+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); - int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); - int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); --int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value); -+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, -+ u8 confirm_hint); - int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); - int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, - u8 status); - int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); -+int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); -+int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, -+ u8 status); -+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, -+ u8 *eir); -+int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); -+int mgmt_discovering(u16 index, u8 discovering); - - /* HCI info for socket */ - #define hci_pi(sk) ((struct hci_pinfo *) sk) -diff -Naur linux-2.6.39-rc6/include/net/bluetooth/hci.h linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/hci.h ---- linux-2.6.39-rc6/include/net/bluetooth/hci.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/hci.h 2011-05-05 23:30:11.204752535 +0200 -@@ -246,6 +246,15 @@ - #define HCI_AT_GENERAL_BONDING 0x04 - #define HCI_AT_GENERAL_BONDING_MITM 0x05 - -+/* Link Key types */ -+#define HCI_LK_COMBINATION 0x00 -+#define HCI_LK_LOCAL_UNIT 0x01 -+#define HCI_LK_REMOTE_UNIT 0x02 -+#define HCI_LK_DEBUG_COMBINATION 0x03 -+#define HCI_LK_UNAUTH_COMBINATION 0x04 -+#define HCI_LK_AUTH_COMBINATION 0x05 -+#define HCI_LK_CHANGED_COMBINATION 0x06 -+ - /* ----- HCI Commands ---- */ - #define HCI_OP_NOP 0x0000 - -@@ -428,6 +437,18 @@ - - #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d - -+#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 -+struct hci_cp_remote_oob_data_reply { -+ bdaddr_t bdaddr; -+ __u8 hash[16]; -+ __u8 randomizer[16]; -+} __packed; -+ -+#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433 -+struct hci_cp_remote_oob_data_neg_reply { -+ bdaddr_t bdaddr; -+} __packed; -+ - #define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434 - struct hci_cp_io_capability_neg_reply { - bdaddr_t bdaddr; -@@ -537,15 +558,17 @@ - __u8 delete_all; - } __packed; - -+#define HCI_MAX_NAME_LENGTH 248 -+ - #define HCI_OP_WRITE_LOCAL_NAME 0x0c13 - struct hci_cp_write_local_name { -- __u8 name[248]; -+ __u8 name[HCI_MAX_NAME_LENGTH]; - } __packed; - - #define HCI_OP_READ_LOCAL_NAME 0x0c14 - struct hci_rp_read_local_name { - __u8 status; -- __u8 name[248]; -+ __u8 name[HCI_MAX_NAME_LENGTH]; - } __packed; - - #define HCI_OP_WRITE_CA_TIMEOUT 0x0c16 -@@ -602,6 +625,14 @@ - - #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 - -+#define HCI_MAX_EIR_LENGTH 240 -+ -+#define HCI_OP_WRITE_EIR 0x0c52 -+struct hci_cp_write_eir { -+ uint8_t fec; -+ uint8_t data[HCI_MAX_EIR_LENGTH]; -+} __packed; -+ - #define HCI_OP_READ_SSP_MODE 0x0c55 - struct hci_rp_read_ssp_mode { - __u8 status; -@@ -613,6 +644,13 @@ - __u8 mode; - } __packed; - -+#define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57 -+struct hci_rp_read_local_oob_data { -+ __u8 status; -+ __u8 hash[16]; -+ __u8 randomizer[16]; -+} __packed; -+ - #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 - - #define HCI_OP_READ_LOCAL_VERSION 0x1001 -@@ -747,7 +785,7 @@ - struct hci_ev_remote_name { - __u8 status; - bdaddr_t bdaddr; -- __u8 name[248]; -+ __u8 name[HCI_MAX_NAME_LENGTH]; - } __packed; - - #define HCI_EV_ENCRYPT_CHANGE 0x08 -@@ -955,6 +993,11 @@ - __le32 passkey; - } __packed; - -+#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 -+struct hci_ev_remote_oob_data_request { -+ bdaddr_t bdaddr; -+} __packed; -+ - #define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36 - struct hci_ev_simple_pair_complete { - __u8 status; -diff -Naur linux-2.6.39-rc6/include/net/bluetooth/l2cap.h linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/l2cap.h ---- linux-2.6.39-rc6/include/net/bluetooth/l2cap.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/l2cap.h 2011-05-05 23:30:11.206752559 +0200 -@@ -276,63 +276,17 @@ - #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 - #define L2CAP_CONN_PARAM_REJECTED 0x0001 - --/* ----- L2CAP connections ----- */ --struct l2cap_chan_list { -- struct sock *head; -- rwlock_t lock; -- long num; --}; -- --struct l2cap_conn { -- struct hci_conn *hcon; -- -- bdaddr_t *dst; -- bdaddr_t *src; -- -- unsigned int mtu; -- -- __u32 feat_mask; -- -- __u8 info_state; -- __u8 info_ident; -- -- struct timer_list info_timer; -- -- spinlock_t lock; -- -- struct sk_buff *rx_skb; -- __u32 rx_len; -- __u8 rx_ident; -- __u8 tx_ident; -- -- __u8 disc_reason; -- -- struct l2cap_chan_list chan_list; --}; -- --struct sock_del_list { -- struct sock *sk; -- struct list_head list; --}; -- --#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 ----- */ --#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) -- -+/* ----- L2CAP channels and connections ----- */ - struct srej_list { - __u8 tx_seq; - struct list_head list; - }; - --struct l2cap_pinfo { -- struct bt_sock bt; -+struct l2cap_chan { -+ struct sock *sk; -+ -+ struct l2cap_conn *conn; -+ - __le16 psm; - __u16 dcid; - __u16 scid; -@@ -341,17 +295,29 @@ - __u16 omtu; - __u16 flush_to; - __u8 mode; -- __u8 num_conf_req; -- __u8 num_conf_rsp; - -- __u8 fcs; -+ __le16 sport; -+ - __u8 sec_level; - __u8 role_switch; - __u8 force_reliable; - __u8 flushable; - -+ __u8 ident; -+ - __u8 conf_req[64]; - __u8 conf_len; -+ __u8 num_conf_req; -+ __u8 num_conf_rsp; -+ -+ __u8 fcs; -+ -+ __u8 tx_win; -+ __u8 max_tx; -+ __u16 retrans_timeout; -+ __u16 monitor_timeout; -+ __u16 mps; -+ - __u8 conf_state; - __u16 conn_state; - -@@ -369,30 +335,60 @@ - __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 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 srej_list srej_l; -- struct l2cap_conn *conn; -- struct sock *next_c; -- struct sock *prev_c; -+ struct list_head srej_l; -+ -+ struct list_head list; -+}; -+ -+struct l2cap_conn { -+ struct hci_conn *hcon; -+ -+ bdaddr_t *dst; -+ bdaddr_t *src; -+ -+ unsigned int mtu; -+ -+ __u32 feat_mask; -+ -+ __u8 info_state; -+ __u8 info_ident; -+ -+ struct timer_list info_timer; -+ -+ spinlock_t lock; -+ -+ struct sk_buff *rx_skb; -+ __u32 rx_len; -+ __u8 tx_ident; -+ -+ __u8 disc_reason; -+ -+ 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 socket info ----- */ -+#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) -+ -+struct l2cap_pinfo { -+ struct bt_sock bt; -+ struct l2cap_chan *chan; - }; - - #define L2CAP_CONF_REQ_SENT 0x01 -@@ -419,24 +415,23 @@ - #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) -@@ -446,24 +441,22 @@ - #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) - - extern int disable_ertm; --extern const struct proto_ops l2cap_sock_ops; - 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 l2cap_chan *chan); - 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); --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); -+struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); -+struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); -+struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); -+int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); -+void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); -+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); -@@ -472,8 +465,10 @@ - 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); --int l2cap_do_connect(struct sock *sk); -+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); -+struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); -+void l2cap_chan_del(struct l2cap_chan *chan, int err); -+void l2cap_chan_free(struct l2cap_chan *chan); -+int l2cap_chan_connect(struct l2cap_chan *chan); - - #endif /* __L2CAP_H */ -diff -Naur linux-2.6.39-rc6/include/net/bluetooth/mgmt.h linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/mgmt.h ---- linux-2.6.39-rc6/include/net/bluetooth/mgmt.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/bluetooth/mgmt.h 2011-05-05 23:30:11.208752583 +0200 -@@ -41,6 +41,10 @@ - __le16 index[0]; - } __packed; - -+/* Reserve one extra byte for names in management messages so that they -+ * are always guaranteed to be nul-terminated */ -+#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) -+ - #define MGMT_OP_READ_INFO 0x0004 - struct mgmt_rp_read_info { - __u8 type; -@@ -55,6 +59,7 @@ - __u16 manufacturer; - __u8 hci_ver; - __u16 hci_rev; -+ __u8 name[MGMT_MAX_NAME_LENGTH]; - } __packed; - - struct mgmt_mode { -@@ -167,6 +172,33 @@ - - #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 - -+#define MGMT_OP_SET_LOCAL_NAME 0x0017 -+struct mgmt_cp_set_local_name { -+ __u8 name[MGMT_MAX_NAME_LENGTH]; -+} __packed; -+ -+#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 -+struct mgmt_rp_read_local_oob_data { -+ __u8 hash[16]; -+ __u8 randomizer[16]; -+} __packed; -+ -+#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 -+struct mgmt_cp_add_remote_oob_data { -+ bdaddr_t bdaddr; -+ __u8 hash[16]; -+ __u8 randomizer[16]; -+} __packed; -+ -+#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A -+struct mgmt_cp_remove_remote_oob_data { -+ bdaddr_t bdaddr; -+} __packed; -+ -+#define MGMT_OP_START_DISCOVERY 0x001B -+ -+#define MGMT_OP_STOP_DISCOVERY 0x001C -+ - #define MGMT_EV_CMD_COMPLETE 0x0001 - struct mgmt_ev_cmd_complete { - __le16 opcode; -@@ -198,8 +230,8 @@ - - #define MGMT_EV_NEW_KEY 0x000A - struct mgmt_ev_new_key { -+ __u8 store_hint; - struct mgmt_key_info key; -- __u8 old_key_type; - } __packed; - - #define MGMT_EV_CONNECTED 0x000B -@@ -221,11 +253,13 @@ - #define MGMT_EV_PIN_CODE_REQUEST 0x000E - struct mgmt_ev_pin_code_request { - bdaddr_t bdaddr; -+ __u8 secure; - } __packed; - - #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F - struct mgmt_ev_user_confirm_request { - bdaddr_t bdaddr; -+ __u8 confirm_hint; - __le32 value; - } __packed; - -@@ -234,3 +268,24 @@ - bdaddr_t bdaddr; - __u8 status; - } __packed; -+ -+#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 -+struct mgmt_ev_local_name_changed { -+ __u8 name[MGMT_MAX_NAME_LENGTH]; -+} __packed; -+ -+#define MGMT_EV_DEVICE_FOUND 0x0012 -+struct mgmt_ev_device_found { -+ bdaddr_t bdaddr; -+ __u8 dev_class[3]; -+ __s8 rssi; -+ __u8 eir[HCI_MAX_EIR_LENGTH]; -+} __packed; -+ -+#define MGMT_EV_REMOTE_NAME 0x0013 -+struct mgmt_ev_remote_name { -+ bdaddr_t bdaddr; -+ __u8 name[MGMT_MAX_NAME_LENGTH]; -+} __packed; -+ -+#define MGMT_EV_DISCOVERING 0x0014 -diff -Naur linux-2.6.39-rc6/include/net/cfg80211.h linux-2.6.39-rc6.rtl8192se/include/net/cfg80211.h ---- linux-2.6.39-rc6/include/net/cfg80211.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/cfg80211.h 2011-05-05 23:30:11.179752233 +0200 -@@ -422,6 +422,8 @@ - * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled - * @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, -@@ -439,6 +441,8 @@ - STATION_INFO_RX_DROP_MISC = 1<<12, - STATION_INFO_SIGNAL_AVG = 1<<13, - STATION_INFO_RX_BITRATE = 1<<14, -+ STATION_INFO_BSS_PARAM = 1<<15, -+ STATION_INFO_CONNECTED_TIME = 1<<16 - }; - - /** -@@ -473,11 +477,43 @@ - }; - - /** -+ * enum station_info_rate_flags - bitrate info flags -+ * -+ * Used by the driver to indicate the specific rate transmission -+ * type for 802.11n transmissions. -+ * -+ * @BSS_PARAM_FLAGS_CTS_PROT: whether CTS protection is enabled -+ * @BSS_PARAM_FLAGS_SHORT_PREAMBLE: whether short preamble is enabled -+ * @BSS_PARAM_FLAGS_SHORT_SLOT_TIME: whether short slot time is enabled -+ */ -+enum bss_param_flags { -+ BSS_PARAM_FLAGS_CTS_PROT = 1<<0, -+ BSS_PARAM_FLAGS_SHORT_PREAMBLE = 1<<1, -+ BSS_PARAM_FLAGS_SHORT_SLOT_TIME = 1<<2, -+}; -+ -+/** -+ * struct sta_bss_parameters - BSS parameters for the attached station -+ * -+ * Information about the currently associated BSS -+ * -+ * @flags: bitflag of flags from &enum bss_param_flags -+ * @dtim_period: DTIM period for the BSS -+ * @beacon_interval: beacon interval -+ */ -+struct sta_bss_parameters { -+ u8 flags; -+ u8 dtim_period; -+ u16 beacon_interval; -+}; -+ -+/** - * struct station_info - station information - * - * 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 -@@ -500,6 +536,7 @@ - */ - struct station_info { - u32 filled; -+ u32 connected_time; - u32 inactive_time; - u32 rx_bytes; - u32 tx_bytes; -@@ -515,6 +552,7 @@ - u32 tx_retries; - u32 tx_failed; - u32 rx_dropped_misc; -+ struct sta_bss_parameters bss_param; - - int generation; - }; -@@ -655,8 +693,9 @@ - * @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. - */ -@@ -665,8 +704,9 @@ - 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; - }; - - /** -@@ -1417,6 +1457,8 @@ - * @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), -@@ -1429,6 +1471,7 @@ - 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 { -@@ -2450,6 +2493,22 @@ - 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 - * - * RFkill integration in cfg80211 is almost invisible to drivers, -@@ -2667,6 +2726,15 @@ - struct station_info *sinfo, gfp_t gfp); - - /** -+ * cfg80211_del_sta - notify userspace about deletion of a station -+ * -+ * @dev: the netdev -+ * @mac_addr: the station's address -+ * @gfp: allocation flags -+ */ -+void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); -+ -+/** - * cfg80211_rx_mgmt - notification of received, unprocessed management frame - * @dev: network device - * @freq: Frequency on which the frame was received in MHz -diff -Naur linux-2.6.39-rc6/include/net/mac80211.h linux-2.6.39-rc6.rtl8192se/include/net/mac80211.h ---- linux-2.6.39-rc6/include/net/mac80211.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/include/net/mac80211.h 2011-05-05 23:30:11.138751739 +0200 -@@ -1819,6 +1819,13 @@ - * @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. -+ * -+ * @set_bitrate_mask: Set a mask of rates to be used for rate control selection -+ * when transmitting a frame. Currently only legacy rates are handled. -+ * The callback can sleep. - */ - struct ieee80211_ops { - void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); -@@ -1906,6 +1913,9 @@ - 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); -+ int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, -+ const struct cfg80211_bitrate_mask *mask); - }; - - /** -@@ -2223,6 +2233,18 @@ - #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 - * - * Call this function for all transmitted frames after they have been -@@ -2276,6 +2298,17 @@ - struct sk_buff *skb); - - /** -+ * ieee80211_report_low_ack - report non-responding station -+ * -+ * When operating in AP-mode, call this function to report a non-responding -+ * connected STA. -+ * -+ * @sta: the non-responding connected sta -+ * @num_packets: number of packets sent to @sta without a response -+ */ -+void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); -+ -+/** - * ieee80211_beacon_get_tim - beacon generation function - * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from the add_interface callback. -diff -Naur linux-2.6.39-rc6/localversion-wireless linux-2.6.39-rc6.rtl8192se/localversion-wireless ---- linux-2.6.39-rc6/localversion-wireless 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/localversion-wireless 2011-05-05 23:30:24.120908487 +0200 -@@ -0,0 +1 @@ -+-wl -diff -Naur linux-2.6.39-rc6/MAINTAINERS linux-2.6.39-rc6.rtl8192se/MAINTAINERS ---- linux-2.6.39-rc6/MAINTAINERS 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/MAINTAINERS 2011-05-05 23:30:02.149643175 +0200 -@@ -1232,13 +1232,6 @@ - S: Supported - F: drivers/net/wireless/ath/ath9k/ - --ATHEROS AR9170 WIRELESS DRIVER --M: Christian Lamparter --L: linux-wireless@vger.kernel.org --W: http://wireless.kernel.org/en/users/Drivers/ar9170 --S: Obsolete --F: drivers/net/wireless/ath/ar9170/ -- - CARL9170 LINUX COMMUNITY WIRELESS DRIVER - M: Christian Lamparter - L: linux-wireless@vger.kernel.org -@@ -3362,6 +3355,12 @@ - F: drivers/net/wimax/i2400m/ - F: include/linux/wimax/i2400m.h - -+INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy) -+M: Stanislaw Gruszka -+L: linux-wireless@vger.kernel.org -+S: Supported -+F: drivers/net/wireless/iwlegacy/ -+ - INTEL WIRELESS WIFI LINK (iwlwifi) - M: Wey-Yi Guy - M: Intel Linux Wireless -diff -Naur linux-2.6.39-rc6/net/bluetooth/bnep/bnep.h linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/bnep.h ---- linux-2.6.39-rc6/net/bluetooth/bnep/bnep.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/bnep.h 2011-05-05 23:30:21.223873511 +0200 -@@ -23,88 +23,88 @@ - #include - #include - --// Limits --#define BNEP_MAX_PROTO_FILTERS 5 --#define BNEP_MAX_MULTICAST_FILTERS 20 -- --// UUIDs --#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB --#define BNEP_UUID16 0x02 --#define BNEP_UUID32 0x04 --#define BNEP_UUID128 0x16 -- --#define BNEP_SVC_PANU 0x1115 --#define BNEP_SVC_NAP 0x1116 --#define BNEP_SVC_GN 0x1117 -- --// Packet types --#define BNEP_GENERAL 0x00 --#define BNEP_CONTROL 0x01 --#define BNEP_COMPRESSED 0x02 --#define BNEP_COMPRESSED_SRC_ONLY 0x03 --#define BNEP_COMPRESSED_DST_ONLY 0x04 -- --// Control types --#define BNEP_CMD_NOT_UNDERSTOOD 0x00 --#define BNEP_SETUP_CONN_REQ 0x01 --#define BNEP_SETUP_CONN_RSP 0x02 --#define BNEP_FILTER_NET_TYPE_SET 0x03 --#define BNEP_FILTER_NET_TYPE_RSP 0x04 --#define BNEP_FILTER_MULTI_ADDR_SET 0x05 --#define BNEP_FILTER_MULTI_ADDR_RSP 0x06 -- --// Extension types --#define BNEP_EXT_CONTROL 0x00 -- --// Response messages --#define BNEP_SUCCESS 0x00 -- --#define BNEP_CONN_INVALID_DST 0x01 --#define BNEP_CONN_INVALID_SRC 0x02 --#define BNEP_CONN_INVALID_SVC 0x03 --#define BNEP_CONN_NOT_ALLOWED 0x04 -- --#define BNEP_FILTER_UNSUPPORTED_REQ 0x01 --#define BNEP_FILTER_INVALID_RANGE 0x02 --#define BNEP_FILTER_INVALID_MCADDR 0x02 --#define BNEP_FILTER_LIMIT_REACHED 0x03 --#define BNEP_FILTER_DENIED_SECURITY 0x04 -- --// L2CAP settings --#define BNEP_MTU 1691 --#define BNEP_PSM 0x0f --#define BNEP_FLUSH_TO 0xffff --#define BNEP_CONNECT_TO 15 --#define BNEP_FILTER_TO 15 -- --// Headers --#define BNEP_TYPE_MASK 0x7f --#define BNEP_EXT_HEADER 0x80 -+/* Limits */ -+#define BNEP_MAX_PROTO_FILTERS 5 -+#define BNEP_MAX_MULTICAST_FILTERS 20 -+ -+/* UUIDs */ -+#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB -+#define BNEP_UUID16 0x02 -+#define BNEP_UUID32 0x04 -+#define BNEP_UUID128 0x16 -+ -+#define BNEP_SVC_PANU 0x1115 -+#define BNEP_SVC_NAP 0x1116 -+#define BNEP_SVC_GN 0x1117 -+ -+/* Packet types */ -+#define BNEP_GENERAL 0x00 -+#define BNEP_CONTROL 0x01 -+#define BNEP_COMPRESSED 0x02 -+#define BNEP_COMPRESSED_SRC_ONLY 0x03 -+#define BNEP_COMPRESSED_DST_ONLY 0x04 -+ -+/* Control types */ -+#define BNEP_CMD_NOT_UNDERSTOOD 0x00 -+#define BNEP_SETUP_CONN_REQ 0x01 -+#define BNEP_SETUP_CONN_RSP 0x02 -+#define BNEP_FILTER_NET_TYPE_SET 0x03 -+#define BNEP_FILTER_NET_TYPE_RSP 0x04 -+#define BNEP_FILTER_MULTI_ADDR_SET 0x05 -+#define BNEP_FILTER_MULTI_ADDR_RSP 0x06 -+ -+/* Extension types */ -+#define BNEP_EXT_CONTROL 0x00 -+ -+/* Response messages */ -+#define BNEP_SUCCESS 0x00 -+ -+#define BNEP_CONN_INVALID_DST 0x01 -+#define BNEP_CONN_INVALID_SRC 0x02 -+#define BNEP_CONN_INVALID_SVC 0x03 -+#define BNEP_CONN_NOT_ALLOWED 0x04 -+ -+#define BNEP_FILTER_UNSUPPORTED_REQ 0x01 -+#define BNEP_FILTER_INVALID_RANGE 0x02 -+#define BNEP_FILTER_INVALID_MCADDR 0x02 -+#define BNEP_FILTER_LIMIT_REACHED 0x03 -+#define BNEP_FILTER_DENIED_SECURITY 0x04 -+ -+/* L2CAP settings */ -+#define BNEP_MTU 1691 -+#define BNEP_PSM 0x0f -+#define BNEP_FLUSH_TO 0xffff -+#define BNEP_CONNECT_TO 15 -+#define BNEP_FILTER_TO 15 -+ -+/* Headers */ -+#define BNEP_TYPE_MASK 0x7f -+#define BNEP_EXT_HEADER 0x80 - - struct bnep_setup_conn_req { -- __u8 type; -- __u8 ctrl; -- __u8 uuid_size; -- __u8 service[0]; -+ __u8 type; -+ __u8 ctrl; -+ __u8 uuid_size; -+ __u8 service[0]; - } __packed; - - struct bnep_set_filter_req { -- __u8 type; -- __u8 ctrl; -+ __u8 type; -+ __u8 ctrl; - __be16 len; -- __u8 list[0]; -+ __u8 list[0]; - } __packed; - - struct bnep_control_rsp { -- __u8 type; -- __u8 ctrl; -+ __u8 type; -+ __u8 ctrl; - __be16 resp; - } __packed; - - struct bnep_ext_hdr { -- __u8 type; -- __u8 len; -- __u8 data[0]; -+ __u8 type; -+ __u8 len; -+ __u8 data[0]; - } __packed; - - /* BNEP ioctl defines */ -@@ -114,10 +114,10 @@ - #define BNEPGETCONNINFO _IOR('B', 211, int) - - struct bnep_connadd_req { -- int sock; // Connected socket -+ int sock; /* Connected socket */ - __u32 flags; - __u16 role; -- char device[16]; // Name of the Ethernet device -+ char device[16]; /* Name of the Ethernet device */ - }; - - struct bnep_conndel_req { -@@ -148,14 +148,14 @@ - int bnep_get_connlist(struct bnep_connlist_req *req); - int bnep_get_conninfo(struct bnep_conninfo *ci); - --// BNEP sessions -+/* BNEP sessions */ - struct bnep_session { - struct list_head list; - - unsigned int role; - unsigned long state; - unsigned long flags; -- atomic_t killed; -+ struct task_struct *task; - - struct ethhdr eh; - struct msghdr msg; -@@ -173,7 +173,7 @@ - - static inline int bnep_mc_hash(__u8 *addr) - { -- return (crc32_be(~0, addr, ETH_ALEN) >> 26); -+ return crc32_be(~0, addr, ETH_ALEN) >> 26; - } - - #endif -diff -Naur linux-2.6.39-rc6/net/bluetooth/bnep/core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/core.c ---- linux-2.6.39-rc6/net/bluetooth/bnep/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/core.c 2011-05-05 23:30:21.223873511 +0200 -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -131,7 +132,8 @@ - return -EILSEQ; - - n = get_unaligned_be16(data); -- data++; len -= 2; -+ data++; -+ len -= 2; - - if (len < n) - return -EILSEQ; -@@ -176,7 +178,8 @@ - return -EILSEQ; - - n = get_unaligned_be16(data); -- data += 2; len -= 2; -+ data += 2; -+ len -= 2; - - if (len < n) - return -EILSEQ; -@@ -187,6 +190,8 @@ - n /= (ETH_ALEN * 2); - - if (n > 0) { -+ int i; -+ - s->mc_filter = 0; - - /* Always send broadcast */ -@@ -196,18 +201,22 @@ - for (; n > 0; n--) { - u8 a1[6], *a2; - -- memcpy(a1, data, ETH_ALEN); data += ETH_ALEN; -- a2 = data; data += ETH_ALEN; -+ memcpy(a1, data, ETH_ALEN); -+ data += ETH_ALEN; -+ a2 = data; -+ data += ETH_ALEN; - - BT_DBG("mc filter %s -> %s", - batostr((void *) a1), batostr((void *) a2)); - -- #define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); } -- - /* Iterate from a1 to a2 */ - set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); - while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) { -- INCA(a1); -+ /* Increment a1 */ -+ i = 5; -+ while (i >= 0 && ++a1[i--] == 0) -+ ; -+ - set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); - } - } -@@ -227,7 +236,8 @@ - u8 cmd = *(u8 *)data; - int err = 0; - -- data++; len--; -+ data++; -+ len--; - - switch (cmd) { - case BNEP_CMD_NOT_UNDERSTOOD: -@@ -302,7 +312,6 @@ - ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */ - ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ - }; --#define BNEP_RX_TYPES (sizeof(__bnep_rx_hlen) - 1) - - static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) - { -@@ -312,9 +321,10 @@ - - dev->stats.rx_bytes += skb->len; - -- type = *(u8 *) skb->data; skb_pull(skb, 1); -+ type = *(u8 *) skb->data; -+ skb_pull(skb, 1); - -- if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES) -+ if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) - goto badframe; - - if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { -@@ -367,14 +377,14 @@ - - case BNEP_COMPRESSED_DST_ONLY: - memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), -- ETH_ALEN); -+ ETH_ALEN); - memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, -- ETH_ALEN + 2); -+ ETH_ALEN + 2); - break; - - case BNEP_GENERAL: - memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), -- ETH_ALEN * 2); -+ ETH_ALEN * 2); - put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); - break; - } -@@ -470,15 +480,14 @@ - - BT_DBG(""); - -- daemonize("kbnepd %s", dev->name); - set_user_nice(current, -15); - - init_waitqueue_entry(&wait, current); - add_wait_queue(sk_sleep(sk), &wait); -- while (!atomic_read(&s->killed)) { -+ while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - -- // RX -+ /* RX */ - while ((skb = skb_dequeue(&sk->sk_receive_queue))) { - skb_orphan(skb); - bnep_rx_frame(s, skb); -@@ -487,7 +496,7 @@ - if (sk->sk_state != BT_CONNECTED) - break; - -- // TX -+ /* TX */ - while ((skb = skb_dequeue(&sk->sk_write_queue))) - if (bnep_tx_frame(s, skb)) - break; -@@ -555,8 +564,8 @@ - - /* session struct allocated as private part of net_device */ - dev = alloc_netdev(sizeof(struct bnep_session), -- (*req->device) ? req->device : "bnep%d", -- bnep_net_setup); -+ (*req->device) ? req->device : "bnep%d", -+ bnep_net_setup); - if (!dev) - return -ENOMEM; - -@@ -571,7 +580,7 @@ - s = netdev_priv(dev); - - /* This is rx header therefore addresses are swapped. -- * ie eh.h_dest is our local address. */ -+ * ie. eh.h_dest is our local address. */ - memcpy(s->eh.h_dest, &src, ETH_ALEN); - memcpy(s->eh.h_source, &dst, ETH_ALEN); - memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); -@@ -597,17 +606,17 @@ - SET_NETDEV_DEVTYPE(dev, &bnep_type); - - err = register_netdev(dev); -- if (err) { -+ if (err) - goto failed; -- } - - __bnep_link_session(s); - -- err = kernel_thread(bnep_session, s, CLONE_KERNEL); -- if (err < 0) { -+ s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); -+ if (IS_ERR(s->task)) { - /* Session thread start failed, gotta cleanup. */ - unregister_netdev(dev); - __bnep_unlink_session(s); -+ err = PTR_ERR(s->task); - goto failed; - } - -@@ -631,15 +640,9 @@ - down_read(&bnep_session_sem); - - s = __bnep_get_session(req->dst); -- if (s) { -- /* Wakeup user-space which is polling for socket errors. -- * This is temporary hack until we have shutdown in L2CAP */ -- s->sock->sk->sk_err = EUNATCH; -- -- /* Kill session thread */ -- atomic_inc(&s->killed); -- wake_up_interruptible(sk_sleep(s->sock->sk)); -- } else -+ if (s) -+ kthread_stop(s->task); -+ else - err = -ENOENT; - - up_read(&bnep_session_sem); -diff -Naur linux-2.6.39-rc6/net/bluetooth/bnep/sock.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/sock.c ---- linux-2.6.39-rc6/net/bluetooth/bnep/sock.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/bnep/sock.c 2011-05-05 23:30:21.224873524 +0200 -@@ -39,10 +39,10 @@ - #include - #include - #include -+#include - #include - - #include --#include - - #include "bnep.h" - -diff -Naur linux-2.6.39-rc6/net/bluetooth/cmtp/capi.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/capi.c ---- linux-2.6.39-rc6/net/bluetooth/cmtp/capi.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/capi.c 2011-05-05 23:30:21.234873645 +0200 -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -143,7 +144,7 @@ - - skb_queue_tail(&session->transmit, skb); - -- cmtp_schedule(session); -+ wake_up_interruptible(sk_sleep(session->sock->sk)); - } - - static void cmtp_send_interopmsg(struct cmtp_session *session, -@@ -386,8 +387,7 @@ - - capi_ctr_down(ctrl); - -- atomic_inc(&session->terminate); -- cmtp_schedule(session); -+ kthread_stop(session->task); - } - - static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) -diff -Naur linux-2.6.39-rc6/net/bluetooth/cmtp/cmtp.h linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/cmtp.h ---- linux-2.6.39-rc6/net/bluetooth/cmtp/cmtp.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/cmtp.h 2011-05-05 23:30:21.235873657 +0200 -@@ -37,7 +37,7 @@ - #define CMTP_LOOPBACK 0 - - struct cmtp_connadd_req { -- int sock; // Connected socket -+ int sock; /* Connected socket */ - __u32 flags; - }; - -@@ -81,7 +81,7 @@ - - char name[BTNAMSIZ]; - -- atomic_t terminate; -+ struct task_struct *task; - - wait_queue_head_t wait; - -@@ -121,13 +121,6 @@ - - void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb); - --static inline void cmtp_schedule(struct cmtp_session *session) --{ -- struct sock *sk = session->sock->sk; -- -- wake_up_interruptible(sk_sleep(sk)); --} -- - /* CMTP init defines */ - int cmtp_init_sockets(void); - void cmtp_cleanup_sockets(void); -diff -Naur linux-2.6.39-rc6/net/bluetooth/cmtp/core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/core.c ---- linux-2.6.39-rc6/net/bluetooth/cmtp/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/core.c 2011-05-05 23:30:21.234873645 +0200 -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -235,9 +236,12 @@ - - size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len); - -- if ((scb->id < 0) && ((scb->id = cmtp_alloc_block_id(session)) < 0)) { -- skb_queue_head(&session->transmit, skb); -- break; -+ if (scb->id < 0) { -+ scb->id = cmtp_alloc_block_id(session); -+ if (scb->id < 0) { -+ skb_queue_head(&session->transmit, skb); -+ break; -+ } - } - - if (size < 256) { -@@ -284,12 +288,11 @@ - - BT_DBG("session %p", session); - -- daemonize("kcmtpd_ctr_%d", session->num); - set_user_nice(current, -15); - - init_waitqueue_entry(&wait, current); - add_wait_queue(sk_sleep(sk), &wait); -- while (!atomic_read(&session->terminate)) { -+ while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - - if (sk->sk_state != BT_CONNECTED) -@@ -343,7 +346,8 @@ - - bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst); - -- session->mtu = min_t(uint, l2cap_pi(sock->sk)->omtu, l2cap_pi(sock->sk)->imtu); -+ session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, -+ l2cap_pi(sock->sk)->chan->imtu); - - BT_DBG("mtu %d", session->mtu); - -@@ -367,9 +371,12 @@ - - __cmtp_link_session(session); - -- err = kernel_thread(cmtp_session, session, CLONE_KERNEL); -- if (err < 0) -+ session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", -+ session->num); -+ if (IS_ERR(session->task)) { -+ err = PTR_ERR(session->task); - goto unlink; -+ } - - if (!(session->flags & (1 << CMTP_LOOPBACK))) { - err = cmtp_attach_device(session); -@@ -406,9 +413,8 @@ - /* Flush the transmit queue */ - skb_queue_purge(&session->transmit); - -- /* Kill session thread */ -- atomic_inc(&session->terminate); -- cmtp_schedule(session); -+ /* Stop session thread */ -+ kthread_stop(session->task); - } else - err = -ENOENT; - -diff -Naur linux-2.6.39-rc6/net/bluetooth/cmtp/sock.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/sock.c ---- linux-2.6.39-rc6/net/bluetooth/cmtp/sock.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/cmtp/sock.c 2011-05-05 23:30:21.236873669 +0200 -@@ -34,12 +34,12 @@ - #include - #include - #include -+#include - #include - - #include - - #include --#include - - #include "cmtp.h" - -diff -Naur linux-2.6.39-rc6/net/bluetooth/hci_conn.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_conn.c ---- linux-2.6.39-rc6/net/bluetooth/hci_conn.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_conn.c 2011-05-05 23:30:21.242873741 +0200 -@@ -269,6 +269,19 @@ - hci_conn_enter_sniff_mode(conn); - } - -+static void hci_conn_auto_accept(unsigned long arg) -+{ -+ struct hci_conn *conn = (void *) arg; -+ struct hci_dev *hdev = conn->hdev; -+ -+ hci_dev_lock(hdev); -+ -+ hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), -+ &conn->dst); -+ -+ hci_dev_unlock(hdev); -+} -+ - struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) - { - struct hci_conn *conn; -@@ -287,6 +300,7 @@ - conn->auth_type = HCI_AT_GENERAL_BONDING; - conn->io_capability = hdev->io_capability; - conn->remote_auth = 0xff; -+ conn->key_type = 0xff; - - conn->power_save = 1; - conn->disc_timeout = HCI_DISCONN_TIMEOUT; -@@ -311,6 +325,8 @@ - - setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); - setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); -+ setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, -+ (unsigned long) conn); - - atomic_set(&conn->refcnt, 0); - -@@ -341,6 +357,8 @@ - - del_timer(&conn->disc_timer); - -+ del_timer(&conn->auto_accept_timer); -+ - if (conn->type == ACL_LINK) { - struct hci_conn *sco = conn->link; - if (sco) -@@ -535,32 +553,72 @@ - return 0; - } - -+/* Encrypt the the link */ -+static void hci_conn_encrypt(struct hci_conn *conn) -+{ -+ BT_DBG("conn %p", conn); -+ -+ if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { -+ struct hci_cp_set_conn_encrypt cp; -+ cp.handle = cpu_to_le16(conn->handle); -+ cp.encrypt = 0x01; -+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), -+ &cp); -+ } -+} -+ - /* Enable security */ - int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) - { - BT_DBG("conn %p", conn); - -+ /* For sdp we don't need the link key. */ - if (sec_level == BT_SECURITY_SDP) - return 1; - -+ /* For non 2.1 devices and low security level we don't need the link -+ key. */ - if (sec_level == BT_SECURITY_LOW && - (!conn->ssp_mode || !conn->hdev->ssp_mode)) - return 1; - -- if (conn->link_mode & HCI_LM_ENCRYPT) -- return hci_conn_auth(conn, sec_level, auth_type); -+ /* For other security levels we need the link key. */ -+ if (!(conn->link_mode & HCI_LM_AUTH)) -+ goto auth; -+ -+ /* An authenticated combination key has sufficient security for any -+ security level. */ -+ if (conn->key_type == HCI_LK_AUTH_COMBINATION) -+ goto encrypt; -+ -+ /* An unauthenticated combination key has sufficient security for -+ security level 1 and 2. */ -+ if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && -+ (sec_level == BT_SECURITY_MEDIUM || -+ sec_level == BT_SECURITY_LOW)) -+ goto encrypt; -+ -+ /* A combination key has always sufficient security for the security -+ levels 1 or 2. High security level requires the combination key -+ is generated using maximum PIN code length (16). -+ For pre 2.1 units. */ -+ if (conn->key_type == HCI_LK_COMBINATION && -+ (sec_level != BT_SECURITY_HIGH || -+ conn->pin_length == 16)) -+ goto encrypt; - -+auth: - if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) - return 0; - -- if (hci_conn_auth(conn, sec_level, auth_type)) { -- struct hci_cp_set_conn_encrypt cp; -- cp.handle = cpu_to_le16(conn->handle); -- cp.encrypt = 1; -- hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, -- sizeof(cp), &cp); -- } -+ hci_conn_auth(conn, sec_level, auth_type); -+ return 0; -+ -+encrypt: -+ if (conn->link_mode & HCI_LM_ENCRYPT) -+ return 1; - -+ hci_conn_encrypt(conn); - return 0; - } - EXPORT_SYMBOL(hci_conn_security); -diff -Naur linux-2.6.39-rc6/net/bluetooth/hci_core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_core.c ---- linux-2.6.39-rc6/net/bluetooth/hci_core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_core.c 2011-05-05 23:30:21.226873549 +0200 -@@ -56,7 +56,6 @@ - static void hci_cmd_task(unsigned long arg); - static void hci_rx_task(unsigned long arg); - static void hci_tx_task(unsigned long arg); --static void hci_notify(struct hci_dev *hdev, int event); - - static DEFINE_RWLOCK(hci_task_lock); - -@@ -1021,18 +1020,54 @@ - return NULL; - } - --int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, -- u8 *val, u8 type, u8 pin_len) -+static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, -+ u8 key_type, u8 old_key_type) -+{ -+ /* Legacy key */ -+ if (key_type < 0x03) -+ return 1; -+ -+ /* Debug keys are insecure so don't store them persistently */ -+ if (key_type == HCI_LK_DEBUG_COMBINATION) -+ return 0; -+ -+ /* Changed combination key and there's no previous one */ -+ if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) -+ return 0; -+ -+ /* Security mode 3 case */ -+ if (!conn) -+ return 1; -+ -+ /* Neither local nor remote side had no-bonding as requirement */ -+ if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) -+ return 1; -+ -+ /* Local side had dedicated bonding as requirement */ -+ if (conn->auth_type == 0x02 || conn->auth_type == 0x03) -+ return 1; -+ -+ /* Remote side had dedicated bonding as requirement */ -+ if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) -+ return 1; -+ -+ /* If none of the above criteria match, then don't store the key -+ * persistently */ -+ return 0; -+} -+ -+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, -+ bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) - { - struct link_key *key, *old_key; -- u8 old_key_type; -+ u8 old_key_type, persistent; - - old_key = hci_find_link_key(hdev, bdaddr); - if (old_key) { - old_key_type = old_key->type; - key = old_key; - } else { -- old_key_type = 0xff; -+ old_key_type = conn ? conn->key_type : 0xff; - key = kzalloc(sizeof(*key), GFP_ATOMIC); - if (!key) - return -ENOMEM; -@@ -1041,16 +1076,37 @@ - - BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); - -+ /* Some buggy controller combinations generate a changed -+ * combination key for legacy pairing even when there's no -+ * previous key */ -+ if (type == HCI_LK_CHANGED_COMBINATION && -+ (!conn || conn->remote_auth == 0xff) && -+ old_key_type == 0xff) { -+ type = HCI_LK_COMBINATION; -+ if (conn) -+ conn->key_type = type; -+ } -+ - bacpy(&key->bdaddr, bdaddr); - memcpy(key->val, val, 16); -- key->type = type; - key->pin_len = pin_len; - -- if (new_key) -- mgmt_new_key(hdev->id, key, old_key_type); -- -- if (type == 0x06) -+ if (type == HCI_LK_CHANGED_COMBINATION) - key->type = old_key_type; -+ else -+ key->type = type; -+ -+ if (!new_key) -+ return 0; -+ -+ persistent = hci_persistent_key(hdev, conn, type, old_key_type); -+ -+ mgmt_new_key(hdev->id, key, persistent); -+ -+ if (!persistent) { -+ list_del(&key->list); -+ kfree(key); -+ } - - return 0; - } -@@ -1082,6 +1138,70 @@ - tasklet_schedule(&hdev->cmd_task); - } - -+struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, -+ bdaddr_t *bdaddr) -+{ -+ struct oob_data *data; -+ -+ list_for_each_entry(data, &hdev->remote_oob_data, list) -+ if (bacmp(bdaddr, &data->bdaddr) == 0) -+ return data; -+ -+ return NULL; -+} -+ -+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) -+{ -+ struct oob_data *data; -+ -+ data = hci_find_remote_oob_data(hdev, bdaddr); -+ if (!data) -+ return -ENOENT; -+ -+ BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); -+ -+ list_del(&data->list); -+ kfree(data); -+ -+ return 0; -+} -+ -+int hci_remote_oob_data_clear(struct hci_dev *hdev) -+{ -+ struct oob_data *data, *n; -+ -+ list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { -+ list_del(&data->list); -+ kfree(data); -+ } -+ -+ return 0; -+} -+ -+int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, -+ u8 *randomizer) -+{ -+ struct oob_data *data; -+ -+ data = hci_find_remote_oob_data(hdev, bdaddr); -+ -+ if (!data) { -+ data = kmalloc(sizeof(*data), GFP_ATOMIC); -+ if (!data) -+ return -ENOMEM; -+ -+ bacpy(&data->bdaddr, bdaddr); -+ list_add(&data->list, &hdev->remote_oob_data); -+ } -+ -+ memcpy(data->hash, hash, sizeof(data->hash)); -+ memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); -+ -+ BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); -+ -+ return 0; -+} -+ - /* Register HCI device */ - int hci_register_dev(struct hci_dev *hdev) - { -@@ -1146,6 +1266,8 @@ - - INIT_LIST_HEAD(&hdev->link_keys); - -+ INIT_LIST_HEAD(&hdev->remote_oob_data); -+ - INIT_WORK(&hdev->power_on, hci_power_on); - INIT_WORK(&hdev->power_off, hci_power_off); - setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); -@@ -1225,6 +1347,7 @@ - hci_blacklist_clear(hdev); - hci_uuids_clear(hdev); - hci_link_keys_clear(hdev); -+ hci_remote_oob_data_clear(hdev); - hci_dev_unlock_bh(hdev); - - __hci_dev_put(hdev); -@@ -1274,7 +1397,7 @@ - EXPORT_SYMBOL(hci_recv_frame); - - static int hci_reassembly(struct hci_dev *hdev, int type, void *data, -- int count, __u8 index, gfp_t gfp_mask) -+ int count, __u8 index) - { - int len = 0; - int hlen = 0; -@@ -1304,7 +1427,7 @@ - break; - } - -- skb = bt_skb_alloc(len, gfp_mask); -+ skb = bt_skb_alloc(len, GFP_ATOMIC); - if (!skb) - return -ENOMEM; - -@@ -1390,8 +1513,7 @@ - return -EILSEQ; - - while (count) { -- rem = hci_reassembly(hdev, type, data, count, -- type - 1, GFP_ATOMIC); -+ rem = hci_reassembly(hdev, type, data, count, type - 1); - if (rem < 0) - return rem; - -@@ -1425,8 +1547,8 @@ - } else - type = bt_cb(skb)->pkt_type; - -- rem = hci_reassembly(hdev, type, data, -- count, STREAM_REASSEMBLY, GFP_ATOMIC); -+ rem = hci_reassembly(hdev, type, data, count, -+ STREAM_REASSEMBLY); - if (rem < 0) - return rem; - -diff -Naur linux-2.6.39-rc6/net/bluetooth/hci_event.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_event.c ---- linux-2.6.39-rc6/net/bluetooth/hci_event.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_event.c 2011-05-05 23:30:21.171872885 +0200 -@@ -56,7 +56,9 @@ - if (status) - return; - -- clear_bit(HCI_INQUIRY, &hdev->flags); -+ if (test_bit(HCI_MGMT, &hdev->flags) && -+ test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) -+ mgmt_discovering(hdev->id, 0); - - hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); - -@@ -72,7 +74,9 @@ - if (status) - return; - -- clear_bit(HCI_INQUIRY, &hdev->flags); -+ if (test_bit(HCI_MGMT, &hdev->flags) && -+ test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) -+ mgmt_discovering(hdev->id, 0); - - hci_conn_check_pending(hdev); - } -@@ -195,14 +199,17 @@ - - BT_DBG("%s status 0x%x", hdev->name, status); - -- if (status) -- return; -- - sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); - if (!sent) - return; - -- memcpy(hdev->dev_name, sent, 248); -+ if (test_bit(HCI_MGMT, &hdev->flags)) -+ mgmt_set_local_name_complete(hdev->id, sent, status); -+ -+ if (status) -+ return; -+ -+ memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); - } - - static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) -@@ -214,7 +221,7 @@ - if (rp->status) - return; - -- memcpy(hdev->dev_name, rp->name, 248); -+ memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); - } - - static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) -@@ -821,16 +828,31 @@ - rp->status); - } - -+static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, -+ struct sk_buff *skb) -+{ -+ struct hci_rp_read_local_oob_data *rp = (void *) skb->data; -+ -+ BT_DBG("%s status 0x%x", hdev->name, rp->status); -+ -+ mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, -+ rp->randomizer, rp->status); -+} -+ - static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) - { - BT_DBG("%s status 0x%x", hdev->name, status); - - if (status) { - hci_req_complete(hdev, HCI_OP_INQUIRY, status); -- - hci_conn_check_pending(hdev); -- } else -- set_bit(HCI_INQUIRY, &hdev->flags); -+ return; -+ } -+ -+ if (test_bit(HCI_MGMT, &hdev->flags) && -+ !test_and_set_bit(HCI_INQUIRY, -+ &hdev->flags)) -+ mgmt_discovering(hdev->id, 1); - } - - static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) -@@ -999,12 +1021,19 @@ - hci_dev_lock(hdev); - - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); -- if (conn && hci_outgoing_auth_needed(hdev, conn)) { -+ if (!conn) -+ goto unlock; -+ -+ if (!hci_outgoing_auth_needed(hdev, conn)) -+ goto unlock; -+ -+ if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { - struct hci_cp_auth_requested cp; - cp.handle = __cpu_to_le16(conn->handle); - hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); - } - -+unlock: - hci_dev_unlock(hdev); - } - -@@ -1194,7 +1223,9 @@ - - BT_DBG("%s status %d", hdev->name, status); - -- clear_bit(HCI_INQUIRY, &hdev->flags); -+ if (test_bit(HCI_MGMT, &hdev->flags) && -+ test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) -+ mgmt_discovering(hdev->id, 0); - - hci_req_complete(hdev, HCI_OP_INQUIRY, status); - -@@ -1214,7 +1245,13 @@ - - hci_dev_lock(hdev); - -- for (; num_rsp; num_rsp--) { -+ if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { -+ -+ if (test_bit(HCI_MGMT, &hdev->flags)) -+ mgmt_discovering(hdev->id, 1); -+ } -+ -+ for (; num_rsp; num_rsp--, info++) { - bacpy(&data.bdaddr, &info->bdaddr); - data.pscan_rep_mode = info->pscan_rep_mode; - data.pscan_period_mode = info->pscan_period_mode; -@@ -1223,8 +1260,9 @@ - data.clock_offset = info->clock_offset; - data.rssi = 0x00; - data.ssp_mode = 0x00; -- info++; - hci_inquiry_cache_update(hdev, &data); -+ mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, -+ NULL); - } - - hci_dev_unlock(hdev); -@@ -1428,7 +1466,6 @@ - conn->sec_level = conn->pending_sec_level; - } else { - mgmt_auth_failed(hdev->id, &conn->dst, ev->status); -- conn->sec_level = BT_SECURITY_LOW; - } - - clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); -@@ -1482,13 +1519,23 @@ - - hci_dev_lock(hdev); - -+ if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) -+ mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); -+ - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); -- if (conn && hci_outgoing_auth_needed(hdev, conn)) { -+ if (!conn) -+ goto unlock; -+ -+ if (!hci_outgoing_auth_needed(hdev, conn)) -+ goto unlock; -+ -+ if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { - struct hci_cp_auth_requested cp; - cp.handle = __cpu_to_le16(conn->handle); - hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); - } - -+unlock: - hci_dev_unlock(hdev); - } - -@@ -1751,6 +1798,10 @@ - hci_cc_pin_code_neg_reply(hdev, skb); - break; - -+ case HCI_OP_READ_LOCAL_OOB_DATA: -+ hci_cc_read_local_oob_data_reply(hdev, skb); -+ break; -+ - case HCI_OP_LE_READ_BUFFER_SIZE: - hci_cc_le_read_buffer_size(hdev, skb); - break; -@@ -1984,9 +2035,16 @@ - if (!test_bit(HCI_PAIRABLE, &hdev->flags)) - hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, - sizeof(ev->bdaddr), &ev->bdaddr); -+ else if (test_bit(HCI_MGMT, &hdev->flags)) { -+ u8 secure; - -- if (test_bit(HCI_MGMT, &hdev->flags)) -- mgmt_pin_code_request(hdev->id, &ev->bdaddr); -+ if (conn->pending_sec_level == BT_SECURITY_HIGH) -+ secure = 1; -+ else -+ secure = 0; -+ -+ mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); -+ } - - hci_dev_unlock(hdev); - } -@@ -2015,17 +2073,30 @@ - BT_DBG("%s found key type %u for %s", hdev->name, key->type, - batostr(&ev->bdaddr)); - -- if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) { -+ if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && -+ key->type == HCI_LK_DEBUG_COMBINATION) { - BT_DBG("%s ignoring debug key", hdev->name); - goto not_found; - } - - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); -+ if (conn) { -+ if (key->type == HCI_LK_UNAUTH_COMBINATION && -+ conn->auth_type != 0xff && -+ (conn->auth_type & 0x01)) { -+ BT_DBG("%s ignoring unauthenticated key", hdev->name); -+ goto not_found; -+ } -+ -+ if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && -+ conn->pending_sec_level == BT_SECURITY_HIGH) { -+ BT_DBG("%s ignoring key unauthenticated for high \ -+ security", hdev->name); -+ goto not_found; -+ } - -- if (key->type == 0x04 && conn && conn->auth_type != 0xff && -- (conn->auth_type & 0x01)) { -- BT_DBG("%s ignoring unauthenticated key", hdev->name); -- goto not_found; -+ conn->key_type = key->type; -+ conn->pin_length = key->pin_len; - } - - bacpy(&cp.bdaddr, &ev->bdaddr); -@@ -2057,11 +2128,15 @@ - hci_conn_hold(conn); - conn->disc_timeout = HCI_DISCONN_TIMEOUT; - pin_len = conn->pin_length; -+ -+ if (ev->key_type != HCI_LK_CHANGED_COMBINATION) -+ conn->key_type = ev->key_type; -+ - hci_conn_put(conn); - } - - if (test_bit(HCI_LINK_KEYS, &hdev->flags)) -- hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, -+ hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, - ev->key_type, pin_len); - - hci_dev_unlock(hdev); -@@ -2136,11 +2211,17 @@ - - hci_dev_lock(hdev); - -+ if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { -+ -+ if (test_bit(HCI_MGMT, &hdev->flags)) -+ mgmt_discovering(hdev->id, 1); -+ } -+ - if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { - struct inquiry_info_with_rssi_and_pscan_mode *info; - info = (void *) (skb->data + 1); - -- for (; num_rsp; num_rsp--) { -+ for (; num_rsp; num_rsp--, info++) { - bacpy(&data.bdaddr, &info->bdaddr); - data.pscan_rep_mode = info->pscan_rep_mode; - data.pscan_period_mode = info->pscan_period_mode; -@@ -2149,13 +2230,15 @@ - data.clock_offset = info->clock_offset; - data.rssi = info->rssi; - data.ssp_mode = 0x00; -- info++; - hci_inquiry_cache_update(hdev, &data); -+ mgmt_device_found(hdev->id, &info->bdaddr, -+ info->dev_class, info->rssi, -+ NULL); - } - } else { - struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); - -- for (; num_rsp; num_rsp--) { -+ for (; num_rsp; num_rsp--, info++) { - bacpy(&data.bdaddr, &info->bdaddr); - data.pscan_rep_mode = info->pscan_rep_mode; - data.pscan_period_mode = info->pscan_period_mode; -@@ -2164,8 +2247,10 @@ - data.clock_offset = info->clock_offset; - data.rssi = info->rssi; - data.ssp_mode = 0x00; -- info++; - hci_inquiry_cache_update(hdev, &data); -+ mgmt_device_found(hdev->id, &info->bdaddr, -+ info->dev_class, info->rssi, -+ NULL); - } - } - -@@ -2294,9 +2379,15 @@ - if (!num_rsp) - return; - -+ if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { -+ -+ if (test_bit(HCI_MGMT, &hdev->flags)) -+ mgmt_discovering(hdev->id, 1); -+ } -+ - hci_dev_lock(hdev); - -- for (; num_rsp; num_rsp--) { -+ for (; num_rsp; num_rsp--, info++) { - bacpy(&data.bdaddr, &info->bdaddr); - data.pscan_rep_mode = info->pscan_rep_mode; - data.pscan_period_mode = info->pscan_period_mode; -@@ -2305,8 +2396,9 @@ - data.clock_offset = info->clock_offset; - data.rssi = info->rssi; - data.ssp_mode = 0x01; -- info++; - hci_inquiry_cache_update(hdev, &data); -+ mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, -+ info->rssi, info->data); - } - - hci_dev_unlock(hdev); -@@ -2326,7 +2418,7 @@ - - /* If remote requests no-bonding follow that lead */ - if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) -- return 0x00; -+ return conn->remote_auth | (conn->auth_type & 0x01); - - return conn->auth_type; - } -@@ -2355,8 +2447,14 @@ - - bacpy(&cp.bdaddr, &ev->bdaddr); - cp.capability = conn->io_capability; -- cp.oob_data = 0; -- cp.authentication = hci_get_auth_req(conn); -+ conn->auth_type = hci_get_auth_req(conn); -+ cp.authentication = conn->auth_type; -+ -+ if ((conn->out == 0x01 || conn->remote_oob == 0x01) && -+ hci_find_remote_oob_data(hdev, &conn->dst)) -+ cp.oob_data = 0x01; -+ else -+ cp.oob_data = 0x00; - - hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, - sizeof(cp), &cp); -@@ -2364,7 +2462,7 @@ - struct hci_cp_io_capability_neg_reply cp; - - bacpy(&cp.bdaddr, &ev->bdaddr); -- cp.reason = 0x16; /* Pairing not allowed */ -+ cp.reason = 0x18; /* Pairing not allowed */ - - hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, - sizeof(cp), &cp); -@@ -2399,14 +2497,67 @@ - struct sk_buff *skb) - { - struct hci_ev_user_confirm_req *ev = (void *) skb->data; -+ int loc_mitm, rem_mitm, confirm_hint = 0; -+ struct hci_conn *conn; - - BT_DBG("%s", hdev->name); - - hci_dev_lock(hdev); - -- if (test_bit(HCI_MGMT, &hdev->flags)) -- mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); -+ if (!test_bit(HCI_MGMT, &hdev->flags)) -+ goto unlock; -+ -+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); -+ if (!conn) -+ goto unlock; -+ -+ loc_mitm = (conn->auth_type & 0x01); -+ rem_mitm = (conn->remote_auth & 0x01); - -+ /* If we require MITM but the remote device can't provide that -+ * (it has NoInputNoOutput) then reject the confirmation -+ * request. The only exception is when we're dedicated bonding -+ * initiators (connect_cfm_cb set) since then we always have the MITM -+ * bit set. */ -+ if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { -+ BT_DBG("Rejecting request: remote device can't provide MITM"); -+ hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, -+ sizeof(ev->bdaddr), &ev->bdaddr); -+ goto unlock; -+ } -+ -+ /* If no side requires MITM protection; auto-accept */ -+ if ((!loc_mitm || conn->remote_cap == 0x03) && -+ (!rem_mitm || conn->io_capability == 0x03)) { -+ -+ /* If we're not the initiators request authorization to -+ * proceed from user space (mgmt_user_confirm with -+ * confirm_hint set to 1). */ -+ if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { -+ BT_DBG("Confirming auto-accept as acceptor"); -+ confirm_hint = 1; -+ goto confirm; -+ } -+ -+ BT_DBG("Auto-accept of user confirmation with %ums delay", -+ hdev->auto_accept_delay); -+ -+ if (hdev->auto_accept_delay > 0) { -+ int delay = msecs_to_jiffies(hdev->auto_accept_delay); -+ mod_timer(&conn->auto_accept_timer, jiffies + delay); -+ goto unlock; -+ } -+ -+ hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, -+ sizeof(ev->bdaddr), &ev->bdaddr); -+ goto unlock; -+ } -+ -+confirm: -+ mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, -+ confirm_hint); -+ -+unlock: - hci_dev_unlock(hdev); - } - -@@ -2453,6 +2604,41 @@ - hci_dev_unlock(hdev); - } - -+static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, -+ struct sk_buff *skb) -+{ -+ struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; -+ struct oob_data *data; -+ -+ BT_DBG("%s", hdev->name); -+ -+ 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; -+ -+ bacpy(&cp.bdaddr, &ev->bdaddr); -+ memcpy(cp.hash, data->hash, sizeof(cp.hash)); -+ memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); -+ -+ hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), -+ &cp); -+ } else { -+ struct hci_cp_remote_oob_data_neg_reply cp; -+ -+ bacpy(&cp.bdaddr, &ev->bdaddr); -+ hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), -+ &cp); -+ } -+ -+unlock: -+ hci_dev_unlock(hdev); -+} -+ - static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) - { - struct hci_ev_le_conn_complete *ev = (void *) skb->data; -@@ -2655,6 +2841,10 @@ - hci_le_meta_evt(hdev, skb); - break; - -+ case HCI_EV_REMOTE_OOB_DATA_REQUEST: -+ hci_remote_oob_data_request_evt(hdev, skb); -+ break; -+ - default: - BT_DBG("%s event 0x%x", hdev->name, event); - break; -diff -Naur linux-2.6.39-rc6/net/bluetooth/hci_sysfs.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_sysfs.c ---- linux-2.6.39-rc6/net/bluetooth/hci_sysfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hci_sysfs.c 2011-05-05 23:30:21.238873693 +0200 -@@ -216,13 +216,13 @@ - static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) - { - struct hci_dev *hdev = dev_get_drvdata(dev); -- char name[249]; -+ char name[HCI_MAX_NAME_LENGTH + 1]; - int i; - -- for (i = 0; i < 248; i++) -+ for (i = 0; i < HCI_MAX_NAME_LENGTH; i++) - name[i] = hdev->dev_name[i]; - -- name[248] = '\0'; -+ name[HCI_MAX_NAME_LENGTH] = '\0'; - return sprintf(buf, "%s\n", name); - } - -@@ -277,10 +277,12 @@ - static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) - { - struct hci_dev *hdev = dev_get_drvdata(dev); -- unsigned long val; -+ unsigned int val; -+ int rv; - -- if (strict_strtoul(buf, 0, &val) < 0) -- return -EINVAL; -+ rv = kstrtouint(buf, 0, &val); -+ if (rv < 0) -+ return rv; - - if (val != 0 && (val < 500 || val > 3600000)) - return -EINVAL; -@@ -299,15 +301,14 @@ - static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) - { - struct hci_dev *hdev = dev_get_drvdata(dev); -- unsigned long val; -- -- if (strict_strtoul(buf, 0, &val) < 0) -- return -EINVAL; -+ u16 val; -+ int rv; - -- if (val < 0x0002 || val > 0xFFFE || val % 2) -- return -EINVAL; -+ rv = kstrtou16(buf, 0, &val); -+ if (rv < 0) -+ return rv; - -- if (val < hdev->sniff_min_interval) -+ if (val == 0 || val % 2 || val < hdev->sniff_min_interval) - return -EINVAL; - - hdev->sniff_max_interval = val; -@@ -324,15 +325,14 @@ - static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) - { - struct hci_dev *hdev = dev_get_drvdata(dev); -- unsigned long val; -+ u16 val; -+ int rv; - -- if (strict_strtoul(buf, 0, &val) < 0) -- return -EINVAL; -- -- if (val < 0x0002 || val > 0xFFFE || val % 2) -- return -EINVAL; -+ rv = kstrtou16(buf, 0, &val); -+ if (rv < 0) -+ return rv; - -- if (val > hdev->sniff_max_interval) -+ if (val == 0 || val % 2 || val > hdev->sniff_max_interval) - return -EINVAL; - - hdev->sniff_min_interval = val; -@@ -511,6 +511,35 @@ - .release = single_release, - }; - -+static int auto_accept_delay_set(void *data, u64 val) -+{ -+ struct hci_dev *hdev = data; -+ -+ hci_dev_lock_bh(hdev); -+ -+ hdev->auto_accept_delay = val; -+ -+ hci_dev_unlock_bh(hdev); -+ -+ return 0; -+} -+ -+static int auto_accept_delay_get(void *data, u64 *val) -+{ -+ struct hci_dev *hdev = data; -+ -+ hci_dev_lock_bh(hdev); -+ -+ *val = hdev->auto_accept_delay; -+ -+ hci_dev_unlock_bh(hdev); -+ -+ return 0; -+} -+ -+DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, -+ auto_accept_delay_set, "%llu\n"); -+ - int hci_register_sysfs(struct hci_dev *hdev) - { - struct device *dev = &hdev->dev; -@@ -545,6 +574,8 @@ - - debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); - -+ debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev, -+ &auto_accept_delay_fops); - return 0; - } - -diff -Naur linux-2.6.39-rc6/net/bluetooth/hidp/core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/core.c ---- linux-2.6.39-rc6/net/bluetooth/hidp/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/core.c 2011-05-05 23:30:21.238873693 +0200 -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -55,22 +56,24 @@ - static LIST_HEAD(hidp_session_list); - - static unsigned char hidp_keycode[256] = { -- 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, -- 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, -- 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, -- 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, -- 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, -- 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, -- 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, -- 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, -- 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, -- 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, -- 150,158,159,128,136,177,178,176,142,152,173,140 -+ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, -+ 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, -+ 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, -+ 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52, -+ 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88, -+ 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69, -+ 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73, -+ 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190, -+ 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, -+ 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94, -+ 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, -+ 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140 - }; - - static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; -@@ -461,8 +464,7 @@ - { - struct hidp_session *session = (struct hidp_session *) arg; - -- atomic_inc(&session->terminate); -- hidp_schedule(session); -+ kthread_stop(session->task); - } - - static void hidp_set_timer(struct hidp_session *session) -@@ -533,9 +535,7 @@ - skb_queue_purge(&session->ctrl_transmit); - skb_queue_purge(&session->intr_transmit); - -- /* Kill session thread */ -- atomic_inc(&session->terminate); -- hidp_schedule(session); -+ kthread_stop(session->task); - } - } - -@@ -694,22 +694,10 @@ - struct sock *ctrl_sk = session->ctrl_sock->sk; - struct sock *intr_sk = session->intr_sock->sk; - struct sk_buff *skb; -- int vendor = 0x0000, product = 0x0000; - wait_queue_t ctrl_wait, intr_wait; - - BT_DBG("session %p", session); - -- if (session->input) { -- vendor = session->input->id.vendor; -- product = session->input->id.product; -- } -- -- if (session->hid) { -- vendor = session->hid->vendor; -- product = session->hid->product; -- } -- -- daemonize("khidpd_%04x%04x", vendor, product); - set_user_nice(current, -15); - - init_waitqueue_entry(&ctrl_wait, current); -@@ -718,10 +706,11 @@ - add_wait_queue(sk_sleep(intr_sk), &intr_wait); - session->waiting_for_startup = 0; - wake_up_interruptible(&session->startup_queue); -- while (!atomic_read(&session->terminate)) { -+ while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - -- if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED) -+ if (ctrl_sk->sk_state != BT_CONNECTED || -+ intr_sk->sk_state != BT_CONNECTED) - break; - - while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { -@@ -965,6 +954,7 @@ - int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) - { - struct hidp_session *session, *s; -+ int vendor, product; - int err; - - BT_DBG(""); -@@ -989,8 +979,10 @@ - - bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst); - -- session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu); -- session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu); -+ session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu, -+ l2cap_pi(ctrl_sock->sk)->chan->imtu); -+ session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu, -+ l2cap_pi(intr_sock->sk)->chan->imtu); - - BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu); - -@@ -1026,9 +1018,24 @@ - - hidp_set_timer(session); - -- err = kernel_thread(hidp_session, session, CLONE_KERNEL); -- if (err < 0) -+ if (session->hid) { -+ vendor = session->hid->vendor; -+ product = session->hid->product; -+ } else if (session->input) { -+ vendor = session->input->id.vendor; -+ product = session->input->id.product; -+ } else { -+ vendor = 0x0000; -+ product = 0x0000; -+ } -+ -+ session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x", -+ vendor, product); -+ if (IS_ERR(session->task)) { -+ err = PTR_ERR(session->task); - goto unlink; -+ } -+ - while (session->waiting_for_startup) { - wait_event_interruptible(session->startup_queue, - !session->waiting_for_startup); -@@ -1053,8 +1060,7 @@ - err_add_device: - hid_destroy_device(session->hid); - session->hid = NULL; -- atomic_inc(&session->terminate); -- hidp_schedule(session); -+ kthread_stop(session->task); - - unlink: - hidp_del_timer(session); -@@ -1105,13 +1111,7 @@ - skb_queue_purge(&session->ctrl_transmit); - skb_queue_purge(&session->intr_transmit); - -- /* Wakeup user-space polling for socket errors */ -- session->intr_sock->sk->sk_err = EUNATCH; -- session->ctrl_sock->sk->sk_err = EUNATCH; -- -- /* Kill session thread */ -- atomic_inc(&session->terminate); -- hidp_schedule(session); -+ kthread_stop(session->task); - } - } else - err = -ENOENT; -diff -Naur linux-2.6.39-rc6/net/bluetooth/hidp/hidp.h linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/hidp.h ---- linux-2.6.39-rc6/net/bluetooth/hidp/hidp.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/hidp.h 2011-05-05 23:30:21.239873705 +0200 -@@ -84,8 +84,8 @@ - #define HIDP_WAITING_FOR_SEND_ACK 11 - - struct hidp_connadd_req { -- int ctrl_sock; // Connected control socket -- int intr_sock; // Connteted interrupt socket -+ int ctrl_sock; /* Connected control socket */ -+ int intr_sock; /* Connected interrupt socket */ - __u16 parser; - __u16 rd_size; - __u8 __user *rd_data; -@@ -142,7 +142,7 @@ - uint ctrl_mtu; - uint intr_mtu; - -- atomic_t terminate; -+ struct task_struct *task; - - unsigned char keys[8]; - unsigned char leds; -diff -Naur linux-2.6.39-rc6/net/bluetooth/hidp/sock.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/sock.c ---- linux-2.6.39-rc6/net/bluetooth/hidp/sock.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/hidp/sock.c 2011-05-05 23:30:21.241873729 +0200 -@@ -85,7 +85,8 @@ - return err; - } - -- if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) { -+ if (csock->sk->sk_state != BT_CONNECTED || -+ isock->sk->sk_state != BT_CONNECTED) { - sockfd_put(csock); - sockfd_put(isock); - return -EBADFD; -@@ -140,8 +141,8 @@ - - #ifdef CONFIG_COMPAT - struct compat_hidp_connadd_req { -- int ctrl_sock; // Connected control socket -- int intr_sock; // Connteted interrupt socket -+ int ctrl_sock; /* Connected control socket */ -+ int intr_sock; /* Connected interrupt socket */ - __u16 parser; - __u16 rd_size; - compat_uptr_t rd_data; -diff -Naur linux-2.6.39-rc6/net/bluetooth/l2cap_core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/l2cap_core.c ---- linux-2.6.39-rc6/net/bluetooth/l2cap_core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/l2cap_core.c 2011-05-05 23:30:21.196873185 +0200 -@@ -70,160 +70,160 @@ - - 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) { -- if (l2cap_pi(s)->dcid == cid) -- break; -+ struct l2cap_chan *c; -+ -+ list_for_each_entry(c, &conn->chan_l, list) { -+ if (c->dcid == cid) -+ 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) { -- if (l2cap_pi(s)->scid == cid) -- break; -+ struct l2cap_chan *c; -+ -+ list_for_each_entry(c, &conn->chan_l, list) { -+ if (c->scid == cid) -+ 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) -+struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) - { -- sock_hold(sk); -+ struct l2cap_chan *chan; - -- if (l->head) -- l2cap_pi(l->head)->prev_c = sk; -+ chan = kzalloc(sizeof(*chan), GFP_ATOMIC); -+ if (!chan) -+ return NULL; -+ -+ chan->sk = sk; - -- l2cap_pi(sk)->next_c = l->head; -- l2cap_pi(sk)->prev_c = NULL; -- l->head = sk; -+ return chan; - } - --static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) -+void l2cap_chan_free(struct l2cap_chan *chan) - { -- 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; -- -- if (next) -- l2cap_pi(next)->prev_c = prev; -- if (prev) -- l2cap_pi(prev)->next_c = next; -- write_unlock_bh(&l->lock); -- -- __sock_put(sk); -+ kfree(chan); - } - --static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) -+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); -+ chan->psm, chan->dcid); - - conn->disc_reason = 0x13; - -- l2cap_pi(sk)->conn = conn; -+ chan->conn = conn; - - if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) { - if (conn->hcon->type == LE_LINK) { - /* LE connection */ -- l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU; -- l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA; -- l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA; -+ chan->omtu = L2CAP_LE_DEFAULT_MTU; -+ chan->scid = L2CAP_CID_LE_DATA; -+ chan->dcid = L2CAP_CID_LE_DATA; - } else { - /* Alloc CID for connection-oriented socket */ -- l2cap_pi(sk)->scid = l2cap_alloc_cid(l); -- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; -+ chan->scid = l2cap_alloc_cid(conn); -+ chan->omtu = L2CAP_DEFAULT_MTU; - } - } else if (sk->sk_type == SOCK_DGRAM) { - /* Connectionless socket */ -- l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS; -- l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS; -- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; -+ chan->scid = L2CAP_CID_CONN_LESS; -+ chan->dcid = L2CAP_CID_CONN_LESS; -+ chan->omtu = L2CAP_DEFAULT_MTU; - } else { - /* Raw socket can send/recv signalling messages only */ -- l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING; -- l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING; -- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; -+ chan->scid = L2CAP_CID_SIGNALING; -+ chan->dcid = L2CAP_CID_SIGNALING; -+ chan->omtu = L2CAP_DEFAULT_MTU; - } - -- __l2cap_chan_link(l, sk); -+ sock_hold(sk); - -- if (parent) -- bt_accept_enqueue(parent, 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 l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct sock *sk = chan->sk; -+ struct l2cap_conn *conn = chan->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); -- l2cap_pi(sk)->conn = NULL; -+ /* Delete from channel list */ -+ write_lock_bh(&conn->chan_lock); -+ list_del(&chan->list); -+ write_unlock_bh(&conn->chan_lock); -+ __sock_put(sk); -+ -+ chan->conn = NULL; - hci_conn_put(conn->hcon); - } - -@@ -239,29 +239,35 @@ - } else - sk->sk_state_change(sk); - -- skb_queue_purge(TX_QUEUE(sk)); -+ if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE && -+ chan->conf_state & L2CAP_CONF_INPUT_DONE)) -+ return; -+ -+ skb_queue_purge(&chan->tx_q); - -- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { -+ if (chan->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); - } - } - } - --static inline u8 l2cap_get_auth_type(struct sock *sk) -+static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) - { -+ struct sock *sk = chan->sk; -+ - if (sk->sk_type == SOCK_RAW) { -- switch (l2cap_pi(sk)->sec_level) { -+ switch (chan->sec_level) { - case BT_SECURITY_HIGH: - return HCI_AT_DEDICATED_BONDING_MITM; - case BT_SECURITY_MEDIUM: -@@ -269,16 +275,16 @@ - default: - return HCI_AT_NO_BONDING; - } -- } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) { -- if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) -- l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; -+ } else if (chan->psm == cpu_to_le16(0x0001)) { -+ if (chan->sec_level == BT_SECURITY_LOW) -+ chan->sec_level = BT_SECURITY_SDP; - -- if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) -+ if (chan->sec_level == BT_SECURITY_HIGH) - return HCI_AT_NO_BONDING_MITM; - else - return HCI_AT_NO_BONDING; - } else { -- switch (l2cap_pi(sk)->sec_level) { -+ switch (chan->sec_level) { - case BT_SECURITY_HIGH: - return HCI_AT_GENERAL_BONDING_MITM; - case BT_SECURITY_MEDIUM: -@@ -290,15 +296,14 @@ - } - - /* Service level security */ --static inline int l2cap_check_security(struct sock *sk) -+static inline int l2cap_check_security(struct l2cap_chan *chan) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct l2cap_conn *conn = chan->conn; - __u8 auth_type; - -- auth_type = l2cap_get_auth_type(sk); -+ auth_type = l2cap_get_auth_type(chan); - -- return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level, -- auth_type); -+ return hci_conn_security(conn->hcon, chan->sec_level, auth_type); - } - - u8 l2cap_get_ident(struct l2cap_conn *conn) -@@ -341,11 +346,12 @@ - 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_conn *conn = pi->conn; -+ struct l2cap_pinfo *pi = l2cap_pi(chan->sk); -+ struct l2cap_conn *conn = chan->conn; - struct sock *sk = (struct sock *)pi; - int count, hlen = L2CAP_HDR_SIZE + 2; - u8 flags; -@@ -353,22 +359,22 @@ - if (sk->sk_state != BT_CONNECTED) - return; - -- if (pi->fcs == L2CAP_FCS_CRC16) -+ if (chan->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); -@@ -377,10 +383,10 @@ - - lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); - lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); -- lh->cid = cpu_to_le16(pi->dcid); -+ lh->cid = cpu_to_le16(chan->dcid); - put_unaligned_le16(control, skb_put(skb, 2)); - -- if (pi->fcs == L2CAP_FCS_CRC16) { -+ if (chan->fcs == L2CAP_FCS_CRC16) { - u16 fcs = crc16(0, (u8 *)lh, count - 2); - put_unaligned_le16(fcs, skb_put(skb, 2)); - } -@@ -390,45 +396,46 @@ - else - flags = ACL_START; - -- hci_send_acl(pi->conn->hcon, skb, flags); -+ hci_send_acl(chan->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) -+static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) - { -- return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND); -+ return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND); - } - --static void l2cap_do_start(struct sock *sk) -+static void l2cap_do_start(struct l2cap_chan *chan) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct l2cap_conn *conn = chan->conn; - - if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { - if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) - return; - -- if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) { -+ if (l2cap_check_security(chan) && -+ __l2cap_no_conn_pending(chan)) { - struct l2cap_conn_req req; -- req.scid = cpu_to_le16(l2cap_pi(sk)->scid); -- req.psm = l2cap_pi(sk)->psm; -+ req.scid = cpu_to_le16(chan->scid); -+ req.psm = chan->psm; - -- l2cap_pi(sk)->ident = l2cap_get_ident(conn); -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -+ chan->ident = l2cap_get_ident(conn); -+ chan->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; -@@ -461,23 +468,24 @@ - } - } - --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); -+ if (chan->mode == L2CAP_MODE_ERTM) { -+ del_timer(&chan->retrans_timer); -+ del_timer(&chan->monitor_timer); -+ del_timer(&chan->ack_timer); - } - -- req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); -- req.scid = cpu_to_le16(l2cap_pi(sk)->scid); -+ req.dcid = cpu_to_le16(chan->dcid); -+ req.scid = cpu_to_le16(chan->scid); - l2cap_send_cmd(conn, l2cap_get_ident(conn), - L2CAP_DISCONN_REQ, sizeof(req), &req); - -@@ -488,17 +496,15 @@ - /* ---- 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 && -@@ -510,40 +516,41 @@ - if (sk->sk_state == BT_CONNECT) { - struct l2cap_conn_req req; - -- if (!l2cap_check_security(sk) || -- !__l2cap_no_conn_pending(sk)) { -+ if (!l2cap_check_security(chan) || -+ !__l2cap_no_conn_pending(chan)) { - bh_unlock_sock(sk); - continue; - } - -- if (!l2cap_mode_supported(l2cap_pi(sk)->mode, -+ if (!l2cap_mode_supported(chan->mode, - conn->feat_mask) -- && l2cap_pi(sk)->conf_state & -+ && chan->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; - } - -- req.scid = cpu_to_le16(l2cap_pi(sk)->scid); -- req.psm = l2cap_pi(sk)->psm; -+ req.scid = cpu_to_le16(chan->scid); -+ req.psm = chan->psm; - -- l2cap_pi(sk)->ident = l2cap_get_ident(conn); -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -+ chan->ident = l2cap_get_ident(conn); -+ chan->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; - char buf[128]; -- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); -- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); -+ rsp.scid = cpu_to_le16(chan->dcid); -+ rsp.dcid = cpu_to_le16(chan->scid); - -- if (l2cap_check_security(sk)) { -+ if (l2cap_check_security(chan)) { - if (bt_sk(sk)->defer_setup) { - struct sock *parent = bt_sk(sk)->parent; - rsp.result = cpu_to_le16(L2CAP_CR_PEND); -@@ -560,33 +567,25 @@ - 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 || -+ if (chan->conf_state & L2CAP_CONF_REQ_SENT || - rsp.result != L2CAP_CR_SUCCESS) { - bh_unlock_sock(sk); - continue; - } - -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; -+ chan->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. -@@ -594,16 +593,18 @@ - */ - 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); - - sk_for_each(sk, node, &l2cap_sk_list.head) { -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; -+ - if (state && sk->sk_state != state) - continue; - -- if (l2cap_pi(sk)->scid == cid) { -+ if (chan->scid == cid) { - /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; -@@ -613,18 +614,16 @@ - 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(""); - -@@ -634,6 +633,8 @@ - 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); -@@ -644,22 +645,33 @@ - if (!sk) - goto clean; - -- write_lock_bh(&list->lock); -+ chan = l2cap_chan_alloc(sk); -+ if (!chan) { -+ l2cap_sock_kill(sk); -+ goto clean; -+ } -+ -+ l2cap_pi(sk)->chan = chan; -+ -+ 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); - -- __l2cap_chan_add(conn, sk, parent); -+ bt_accept_enqueue(parent, sk); -+ -+ __l2cap_chan_add(conn, 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); -@@ -667,17 +679,18 @@ - - 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) { -@@ -692,30 +705,31 @@ - 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); - -- for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { -- if (l2cap_pi(sk)->force_reliable) -+ list_for_each_entry(chan, &conn->chan_l, list) { -+ struct sock *sk = chan->sk; -+ -+ if (chan->force_reliable) - sk->sk_err = err; - } - -- read_unlock(&l->lock); -+ read_unlock(&conn->chan_lock); - } - - static void l2cap_info_timeout(unsigned long arg) -@@ -755,7 +769,9 @@ - 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, -@@ -769,6 +785,7 @@ - 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) -@@ -779,9 +796,10 @@ - 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); - } -@@ -793,12 +811,11 @@ - kfree(conn); - } - --static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) -+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, parent); -- write_unlock_bh(&l->lock); -+ write_lock_bh(&conn->chan_lock); -+ __l2cap_chan_add(conn, chan); -+ write_unlock_bh(&conn->chan_lock); - } - - /* ---- Socket interface ---- */ -@@ -814,10 +831,12 @@ - read_lock(&l2cap_sk_list.lock); - - sk_for_each(sk, node, &l2cap_sk_list.head) { -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; -+ - if (state && sk->sk_state != state) - continue; - -- if (l2cap_pi(sk)->psm == psm) { -+ if (chan->psm == psm) { - /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) - break; -@@ -833,8 +852,9 @@ - return node ? sk : sk1; - } - --int l2cap_do_connect(struct sock *sk) -+int l2cap_chan_connect(struct l2cap_chan *chan) - { -+ struct sock *sk = chan->sk; - bdaddr_t *src = &bt_sk(sk)->src; - bdaddr_t *dst = &bt_sk(sk)->dst; - struct l2cap_conn *conn; -@@ -844,7 +864,7 @@ - int err; - - BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), -- l2cap_pi(sk)->psm); -+ chan->psm); - - hdev = hci_get_route(dst, src); - if (!hdev) -@@ -852,14 +872,14 @@ - - hci_dev_lock_bh(hdev); - -- auth_type = l2cap_get_auth_type(sk); -+ auth_type = l2cap_get_auth_type(chan); - -- if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) -+ if (chan->dcid == L2CAP_CID_LE_DATA) - hcon = hci_connect(hdev, LE_LINK, dst, -- l2cap_pi(sk)->sec_level, auth_type); -+ chan->sec_level, auth_type); - else - hcon = hci_connect(hdev, ACL_LINK, dst, -- l2cap_pi(sk)->sec_level, auth_type); -+ chan->sec_level, auth_type); - - if (IS_ERR(hcon)) { - err = PTR_ERR(hcon); -@@ -876,7 +896,7 @@ - /* Update source addr of the socket */ - bacpy(src, conn->src); - -- l2cap_chan_add(conn, sk, NULL); -+ l2cap_chan_add(conn, chan); - - sk->sk_state = BT_CONNECT; - l2cap_sock_set_timer(sk, sk->sk_sndtimeo); -@@ -885,10 +905,10 @@ - if (sk->sk_type != SOCK_SEQPACKET && - sk->sk_type != SOCK_STREAM) { - l2cap_sock_clear_timer(sk); -- if (l2cap_check_security(sk)) -+ if (l2cap_check_security(chan)) - sk->sk_state = BT_CONNECTED; - } else -- l2cap_do_start(sk); -+ l2cap_do_start(chan); - } - - err = 0; -@@ -901,12 +921,13 @@ - - int __l2cap_wait_ack(struct sock *sk) - { -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - DECLARE_WAITQUEUE(wait, current); - int err = 0; - int timeo = HZ/5; - - add_wait_queue(sk_sleep(sk), &wait); -- while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { -+ while ((chan->unacked_frames > 0 && chan->conn)) { - set_current_state(TASK_INTERRUPTIBLE); - - if (!timeo) -@@ -932,68 +953,69 @@ - - 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(chan->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) -+void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) - { -- struct l2cap_pinfo *pi = l2cap_pi(sk); -- struct hci_conn *hcon = pi->conn->hcon; -+ struct hci_conn *hcon = chan->conn->hcon; - u16 flags; - -- BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); -+ BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len); - -- if (!pi->flushable && lmp_no_flush_capable(hcon->hdev)) -+ if (!chan->flushable && lmp_no_flush_capable(hcon->hdev)) - flags = ACL_START_NO_FLUSH; - else - flags = ACL_START; -@@ -1001,35 +1023,33 @@ - hci_send_acl(hcon, skb, flags); - } - --void l2cap_streaming_send(struct sock *sk) -+void l2cap_streaming_send(struct l2cap_chan *chan) - { - 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) { -+ if (chan->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)skb->data, skb->len - 2); - put_unaligned_le16(fcs, skb->data + skb->len - 2); - } - -- l2cap_do_send(sk, skb); -+ l2cap_do_send(chan, 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 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; - -@@ -1037,14 +1057,14 @@ - 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(chan->conn, chan, ECONNABORTED); - return; - } - -@@ -1053,39 +1073,39 @@ - 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) -+ control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) - | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); - - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); - -- if (pi->fcs == L2CAP_FCS_CRC16) { -+ if (chan->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2); - put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); - } - -- l2cap_do_send(sk, tx_skb); -+ l2cap_do_send(chan, tx_skb); - } - --int l2cap_ertm_send(struct sock *sk) -+int l2cap_ertm_send(struct l2cap_chan *chan) - { - struct sk_buff *skb, *tx_skb; -- struct l2cap_pinfo *pi = l2cap_pi(sk); -+ struct sock *sk = chan->sk; - u16 control, fcs; - int nsent = 0; - - 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(chan->conn, chan, ECONNABORTED); - break; - } - -@@ -1096,36 +1116,36 @@ - 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); - - -- if (pi->fcs == L2CAP_FCS_CRC16) { -+ if (chan->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2); - put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); - } - -- l2cap_do_send(sk, tx_skb); -+ l2cap_do_send(chan, tx_skb); - - __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++; - } -@@ -1133,41 +1153,39 @@ - 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; -@@ -1175,15 +1193,15 @@ - 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) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; - struct sk_buff **frag; - int err, sent = 0; - -@@ -1213,9 +1231,10 @@ - return sent; - } - --struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len) -+struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct sock *sk = chan->sk; -+ struct l2cap_conn *conn = chan->conn; - struct sk_buff *skb; - int err, count, hlen = L2CAP_HDR_SIZE + 2; - struct l2cap_hdr *lh; -@@ -1230,9 +1249,9 @@ - - /* Create L2CAP header */ - lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); -- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ lh->cid = cpu_to_le16(chan->dcid); - lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); -- put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2)); -+ put_unaligned_le16(chan->psm, skb_put(skb, 2)); - - err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); - if (unlikely(err < 0)) { -@@ -1242,9 +1261,10 @@ - return skb; - } - --struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len) -+struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct sock *sk = chan->sk; -+ struct l2cap_conn *conn = chan->conn; - struct sk_buff *skb; - int err, count, hlen = L2CAP_HDR_SIZE; - struct l2cap_hdr *lh; -@@ -1259,7 +1279,7 @@ - - /* Create L2CAP header */ - lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); -- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ lh->cid = cpu_to_le16(chan->dcid); - lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); - - err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb); -@@ -1270,9 +1290,10 @@ - return skb; - } - --struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen) -+struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) - { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct sock *sk = chan->sk; -+ struct l2cap_conn *conn = chan->conn; - struct sk_buff *skb; - int err, count, hlen = L2CAP_HDR_SIZE + 2; - struct l2cap_hdr *lh; -@@ -1285,7 +1306,7 @@ - if (sdulen) - hlen += 2; - -- if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) -+ if (chan->fcs == L2CAP_FCS_CRC16) - hlen += 2; - - count = min_t(unsigned int, (conn->mtu - hlen), len); -@@ -1296,7 +1317,7 @@ - - /* Create L2CAP header */ - lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); -- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ lh->cid = cpu_to_le16(chan->dcid); - lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE)); - put_unaligned_le16(control, skb_put(skb, 2)); - if (sdulen) -@@ -1308,16 +1329,15 @@ - return ERR_PTR(err); - } - -- if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) -+ if (chan->fcs == L2CAP_FCS_CRC16) - put_unaligned_le16(0, skb_put(skb, 2)); - - bt_cb(skb)->retries = 0; - 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 sk_buff *skb; - struct sk_buff_head sar_queue; - u16 control; -@@ -1325,26 +1345,26 @@ - - 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(chan, 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; - } - -- skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0); -+ skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0); - if (IS_ERR(skb)) { - skb_queue_purge(&sar_queue); - return PTR_ERR(skb); -@@ -1354,9 +1374,9 @@ - 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; - } -@@ -1364,10 +1384,11 @@ - static void l2cap_chan_ready(struct sock *sk) - { - struct sock *parent = bt_sk(sk)->parent; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - - BT_DBG("sk %p, parent %p", sk, parent); - -- l2cap_pi(sk)->conf_state = 0; -+ chan->conf_state = 0; - l2cap_sock_clear_timer(sk); - - if (!parent) { -@@ -1387,14 +1408,14 @@ - /* 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; - -@@ -1408,7 +1429,7 @@ - if (sock_queue_rcv_skb(sk, nskb)) - kfree_skb(nskb); - } -- read_unlock(&l->lock); -+ read_unlock(&conn->chan_lock); - } - - /* ---- L2CAP signalling commands ---- */ -@@ -1540,32 +1561,35 @@ - - 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; -- -- 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); -+ 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; - -- __skb_queue_head_init(SREJ_QUEUE(sk)); -- __skb_queue_head_init(BUSY_QUEUE(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); - -- INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); -+ skb_queue_head_init(&chan->srej_q); -+ skb_queue_head_init(&chan->busy_q); -+ -+ INIT_LIST_HEAD(&chan->srej_l); -+ -+ INIT_WORK(&chan->busy_work, l2cap_busy_work); - - sk->sk_backlog_rcv = l2cap_ertm_data_rcv; - } -@@ -1583,38 +1607,37 @@ - } - } - --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_conf_req *req = data; -- struct l2cap_conf_rfc rfc = { .mode = pi->mode }; -+ struct l2cap_conf_rfc rfc = { .mode = chan->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) { -+ switch (chan->mode) { - case L2CAP_MODE_STREAMING: - case L2CAP_MODE_ERTM: -- if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE) -+ if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE) - break; - - /* fall through */ - default: -- pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask); -+ chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask); - break; - } - - done: -- if (pi->imtu != L2CAP_DEFAULT_MTU) -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); -+ if (chan->imtu != L2CAP_DEFAULT_MTU) -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); - -- switch (pi->mode) { -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: -- if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) && -- !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING)) -+ if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && -+ !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) - break; - - rfc.mode = L2CAP_MODE_BASIC; -@@ -1630,24 +1653,24 @@ - - case L2CAP_MODE_ERTM: - rfc.mode = L2CAP_MODE_ERTM; -- rfc.txwin_size = pi->tx_win; -- rfc.max_transmit = pi->max_tx; -+ rfc.txwin_size = chan->tx_win; -+ rfc.max_transmit = chan->max_tx; - rfc.retrans_timeout = 0; - rfc.monitor_timeout = 0; - rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); -- if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) -- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); -+ if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) -+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc); - -- if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) -+ if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) - break; - -- if (pi->fcs == L2CAP_FCS_NONE || -- pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { -- pi->fcs = L2CAP_FCS_NONE; -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); -+ if (chan->fcs == L2CAP_FCS_NONE || -+ chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { -+ chan->fcs = L2CAP_FCS_NONE; -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); - } - break; - -@@ -1658,43 +1681,42 @@ - rfc.retrans_timeout = 0; - rfc.monitor_timeout = 0; - rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE); -- if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10) -- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); -+ if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10) -+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), - (unsigned long) &rfc); - -- if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS)) -+ if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) - break; - -- if (pi->fcs == L2CAP_FCS_NONE || -- pi->conf_state & L2CAP_CONF_NO_FCS_RECV) { -- pi->fcs = L2CAP_FCS_NONE; -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs); -+ if (chan->fcs == L2CAP_FCS_NONE || -+ chan->conf_state & L2CAP_CONF_NO_FCS_RECV) { -+ chan->fcs = L2CAP_FCS_NONE; -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); - } - break; - } - -- req->dcid = cpu_to_le16(pi->dcid); -+ req->dcid = cpu_to_le16(chan->dcid); - req->flags = cpu_to_le16(0); - - 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_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); -@@ -1708,7 +1730,7 @@ - break; - - case L2CAP_CONF_FLUSH_TO: -- pi->flush_to = val; -+ chan->flush_to = val; - break; - - case L2CAP_CONF_QOS: -@@ -1721,7 +1743,7 @@ - - case L2CAP_CONF_FCS: - if (val == L2CAP_FCS_NONE) -- pi->conf_state |= L2CAP_CONF_NO_FCS_RECV; -+ chan->conf_state |= L2CAP_CONF_NO_FCS_RECV; - - break; - -@@ -1735,30 +1757,30 @@ - } - } - -- 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) { -+ switch (chan->mode) { - case L2CAP_MODE_STREAMING: - case L2CAP_MODE_ERTM: -- if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) { -- pi->mode = l2cap_select_mode(rfc.mode, -- pi->conn->feat_mask); -+ if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) { -+ chan->mode = l2cap_select_mode(rfc.mode, -+ chan->conn->feat_mask); - break; - } - -- if (pi->mode != rfc.mode) -+ if (chan->mode != rfc.mode) - return -ECONNREFUSED; - - break; - } - - done: -- if (pi->mode != rfc.mode) { -+ if (chan->mode != rfc.mode) { - result = L2CAP_CONF_UNACCEPT; -- rfc.mode = pi->mode; -+ rfc.mode = chan->mode; - -- if (pi->num_conf_rsp == 1) -+ if (chan->num_conf_rsp == 1) - return -ECONNREFUSED; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, -@@ -1773,32 +1795,32 @@ - if (mtu < L2CAP_DEFAULT_MIN_MTU) - result = L2CAP_CONF_UNACCEPT; - else { -- pi->omtu = mtu; -- pi->conf_state |= L2CAP_CONF_MTU_DONE; -+ chan->omtu = mtu; -+ chan->conf_state |= L2CAP_CONF_MTU_DONE; - } -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu); -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); - - switch (rfc.mode) { - case L2CAP_MODE_BASIC: -- pi->fcs = L2CAP_FCS_NONE; -- pi->conf_state |= L2CAP_CONF_MODE_DONE; -+ chan->fcs = L2CAP_FCS_NONE; -+ chan->conf_state |= L2CAP_CONF_MODE_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); -+ if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) -+ rfc.max_pdu_size = cpu_to_le16(chan->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); - rfc.monitor_timeout = - le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO); - -- pi->conf_state |= L2CAP_CONF_MODE_DONE; -+ chan->conf_state |= L2CAP_CONF_MODE_DONE; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc); -@@ -1806,12 +1828,12 @@ - break; - - case L2CAP_MODE_STREAMING: -- if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10) -- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); -+ if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10) -+ rfc.max_pdu_size = cpu_to_le16(chan->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; -+ chan->conf_state |= L2CAP_CONF_MODE_DONE; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc); -@@ -1822,29 +1844,28 @@ - result = L2CAP_CONF_UNACCEPT; - - memset(&rfc, 0, sizeof(rfc)); -- rfc.mode = pi->mode; -+ rfc.mode = chan->mode; - } - - if (result == L2CAP_CONF_SUCCESS) -- pi->conf_state |= L2CAP_CONF_OUTPUT_DONE; -+ chan->conf_state |= L2CAP_CONF_OUTPUT_DONE; - } -- rsp->scid = cpu_to_le16(pi->dcid); -+ rsp->scid = cpu_to_le16(chan->dcid); - rsp->result = cpu_to_le16(result); - rsp->flags = cpu_to_le16(0x0000); - - return ptr - data; - } - --static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result) -+static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) - { -- struct l2cap_pinfo *pi = l2cap_pi(sk); - struct l2cap_conf_req *req = data; - void *ptr = req->data; - int type, olen; - unsigned long val; - struct l2cap_conf_rfc rfc; - -- BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data); -+ BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data); - - while (len >= L2CAP_CONF_OPT_SIZE) { - len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); -@@ -1853,27 +1874,27 @@ - case L2CAP_CONF_MTU: - if (val < L2CAP_DEFAULT_MIN_MTU) { - *result = L2CAP_CONF_UNACCEPT; -- pi->imtu = L2CAP_DEFAULT_MIN_MTU; -+ chan->imtu = L2CAP_DEFAULT_MIN_MTU; - } else -- pi->imtu = val; -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu); -+ chan->imtu = val; -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); - break; - - case L2CAP_CONF_FLUSH_TO: -- pi->flush_to = val; -+ chan->flush_to = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, -- 2, pi->flush_to); -+ 2, chan->flush_to); - break; - - case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *)val, olen); - -- if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) && -- rfc.mode != pi->mode) -+ if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) && -+ rfc.mode != chan->mode) - return -ECONNREFUSED; - -- pi->fcs = 0; -+ chan->fcs = 0; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc); -@@ -1881,53 +1902,74 @@ - } - } - -- if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode) -+ if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) - return -ECONNREFUSED; - -- pi->mode = rfc.mode; -+ chan->mode = rfc.mode; - - if (*result == L2CAP_CONF_SUCCESS) { - switch (rfc.mode) { - case L2CAP_MODE_ERTM: -- pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); -- pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); -- pi->mps = le16_to_cpu(rfc.max_pdu_size); -+ chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); -+ chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); -+ chan->mps = le16_to_cpu(rfc.max_pdu_size); - break; - case L2CAP_MODE_STREAMING: -- pi->mps = le16_to_cpu(rfc.max_pdu_size); -+ chan->mps = le16_to_cpu(rfc.max_pdu_size); - } - } - -- req->dcid = cpu_to_le16(pi->dcid); -+ req->dcid = cpu_to_le16(chan->dcid); - req->flags = cpu_to_le16(0x0000); - - return ptr - data; - } - --static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags) -+static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) - { - struct l2cap_conf_rsp *rsp = data; - void *ptr = rsp->data; - -- BT_DBG("sk %p", sk); -+ BT_DBG("chan %p", chan); - -- rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ rsp->scid = cpu_to_le16(chan->dcid); - rsp->result = cpu_to_le16(result); - rsp->flags = cpu_to_le16(flags); - - return ptr - data; - } - --static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) -+void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) -+{ -+ struct l2cap_conn_rsp rsp; -+ struct l2cap_conn *conn = chan->conn; -+ u8 buf[128]; -+ -+ rsp.scid = cpu_to_le16(chan->dcid); -+ rsp.dcid = cpu_to_le16(chan->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 (chan->conf_state & L2CAP_CONF_REQ_SENT) -+ return; -+ -+ chan->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 l2cap_chan *chan, void *rsp, int len) - { -- struct l2cap_pinfo *pi = l2cap_pi(sk); - int type, olen; - unsigned long val; - struct l2cap_conf_rfc rfc; - -- BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); -+ BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len); - -- if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) -+ if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING)) - return; - - while (len >= L2CAP_CONF_OPT_SIZE) { -@@ -1944,12 +1986,12 @@ - done: - switch (rfc.mode) { - case L2CAP_MODE_ERTM: -- pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); -- pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); -- pi->mps = le16_to_cpu(rfc.max_pdu_size); -+ chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout); -+ chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout); -+ chan->mps = le16_to_cpu(rfc.max_pdu_size); - break; - case L2CAP_MODE_STREAMING: -- pi->mps = le16_to_cpu(rfc.max_pdu_size); -+ chan->mps = le16_to_cpu(rfc.max_pdu_size); - } - } - -@@ -1975,9 +2017,9 @@ - - 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; - -@@ -2015,11 +2057,19 @@ - if (!sk) - goto response; - -- write_lock_bh(&list->lock); -+ chan = l2cap_chan_alloc(sk); -+ if (!chan) { -+ l2cap_sock_kill(sk); -+ goto response; -+ } -+ -+ l2cap_pi(sk)->chan = chan; -+ -+ 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; -@@ -2030,18 +2080,21 @@ - l2cap_sock_init(sk, parent); - bacpy(&bt_sk(sk)->src, conn->src); - bacpy(&bt_sk(sk)->dst, conn->dst); -- l2cap_pi(sk)->psm = psm; -- l2cap_pi(sk)->dcid = scid; -+ chan->psm = psm; -+ chan->dcid = scid; -+ -+ bt_accept_enqueue(parent, sk); - -- __l2cap_chan_add(conn, sk, parent); -- dcid = l2cap_pi(sk)->scid; -+ __l2cap_chan_add(conn, chan); -+ -+ dcid = chan->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)) { -+ if (l2cap_check_security(chan)) { - if (bt_sk(sk)->defer_setup) { - sk->sk_state = BT_CONNECT2; - result = L2CAP_CR_PEND; -@@ -2063,7 +2116,7 @@ - status = L2CAP_CS_NO_INFO; - } - -- write_unlock_bh(&list->lock); -+ write_unlock_bh(&conn->chan_lock); - - response: - bh_unlock_sock(parent); -@@ -2089,13 +2142,13 @@ - L2CAP_INFO_REQ, sizeof(info), &info); - } - -- if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && -+ if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) && - result == L2CAP_CR_SUCCESS) { - u8 buf[128]; -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; -+ chan->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 +2158,7 @@ - { - 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,34 +2170,36 @@ - 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; -- l2cap_pi(sk)->dcid = dcid; -- l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; -+ chan->ident = 0; -+ chan->dcid = dcid; -+ chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND; - -- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) -+ if (chan->conf_state & L2CAP_CONF_REQ_SENT) - break; - -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; -+ chan->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: -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -+ chan->conf_state |= L2CAP_CONF_CONNECT_PEND; - break; - - default: -@@ -2155,7 +2211,7 @@ - break; - } - -- l2cap_chan_del(sk, ECONNREFUSED); -+ l2cap_chan_del(chan, ECONNREFUSED); - break; - } - -@@ -2163,15 +2219,17 @@ - return 0; - } - --static inline void set_default_fcs(struct l2cap_pinfo *pi) -+static inline void set_default_fcs(struct l2cap_chan *chan) - { -+ struct l2cap_pinfo *pi = l2cap_pi(chan->sk); -+ - /* FCS is enabled only in ERTM or streaming mode, if one or both - * sides request it. - */ -- if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING) -- pi->fcs = L2CAP_FCS_NONE; -- else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV)) -- pi->fcs = L2CAP_FCS_CRC16; -+ if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) -+ chan->fcs = L2CAP_FCS_NONE; -+ else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV)) -+ chan->fcs = L2CAP_FCS_CRC16; - } - - static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) -@@ -2179,6 +2237,7 @@ - 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 +2246,12 @@ - - 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,62 +2263,62 @@ - - /* 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_build_conf_rsp(chan, rsp, - L2CAP_CONF_REJECT, flags), rsp); - goto unlock; - } - - /* 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. */ - l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, -- l2cap_build_conf_rsp(sk, rsp, -+ l2cap_build_conf_rsp(chan, rsp, - L2CAP_CONF_SUCCESS, 0x0001), rsp); - goto unlock; - } - - /* 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)) -+ if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE)) - goto unlock; - -- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { -- set_default_fcs(l2cap_pi(sk)); -+ if (chan->conf_state & L2CAP_CONF_INPUT_DONE) { -+ set_default_fcs(chan); - - 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)); -- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) -- l2cap_ertm_init(sk); -+ chan->next_tx_seq = 0; -+ chan->expected_tx_seq = 0; -+ skb_queue_head_init(&chan->tx_q); -+ if (chan->mode == L2CAP_MODE_ERTM) -+ l2cap_ertm_init(chan); - - l2cap_chan_ready(sk); - goto unlock; - } - -- if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { -+ if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) { - u8 buf[64]; -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; -+ chan->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 +2330,7 @@ - { - 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,36 +2341,38 @@ - 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); -+ l2cap_conf_rfc_get(chan, 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; - } - - /* throw out any old stored conf requests */ - result = L2CAP_CONF_SUCCESS; -- len = l2cap_parse_conf_rsp(sk, rsp->data, -- len, req, &result); -+ len = l2cap_parse_conf_rsp(chan, 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,24 +2381,24 @@ - 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; - } - - if (flags & 0x01) - goto done; - -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; -+ chan->conf_state |= L2CAP_CONF_INPUT_DONE; - -- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { -- set_default_fcs(l2cap_pi(sk)); -+ if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) { -+ set_default_fcs(chan); - - 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)); -- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) -- l2cap_ertm_init(sk); -+ chan->next_tx_seq = 0; -+ chan->expected_tx_seq = 0; -+ skb_queue_head_init(&chan->tx_q); -+ if (chan->mode == L2CAP_MODE_ERTM) -+ l2cap_ertm_init(chan); - - l2cap_chan_ready(sk); - } -@@ -2349,6 +2413,7 @@ - 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,12 +2421,14 @@ - - 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; - -- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); -- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ sk = chan->sk; -+ -+ rsp.dcid = cpu_to_le16(chan->scid); -+ rsp.scid = cpu_to_le16(chan->dcid); - l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); - - sk->sk_shutdown = SHUTDOWN_MASK; -@@ -2375,7 +2442,7 @@ - return 0; - } - -- l2cap_chan_del(sk, ECONNRESET); -+ l2cap_chan_del(chan, ECONNRESET); - bh_unlock_sock(sk); - - l2cap_sock_kill(sk); -@@ -2386,6 +2453,7 @@ - { - 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 +2461,12 @@ - - 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 +2476,7 @@ - return 0; - } - -- l2cap_chan_del(sk, 0); -+ l2cap_chan_del(chan, 0); - bh_unlock_sock(sk); - - l2cap_sock_kill(sk); -@@ -2463,6 +2533,11 @@ - - BT_DBG("type 0x%4.4x result 0x%2.2x", type, result); - -+ /* L2CAP Info req/rsp are unbound to channels, add extra checks */ -+ if (cmd->ident != conn->info_ident || -+ conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) -+ return 0; -+ - del_timer(&conn->info_timer); - - if (result != L2CAP_IR_SUCCESS) { -@@ -2673,7 +2748,8 @@ - - if (err) { - struct l2cap_cmd_rej rej; -- BT_DBG("error %d", err); -+ -+ BT_ERR("Wrong link type (%d)", err); - - /* FIXME: Map err to a valid reason */ - rej.reason = cpu_to_le16(0); -@@ -2687,12 +2763,12 @@ - kfree_skb(skb); - } - --static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb) -+static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb) - { - u16 our_fcs, rcv_fcs; - int hdr_size = L2CAP_HDR_SIZE + 2; - -- if (pi->fcs == L2CAP_FCS_CRC16) { -+ if (chan->fcs == L2CAP_FCS_CRC16) { - skb_trim(skb, skb->len - 2); - rcv_fcs = get_unaligned_le16(skb->data + skb->len); - our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size); -@@ -2703,49 +2779,47 @@ - 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; - -@@ -2754,53 +2828,52 @@ - 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 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 > chan->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 -@@ -2808,63 +2881,63 @@ - * 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 > chan->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; - } - -@@ -2872,51 +2945,50 @@ - 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(chan->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; - } -@@ -2924,21 +2996,21 @@ - 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(chan->conn, chan, EBUSY); - break; - } - -@@ -2958,7 +3030,7 @@ - if (err) - break; - -- if (l2cap_try_push_rx_skb(sk) == 0) -+ if (l2cap_try_push_rx_skb(chan) == 0) - break; - } - -@@ -2968,48 +3040,46 @@ - 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 sk_buff *_skb; - int err = -EINVAL; - -@@ -3020,80 +3090,80 @@ - - 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 > chan->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 > chan->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; - } - -@@ -3101,31 +3171,30 @@ - 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); -@@ -3133,107 +3202,105 @@ - } - 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); - u8 tx_seq = __get_txseq(rx_control); - u8 req_seq = __get_reqseq(rx_control); - u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; - int tx_seq_offset, expected_tx_seq_offset; -- int num_to_ack = (pi->tx_win/6) + 1; -+ int num_to_ack = (chan->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); -+ if (tx_seq_offset >= chan->tx_win) { -+ l2cap_send_disconn_req(chan->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; - -@@ -3241,51 +3308,51 @@ - 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; - -@@ -3294,165 +3361,160 @@ - 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; - } - -@@ -3462,7 +3524,7 @@ - - static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb) - { -- struct l2cap_pinfo *pi = l2cap_pi(sk); -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - u16 control; - u8 req_seq; - int len, next_tx_seq_offset, req_seq_offset; -@@ -3476,51 +3538,51 @@ - * Receiver will miss it and start proper recovery - * procedures and ask retransmission. - */ -- if (l2cap_check_fcs(pi, skb)) -+ if (l2cap_check_fcs(chan, skb)) - goto drop; - - if (__is_sar_start(control) && __is_iframe(control)) - len -= 2; - -- if (pi->fcs == L2CAP_FCS_CRC16) -+ if (chan->fcs == L2CAP_FCS_CRC16) - len -= 2; - -- if (len > pi->mps) { -- l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); -+ if (len > chan->mps) { -+ l2cap_send_disconn_req(chan->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(chan->conn, chan, ECONNRESET); - goto drop; - } - - if (__is_iframe(control)) { - if (len < 0) { -- l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); -+ l2cap_send_disconn_req(chan->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(chan->conn, chan, ECONNRESET); - goto drop; - } - -- l2cap_data_channel_sframe(sk, control, skb); -+ l2cap_data_channel_sframe(chan, control, skb); - } - - return 0; -@@ -3532,33 +3594,35 @@ - - 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; - -- switch (pi->mode) { -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: - /* If socket recv buffers overflows we drop data here - * which is *bad* because L2CAP has to be reliable. - * But we don't have any other choice. L2CAP doesn't - * provide flow control mechanism. */ - -- if (pi->imtu < skb->len) -+ if (chan->imtu < skb->len) - goto drop; - - if (!sock_queue_rcv_skb(sk, skb)) -@@ -3580,31 +3644,31 @@ - skb_pull(skb, 2); - len = skb->len; - -- if (l2cap_check_fcs(pi, skb)) -+ if (l2cap_check_fcs(chan, skb)) - goto drop; - - if (__is_sar_start(control)) - len -= 2; - -- if (pi->fcs == L2CAP_FCS_CRC16) -+ if (chan->fcs == L2CAP_FCS_CRC16) - len -= 2; - -- if (len > pi->mps || len < 0 || __is_sframe(control)) -+ if (len > chan->mps || len < 0 || __is_sframe(control)) - goto drop; - - 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, chan->mode); - break; - } - -@@ -3633,7 +3697,37 @@ - if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) - goto drop; - -- if (l2cap_pi(sk)->imtu < skb->len) -+ if (l2cap_pi(sk)->chan->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 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)->chan->imtu < skb->len) - goto drop; - - if (!sock_queue_rcv_skb(sk, skb)) -@@ -3677,6 +3771,10 @@ - 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; -@@ -3699,17 +3797,19 @@ - /* Find listening sockets and check their link_mode */ - read_lock(&l2cap_sk_list.lock); - sk_for_each(sk, node, &l2cap_sk_list.head) { -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; -+ - if (sk->sk_state != BT_LISTEN) - continue; - - if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { - lm1 |= HCI_LM_ACCEPT; -- if (l2cap_pi(sk)->role_switch) -+ if (chan->role_switch) - lm1 |= HCI_LM_MASTER; - exact++; - } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { - lm2 |= HCI_LM_ACCEPT; -- if (l2cap_pi(sk)->role_switch) -+ if (chan->role_switch) - lm2 |= HCI_LM_MASTER; - } - } -@@ -3761,49 +3861,50 @@ - return 0; - } - --static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt) -+static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) - { -+ struct sock *sk = chan->sk; -+ - if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM) - return; - - if (encrypt == 0x00) { -- if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) { -+ if (chan->sec_level == BT_SECURITY_MEDIUM) { - l2cap_sock_clear_timer(sk); - l2cap_sock_set_timer(sk, HZ * 5); -- } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) -+ } else if (chan->sec_level == BT_SECURITY_HIGH) - __l2cap_sock_close(sk, ECONNREFUSED); - } else { -- if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) -+ if (chan->sec_level == BT_SECURITY_MEDIUM) - l2cap_sock_clear_timer(sk); - } - } - - 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) { -+ if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { - bh_unlock_sock(sk); - continue; - } - - if (!status && (sk->sk_state == BT_CONNECTED || - sk->sk_state == BT_CONFIG)) { -- l2cap_check_encryption(sk, encrypt); -+ l2cap_check_encryption(chan, encrypt); - bh_unlock_sock(sk); - continue; - } -@@ -3811,13 +3912,13 @@ - if (sk->sk_state == BT_CONNECT) { - if (!status) { - struct l2cap_conn_req req; -- req.scid = cpu_to_le16(l2cap_pi(sk)->scid); -- req.psm = l2cap_pi(sk)->psm; -+ req.scid = cpu_to_le16(chan->scid); -+ req.psm = chan->psm; - -- l2cap_pi(sk)->ident = l2cap_get_ident(conn); -- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -+ chan->ident = l2cap_get_ident(conn); -+ chan->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); -@@ -3836,18 +3937,18 @@ - result = L2CAP_CR_SEC_BLOCK; - } - -- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); -- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); -+ rsp.scid = cpu_to_le16(chan->dcid); -+ rsp.dcid = cpu_to_le16(chan->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; - } -@@ -3866,7 +3967,7 @@ - - if (!(flags & ACL_CONT)) { - struct l2cap_hdr *hdr; -- struct sock *sk; -+ struct l2cap_chan *chan; - u16 cid; - int len; - -@@ -3904,18 +4005,21 @@ - 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 (chan->imtu < len - L2CAP_HDR_SIZE) { -+ BT_ERR("Frame exceeding recv MTU (len %d, " -+ "MTU %d)", len, -+ chan->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); -@@ -3969,14 +4073,15 @@ - - sk_for_each(sk, node, &l2cap_sk_list.head) { - struct l2cap_pinfo *pi = l2cap_pi(sk); -+ struct l2cap_chan *chan = pi->chan; - - seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", - batostr(&bt_sk(sk)->src), - batostr(&bt_sk(sk)->dst), -- sk->sk_state, __le16_to_cpu(pi->psm), -- pi->scid, pi->dcid, -- pi->imtu, pi->omtu, pi->sec_level, -- pi->mode); -+ sk->sk_state, __le16_to_cpu(chan->psm), -+ chan->scid, chan->dcid, -+ chan->imtu, chan->omtu, chan->sec_level, -+ chan->mode); - } - - read_unlock_bh(&l2cap_sk_list.lock); -diff -Naur linux-2.6.39-rc6/net/bluetooth/l2cap_sock.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/l2cap_sock.c ---- linux-2.6.39-rc6/net/bluetooth/l2cap_sock.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/l2cap_sock.c 2011-05-05 23:30:21.227873561 +0200 -@@ -30,6 +30,8 @@ - #include - #include - -+static const struct proto_ops l2cap_sock_ops; -+ - /* ---- L2CAP timers ---- */ - static void l2cap_sock_timeout(unsigned long arg) - { -@@ -51,7 +53,7 @@ - if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) - reason = ECONNREFUSED; - else if (sk->sk_state == BT_CONNECT && -- l2cap_pi(sk)->sec_level != BT_SECURITY_SDP) -+ l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP) - reason = ECONNREFUSED; - else - reason = ETIMEDOUT; -@@ -80,9 +82,13 @@ - { - struct sock *sk; - struct hlist_node *node; -- sk_for_each(sk, node, &l2cap_sk_list.head) -- if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src)) -+ sk_for_each(sk, node, &l2cap_sk_list.head) { -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; -+ -+ if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) - goto found; -+ } -+ - sk = NULL; - found: - return sk; -@@ -91,6 +97,7 @@ - static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct sockaddr_l2 la; - int len, err = 0; - -@@ -136,17 +143,17 @@ - } else { - /* Save source address */ - bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); -- l2cap_pi(sk)->psm = la.l2_psm; -- l2cap_pi(sk)->sport = la.l2_psm; -+ chan->psm = la.l2_psm; -+ chan->sport = la.l2_psm; - sk->sk_state = BT_BOUND; - - if (__le16_to_cpu(la.l2_psm) == 0x0001 || - __le16_to_cpu(la.l2_psm) == 0x0003) -- l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; -+ chan->sec_level = BT_SECURITY_SDP; - } - - if (la.l2_cid) -- l2cap_pi(sk)->scid = la.l2_cid; -+ chan->scid = la.l2_cid; - - write_unlock_bh(&l2cap_sk_list.lock); - -@@ -158,6 +165,7 @@ - static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct sockaddr_l2 la; - int len, err = 0; - -@@ -182,7 +190,7 @@ - goto done; - } - -- switch (l2cap_pi(sk)->mode) { -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: - break; - case L2CAP_MODE_ERTM: -@@ -226,10 +234,10 @@ - - /* Set destination address and psm */ - bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); -- l2cap_pi(sk)->psm = la.l2_psm; -- l2cap_pi(sk)->dcid = la.l2_cid; -+ chan->psm = la.l2_psm; -+ chan->dcid = la.l2_cid; - -- err = l2cap_do_connect(sk); -+ err = l2cap_chan_connect(l2cap_pi(sk)->chan); - if (err) - goto done; - -@@ -244,6 +252,7 @@ - static int l2cap_sock_listen(struct socket *sock, int backlog) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - int err = 0; - - BT_DBG("sk %p backlog %d", sk, backlog); -@@ -256,7 +265,7 @@ - goto done; - } - -- switch (l2cap_pi(sk)->mode) { -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: - break; - case L2CAP_MODE_ERTM: -@@ -269,7 +278,7 @@ - goto done; - } - -- if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) { -+ if (!chan->psm && !chan->scid) { - bdaddr_t *src = &bt_sk(sk)->src; - u16 psm; - -@@ -279,8 +288,8 @@ - - for (psm = 0x1001; psm < 0x1100; psm += 2) - if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { -- l2cap_pi(sk)->psm = cpu_to_le16(psm); -- l2cap_pi(sk)->sport = cpu_to_le16(psm); -+ chan->psm = cpu_to_le16(psm); -+ chan->sport = cpu_to_le16(psm); - err = 0; - break; - } -@@ -360,6 +369,7 @@ - { - struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - - BT_DBG("sock %p, sk %p", sock, sk); - -@@ -367,13 +377,13 @@ - *len = sizeof(struct sockaddr_l2); - - if (peer) { -- la->l2_psm = l2cap_pi(sk)->psm; -+ la->l2_psm = chan->psm; - bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); -- la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid); -+ la->l2_cid = cpu_to_le16(chan->dcid); - } else { -- la->l2_psm = l2cap_pi(sk)->sport; -+ la->l2_psm = chan->sport; - bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); -- la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid); -+ la->l2_cid = cpu_to_le16(chan->scid); - } - - return 0; -@@ -382,6 +392,7 @@ - static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct l2cap_options opts; - struct l2cap_conninfo cinfo; - int len, err = 0; -@@ -397,13 +408,13 @@ - switch (optname) { - case L2CAP_OPTIONS: - memset(&opts, 0, sizeof(opts)); -- opts.imtu = l2cap_pi(sk)->imtu; -- opts.omtu = l2cap_pi(sk)->omtu; -- opts.flush_to = l2cap_pi(sk)->flush_to; -- opts.mode = l2cap_pi(sk)->mode; -- opts.fcs = l2cap_pi(sk)->fcs; -- opts.max_tx = l2cap_pi(sk)->max_tx; -- opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; -+ opts.imtu = chan->imtu; -+ opts.omtu = chan->omtu; -+ opts.flush_to = chan->flush_to; -+ opts.mode = chan->mode; -+ opts.fcs = chan->fcs; -+ opts.max_tx = chan->max_tx; -+ opts.txwin_size = (__u16)chan->tx_win; - - len = min_t(unsigned int, len, sizeof(opts)); - if (copy_to_user(optval, (char *) &opts, len)) -@@ -412,7 +423,7 @@ - break; - - case L2CAP_LM: -- switch (l2cap_pi(sk)->sec_level) { -+ switch (chan->sec_level) { - case BT_SECURITY_LOW: - opt = L2CAP_LM_AUTH; - break; -@@ -428,10 +439,10 @@ - break; - } - -- if (l2cap_pi(sk)->role_switch) -+ if (chan->role_switch) - opt |= L2CAP_LM_MASTER; - -- if (l2cap_pi(sk)->force_reliable) -+ if (chan->force_reliable) - opt |= L2CAP_LM_RELIABLE; - - if (put_user(opt, (u32 __user *) optval)) -@@ -446,8 +457,8 @@ - break; - } - -- cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle; -- memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3); -+ cinfo.hci_handle = chan->conn->hcon->handle; -+ memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); - - len = min_t(unsigned int, len, sizeof(cinfo)); - if (copy_to_user(optval, (char *) &cinfo, len)) -@@ -467,6 +478,7 @@ - static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct bt_security sec; - int len, err = 0; - -@@ -491,7 +503,7 @@ - break; - } - -- sec.level = l2cap_pi(sk)->sec_level; -+ sec.level = chan->sec_level; - - len = min_t(unsigned int, len, sizeof(sec)); - if (copy_to_user(optval, (char *) &sec, len)) -@@ -511,7 +523,7 @@ - break; - - case BT_FLUSHABLE: -- if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval)) -+ if (put_user(chan->flushable, (u32 __user *) optval)) - err = -EFAULT; - - break; -@@ -528,6 +540,7 @@ - static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct l2cap_options opts; - int len, err = 0; - u32 opt; -@@ -543,13 +556,13 @@ - break; - } - -- opts.imtu = l2cap_pi(sk)->imtu; -- opts.omtu = l2cap_pi(sk)->omtu; -- opts.flush_to = l2cap_pi(sk)->flush_to; -- opts.mode = l2cap_pi(sk)->mode; -- opts.fcs = l2cap_pi(sk)->fcs; -- opts.max_tx = l2cap_pi(sk)->max_tx; -- opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win; -+ opts.imtu = chan->imtu; -+ opts.omtu = chan->omtu; -+ opts.flush_to = chan->flush_to; -+ opts.mode = chan->mode; -+ opts.fcs = chan->fcs; -+ opts.max_tx = chan->max_tx; -+ opts.txwin_size = (__u16)chan->tx_win; - - len = min_t(unsigned int, sizeof(opts), optlen); - if (copy_from_user((char *) &opts, optval, len)) { -@@ -562,10 +575,10 @@ - break; - } - -- l2cap_pi(sk)->mode = opts.mode; -- switch (l2cap_pi(sk)->mode) { -+ chan->mode = opts.mode; -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: -- l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; -+ chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE; - break; - case L2CAP_MODE_ERTM: - case L2CAP_MODE_STREAMING: -@@ -577,11 +590,11 @@ - break; - } - -- l2cap_pi(sk)->imtu = opts.imtu; -- l2cap_pi(sk)->omtu = opts.omtu; -- l2cap_pi(sk)->fcs = opts.fcs; -- l2cap_pi(sk)->max_tx = opts.max_tx; -- l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size; -+ chan->imtu = opts.imtu; -+ chan->omtu = opts.omtu; -+ chan->fcs = opts.fcs; -+ chan->max_tx = opts.max_tx; -+ chan->tx_win = (__u8)opts.txwin_size; - break; - - case L2CAP_LM: -@@ -591,14 +604,14 @@ - } - - if (opt & L2CAP_LM_AUTH) -- l2cap_pi(sk)->sec_level = BT_SECURITY_LOW; -+ chan->sec_level = BT_SECURITY_LOW; - if (opt & L2CAP_LM_ENCRYPT) -- l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM; -+ chan->sec_level = BT_SECURITY_MEDIUM; - if (opt & L2CAP_LM_SECURE) -- l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH; -+ chan->sec_level = BT_SECURITY_HIGH; - -- l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER); -- l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE); -+ chan->role_switch = (opt & L2CAP_LM_MASTER); -+ chan->force_reliable = (opt & L2CAP_LM_RELIABLE); - break; - - default: -@@ -613,6 +626,7 @@ - static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct bt_security sec; - int len, err = 0; - u32 opt; -@@ -649,7 +663,7 @@ - break; - } - -- l2cap_pi(sk)->sec_level = sec.level; -+ chan->sec_level = sec.level; - break; - - case BT_DEFER_SETUP: -@@ -678,7 +692,7 @@ - } - - if (opt == BT_FLUSHABLE_OFF) { -- struct l2cap_conn *conn = l2cap_pi(sk)->conn; -+ struct l2cap_conn *conn = chan->conn; - /* proceed further only when we have l2cap_conn and - No Flush support in the LM */ - if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { -@@ -687,7 +701,7 @@ - } - } - -- l2cap_pi(sk)->flushable = opt; -+ chan->flushable = opt; - break; - - default: -@@ -702,7 +716,7 @@ - static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) - { - struct sock *sk = sock->sk; -- struct l2cap_pinfo *pi = l2cap_pi(sk); -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - struct sk_buff *skb; - u16 control; - int err; -@@ -725,74 +739,77 @@ - - /* Connectionless channel */ - if (sk->sk_type == SOCK_DGRAM) { -- skb = l2cap_create_connless_pdu(sk, msg, len); -+ skb = l2cap_create_connless_pdu(chan, msg, len); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - } else { -- l2cap_do_send(sk, skb); -+ l2cap_do_send(chan, skb); - err = len; - } - goto done; - } - -- switch (pi->mode) { -+ switch (chan->mode) { - case L2CAP_MODE_BASIC: - /* Check outgoing MTU */ -- if (len > pi->omtu) { -+ if (len > chan->omtu) { - err = -EMSGSIZE; - goto done; - } - - /* Create a basic PDU */ -- skb = l2cap_create_basic_pdu(sk, msg, len); -+ skb = l2cap_create_basic_pdu(chan, msg, len); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - goto done; - } - -- l2cap_do_send(sk, skb); -+ l2cap_do_send(chan, skb); - err = len; - break; - - case L2CAP_MODE_ERTM: - case L2CAP_MODE_STREAMING: - /* Entire SDU fits into one PDU */ -- if (len <= pi->remote_mps) { -+ if (len <= chan->remote_mps) { - control = L2CAP_SDU_UNSEGMENTED; -- skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); -+ skb = l2cap_create_iframe_pdu(chan, msg, len, control, -+ 0); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - goto done; - } -- __skb_queue_tail(TX_QUEUE(sk), skb); -+ __skb_queue_tail(&chan->tx_q, skb); - -- if (sk->sk_send_head == NULL) -- sk->sk_send_head = skb; -+ if (chan->tx_send_head == NULL) -+ chan->tx_send_head = skb; - - } else { - /* Segment SDU into multiples PDUs */ -- err = l2cap_sar_segment_sdu(sk, msg, len); -+ err = l2cap_sar_segment_sdu(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); -+ if (chan->mode == L2CAP_MODE_STREAMING) { -+ l2cap_streaming_send(chan); -+ err = len; -+ break; -+ } -+ -+ if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && -+ (chan->conn_state & L2CAP_CONN_WAIT_F)) { -+ err = len; -+ break; - } -+ err = l2cap_ertm_send(chan); - - if (err >= 0) - err = len; - break; - - default: -- BT_DBG("bad state %1.1x", pi->mode); -+ BT_DBG("bad state %1.1x", chan->mode); - err = -EBADFD; - } - -@@ -808,29 +825,9 @@ - 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(l2cap_pi(sk)->chan); - release_sock(sk); - return 0; - } -@@ -854,6 +851,8 @@ - BT_DBG("sk %p state %d", sk, sk->sk_state); - - /* Kill poor orphan */ -+ -+ l2cap_chan_free(l2cap_pi(sk)->chan); - bt_sock_unlink(&l2cap_sk_list, sk); - sock_set_flag(sk, SOCK_DEAD); - sock_put(sk); -@@ -885,7 +884,8 @@ - - 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; -+ struct l2cap_conn *conn = chan->conn; - - BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); - -@@ -900,9 +900,9 @@ - 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: -@@ -917,20 +917,20 @@ - else - result = L2CAP_CR_BAD_PSM; - -- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); -- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); -+ rsp.scid = cpu_to_le16(chan->dcid); -+ rsp.dcid = cpu_to_le16(chan->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: -@@ -942,6 +942,7 @@ - static int l2cap_sock_shutdown(struct socket *sock, int how) - { - struct sock *sk = sock->sk; -+ struct l2cap_chan *chan = l2cap_pi(sk)->chan; - int err = 0; - - BT_DBG("sock %p, sk %p", sock, sk); -@@ -951,7 +952,7 @@ - - lock_sock(sk); - if (!sk->sk_shutdown) { -- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) -+ if (chan->mode == L2CAP_MODE_ERTM) - err = __l2cap_wait_ack(sk); - - sk->sk_shutdown = SHUTDOWN_MASK; -@@ -998,49 +999,47 @@ - void l2cap_sock_init(struct sock *sk, struct sock *parent) - { - struct l2cap_pinfo *pi = l2cap_pi(sk); -+ struct l2cap_chan *chan = pi->chan; - - BT_DBG("sk %p", sk); - - if (parent) { -+ struct l2cap_chan *pchan = l2cap_pi(parent)->chan; -+ - sk->sk_type = parent->sk_type; - bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; - -- pi->imtu = l2cap_pi(parent)->imtu; -- pi->omtu = l2cap_pi(parent)->omtu; -- pi->conf_state = l2cap_pi(parent)->conf_state; -- pi->mode = l2cap_pi(parent)->mode; -- pi->fcs = l2cap_pi(parent)->fcs; -- pi->max_tx = l2cap_pi(parent)->max_tx; -- pi->tx_win = l2cap_pi(parent)->tx_win; -- pi->sec_level = l2cap_pi(parent)->sec_level; -- pi->role_switch = l2cap_pi(parent)->role_switch; -- pi->force_reliable = l2cap_pi(parent)->force_reliable; -- pi->flushable = l2cap_pi(parent)->flushable; -+ chan->imtu = pchan->imtu; -+ chan->omtu = pchan->omtu; -+ chan->conf_state = pchan->conf_state; -+ chan->mode = pchan->mode; -+ chan->fcs = pchan->fcs; -+ chan->max_tx = pchan->max_tx; -+ chan->tx_win = pchan->tx_win; -+ chan->sec_level = pchan->sec_level; -+ chan->role_switch = pchan->role_switch; -+ chan->force_reliable = pchan->force_reliable; -+ chan->flushable = pchan->flushable; - } else { -- pi->imtu = L2CAP_DEFAULT_MTU; -- pi->omtu = 0; -+ chan->imtu = L2CAP_DEFAULT_MTU; -+ chan->omtu = 0; - if (!disable_ertm && sk->sk_type == SOCK_STREAM) { -- pi->mode = L2CAP_MODE_ERTM; -- pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; -+ chan->mode = L2CAP_MODE_ERTM; -+ chan->conf_state |= L2CAP_CONF_STATE2_DEVICE; - } else { -- pi->mode = L2CAP_MODE_BASIC; -+ chan->mode = L2CAP_MODE_BASIC; - } -- pi->max_tx = L2CAP_DEFAULT_MAX_TX; -- pi->fcs = L2CAP_FCS_CRC16; -- pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; -- pi->sec_level = BT_SECURITY_LOW; -- pi->role_switch = 0; -- pi->force_reliable = 0; -- pi->flushable = BT_FLUSHABLE_OFF; -+ chan->max_tx = L2CAP_DEFAULT_MAX_TX; -+ chan->fcs = L2CAP_FCS_CRC16; -+ chan->tx_win = L2CAP_DEFAULT_TX_WINDOW; -+ chan->sec_level = BT_SECURITY_LOW; -+ chan->role_switch = 0; -+ chan->force_reliable = 0; -+ chan->flushable = BT_FLUSHABLE_OFF; - } - - /* 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)); -+ chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; - } - - static struct proto l2cap_proto = { -@@ -1078,6 +1077,7 @@ - int kern) - { - struct sock *sk; -+ struct l2cap_chan *chan; - - BT_DBG("sock %p", sock); - -@@ -1096,11 +1096,19 @@ - if (!sk) - return -ENOMEM; - -+ chan = l2cap_chan_alloc(sk); -+ if (!chan) { -+ l2cap_sock_kill(sk); -+ return -ENOMEM; -+ } -+ -+ l2cap_pi(sk)->chan = chan; -+ - l2cap_sock_init(sk, NULL); - return 0; - } - --const struct proto_ops l2cap_sock_ops = { -+static const struct proto_ops l2cap_sock_ops = { - .family = PF_BLUETOOTH, - .owner = THIS_MODULE, - .release = l2cap_sock_release, -diff -Naur linux-2.6.39-rc6/net/bluetooth/mgmt.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/mgmt.c ---- linux-2.6.39-rc6/net/bluetooth/mgmt.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/mgmt.c 2011-05-05 23:30:21.166872823 +0200 -@@ -36,7 +36,7 @@ - struct list_head list; - __u16 opcode; - int index; -- void *cmd; -+ void *param; - struct sock *sk; - void *user_data; - }; -@@ -179,10 +179,12 @@ - - hci_del_off_timer(hdev); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - set_bit(HCI_MGMT, &hdev->flags); - -+ memset(&rp, 0, sizeof(rp)); -+ - rp.type = hdev->dev_type; - - rp.powered = test_bit(HCI_UP, &hdev->flags); -@@ -204,7 +206,9 @@ - rp.hci_ver = hdev->hci_ver; - put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); - -- hci_dev_unlock_bh(hdev); -+ memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); -+ -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); -@@ -213,7 +217,7 @@ - static void mgmt_pending_free(struct pending_cmd *cmd) - { - sock_put(cmd->sk); -- kfree(cmd->cmd); -+ kfree(cmd->param); - kfree(cmd); - } - -@@ -229,13 +233,14 @@ - cmd->opcode = opcode; - cmd->index = index; - -- cmd->cmd = kmalloc(len, GFP_ATOMIC); -- if (!cmd->cmd) { -+ cmd->param = kmalloc(len, GFP_ATOMIC); -+ if (!cmd->param) { - kfree(cmd); - return NULL; - } - -- memcpy(cmd->cmd, data, len); -+ if (data) -+ memcpy(cmd->param, data, len); - - cmd->sk = sk; - sock_hold(sk); -@@ -311,7 +316,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - up = test_bit(HCI_UP, &hdev->flags); - if ((cp->val && up) || (!cp->val && !up)) { -@@ -338,7 +343,7 @@ - err = 0; - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - return err; - } -@@ -363,7 +368,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); -@@ -398,7 +403,7 @@ - mgmt_pending_remove(cmd); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -424,7 +429,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); -@@ -458,7 +463,7 @@ - mgmt_pending_remove(cmd); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -517,7 +522,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (cp->val) - set_bit(HCI_PAIRABLE, &hdev->flags); -@@ -533,12 +538,156 @@ - err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; - } - -+#define EIR_FLAGS 0x01 /* flags */ -+#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */ -+#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ -+#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */ -+#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ -+#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */ -+#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ -+#define EIR_NAME_SHORT 0x08 /* shortened local name */ -+#define EIR_NAME_COMPLETE 0x09 /* complete local name */ -+#define EIR_TX_POWER 0x0A /* transmit power level */ -+#define EIR_DEVICE_ID 0x10 /* device ID */ -+ -+#define PNP_INFO_SVCLASS_ID 0x1200 -+ -+static u8 bluetooth_base_uuid[] = { -+ 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, -+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+}; -+ -+static u16 get_uuid16(u8 *uuid128) -+{ -+ u32 val; -+ int i; -+ -+ for (i = 0; i < 12; i++) { -+ if (bluetooth_base_uuid[i] != uuid128[i]) -+ return 0; -+ } -+ -+ memcpy(&val, &uuid128[12], 4); -+ -+ val = le32_to_cpu(val); -+ if (val > 0xffff) -+ return 0; -+ -+ return (u16) val; -+} -+ -+static void create_eir(struct hci_dev *hdev, u8 *data) -+{ -+ u8 *ptr = data; -+ u16 eir_len = 0; -+ u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; -+ int i, truncated = 0; -+ struct list_head *p; -+ size_t name_len; -+ -+ name_len = strlen(hdev->dev_name); -+ -+ if (name_len > 0) { -+ /* EIR Data type */ -+ if (name_len > 48) { -+ name_len = 48; -+ ptr[1] = EIR_NAME_SHORT; -+ } else -+ ptr[1] = EIR_NAME_COMPLETE; -+ -+ /* EIR Data length */ -+ ptr[0] = name_len + 1; -+ -+ memcpy(ptr + 2, hdev->dev_name, name_len); -+ -+ eir_len += (name_len + 2); -+ ptr += (name_len + 2); -+ } -+ -+ memset(uuid16_list, 0, sizeof(uuid16_list)); -+ -+ /* Group all UUID16 types */ -+ list_for_each(p, &hdev->uuids) { -+ struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list); -+ u16 uuid16; -+ -+ uuid16 = get_uuid16(uuid->uuid); -+ if (uuid16 == 0) -+ return; -+ -+ if (uuid16 < 0x1100) -+ continue; -+ -+ if (uuid16 == PNP_INFO_SVCLASS_ID) -+ continue; -+ -+ /* Stop if not enough space to put next UUID */ -+ if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { -+ truncated = 1; -+ break; -+ } -+ -+ /* Check for duplicates */ -+ for (i = 0; uuid16_list[i] != 0; i++) -+ if (uuid16_list[i] == uuid16) -+ break; -+ -+ if (uuid16_list[i] == 0) { -+ uuid16_list[i] = uuid16; -+ eir_len += sizeof(u16); -+ } -+ } -+ -+ if (uuid16_list[0] != 0) { -+ u8 *length = ptr; -+ -+ /* EIR Data type */ -+ ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; -+ -+ ptr += 2; -+ eir_len += 2; -+ -+ for (i = 0; uuid16_list[i] != 0; i++) { -+ *ptr++ = (uuid16_list[i] & 0x00ff); -+ *ptr++ = (uuid16_list[i] & 0xff00) >> 8; -+ } -+ -+ /* EIR Data length */ -+ *length = (i * sizeof(u16)) + 1; -+ } -+} -+ -+static int update_eir(struct hci_dev *hdev) -+{ -+ struct hci_cp_write_eir cp; -+ -+ if (!(hdev->features[6] & LMP_EXT_INQ)) -+ return 0; -+ -+ if (hdev->ssp_mode == 0) -+ return 0; -+ -+ if (test_bit(HCI_SERVICE_CACHE, &hdev->flags)) -+ return 0; -+ -+ memset(&cp, 0, sizeof(cp)); -+ -+ create_eir(hdev, cp.data); -+ -+ if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) -+ return 0; -+ -+ memcpy(hdev->eir, cp.data, sizeof(cp.data)); -+ -+ return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); -+} -+ - static u8 get_service_classes(struct hci_dev *hdev) - { - struct list_head *p; -@@ -590,7 +739,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); - if (!uuid) { -@@ -607,10 +756,14 @@ - if (err < 0) - goto failed; - -+ err = update_eir(hdev); -+ if (err < 0) -+ goto failed; -+ - err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -635,7 +788,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { - err = hci_uuids_clear(hdev); -@@ -663,10 +816,14 @@ - if (err < 0) - goto unlock; - -+ err = update_eir(hdev); -+ if (err < 0) -+ goto unlock; -+ - err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); - - unlock: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -690,7 +847,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - hdev->major_class = cp->major; - hdev->minor_class = cp->minor; -@@ -700,7 +857,7 @@ - if (err == 0) - err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); - -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -722,7 +879,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - BT_DBG("hci%u enable %d", index, cp->enable); - -@@ -732,13 +889,15 @@ - } else { - clear_bit(HCI_SERVICE_CACHE, &hdev->flags); - err = update_class(hdev); -+ if (err == 0) -+ err = update_eir(hdev); - } - - if (err == 0) - err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL, - 0); - -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -772,7 +931,7 @@ - BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, - key_count); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - hci_link_keys_clear(hdev); - -@@ -786,11 +945,11 @@ - for (i = 0; i < key_count; i++) { - struct mgmt_key_info *key = &cp->keys[i]; - -- hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type, -+ hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, - key->pin_len); - } - -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return 0; -@@ -812,7 +971,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - err = hci_remove_link_key(hdev, &cp->bdaddr); - if (err < 0) { -@@ -835,7 +994,7 @@ - } - - unlock: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -861,7 +1020,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); -@@ -893,7 +1052,7 @@ - mgmt_pending_remove(cmd); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -914,7 +1073,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - count = 0; - list_for_each(p, &hdev->conn_hash.list) { -@@ -945,7 +1104,7 @@ - - unlock: - kfree(rp); -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - return err; - } -@@ -970,7 +1129,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); -@@ -992,7 +1151,7 @@ - mgmt_pending_remove(cmd); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -1019,7 +1178,7 @@ - return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, - ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, -@@ -1040,7 +1199,7 @@ - mgmt_pending_remove(cmd); - - failed: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -1063,14 +1222,14 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - hdev->io_capability = cp->io_capability; - - BT_DBG("%s IO capability set to 0x%02x", hdev->name, - hdev->io_capability); - -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); -@@ -1156,7 +1315,7 @@ - if (!hdev) - return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (cp->io_cap == 0x03) { - sec_level = BT_SECURITY_MEDIUM; -@@ -1198,7 +1357,7 @@ - err = 0; - - unlock: -- hci_dev_unlock_bh(hdev); -+ hci_dev_unlock(hdev); - hci_dev_put(hdev); - - return err; -@@ -1230,7 +1389,7 @@ - if (!hdev) - return cmd_status(sk, index, mgmt_op, ENODEV); - -- hci_dev_lock_bh(hdev); -+ hci_dev_lock(hdev); - - if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, mgmt_op, ENETDOWN); -@@ -1248,6 +1407,231 @@ - mgmt_pending_remove(cmd); - - failed: -+ hci_dev_unlock(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int set_local_name(struct sock *sk, u16 index, unsigned char *data, -+ u16 len) -+{ -+ struct mgmt_cp_set_local_name *mgmt_cp = (void *) data; -+ struct hci_cp_write_local_name hci_cp; -+ struct hci_dev *hdev; -+ struct pending_cmd *cmd; -+ int err; -+ -+ BT_DBG(""); -+ -+ if (len != sizeof(*mgmt_cp)) -+ return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); -+ -+ hci_dev_lock(hdev); -+ -+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len); -+ if (!cmd) { -+ err = -ENOMEM; -+ goto failed; -+ } -+ -+ memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name)); -+ err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp), -+ &hci_cp); -+ if (err < 0) -+ mgmt_pending_remove(cmd); -+ -+failed: -+ hci_dev_unlock(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int read_local_oob_data(struct sock *sk, u16 index) -+{ -+ struct hci_dev *hdev; -+ struct pending_cmd *cmd; -+ int err; -+ -+ BT_DBG("hci%u", index); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, -+ ENODEV); -+ -+ hci_dev_lock(hdev); -+ -+ if (!test_bit(HCI_UP, &hdev->flags)) { -+ err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, -+ ENETDOWN); -+ goto unlock; -+ } -+ -+ if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { -+ err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, -+ EOPNOTSUPP); -+ goto unlock; -+ } -+ -+ if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) { -+ err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); -+ goto unlock; -+ } -+ -+ cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0); -+ if (!cmd) { -+ err = -ENOMEM; -+ goto unlock; -+ } -+ -+ err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); -+ if (err < 0) -+ mgmt_pending_remove(cmd); -+ -+unlock: -+ hci_dev_unlock(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, -+ u16 len) -+{ -+ struct hci_dev *hdev; -+ struct mgmt_cp_add_remote_oob_data *cp = (void *) data; -+ int err; -+ -+ BT_DBG("hci%u ", index); -+ -+ if (len != sizeof(*cp)) -+ return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -+ EINVAL); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -+ ENODEV); -+ -+ hci_dev_lock(hdev); -+ -+ err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, -+ cp->randomizer); -+ if (err < 0) -+ err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); -+ else -+ err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, -+ 0); -+ -+ hci_dev_unlock(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int remove_remote_oob_data(struct sock *sk, u16 index, -+ unsigned char *data, u16 len) -+{ -+ struct hci_dev *hdev; -+ struct mgmt_cp_remove_remote_oob_data *cp = (void *) data; -+ int err; -+ -+ BT_DBG("hci%u ", index); -+ -+ if (len != sizeof(*cp)) -+ return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, -+ EINVAL); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, -+ ENODEV); -+ -+ hci_dev_lock(hdev); -+ -+ err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); -+ if (err < 0) -+ err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, -+ -err); -+ else -+ err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, -+ NULL, 0); -+ -+ hci_dev_unlock(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int start_discovery(struct sock *sk, u16 index) -+{ -+ u8 lap[3] = { 0x33, 0x8b, 0x9e }; -+ struct hci_cp_inquiry cp; -+ struct pending_cmd *cmd; -+ struct hci_dev *hdev; -+ int err; -+ -+ BT_DBG("hci%u", index); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV); -+ -+ hci_dev_lock_bh(hdev); -+ -+ cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0); -+ if (!cmd) { -+ err = -ENOMEM; -+ goto failed; -+ } -+ -+ memset(&cp, 0, sizeof(cp)); -+ memcpy(&cp.lap, lap, 3); -+ cp.length = 0x08; -+ cp.num_rsp = 0x00; -+ -+ err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); -+ if (err < 0) -+ mgmt_pending_remove(cmd); -+ -+failed: -+ hci_dev_unlock_bh(hdev); -+ hci_dev_put(hdev); -+ -+ return err; -+} -+ -+static int stop_discovery(struct sock *sk, u16 index) -+{ -+ struct hci_dev *hdev; -+ struct pending_cmd *cmd; -+ int err; -+ -+ BT_DBG("hci%u", index); -+ -+ hdev = hci_dev_get(index); -+ if (!hdev) -+ return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV); -+ -+ hci_dev_lock_bh(hdev); -+ -+ cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0); -+ if (!cmd) { -+ err = -ENOMEM; -+ goto failed; -+ } -+ -+ err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); -+ if (err < 0) -+ mgmt_pending_remove(cmd); -+ -+failed: - hci_dev_unlock_bh(hdev); - hci_dev_put(hdev); - -@@ -1266,7 +1650,7 @@ - if (msglen < sizeof(*hdr)) - return -EINVAL; - -- buf = kmalloc(msglen, GFP_ATOMIC); -+ buf = kmalloc(msglen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - -@@ -1349,6 +1733,25 @@ - case MGMT_OP_USER_CONFIRM_NEG_REPLY: - err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); - break; -+ case MGMT_OP_SET_LOCAL_NAME: -+ err = set_local_name(sk, index, buf + sizeof(*hdr), len); -+ break; -+ case MGMT_OP_READ_LOCAL_OOB_DATA: -+ err = read_local_oob_data(sk, index); -+ break; -+ case MGMT_OP_ADD_REMOTE_OOB_DATA: -+ err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len); -+ break; -+ case MGMT_OP_REMOVE_REMOTE_OOB_DATA: -+ err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr), -+ len); -+ break; -+ case MGMT_OP_START_DISCOVERY: -+ err = start_discovery(sk, index); -+ break; -+ case MGMT_OP_STOP_DISCOVERY: -+ err = stop_discovery(sk, index); -+ break; - default: - BT_DBG("Unknown op %u", opcode); - err = cmd_status(sk, index, opcode, 0x01); -@@ -1382,7 +1785,7 @@ - - static void mode_rsp(struct pending_cmd *cmd, void *data) - { -- struct mgmt_mode *cp = cmd->cmd; -+ struct mgmt_mode *cp = cmd->param; - struct cmd_lookup *match = data; - - if (cp->val != match->val) -@@ -1455,17 +1858,17 @@ - return ret; - } - --int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type) -+int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) - { - struct mgmt_ev_new_key ev; - - memset(&ev, 0, sizeof(ev)); - -+ ev.store_hint = persistent; - bacpy(&ev.key.bdaddr, &key->bdaddr); - ev.key.type = key->type; - memcpy(ev.key.val, key->val, 16); - ev.key.pin_len = key->pin_len; -- ev.old_key_type = old_key_type; - - return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); - } -@@ -1481,7 +1884,7 @@ - - static void disconnect_rsp(struct pending_cmd *cmd, void *data) - { -- struct mgmt_cp_disconnect *cp = cmd->cmd; -+ struct mgmt_cp_disconnect *cp = cmd->param; - struct sock **sk = data; - struct mgmt_rp_disconnect rp; - -@@ -1539,11 +1942,12 @@ - return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL); - } - --int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr) -+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure) - { - struct mgmt_ev_pin_code_request ev; - - bacpy(&ev.bdaddr, bdaddr); -+ ev.secure = secure; - - return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev), - NULL); -@@ -1591,13 +1995,15 @@ - return err; - } - --int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value) -+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, -+ u8 confirm_hint) - { - struct mgmt_ev_user_confirm_request ev; - - BT_DBG("hci%u", index); - - bacpy(&ev.bdaddr, bdaddr); -+ ev.confirm_hint = confirm_hint; - put_unaligned_le32(value, &ev.value); - - return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev), -@@ -1645,3 +2051,110 @@ - - return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL); - } -+ -+int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status) -+{ -+ struct pending_cmd *cmd; -+ struct hci_dev *hdev; -+ struct mgmt_cp_set_local_name ev; -+ int err; -+ -+ memset(&ev, 0, sizeof(ev)); -+ memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); -+ -+ cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index); -+ if (!cmd) -+ goto send_event; -+ -+ if (status) { -+ err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO); -+ goto failed; -+ } -+ -+ hdev = hci_dev_get(index); -+ if (hdev) { -+ hci_dev_lock_bh(hdev); -+ update_eir(hdev); -+ hci_dev_unlock_bh(hdev); -+ hci_dev_put(hdev); -+ } -+ -+ err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev, -+ sizeof(ev)); -+ if (err < 0) -+ goto failed; -+ -+send_event: -+ err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev), -+ cmd ? cmd->sk : NULL); -+ -+failed: -+ if (cmd) -+ mgmt_pending_remove(cmd); -+ return err; -+} -+ -+int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, -+ u8 status) -+{ -+ struct pending_cmd *cmd; -+ int err; -+ -+ BT_DBG("hci%u status %u", index, status); -+ -+ cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index); -+ if (!cmd) -+ return -ENOENT; -+ -+ if (status) { -+ err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, -+ EIO); -+ } else { -+ struct mgmt_rp_read_local_oob_data rp; -+ -+ memcpy(rp.hash, hash, sizeof(rp.hash)); -+ memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); -+ -+ err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, -+ &rp, sizeof(rp)); -+ } -+ -+ mgmt_pending_remove(cmd); -+ -+ return err; -+} -+ -+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, -+ u8 *eir) -+{ -+ struct mgmt_ev_device_found ev; -+ -+ memset(&ev, 0, sizeof(ev)); -+ -+ bacpy(&ev.bdaddr, bdaddr); -+ memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); -+ ev.rssi = rssi; -+ -+ if (eir) -+ memcpy(ev.eir, eir, sizeof(ev.eir)); -+ -+ return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); -+} -+ -+int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name) -+{ -+ struct mgmt_ev_remote_name ev; -+ -+ memset(&ev, 0, sizeof(ev)); -+ -+ bacpy(&ev.bdaddr, bdaddr); -+ memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); -+ -+ return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL); -+} -+ -+int mgmt_discovering(u16 index, u8 discovering) -+{ -+ return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, -+ sizeof(discovering), NULL); -+} -diff -Naur linux-2.6.39-rc6/net/bluetooth/rfcomm/core.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/rfcomm/core.c ---- linux-2.6.39-rc6/net/bluetooth/rfcomm/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/rfcomm/core.c 2011-05-05 23:30:21.187873077 +0200 -@@ -232,6 +232,8 @@ - static inline int rfcomm_check_security(struct rfcomm_dlc *d) - { - struct sock *sk = d->session->sock->sk; -+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; -+ - __u8 auth_type; - - switch (d->sec_level) { -@@ -246,8 +248,7 @@ - break; - } - -- return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level, -- auth_type); -+ return hci_conn_security(conn->hcon, d->sec_level, auth_type); - } - - static void rfcomm_session_timeout(unsigned long arg) -@@ -710,10 +711,10 @@ - /* Set L2CAP options */ - sk = sock->sk; - lock_sock(sk); -- l2cap_pi(sk)->imtu = l2cap_mtu; -- l2cap_pi(sk)->sec_level = sec_level; -+ l2cap_pi(sk)->chan->imtu = l2cap_mtu; -+ l2cap_pi(sk)->chan->sec_level = sec_level; - if (l2cap_ertm) -- l2cap_pi(sk)->mode = L2CAP_MODE_ERTM; -+ l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM; - release_sock(sk); - - s = rfcomm_session_add(sock, BT_BOUND); -@@ -1241,6 +1242,7 @@ - void rfcomm_dlc_accept(struct rfcomm_dlc *d) - { - struct sock *sk = d->session->sock->sk; -+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; - - BT_DBG("dlc %p", d); - -@@ -1254,7 +1256,7 @@ - rfcomm_dlc_unlock(d); - - if (d->role_switch) -- hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00); -+ hci_conn_switch_role(conn->hcon, 0x00); - - rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); - } -@@ -1890,7 +1892,8 @@ - - /* We should adjust MTU on incoming sessions. - * L2CAP MTU minus UIH header and FCS. */ -- s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5; -+ s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, -+ l2cap_pi(nsock->sk)->chan->imtu) - 5; - - rfcomm_schedule(); - } else -@@ -1909,7 +1912,7 @@ - - /* We can adjust MTU on outgoing sessions. - * L2CAP MTU minus UIH header and FCS. */ -- s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5; -+ s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5; - - rfcomm_send_sabm(s, 0); - break; -@@ -1992,7 +1995,7 @@ - /* Set L2CAP options */ - sk = sock->sk; - lock_sock(sk); -- l2cap_pi(sk)->imtu = l2cap_mtu; -+ l2cap_pi(sk)->chan->imtu = l2cap_mtu; - release_sock(sk); - - /* Start listening on the socket */ -diff -Naur linux-2.6.39-rc6/net/bluetooth/rfcomm/sock.c linux-2.6.39-rc6.rtl8192se/net/bluetooth/rfcomm/sock.c ---- linux-2.6.39-rc6/net/bluetooth/rfcomm/sock.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/bluetooth/rfcomm/sock.c 2011-05-05 23:30:21.188873089 +0200 -@@ -743,6 +743,7 @@ - struct sock *sk = sock->sk; - struct sock *l2cap_sk; - struct rfcomm_conninfo cinfo; -+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; - int len, err = 0; - u32 opt; - -@@ -787,8 +788,8 @@ - - l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; - -- cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle; -- memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3); -+ cinfo.hci_handle = conn->hcon->handle; -+ memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); - - len = min_t(unsigned int, len, sizeof(cinfo)); - if (copy_to_user(optval, (char *) &cinfo, len)) -diff -Naur linux-2.6.39-rc6/net/mac80211/aes_ccm.c linux-2.6.39-rc6.rtl8192se/net/mac80211/aes_ccm.c ---- linux-2.6.39-rc6/net/mac80211/aes_ccm.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/aes_ccm.c 2011-05-05 23:30:21.815880659 +0200 -@@ -54,13 +54,12 @@ - u8 *cdata, u8 *mic) - { - int i, j, last_len, num_blocks; -- u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad; -+ u8 *pos, *cpos, *b, *s_0, *e, *b_0; - - b = scratch; - s_0 = scratch + AES_BLOCK_LEN; - e = scratch + 2 * AES_BLOCK_LEN; - b_0 = scratch + 3 * AES_BLOCK_LEN; -- aad = scratch + 4 * AES_BLOCK_LEN; - - num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last_len = data_len % AES_BLOCK_LEN; -@@ -94,13 +93,12 @@ - u8 *cdata, size_t data_len, u8 *mic, u8 *data) - { - int i, j, last_len, num_blocks; -- u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad; -+ u8 *pos, *cpos, *b, *s_0, *a, *b_0; - - b = scratch; - s_0 = scratch + AES_BLOCK_LEN; - a = scratch + 2 * AES_BLOCK_LEN; - b_0 = scratch + 3 * AES_BLOCK_LEN; -- aad = scratch + 4 * AES_BLOCK_LEN; - - num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last_len = data_len % AES_BLOCK_LEN; -diff -Naur linux-2.6.39-rc6/net/mac80211/cfg.c linux-2.6.39-rc6.rtl8192se/net/mac80211/cfg.c ---- linux-2.6.39-rc6/net/mac80211/cfg.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/cfg.c 2011-05-05 23:30:21.771880129 +0200 -@@ -330,6 +330,7 @@ - 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; - -@@ -342,7 +343,12 @@ - STATION_INFO_TX_FAILED | - STATION_INFO_TX_BITRATE | - STATION_INFO_RX_BITRATE | -- STATION_INFO_RX_DROP_MISC; -+ STATION_INFO_RX_DROP_MISC | -+ 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; -@@ -389,6 +395,16 @@ - sinfo->plink_state = sta->plink_state; - #endif - } -+ -+ sinfo->bss_param.flags = 0; -+ if (sdata->vif.bss_conf.use_cts_prot) -+ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; -+ if (sdata->vif.bss_conf.use_short_preamble) -+ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; -+ if (sdata->vif.bss_conf.use_short_slot) -+ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; -+ sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; -+ sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; - } - - -@@ -675,6 +691,12 @@ - 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); - - /* -@@ -1023,26 +1045,26 @@ - 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; - } -@@ -1611,16 +1633,13 @@ - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); -- int i; -- -- /* -- * This _could_ be supported by providing a hook for -- * drivers for this function, but at this point it -- * doesn't seem worth bothering. -- */ -- if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) -- return -EOPNOTSUPP; -+ int i, ret; - -+ if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { -+ ret = drv_set_bitrate_mask(local, sdata, mask); -+ if (ret) -+ return ret; -+ } - - for (i = 0; i < IEEE80211_NUM_BANDS; i++) - sdata->rc_rateidx_mask[i] = mask->control[i].legacy; -diff -Naur linux-2.6.39-rc6/net/mac80211/debugfs.c linux-2.6.39-rc6.rtl8192se/net/mac80211/debugfs.c ---- linux-2.6.39-rc6/net/mac80211/debugfs.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/debugfs.c 2011-05-05 23:30:21.822880743 +0200 -@@ -37,7 +37,7 @@ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); - } - --#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ -+#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...) \ - static ssize_t name## _read(struct file *file, char __user *userbuf, \ - size_t count, loff_t *ppos) \ - { \ -@@ -45,14 +45,19 @@ - \ - return mac80211_format_buffer(userbuf, count, ppos, \ - fmt "\n", ##value); \ --} \ -- \ -+} -+ -+#define DEBUGFS_READONLY_FILE_OPS(name) \ - static const struct file_operations name## _ops = { \ - .read = name## _read, \ - .open = mac80211_open_file_generic, \ - .llseek = generic_file_llseek, \ - }; - -+#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ -+ DEBUGFS_READONLY_FILE_FN(name, fmt, value) \ -+ DEBUGFS_READONLY_FILE_OPS(name) -+ - #define DEBUGFS_ADD(name) \ - debugfs_create_file(#name, 0400, phyd, local, &name## _ops); - -@@ -291,11 +296,70 @@ - return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); - } - --static const struct file_operations channel_type_ops = { -- .read = channel_type_read, -- .open = mac80211_open_file_generic, -- .llseek = default_llseek, --}; -+static ssize_t hwflags_read(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ieee80211_local *local = file->private_data; -+ int mxln = 500; -+ ssize_t rv; -+ char *buf = kzalloc(mxln, GFP_KERNEL); -+ int sf = 0; /* how many written so far */ -+ -+ sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); -+ if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) -+ sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); -+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) -+ sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); -+ if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) -+ sf += snprintf(buf + sf, mxln - sf, -+ "HOST_BCAST_PS_BUFFERING\n"); -+ if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) -+ sf += snprintf(buf + sf, mxln - sf, -+ "2GHZ_SHORT_SLOT_INCAPABLE\n"); -+ if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) -+ sf += snprintf(buf + sf, mxln - sf, -+ "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); -+ if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) -+ sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); -+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) -+ sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); -+ if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) -+ sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); -+ if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) -+ sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); -+ if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) -+ sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); -+ if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) -+ sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); -+ if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) -+ sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); -+ if (local->hw.flags & IEEE80211_HW_BEACON_FILTER) -+ sf += snprintf(buf + sf, mxln - sf, "BEACON_FILTER\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); -+ if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) -+ sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); -+ if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) -+ sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_CQM_RSSI\n"); -+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) -+ sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); -+ if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) -+ sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); -+ -+ rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); -+ kfree(buf); -+ return rv; -+} - - static ssize_t queues_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -@@ -315,11 +379,9 @@ - return simple_read_from_buffer(user_buf, count, ppos, buf, res); - } - --static const struct file_operations queues_ops = { -- .read = queues_read, -- .open = mac80211_open_file_generic, -- .llseek = default_llseek, --}; -+DEBUGFS_READONLY_FILE_OPS(hwflags); -+DEBUGFS_READONLY_FILE_OPS(channel_type); -+DEBUGFS_READONLY_FILE_OPS(queues); - - /* statistics stuff */ - -@@ -395,6 +457,7 @@ - DEBUGFS_ADD(uapsd_queues); - DEBUGFS_ADD(uapsd_max_sp_len); - DEBUGFS_ADD(channel_type); -+ DEBUGFS_ADD(hwflags); - DEBUGFS_ADD(user_power); - DEBUGFS_ADD(power); - -diff -Naur linux-2.6.39-rc6/net/mac80211/debugfs_sta.c linux-2.6.39-rc6.rtl8192se/net/mac80211/debugfs_sta.c ---- linux-2.6.39-rc6/net/mac80211/debugfs_sta.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/debugfs_sta.c 2011-05-05 23:30:21.820880719 +0200 -@@ -92,6 +92,31 @@ - } - 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 @@ - 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); -diff -Naur linux-2.6.39-rc6/net/mac80211/driver-ops.h linux-2.6.39-rc6.rtl8192se/net/mac80211/driver-ops.h ---- linux-2.6.39-rc6/net/mac80211/driver-ops.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/driver-ops.h 2011-05-05 23:30:21.807880563 +0200 -@@ -552,4 +552,35 @@ - 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; -+} -+ -+static inline int drv_set_bitrate_mask(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ const struct cfg80211_bitrate_mask *mask) -+{ -+ int ret = -EOPNOTSUPP; -+ -+ might_sleep(); -+ -+ trace_drv_set_bitrate_mask(local, sdata, mask); -+ if (local->ops->set_bitrate_mask) -+ ret = local->ops->set_bitrate_mask(&local->hw, -+ &sdata->vif, mask); -+ trace_drv_return_int(local, ret); -+ -+ return ret; -+} -+ - #endif /* __MAC80211_DRIVER_OPS */ -diff -Naur linux-2.6.39-rc6/net/mac80211/driver-trace.h linux-2.6.39-rc6.rtl8192se/net/mac80211/driver-trace.h ---- linux-2.6.39-rc6/net/mac80211/driver-trace.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/driver-trace.h 2011-05-05 23:30:21.828880817 +0200 -@@ -74,6 +74,21 @@ - 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,11 +979,43 @@ - ) - ); - -+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) - ); - -+TRACE_EVENT(drv_set_bitrate_mask, -+ TP_PROTO(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ const struct cfg80211_bitrate_mask *mask), -+ -+ TP_ARGS(local, sdata, mask), -+ -+ TP_STRUCT__entry( -+ LOCAL_ENTRY -+ VIF_ENTRY -+ __field(u32, legacy_2g) -+ __field(u32, legacy_5g) -+ ), -+ -+ TP_fast_assign( -+ LOCAL_ASSIGN; -+ VIF_ASSIGN; -+ __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy; -+ __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy; -+ ), -+ -+ TP_printk( -+ LOCAL_PR_FMT VIF_PR_FMT " 2G Mask:0x%x 5G Mask:0x%x", -+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->legacy_2g, __entry->legacy_5g -+ ) -+); -+ - /* - * Tracing for API calls that drivers call. - */ -diff -Naur linux-2.6.39-rc6/net/mac80211/ibss.c linux-2.6.39-rc6.rtl8192se/net/mac80211/ibss.c ---- linux-2.6.39-rc6/net/mac80211/ibss.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/ibss.c 2011-05-05 23:30:21.826880793 +0200 -@@ -40,7 +40,7 @@ - struct ieee80211_mgmt *mgmt, - size_t len) - { -- u16 auth_alg, auth_transaction, status_code; -+ u16 auth_alg, auth_transaction; - - lockdep_assert_held(&sdata->u.ibss.mtx); - -@@ -49,7 +49,6 @@ - - auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); - auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); -- status_code = le16_to_cpu(mgmt->u.auth.status_code); - - /* - * IEEE 802.11 standard does not require authentication in IBSS -@@ -527,8 +526,6 @@ - static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) - { - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; -- struct ieee80211_local *local = sdata->local; -- struct ieee80211_supported_band *sband; - u8 bssid[ETH_ALEN]; - u16 capability; - int i; -@@ -551,8 +548,6 @@ - printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", - sdata->name, bssid); - -- sband = local->hw.wiphy->bands[ifibss->channel->band]; -- - capability = WLAN_CAPABILITY_IBSS; - - if (ifibss->privacy) -@@ -661,7 +656,6 @@ - static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, - struct sk_buff *req) - { -- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); - struct ieee80211_mgmt *mgmt = (void *)req->data; - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - struct ieee80211_local *local = sdata->local; -@@ -685,7 +679,7 @@ - mgmt->bssid, tx_last_beacon); - #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - -- if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da)) - return; - - if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && -diff -Naur linux-2.6.39-rc6/net/mac80211/ieee80211_i.h linux-2.6.39-rc6.rtl8192se/net/mac80211/ieee80211_i.h ---- linux-2.6.39-rc6/net/mac80211/ieee80211_i.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/ieee80211_i.h 2011-05-05 23:30:21.817880683 +0200 -@@ -488,8 +488,9 @@ - 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 -@@ -765,6 +766,9 @@ - - int tx_headroom; /* required headroom for hardware/radiotap */ - -+ /* count for keys needing tailroom space allocation */ -+ int crypto_tx_tailroom_needed_cnt; -+ - /* Tasklet and skb queue to process calls from IRQ mode. All frames - * added to skb_queue will be processed, but frames in - * skb_queue_unreliable may be dropped if the total length of these -@@ -809,8 +813,8 @@ - - struct rate_control_ref *rate_ctrl; - -- struct crypto_blkcipher *wep_tx_tfm; -- struct crypto_blkcipher *wep_rx_tfm; -+ struct crypto_cipher *wep_tx_tfm; -+ struct crypto_cipher *wep_rx_tfm; - u32 wep_iv; - - /* see iface.c */ -diff -Naur linux-2.6.39-rc6/net/mac80211/Kconfig linux-2.6.39-rc6.rtl8192se/net/mac80211/Kconfig ---- linux-2.6.39-rc6/net/mac80211/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/Kconfig 2011-05-05 23:30:21.830880841 +0200 -@@ -2,7 +2,6 @@ - tristate "Generic IEEE 802.11 Networking Stack (mac80211)" - depends on CFG80211 - select CRYPTO -- select CRYPTO_ECB - select CRYPTO_ARC4 - select CRYPTO_AES - select CRC32 -diff -Naur linux-2.6.39-rc6/net/mac80211/key.c linux-2.6.39-rc6.rtl8192se/net/mac80211/key.c ---- linux-2.6.39-rc6/net/mac80211/key.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/key.c 2011-05-05 23:30:21.819880707 +0200 -@@ -101,6 +101,10 @@ - - if (!ret) { - key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; -+ -+ if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) -+ key->local->crypto_tx_tailroom_needed_cnt--; -+ - return 0; - } - -@@ -156,6 +160,9 @@ - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); - - key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; -+ -+ if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) -+ key->local->crypto_tx_tailroom_needed_cnt++; - } - - void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) -@@ -388,8 +395,10 @@ - ieee80211_aes_key_free(key->u.ccmp.tfm); - if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) - ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); -- if (key->local) -+ if (key->local) { - ieee80211_debugfs_key_remove(key); -+ key->local->crypto_tx_tailroom_needed_cnt--; -+ } - - kfree(key); - } -@@ -451,6 +460,8 @@ - - ieee80211_debugfs_key_add(key); - -+ key->local->crypto_tx_tailroom_needed_cnt++; -+ - ret = ieee80211_key_enable_hw_accel(key); - - mutex_unlock(&sdata->local->key_mtx); -@@ -492,8 +503,12 @@ - - mutex_lock(&sdata->local->key_mtx); - -- list_for_each_entry(key, &sdata->key_list, list) -+ sdata->local->crypto_tx_tailroom_needed_cnt = 0; -+ -+ list_for_each_entry(key, &sdata->key_list, list) { -+ sdata->local->crypto_tx_tailroom_needed_cnt++; - ieee80211_key_enable_hw_accel(key); -+ } - - mutex_unlock(&sdata->local->key_mtx); - } -diff -Naur linux-2.6.39-rc6/net/mac80211/main.c linux-2.6.39-rc6.rtl8192se/net/mac80211/main.c ---- linux-2.6.39-rc6/net/mac80211/main.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/main.c 2011-05-05 23:30:21.825880780 +0200 -@@ -33,12 +33,6 @@ - #include "cfg.h" - #include "debugfs.h" - -- --static bool ieee80211_disable_40mhz_24ghz; --module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); --MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, -- "Disable 40MHz support in the 2.4GHz band"); -- - static struct lock_class_key ieee80211_rx_skb_queue_class; - - void ieee80211_configure_filter(struct ieee80211_local *local) -@@ -545,7 +539,9 @@ - }, - [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), - }, - }; - -@@ -726,18 +722,6 @@ - } - channels += sband->n_channels; - -- /* -- * Since ieee80211_disable_40mhz_24ghz is global, we can -- * modify the sband's ht data even if the driver uses a -- * global structure for that. -- */ -- if (ieee80211_disable_40mhz_24ghz && -- band == IEEE80211_BAND_2GHZ && -- sband->ht_cap.ht_supported) { -- sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; -- sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; -- } -- - if (max_bitrates < sband->n_bitrates) - max_bitrates = sband->n_bitrates; - supp_ht = supp_ht || sband->ht_cap.ht_supported; -@@ -760,6 +744,11 @@ - 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; - -@@ -879,10 +868,6 @@ - - local->dynamic_ps_forced_timeout = -1; - -- result = sta_info_start(local); -- if (result < 0) -- goto fail_sta_info; -- - result = ieee80211_wep_init(local); - if (result < 0) - wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", -@@ -945,7 +930,6 @@ - rtnl_unlock(); - ieee80211_wep_free(local); - sta_info_stop(local); -- fail_sta_info: - destroy_workqueue(local->workqueue); - fail_workqueue: - wiphy_unregister(local->hw.wiphy); -diff -Naur linux-2.6.39-rc6/net/mac80211/mesh.c linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh.c ---- linux-2.6.39-rc6/net/mac80211/mesh.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh.c 2011-05-05 23:30:21.806880551 +0200 -@@ -279,9 +279,9 @@ - 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 @@ - 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 @@ - 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); - } - } - -@@ -611,12 +613,9 @@ - struct sk_buff *skb) - { - struct ieee80211_rx_status *rx_status; -- struct ieee80211_if_mesh *ifmsh; - struct ieee80211_mgmt *mgmt; - u16 stype; - -- ifmsh = &sdata->u.mesh; -- - rx_status = IEEE80211_SKB_RXCB(skb); - mgmt = (struct ieee80211_mgmt *) skb->data; - stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; -diff -Naur linux-2.6.39-rc6/net/mac80211/mesh.h linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh.h ---- linux-2.6.39-rc6/net/mac80211/mesh.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh.h 2011-05-05 23:30:21.832880865 +0200 -@@ -226,7 +226,8 @@ - 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); -diff -Naur linux-2.6.39-rc6/net/mac80211/mesh_hwmp.c linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_hwmp.c ---- linux-2.6.39-rc6/net/mac80211/mesh_hwmp.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_hwmp.c 2011-05-05 23:30:21.782880261 +0200 -@@ -633,7 +633,6 @@ - struct mesh_path *mpath; - u8 ttl; - u8 *ta, *target_addr; -- u8 target_flags; - u32 target_sn; - u16 target_rcode; - -@@ -644,7 +643,6 @@ - return; - } - ttl--; -- target_flags = PERR_IE_TARGET_FLAGS(perr_elem); - target_addr = PERR_IE_TARGET_ADDR(perr_elem); - target_sn = PERR_IE_TARGET_SN(perr_elem); - target_rcode = PERR_IE_TARGET_RCODE(perr_elem); -@@ -675,12 +673,10 @@ - { - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct mesh_path *mpath; -- u8 *ta; - u8 ttl, flags, hopcount; - u8 *orig_addr; - u32 orig_sn, metric; - -- ta = mgmt->sa; - ttl = rann->rann_ttl; - if (ttl <= 1) { - ifmsh->mshstats.dropped_frames_ttl++; -diff -Naur linux-2.6.39-rc6/net/mac80211/mesh_pathtbl.c linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_pathtbl.c ---- linux-2.6.39-rc6/net/mac80211/mesh_pathtbl.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_pathtbl.c 2011-05-05 23:30:21.833880877 +0200 -@@ -65,42 +65,37 @@ - __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 @@ - { - 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 @@ - { - 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; - } -diff -Naur linux-2.6.39-rc6/net/mac80211/mesh_plink.c linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_plink.c ---- linux-2.6.39-rc6/net/mac80211/mesh_plink.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mesh_plink.c 2011-05-05 23:30:21.808880575 +0200 -@@ -105,7 +105,7 @@ - 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 @@ - __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 @@ - 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 @@ - 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 @@ - - 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 @@ - __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 @@ - 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 @@ - 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; -diff -Naur linux-2.6.39-rc6/net/mac80211/mlme.c linux-2.6.39-rc6.rtl8192se/net/mac80211/mlme.c ---- linux-2.6.39-rc6/net/mac80211/mlme.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/mlme.c 2011-05-05 23:30:21.781880249 +0200 -@@ -90,20 +90,11 @@ - /* no action required */ - RX_MGMT_NONE, - -- /* caller must call cfg80211_send_rx_auth() */ -- RX_MGMT_CFG80211_AUTH, -- -- /* caller must call cfg80211_send_rx_assoc() */ -- RX_MGMT_CFG80211_ASSOC, -- - /* caller must call cfg80211_send_deauth() */ - RX_MGMT_CFG80211_DEAUTH, - - /* caller must call cfg80211_send_disassoc() */ - RX_MGMT_CFG80211_DISASSOC, -- -- /* caller must tell cfg80211 about internal error */ -- RX_MGMT_CFG80211_ASSOC_ERROR, - }; - - /* utils */ -@@ -770,15 +761,16 @@ - 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) && -diff -Naur linux-2.6.39-rc6/net/mac80211/pm.c linux-2.6.39-rc6.rtl8192se/net/mac80211/pm.c ---- linux-2.6.39-rc6/net/mac80211/pm.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/pm.c 2011-05-05 23:30:21.822880743 +0200 -@@ -14,12 +14,23 @@ - - ieee80211_scan_cancel(local); - -+ if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { -+ mutex_lock(&local->sta_mtx); -+ list_for_each_entry(sta, &local->sta_list, list) { -+ set_sta_flags(sta, WLAN_STA_BLOCK_BA); -+ ieee80211_sta_tear_down_BA_sessions(sta, true); -+ } -+ mutex_unlock(&local->sta_mtx); -+ } -+ - ieee80211_stop_queues_by_reason(hw, - IEEE80211_QUEUE_STOP_REASON_SUSPEND); - - /* flush out all packets */ - synchronize_net(); - -+ drv_flush(local, false); -+ - local->quiescing = true; - /* make quiescing visible to timers everywhere */ - mb(); -@@ -43,11 +54,6 @@ - /* tear down aggregation sessions and remove STAs */ - mutex_lock(&local->sta_mtx); - list_for_each_entry(sta, &local->sta_list, list) { -- if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { -- set_sta_flags(sta, WLAN_STA_BLOCK_BA); -- ieee80211_sta_tear_down_BA_sessions(sta, true); -- } -- - if (sta->uploaded) { - sdata = sta->sdata; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -diff -Naur linux-2.6.39-rc6/net/mac80211/rx.c linux-2.6.39-rc6.rtl8192se/net/mac80211/rx.c ---- linux-2.6.39-rc6/net/mac80211/rx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/rx.c 2011-05-05 23:30:21.814880647 +0200 -@@ -143,7 +143,8 @@ - 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 @@ - - 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; -@@ -650,7 +652,7 @@ - set_release_timer: - - mod_timer(&tid_agg_rx->reorder_timer, -- tid_agg_rx->reorder_time[j] + -+ tid_agg_rx->reorder_time[j] + 1 + - HT_RX_REORDER_BUF_TIMEOUT); - } else { - del_timer(&tid_agg_rx->reorder_timer); -@@ -707,6 +709,8 @@ - /* - * If the current MPDU is in the right order and nothing else - * is stored we can process it directly, no need to buffer it. -+ * If it is first but there's something stored, we may be able -+ * to release frames after this one. - */ - if (mpdu_seq_num == tid_agg_rx->head_seq_num && - tid_agg_rx->stored_mpdu_num == 0) { -@@ -1583,7 +1587,7 @@ - } - - 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; -@@ -1591,6 +1595,7 @@ - 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; -@@ -1609,11 +1614,13 @@ - 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; -@@ -1914,6 +1921,7 @@ - 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))) -@@ -1930,13 +1938,21 @@ - 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++; -@@ -2352,47 +2368,6 @@ - return RX_QUEUED; - } - --static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, -- struct ieee80211_rx_data *rx) --{ -- int keyidx; -- unsigned int hdrlen; -- -- hdrlen = ieee80211_hdrlen(hdr->frame_control); -- if (rx->skb->len >= hdrlen + 4) -- keyidx = rx->skb->data[hdrlen + 3] >> 6; -- else -- keyidx = -1; -- -- if (!rx->sta) { -- /* -- * Some hardware seem to generate incorrect Michael MIC -- * reports; ignore them to avoid triggering countermeasures. -- */ -- return; -- } -- -- if (!ieee80211_has_protected(hdr->frame_control)) -- return; -- -- if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { -- /* -- * APs with pairwise keys should never receive Michael MIC -- * errors for non-zero keyidx because these are reserved for -- * group keys and only the AP is sending real multicast -- * frames in the BSS. -- */ -- return; -- } -- -- if (!ieee80211_is_data(hdr->frame_control) && -- !ieee80211_is_auth(hdr->frame_control)) -- return; -- -- mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL, -- GFP_ATOMIC); --} -- - /* TODO: use IEEE80211_RX_FRAGMENTED */ - static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, - struct ieee80211_rate *rate) -@@ -2736,12 +2711,6 @@ - if (!prepares) - return false; - -- if (status->flag & RX_FLAG_MMIC_ERROR) { -- if (status->rx_flags & IEEE80211_RX_RA_MATCH) -- ieee80211_rx_michael_mic_report(hdr, rx); -- return false; -- } -- - if (!consume) { - skb = skb_copy(skb, GFP_ATOMIC); - if (!skb) { -diff -Naur linux-2.6.39-rc6/net/mac80211/sta_info.c linux-2.6.39-rc6.rtl8192se/net/mac80211/sta_info.c ---- linux-2.6.39-rc6/net/mac80211/sta_info.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/sta_info.c 2011-05-05 23:30:21.772880141 +0200 -@@ -228,6 +228,7 @@ - { - 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 @@ - 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)) { -@@ -584,7 +587,6 @@ - { - unsigned long flags; - struct sk_buff *skb; -- struct ieee80211_sub_if_data *sdata; - - if (skb_queue_empty(&sta->ps_tx_buf)) - return false; -@@ -601,7 +603,6 @@ - if (!skb) - break; - -- sdata = sta->sdata; - local->total_ps_buffered--; - #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "Buffered frame expired (STA %pM)\n", -@@ -609,7 +610,8 @@ - #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); - } - -@@ -698,6 +700,8 @@ - #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - cancel_work_sync(&sta->drv_unblock_wk); - -+ cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); -+ - rate_control_remove_sta_debugfs(sta); - ieee80211_sta_debugfs_remove(sta); - -@@ -766,9 +770,8 @@ - if (!timer_needed) - return; - -- local->sta_cleanup.expires = -- round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); -- add_timer(&local->sta_cleanup); -+ mod_timer(&local->sta_cleanup, -+ round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); - } - - void sta_info_init(struct ieee80211_local *local) -@@ -781,14 +784,6 @@ - - setup_timer(&local->sta_cleanup, sta_info_cleanup, - (unsigned long)local); -- local->sta_cleanup.expires = -- round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); --} -- --int sta_info_start(struct ieee80211_local *local) --{ -- add_timer(&local->sta_cleanup); -- return 0; - } - - void sta_info_stop(struct ieee80211_local *local) -@@ -900,6 +895,7 @@ - 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); - -@@ -992,3 +988,12 @@ - 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); -diff -Naur linux-2.6.39-rc6/net/mac80211/sta_info.h linux-2.6.39-rc6.rtl8192se/net/mac80211/sta_info.h ---- linux-2.6.39-rc6/net/mac80211/sta_info.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/sta_info.h 2011-05-05 23:30:21.786880309 +0200 -@@ -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 @@ - 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 @@ - * @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 @@ - 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; -@@ -497,7 +502,6 @@ - void sta_info_clear_tim_bit(struct sta_info *sta); - - void sta_info_init(struct ieee80211_local *local); --int sta_info_start(struct ieee80211_local *local); - void sta_info_stop(struct ieee80211_local *local); - int sta_info_flush(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata); -diff -Naur linux-2.6.39-rc6/net/mac80211/status.c linux-2.6.39-rc6.rtl8192se/net/mac80211/status.c ---- linux-2.6.39-rc6/net/mac80211/status.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/status.c 2011-05-05 23:30:21.809880587 +0200 -@@ -189,16 +189,19 @@ - bool acked; - - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -- /* the HW cannot have attempted that rate */ -- if (i >= hw->max_report_rates) { -+ if (info->status.rates[i].idx < 0) { -+ break; -+ } else if (i >= hw->max_report_rates) { -+ /* the HW cannot have attempted that rate */ - info->status.rates[i].idx = -1; - info->status.rates[i].count = 0; -- } else if (info->status.rates[i].idx >= 0) { -- rates_idx = i; -+ break; - } - - retry_count += info->status.rates[i].count; - } -+ rates_idx = i - 1; -+ - if (retry_count < 0) - retry_count = 0; - -@@ -443,3 +446,11 @@ - dev_kfree_skb(skb); - } - EXPORT_SYMBOL(ieee80211_tx_status); -+ -+void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) -+{ -+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); -+ cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, -+ num_packets, GFP_ATOMIC); -+} -+EXPORT_SYMBOL(ieee80211_report_low_ack); -diff -Naur linux-2.6.39-rc6/net/mac80211/tkip.c linux-2.6.39-rc6.rtl8192se/net/mac80211/tkip.c ---- linux-2.6.39-rc6/net/mac80211/tkip.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/tkip.c 2011-05-05 23:30:21.820880719 +0200 -@@ -202,7 +202,7 @@ - * @payload_len is the length of payload (_not_ including IV/ICV length). - * @ta is the transmitter addresses. - */ --int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, -+int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, - struct ieee80211_key *key, - u8 *pos, size_t payload_len, u8 *ta) - { -@@ -223,7 +223,7 @@ - * beginning of the buffer containing IEEE 802.11 header payload, i.e., - * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the - * length of payload, including IV, Ext. IV, MIC, ICV. */ --int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, -+int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, - struct ieee80211_key *key, - u8 *payload, size_t payload_len, u8 *ta, - u8 *ra, int only_iv, int queue, -diff -Naur linux-2.6.39-rc6/net/mac80211/tkip.h linux-2.6.39-rc6.rtl8192se/net/mac80211/tkip.h ---- linux-2.6.39-rc6/net/mac80211/tkip.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/tkip.h 2011-05-05 23:30:21.809880587 +0200 -@@ -15,7 +15,7 @@ - - u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16); - --int ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, -+int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, - struct ieee80211_key *key, - u8 *pos, size_t payload_len, u8 *ta); - enum { -@@ -24,7 +24,7 @@ - TKIP_DECRYPT_INVALID_KEYIDX = -2, - TKIP_DECRYPT_REPLAY = -3, - }; --int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, -+int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, - struct ieee80211_key *key, - u8 *payload, size_t payload_len, u8 *ta, - u8 *ra, int only_iv, int queue, -diff -Naur linux-2.6.39-rc6/net/mac80211/tx.c linux-2.6.39-rc6.rtl8192se/net/mac80211/tx.c ---- linux-2.6.39-rc6/net/mac80211/tx.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/tx.c 2011-05-05 23:30:21.758879971 +0200 -@@ -1036,14 +1036,11 @@ - struct ieee80211_radiotap_iterator iterator; - struct ieee80211_radiotap_header *rthdr = - (struct ieee80211_radiotap_header *) skb->data; -- struct ieee80211_supported_band *sband; - bool hw_frag; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, - NULL); - -- sband = tx->local->hw.wiphy->bands[tx->channel->band]; -- - info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - tx->flags &= ~IEEE80211_TX_FRAGMENTED; - -@@ -1442,11 +1439,8 @@ - struct ieee80211_tx_data tx; - ieee80211_tx_result res_prepare; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- u16 queue; - bool result = true; - -- queue = skb_get_queue_mapping(skb); -- - if (unlikely(skb->len < 10)) { - dev_kfree_skb(skb); - return true; -@@ -1482,12 +1476,7 @@ - { - int tail_need = 0; - -- /* -- * This could be optimised, devices that do full hardware -- * crypto (including TKIP MMIC) need no tailroom... But we -- * have no drivers for such devices currently. -- */ -- if (may_encrypt) { -+ if (may_encrypt && local->crypto_tx_tailroom_needed_cnt) { - tail_need = IEEE80211_ENCRYPT_TAILROOM; - tail_need -= skb_tailroom(skb); - tail_need = max_t(int, tail_need, 0); -@@ -2262,7 +2251,7 @@ - - /* 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; - -@@ -2485,7 +2474,6 @@ - { - struct ieee80211_local *local = hw_to_local(hw); - struct sk_buff *skb = NULL; -- struct sta_info *sta; - struct ieee80211_tx_data tx; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_ap *bss = NULL; -@@ -2527,7 +2515,6 @@ - - info = IEEE80211_SKB_CB(skb); - -- sta = tx.sta; - tx.flags |= IEEE80211_TX_PS_BUFFERED; - tx.channel = local->hw.conf.channel; - info->band = tx.channel->band; -diff -Naur linux-2.6.39-rc6/net/mac80211/util.c linux-2.6.39-rc6.rtl8192se/net/mac80211/util.c ---- linux-2.6.39-rc6/net/mac80211/util.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/util.c 2011-05-05 23:30:21.786880309 +0200 -@@ -1290,7 +1290,7 @@ - } - } - -- add_timer(&local->sta_cleanup); -+ mod_timer(&local->sta_cleanup, jiffies + 1); - - mutex_lock(&local->sta_mtx); - list_for_each_entry(sta, &local->sta_list, list) -diff -Naur linux-2.6.39-rc6/net/mac80211/wep.c linux-2.6.39-rc6.rtl8192se/net/mac80211/wep.c ---- linux-2.6.39-rc6/net/mac80211/wep.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/wep.c 2011-05-05 23:30:21.733879669 +0200 -@@ -30,17 +30,15 @@ - /* start WEP IV from a random value */ - get_random_bytes(&local->wep_iv, WEP_IV_LEN); - -- local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, -- CRYPTO_ALG_ASYNC); -+ local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(local->wep_tx_tfm)) { - local->wep_rx_tfm = ERR_PTR(-EINVAL); - return PTR_ERR(local->wep_tx_tfm); - } - -- local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, -- CRYPTO_ALG_ASYNC); -+ local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(local->wep_rx_tfm)) { -- crypto_free_blkcipher(local->wep_tx_tfm); -+ crypto_free_cipher(local->wep_tx_tfm); - local->wep_tx_tfm = ERR_PTR(-EINVAL); - return PTR_ERR(local->wep_rx_tfm); - } -@@ -51,9 +49,9 @@ - void ieee80211_wep_free(struct ieee80211_local *local) - { - if (!IS_ERR(local->wep_tx_tfm)) -- crypto_free_blkcipher(local->wep_tx_tfm); -+ crypto_free_cipher(local->wep_tx_tfm); - if (!IS_ERR(local->wep_rx_tfm)) -- crypto_free_blkcipher(local->wep_rx_tfm); -+ crypto_free_cipher(local->wep_rx_tfm); - } - - static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) -@@ -127,12 +125,11 @@ - /* Perform WEP encryption using given key. data buffer must have tailroom - * for 4-byte ICV. data_len must not include this ICV. Note: this function - * does _not_ add IV. data = RC4(data | CRC32(data)) */ --int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, -+int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, - size_t klen, u8 *data, size_t data_len) - { -- struct blkcipher_desc desc = { .tfm = tfm }; -- struct scatterlist sg; - __le32 icv; -+ int i; - - if (IS_ERR(tfm)) - return -1; -@@ -140,9 +137,9 @@ - icv = cpu_to_le32(~crc32_le(~0, data, data_len)); - put_unaligned(icv, (__le32 *)(data + data_len)); - -- crypto_blkcipher_setkey(tfm, rc4key, klen); -- sg_init_one(&sg, data, data_len + WEP_ICV_LEN); -- crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); -+ crypto_cipher_setkey(tfm, rc4key, klen); -+ for (i = 0; i < data_len + WEP_ICV_LEN; i++) -+ crypto_cipher_encrypt_one(tfm, data + i, data + i); - - return 0; - } -@@ -186,19 +183,18 @@ - /* Perform WEP decryption using given key. data buffer includes encrypted - * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. - * Return 0 on success and -1 on ICV mismatch. */ --int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, -+int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, - size_t klen, u8 *data, size_t data_len) - { -- struct blkcipher_desc desc = { .tfm = tfm }; -- struct scatterlist sg; - __le32 crc; -+ int i; - - if (IS_ERR(tfm)) - return -1; - -- crypto_blkcipher_setkey(tfm, rc4key, klen); -- sg_init_one(&sg, data, data_len + WEP_ICV_LEN); -- crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); -+ crypto_cipher_setkey(tfm, rc4key, klen); -+ for (i = 0; i < data_len + WEP_ICV_LEN; i++) -+ crypto_cipher_decrypt_one(tfm, data + i, data + i); - - crc = cpu_to_le32(~crc32_le(~0, data, data_len)); - if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) -diff -Naur linux-2.6.39-rc6/net/mac80211/wep.h linux-2.6.39-rc6.rtl8192se/net/mac80211/wep.h ---- linux-2.6.39-rc6/net/mac80211/wep.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/wep.h 2011-05-05 23:30:21.818880695 +0200 -@@ -18,12 +18,12 @@ - - int ieee80211_wep_init(struct ieee80211_local *local); - void ieee80211_wep_free(struct ieee80211_local *local); --int ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, -+int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, - size_t klen, u8 *data, size_t data_len); - int ieee80211_wep_encrypt(struct ieee80211_local *local, - struct sk_buff *skb, - const u8 *key, int keylen, int keyidx); --int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, -+int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, - size_t klen, u8 *data, size_t data_len); - bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); - -diff -Naur linux-2.6.39-rc6/net/mac80211/work.c linux-2.6.39-rc6.rtl8192se/net/mac80211/work.c ---- linux-2.6.39-rc6/net/mac80211/work.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/work.c 2011-05-05 23:30:21.806880551 +0200 -@@ -198,9 +198,8 @@ - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, qos_info; -- const u8 *ies; - size_t offset = 0, noffset; -- int i, len, count, rates_len, supp_rates_len; -+ int i, count, rates_len, supp_rates_len; - u16 capab; - struct ieee80211_supported_band *sband; - u32 rates = 0; -@@ -285,7 +284,7 @@ - } - - /* SSID */ -- ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); -+ pos = skb_put(skb, 2 + wk->assoc.ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = wk->assoc.ssid_len; - memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); -@@ -295,7 +294,6 @@ - if (supp_rates_len > 8) - supp_rates_len = 8; - -- len = sband->n_bitrates; - pos = skb_put(skb, supp_rates_len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = supp_rates_len; -diff -Naur linux-2.6.39-rc6/net/mac80211/wpa.c linux-2.6.39-rc6.rtl8192se/net/mac80211/wpa.c ---- linux-2.6.39-rc6/net/mac80211/wpa.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/mac80211/wpa.c 2011-05-05 23:30:21.808880575 +0200 -@@ -87,42 +87,76 @@ - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - -- /* No way to verify the MIC if the hardware stripped it */ -- if (status->flag & RX_FLAG_MMIC_STRIPPED) -+ /* -+ * it makes no sense to check for MIC errors on anything other -+ * than data frames. -+ */ -+ if (!ieee80211_is_data_present(hdr->frame_control)) -+ return RX_CONTINUE; -+ -+ /* -+ * No way to verify the MIC if the hardware stripped it or -+ * the IV with the key index. In this case we have solely rely -+ * on the driver to set RX_FLAG_MMIC_ERROR in the event of a -+ * MIC failure report. -+ */ -+ if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) { -+ if (status->flag & RX_FLAG_MMIC_ERROR) -+ goto mic_fail; -+ -+ if (!(status->flag & RX_FLAG_IV_STRIPPED)) -+ goto update_iv; -+ - return RX_CONTINUE; -+ } - -+ /* -+ * Some hardware seems to generate Michael MIC failure reports; even -+ * though, the frame was not encrypted with TKIP and therefore has no -+ * MIC. Ignore the flag them to avoid triggering countermeasures. -+ */ - if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || -- !ieee80211_has_protected(hdr->frame_control) || -- !ieee80211_is_data_present(hdr->frame_control)) -+ !(status->flag & RX_FLAG_DECRYPTED)) - return RX_CONTINUE; - -+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) { -+ /* -+ * APs with pairwise keys should never receive Michael MIC -+ * errors for non-zero keyidx because these are reserved for -+ * group keys and only the AP is sending real multicast -+ * frames in the BSS. ( -+ */ -+ return RX_DROP_UNUSABLE; -+ } -+ -+ if (status->flag & RX_FLAG_MMIC_ERROR) -+ goto mic_fail; -+ - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (skb->len < hdrlen + MICHAEL_MIC_LEN) - return RX_DROP_UNUSABLE; - - data = skb->data + hdrlen; - data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; -- - key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; - michael_mic(key, hdr, data, data_len, mic); -- if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) { -- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -- return RX_DROP_UNUSABLE; -- -- mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, -- (void *) skb->data, NULL, -- GFP_ATOMIC); -- return RX_DROP_UNUSABLE; -- } -+ if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) -+ goto mic_fail; - - /* remove Michael MIC from payload */ - skb_trim(skb, skb->len - MICHAEL_MIC_LEN); - -+update_iv: - /* update IV in key information to be able to detect replays */ - rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32; - rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16; - - return RX_CONTINUE; -+ -+mic_fail: -+ mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, -+ (void *) skb->data, NULL, GFP_ATOMIC); -+ return RX_DROP_UNUSABLE; - } - - -diff -Naur linux-2.6.39-rc6/net/rfkill/Kconfig linux-2.6.39-rc6.rtl8192se/net/rfkill/Kconfig ---- linux-2.6.39-rc6/net/rfkill/Kconfig 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/rfkill/Kconfig 2011-05-05 23:30:19.015846853 +0200 -@@ -22,3 +22,14 @@ - 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. -diff -Naur linux-2.6.39-rc6/net/rfkill/Makefile linux-2.6.39-rc6.rtl8192se/net/rfkill/Makefile ---- linux-2.6.39-rc6/net/rfkill/Makefile 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/rfkill/Makefile 2011-05-05 23:30:19.005846733 +0200 -@@ -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 -Naur linux-2.6.39-rc6/net/rfkill/rfkill-regulator.c linux-2.6.39-rc6.rtl8192se/net/rfkill/rfkill-regulator.c ---- linux-2.6.39-rc6/net/rfkill/rfkill-regulator.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.39-rc6.rtl8192se/net/rfkill/rfkill-regulator.c 2011-05-05 23:30:19.005846733 +0200 -@@ -0,0 +1,164 @@ -+/* -+ * rfkill-regulator.c - Regulator consumer driver for rfkill -+ * -+ * Copyright (C) 2009 Guiming Zhuo -+ * Copyright (C) 2011 Antonio Ospite -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 "); -+MODULE_AUTHOR("Antonio Ospite "); -+MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:rfkill-regulator"); -diff -Naur linux-2.6.39-rc6/net/wireless/core.c linux-2.6.39-rc6.rtl8192se/net/wireless/core.c ---- linux-2.6.39-rc6/net/wireless/core.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/core.c 2011-05-05 23:30:21.708879367 +0200 -@@ -46,6 +46,11 @@ - /* for the cleanup, scan and event works */ - struct workqueue_struct *cfg80211_wq; - -+static bool cfg80211_disable_40mhz_24ghz; -+module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); -+MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, -+ "Disable 40MHz support in the 2.4GHz band"); -+ - /* requires cfg80211_mutex to be held! */ - struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) - { -@@ -451,6 +456,18 @@ - return -EINVAL; - - /* -+ * Since cfg80211_disable_40mhz_24ghz is global, we can -+ * modify the sband's ht data even if the driver uses a -+ * global structure for that. -+ */ -+ if (cfg80211_disable_40mhz_24ghz && -+ band == IEEE80211_BAND_2GHZ && -+ sband->ht_cap.ht_supported) { -+ sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; -+ } -+ -+ /* - * Since we use a u32 for rate bitmaps in - * ieee80211_get_response_rate, we cannot - * have more than 32 legacy rates. -diff -Naur linux-2.6.39-rc6/net/wireless/mesh.c linux-2.6.39-rc6.rtl8192se/net/wireless/mesh.c ---- linux-2.6.39-rc6/net/wireless/mesh.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/mesh.c 2011-05-05 23:30:21.706879343 +0200 -@@ -1,5 +1,6 @@ - #include - #include -+#include "nl80211.h" - #include "core.h" - - /* Default values, timeouts in ms */ -@@ -53,8 +54,9 @@ - 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 @@ - 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 @@ - 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) - { -diff -Naur linux-2.6.39-rc6/net/wireless/mlme.c linux-2.6.39-rc6.rtl8192se/net/wireless/mlme.c ---- linux-2.6.39-rc6/net/wireless/mlme.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/mlme.c 2011-05-05 23:30:21.696879223 +0200 -@@ -770,6 +770,15 @@ - } - EXPORT_SYMBOL(cfg80211_new_sta); - -+void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) -+{ -+ struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; -+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); -+ -+ nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); -+} -+EXPORT_SYMBOL(cfg80211_del_sta); -+ - struct cfg80211_mgmt_registration { - struct list_head list; - -diff -Naur linux-2.6.39-rc6/net/wireless/nl80211.c linux-2.6.39-rc6.rtl8192se/net/wireless/nl80211.c ---- linux-2.6.39-rc6/net/wireless/nl80211.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/nl80211.c 2011-05-05 23:30:21.700879271 +0200 -@@ -124,6 +124,7 @@ - [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 @@ - - 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 @@ - [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, -@@ -2002,7 +2006,7 @@ - const u8 *mac_addr, struct station_info *sinfo) - { - void *hdr; -- struct nlattr *sinfoattr; -+ struct nlattr *sinfoattr, *bss_param; - - hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); - if (!hdr) -@@ -2016,6 +2020,9 @@ - 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); -@@ -2062,6 +2069,25 @@ - if (sinfo->filled & STATION_INFO_TX_FAILED) - NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, - sinfo->tx_failed); -+ if (sinfo->filled & STATION_INFO_BSS_PARAM) { -+ bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); -+ if (!bss_param) -+ goto nla_put_failure; -+ -+ if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) -+ NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); -+ if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) -+ NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); -+ if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) -+ NLA_PUT_FLAG(msg, -+ NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); -+ NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, -+ sinfo->bss_param.dtim_period); -+ NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, -+ sinfo->bss_param.beacon_interval); -+ -+ nla_nest_end(msg, bss_param); -+ } - nla_nest_end(msg, sinfoattr); - - return genlmsg_end(msg, hdr); -@@ -2262,7 +2288,9 @@ - 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: -@@ -2324,11 +2352,16 @@ - 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, ¶ms)) - 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; - -@@ -2804,7 +2837,8 @@ - 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 }, - }; - -@@ -2906,14 +2940,16 @@ - 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; - } -@@ -5785,6 +5821,44 @@ - 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, -@@ -5966,6 +6040,40 @@ - nl80211_mlme_mcgrp.id, gfp); - } - -+void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, -+ struct net_device *dev, const u8 *mac_addr, -+ gfp_t gfp) -+{ -+ struct sk_buff *msg; -+ void *hdr; -+ -+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp); -+ if (!msg) -+ return; -+ -+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); -+ if (!hdr) { -+ nlmsg_free(msg); -+ return; -+ } -+ -+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); -+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); -+ -+ 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); -+} -+ - int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 nlpid, - int freq, const u8 *buf, size_t len, gfp_t gfp) -diff -Naur linux-2.6.39-rc6/net/wireless/nl80211.h linux-2.6.39-rc6.rtl8192se/net/wireless/nl80211.h ---- linux-2.6.39-rc6/net/wireless/nl80211.h 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/nl80211.h 2011-05-05 23:30:21.713879427 +0200 -@@ -50,6 +50,10 @@ - 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, -@@ -79,6 +83,9 @@ - void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *mac_addr, - struct station_info *sinfo, gfp_t gfp); -+void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, -+ struct net_device *dev, const u8 *mac_addr, -+ gfp_t gfp); - - int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 nlpid, int freq, -diff -Naur linux-2.6.39-rc6/net/wireless/reg.c linux-2.6.39-rc6.rtl8192se/net/wireless/reg.c ---- linux-2.6.39-rc6/net/wireless/reg.c 2011-05-04 04:59:13.000000000 +0200 -+++ linux-2.6.39-rc6.rtl8192se/net/wireless/reg.c 2011-05-05 23:30:21.710879391 +0200 -@@ -106,6 +106,9 @@ - static void reg_todo(struct work_struct *work); - static DECLARE_WORK(reg_work, reg_todo); - -+static void reg_timeout_work(struct work_struct *work); -+static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); -+ - /* We keep a static world regulatory domain in case of the absence of CRDA */ - static const struct ieee80211_regdomain world_regdom = { - .n_reg_rules = 5, -@@ -1330,6 +1333,9 @@ - need_more_processing = true; - spin_unlock(®_requests_lock); - -+ if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) -+ cancel_delayed_work_sync(®_timeout); -+ - if (need_more_processing) - schedule_work(®_work); - } -@@ -1440,8 +1446,18 @@ - r = __regulatory_hint(wiphy, reg_request); - /* This is required so that the orig_* parameters are saved */ - if (r == -EALREADY && wiphy && -- wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) -+ wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { - wiphy_update_regulatory(wiphy, initiator); -+ return; -+ } -+ -+ /* -+ * We only time out user hints, given that they should be the only -+ * source of bogus requests. -+ */ -+ if (r != -EALREADY && -+ reg_request->initiator == NL80211_REGDOM_SET_BY_USER) -+ schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); - } - - /* -@@ -1744,6 +1760,8 @@ - { - char alpha2[2]; - struct reg_beacon *reg_beacon, *btmp; -+ struct regulatory_request *reg_request, *tmp; -+ LIST_HEAD(tmp_reg_req_list); - - mutex_lock(&cfg80211_mutex); - mutex_lock(®_mutex); -@@ -1751,6 +1769,25 @@ - reset_regdomains(); - restore_alpha2(alpha2, reset_user); - -+ /* -+ * If there's any pending requests we simply -+ * stash them to a temporary pending queue and -+ * add then after we've restored regulatory -+ * settings. -+ */ -+ spin_lock(®_requests_lock); -+ if (!list_empty(®_requests_list)) { -+ list_for_each_entry_safe(reg_request, tmp, -+ ®_requests_list, list) { -+ if (reg_request->initiator != -+ NL80211_REGDOM_SET_BY_USER) -+ continue; -+ list_del(®_request->list); -+ list_add_tail(®_request->list, &tmp_reg_req_list); -+ } -+ } -+ spin_unlock(®_requests_lock); -+ - /* Clear beacon hints */ - spin_lock_bh(®_pending_beacons_lock); - if (!list_empty(®_pending_beacons)) { -@@ -1785,8 +1822,31 @@ - */ - if (is_an_alpha2(alpha2)) - regulatory_hint_user(user_alpha2); --} - -+ if (list_empty(&tmp_reg_req_list)) -+ return; -+ -+ mutex_lock(&cfg80211_mutex); -+ mutex_lock(®_mutex); -+ -+ spin_lock(®_requests_lock); -+ list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { -+ REG_DBG_PRINT("Adding request for country %c%c back " -+ "into the queue\n", -+ reg_request->alpha2[0], -+ reg_request->alpha2[1]); -+ list_del(®_request->list); -+ list_add_tail(®_request->list, ®_requests_list); -+ } -+ spin_unlock(®_requests_lock); -+ -+ mutex_unlock(®_mutex); -+ mutex_unlock(&cfg80211_mutex); -+ -+ REG_DBG_PRINT("Kicking the queue\n"); -+ -+ schedule_work(®_work); -+} - - void regulatory_hint_disconnect(void) - { -@@ -2125,6 +2185,13 @@ - mutex_unlock(®_mutex); - } - -+static void reg_timeout_work(struct work_struct *work) -+{ -+ REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " -+ "restoring regulatory settings"); -+ restore_regulatory_settings(true); -+} -+ - int __init regulatory_init(void) - { - int err = 0; -@@ -2178,6 +2245,7 @@ - struct reg_beacon *reg_beacon, *btmp; - - cancel_work_sync(®_work); -+ cancel_delayed_work_sync(®_timeout); - - mutex_lock(&cfg80211_mutex); - mutex_lock(®_mutex); diff --git a/projects/Generic/options b/projects/Generic/options index b6041558d6..2d6a437ce2 100644 --- a/projects/Generic/options +++ b/projects/Generic/options @@ -120,7 +120,7 @@ # bcm_sta: Broadcom STA WLAN Driver # Space separated list is supported, # e.g. ADDITIONAL_DRIVERS="bcm_sta" - ADDITIONAL_DRIVERS="" + ADDITIONAL_DRIVERS="rtl8192se" # build with network support (yes / no) NETWORK="yes" diff --git a/projects/ION/options b/projects/ION/options index 686e01f069..1bd8a646c5 100644 --- a/projects/ION/options +++ b/projects/ION/options @@ -120,7 +120,7 @@ # bcm_sta: Broadcom STA WLAN Driver # Space separated list is supported, # e.g. ADDITIONAL_DRIVERS="bcm_sta" - ADDITIONAL_DRIVERS="" + ADDITIONAL_DRIVERS="rtl8192se" # build with network support (yes / no) NETWORK="yes"