Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
345578d97c
|
@ -188,7 +188,7 @@ config BT_MRVL
|
||||||
The core driver to support Marvell Bluetooth devices.
|
The core driver to support Marvell Bluetooth devices.
|
||||||
|
|
||||||
This driver is required if you want to support
|
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
|
Say Y here to compile Marvell Bluetooth driver
|
||||||
into the kernel or say M to compile it as module.
|
into the kernel or say M to compile it as module.
|
||||||
|
@ -201,7 +201,7 @@ config BT_MRVL_SDIO
|
||||||
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
||||||
|
|
||||||
This driver is required if you want to use Marvell Bluetooth
|
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.
|
supported.
|
||||||
|
|
||||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||||
|
|
|
@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
||||||
count -= size;
|
count -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(send_buf);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
kfree(send_buf);
|
kfree(send_buf);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -49,15 +49,59 @@
|
||||||
static u8 user_rmmod;
|
static u8 user_rmmod;
|
||||||
static u8 sdio_ireg;
|
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 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
|
||||||
.helper = "sd8688_helper.bin",
|
.helper = "sd8688_helper.bin",
|
||||||
.firmware = "sd8688.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[] = {
|
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
||||||
/* Marvell SD8688 Bluetooth device */
|
/* Marvell SD8688 Bluetooth device */
|
||||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
||||||
.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
|
.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 */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
|
||||||
u8 reg;
|
u8 reg;
|
||||||
int ret;
|
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)
|
if (!ret)
|
||||||
card->rx_unit = reg;
|
card->rx_unit = reg;
|
||||||
|
|
||||||
|
@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
|
||||||
|
|
||||||
*dat = 0;
|
*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)
|
if (ret)
|
||||||
return -EIO;
|
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)
|
if (ret)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
|
||||||
u8 reg;
|
u8 reg;
|
||||||
int ret;
|
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)
|
if (!ret)
|
||||||
*dat = (u16) reg << card->rx_unit;
|
*dat = (u16) reg << card->rx_unit;
|
||||||
|
|
||||||
|
@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
|
||||||
{
|
{
|
||||||
int ret;
|
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) {
|
if (ret) {
|
||||||
BT_ERR("Unable to enable the host interrupt!");
|
BT_ERR("Unable to enable the host interrupt!");
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
|
||||||
u8 host_int_mask;
|
u8 host_int_mask;
|
||||||
int ret;
|
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)
|
if (ret)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
host_int_mask &= ~mask;
|
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) {
|
if (ret < 0) {
|
||||||
BT_ERR("Unable to disable the host interrupt!");
|
BT_ERR("Unable to disable the host interrupt!");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
|
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)
|
if (ret)
|
||||||
goto failed;
|
goto failed;
|
||||||
if ((status & bits) == bits)
|
if ((status & bits) == bits)
|
||||||
|
@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||||
u8 base0, base1;
|
u8 base0, base1;
|
||||||
void *tmpfwbuf = NULL;
|
void *tmpfwbuf = NULL;
|
||||||
u8 *fwbuf;
|
u8 *fwbuf;
|
||||||
u16 len;
|
u16 len, blksz_dl = card->sd_blksz_fw_dl;
|
||||||
int txlen = 0, tx_blocks = 0, count = 0;
|
int txlen = 0, tx_blocks = 0, count = 0;
|
||||||
|
|
||||||
ret = request_firmware(&fw_firmware, card->firmware,
|
ret = request_firmware(&fw_firmware, card->firmware,
|
||||||
|
@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||||
|
|
||||||
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
|
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
|
||||||
base0 = sdio_readb(card->func,
|
base0 = sdio_readb(card->func,
|
||||||
SQ_READ_BASE_ADDRESS_A0_REG, &ret);
|
card->reg->sq_read_base_addr_a0, &ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("BASE0 register read failed:"
|
BT_ERR("BASE0 register read failed:"
|
||||||
" base0 = 0x%04X(%d)."
|
" base0 = 0x%04X(%d)."
|
||||||
|
@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
base1 = sdio_readb(card->func,
|
base1 = sdio_readb(card->func,
|
||||||
SQ_READ_BASE_ADDRESS_A1_REG, &ret);
|
card->reg->sq_read_base_addr_a1, &ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("BASE1 register read failed:"
|
BT_ERR("BASE1 register read failed:"
|
||||||
" base1 = 0x%04X(%d)."
|
" base1 = 0x%04X(%d)."
|
||||||
|
@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||||
if (firmwarelen - offset < txlen)
|
if (firmwarelen - offset < txlen)
|
||||||
txlen = firmwarelen - offset;
|
txlen = firmwarelen - offset;
|
||||||
|
|
||||||
tx_blocks =
|
tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
|
||||||
(txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
|
|
||||||
|
|
||||||
memcpy(fwbuf, &firmware[offset], txlen);
|
memcpy(fwbuf, &firmware[offset], txlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sdio_writesb(card->func, card->ioport, fwbuf,
|
ret = sdio_writesb(card->func, card->ioport, fwbuf,
|
||||||
tx_blocks * SDIO_BLOCK_SIZE);
|
tx_blocks * blksz_dl);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
BT_ERR("FW download, writesb(%d) failed @%d",
|
BT_ERR("FW download, writesb(%d) failed @%d",
|
||||||
count, offset);
|
count, offset);
|
||||||
sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
|
sdio_writeb(card->func, HOST_CMD53_FIN,
|
||||||
&ret);
|
card->reg->cfg, &ret);
|
||||||
if (ret)
|
if (ret)
|
||||||
BT_ERR("writeb failed (CFG)");
|
BT_ERR("writeb failed (CFG)");
|
||||||
}
|
}
|
||||||
|
@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||||
|
|
||||||
priv = card->priv;
|
priv = card->priv;
|
||||||
|
|
||||||
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
|
ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("sdio_readb: read int status register failed");
|
BT_ERR("sdio_readb: read int status register failed");
|
||||||
return;
|
return;
|
||||||
|
@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||||
|
|
||||||
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
|
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
|
||||||
UP_LD_HOST_INT_STATUS),
|
UP_LD_HOST_INT_STATUS),
|
||||||
HOST_INTSTATUS_REG, &ret);
|
card->reg->host_intstatus, &ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("sdio_writeb: clear int status register failed");
|
BT_ERR("sdio_writeb: clear int status register failed");
|
||||||
return;
|
return;
|
||||||
|
@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||||
goto release_irq;
|
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) {
|
if (ret < 0) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto release_irq;
|
goto release_irq;
|
||||||
|
@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||||
|
|
||||||
card->ioport = reg;
|
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) {
|
if (ret < 0) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto release_irq;
|
goto release_irq;
|
||||||
|
@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||||
|
|
||||||
card->ioport |= (reg << 8);
|
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) {
|
if (ret < 0) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto release_irq;
|
goto release_irq;
|
||||||
|
@ -815,6 +858,8 @@ exit:
|
||||||
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
u8 fws0;
|
||||||
|
int pollnum = MAX_POLL_TRIES;
|
||||||
|
|
||||||
if (!card || !card->func) {
|
if (!card || !card->func) {
|
||||||
BT_ERR("card or function is NULL!");
|
BT_ERR("card or function is NULL!");
|
||||||
|
@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 read FW downloading status!");
|
||||||
|
ret = -EIO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (fws0) {
|
||||||
|
BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
|
||||||
|
|
||||||
|
/* Give other function more time to download the firmware */
|
||||||
|
pollnum *= 10;
|
||||||
|
} else {
|
||||||
|
if (card->helper) {
|
||||||
ret = btmrvl_sdio_download_helper(card);
|
ret = btmrvl_sdio_download_helper(card);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
BT_ERR("Failed to download helper!");
|
BT_ERR("Failed to download helper!");
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
||||||
BT_ERR("Failed to download firmware!");
|
BT_ERR("Failed to download firmware!");
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto done;
|
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!");
|
BT_ERR("FW failed to be active in time!");
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
|
||||||
|
|
||||||
sdio_claim_host(card->func);
|
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);
|
sdio_release_host(card->func);
|
||||||
|
|
||||||
|
@ -895,6 +956,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||||
struct btmrvl_sdio_device *data = (void *) 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->firmware = data->firmware;
|
||||||
|
card->reg = data->reg;
|
||||||
|
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||||
|
@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||||
MODULE_FIRMWARE("sd8688.bin");
|
MODULE_FIRMWARE("sd8688.bin");
|
||||||
|
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||||
|
|
|
@ -47,44 +47,46 @@
|
||||||
/* Max retry number of CMD53 write */
|
/* Max retry number of CMD53 write */
|
||||||
#define MAX_WRITE_IOMEM_RETRY 2
|
#define MAX_WRITE_IOMEM_RETRY 2
|
||||||
|
|
||||||
/* Host Control Registers */
|
/* register bitmasks */
|
||||||
#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_POWER_UP BIT(1)
|
||||||
#define HOST_CMD53_FIN BIT(2)
|
#define HOST_CMD53_FIN BIT(2)
|
||||||
|
|
||||||
#define HOST_INT_MASK_REG 0x04
|
|
||||||
#define HIM_DISABLE 0xff
|
#define HIM_DISABLE 0xff
|
||||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||||
|
|
||||||
#define HOST_INTSTATUS_REG 0x05
|
|
||||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
#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 DN_LD_CARD_RDY BIT(0)
|
||||||
#define CARD_IO_READY BIT(3)
|
#define CARD_IO_READY BIT(3)
|
||||||
|
|
||||||
#define CARD_FW_STATUS0_REG 0x40
|
|
||||||
#define CARD_FW_STATUS1_REG 0x41
|
|
||||||
#define FIRMWARE_READY 0xfedc
|
#define FIRMWARE_READY 0xfedc
|
||||||
|
|
||||||
#define CARD_RX_LEN_REG 0x42
|
|
||||||
#define CARD_RX_UNIT_REG 0x43
|
|
||||||
|
|
||||||
|
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 btmrvl_sdio_card {
|
||||||
struct sdio_func *func;
|
struct sdio_func *func;
|
||||||
u32 ioport;
|
u32 ioport;
|
||||||
const char *helper;
|
const char *helper;
|
||||||
const char *firmware;
|
const char *firmware;
|
||||||
|
const struct btmrvl_sdio_card_reg *reg;
|
||||||
|
u16 sd_blksz_fw_dl;
|
||||||
u8 rx_unit;
|
u8 rx_unit;
|
||||||
struct btmrvl_private *priv;
|
struct btmrvl_private *priv;
|
||||||
};
|
};
|
||||||
|
@ -92,6 +94,8 @@ struct btmrvl_sdio_card {
|
||||||
struct btmrvl_sdio_device {
|
struct btmrvl_sdio_device {
|
||||||
const char *helper;
|
const char *helper;
|
||||||
const char *firmware;
|
const char *firmware;
|
||||||
|
const struct btmrvl_sdio_card_reg *reg;
|
||||||
|
u16 sd_blksz_fw_dl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
|
||||||
/* Recv data */
|
/* Recv data */
|
||||||
static int ath_recv(struct hci_uart *hu, void *data, int count)
|
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");
|
BT_ERR("Frame Reassembly Failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
|
||||||
/* Recv data */
|
/* Recv data */
|
||||||
static int h4_recv(struct hci_uart *hu, void *data, int count)
|
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");
|
BT_ERR("Frame Reassembly Failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
||||||
*/
|
*/
|
||||||
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
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;
|
struct hci_uart *hu = (void *)tty->disc_data;
|
||||||
|
|
||||||
if (!hu || tty != hu->tty)
|
if (!hu || tty != hu->tty)
|
||||||
|
@ -368,7 +369,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&hu->rx_lock);
|
spin_lock(&hu->rx_lock);
|
||||||
hu->proto->recv(hu, (void *) data, count);
|
ret = hu->proto->recv(hu, (void *) data, count);
|
||||||
|
if (ret > 0)
|
||||||
hu->hdev->stat.byte_rx += count;
|
hu->hdev->stat.byte_rx += count;
|
||||||
spin_unlock(&hu->rx_lock);
|
spin_unlock(&hu->rx_lock);
|
||||||
|
|
||||||
|
|
|
@ -123,14 +123,7 @@ struct ath_ops {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_common;
|
struct ath_common;
|
||||||
|
struct ath_bus_ops;
|
||||||
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_common {
|
struct ath_common {
|
||||||
void *ah;
|
void *ah;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <linux/nl80211.h>
|
#include <linux/nl80211.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
#include <ar231x_platform.h>
|
#include <ar231x_platform.h>
|
||||||
#include "ath5k.h"
|
#include "ath5k.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
|
||||||
return 0;
|
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 = {
|
static const struct ath_bus_ops ath_ahb_bus_ops = {
|
||||||
.ath_bus_type = ATH_AHB,
|
.ath_bus_type = ATH_AHB,
|
||||||
.read_cachesize = ath5k_ahb_read_cachesize,
|
.read_cachesize = ath5k_ahb_read_cachesize,
|
||||||
.eeprom_read = ath5k_ahb_eeprom_read,
|
.eeprom_read = ath5k_ahb_eeprom_read,
|
||||||
|
.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Initialization*/
|
/*Initialization*/
|
||||||
|
@ -142,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||||
else
|
else
|
||||||
reg |= AR5K_AR5312_ENABLE_WLAN1;
|
reg |= AR5K_AR5312_ENABLE_WLAN1;
|
||||||
__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
|
__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);
|
ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
|
||||||
|
|
|
@ -224,8 +224,7 @@
|
||||||
|
|
||||||
/* SIFS */
|
/* SIFS */
|
||||||
#define AR5K_INIT_SIFS_TURBO 6
|
#define AR5K_INIT_SIFS_TURBO 6
|
||||||
/* XXX: 8 from initvals 10 from standard */
|
#define AR5K_INIT_SIFS_DEFAULT_BG 10
|
||||||
#define AR5K_INIT_SIFS_DEFAULT_BG 8
|
|
||||||
#define AR5K_INIT_SIFS_DEFAULT_A 16
|
#define AR5K_INIT_SIFS_DEFAULT_A 16
|
||||||
#define AR5K_INIT_SIFS_HALF_RATE 32
|
#define AR5K_INIT_SIFS_HALF_RATE 32
|
||||||
#define AR5K_INIT_SIFS_QUARTER_RATE 64
|
#define AR5K_INIT_SIFS_QUARTER_RATE 64
|
||||||
|
@ -453,12 +452,10 @@ struct ath5k_tx_status {
|
||||||
u16 ts_seqnum;
|
u16 ts_seqnum;
|
||||||
u16 ts_tstamp;
|
u16 ts_tstamp;
|
||||||
u8 ts_status;
|
u8 ts_status;
|
||||||
u8 ts_rate[4];
|
|
||||||
u8 ts_retry[4];
|
|
||||||
u8 ts_final_idx;
|
u8 ts_final_idx;
|
||||||
|
u8 ts_final_retry;
|
||||||
s8 ts_rssi;
|
s8 ts_rssi;
|
||||||
u8 ts_shortretry;
|
u8 ts_shortretry;
|
||||||
u8 ts_longretry;
|
|
||||||
u8 ts_virtcol;
|
u8 ts_virtcol;
|
||||||
u8 ts_antenna;
|
u8 ts_antenna;
|
||||||
};
|
};
|
||||||
|
@ -875,6 +872,19 @@ enum ath5k_int {
|
||||||
AR5K_INT_QTRIG = 0x40000000, /* Non common */
|
AR5K_INT_QTRIG = 0x40000000, /* Non common */
|
||||||
AR5K_INT_GLOBAL = 0x80000000,
|
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_COMMON = AR5K_INT_RXOK
|
||||||
| AR5K_INT_RXDESC
|
| AR5K_INT_RXDESC
|
||||||
| AR5K_INT_RXERR
|
| AR5K_INT_RXERR
|
||||||
|
@ -1058,6 +1068,7 @@ struct ath5k_hw {
|
||||||
u8 ah_coverage_class;
|
u8 ah_coverage_class;
|
||||||
bool ah_ack_bitrate_high;
|
bool ah_ack_bitrate_high;
|
||||||
u8 ah_bwmode;
|
u8 ah_bwmode;
|
||||||
|
bool ah_short_slot;
|
||||||
|
|
||||||
/* Antenna Control */
|
/* Antenna Control */
|
||||||
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
|
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
|
||||||
|
@ -1144,6 +1155,13 @@ struct ath5k_hw {
|
||||||
struct ath5k_rx_status *);
|
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
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
@ -1227,13 +1245,12 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
|
||||||
/* EEPROM access functions */
|
/* EEPROM access functions */
|
||||||
int ath5k_eeprom_init(struct ath5k_hw *ah);
|
int ath5k_eeprom_init(struct ath5k_hw *ah);
|
||||||
void ath5k_eeprom_detach(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 */
|
/* Protocol Control Unit Functions */
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
|
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_slottime(struct ath5k_hw *ah);
|
||||||
unsigned int ath5k_hw_get_default_sifs(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);
|
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
|
||||||
|
|
|
@ -313,12 +313,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
|
||||||
goto err;
|
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 */
|
/* Crypto settings */
|
||||||
common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
|
common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
|
||||||
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
|
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
|
||||||
|
|
||||||
if (srev >= AR5K_SREV_AR5212_V4 &&
|
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)))
|
!AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
|
||||||
common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
|
common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
|
||||||
|
|
||||||
|
|
|
@ -1443,6 +1443,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ath5k_set_current_imask(struct ath5k_softc *sc)
|
||||||
|
{
|
||||||
|
enum ath5k_int imask = sc->imask;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sc->irqlock, flags);
|
||||||
|
if (sc->rx_pending)
|
||||||
|
imask &= ~AR5K_INT_RX_ALL;
|
||||||
|
if (sc->tx_pending)
|
||||||
|
imask &= ~AR5K_INT_TX_ALL;
|
||||||
|
ath5k_hw_set_imr(sc->ah, imask);
|
||||||
|
spin_unlock_irqrestore(&sc->irqlock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ath5k_tasklet_rx(unsigned long data)
|
ath5k_tasklet_rx(unsigned long data)
|
||||||
{
|
{
|
||||||
|
@ -1506,6 +1521,8 @@ next:
|
||||||
} while (ath5k_rxbuf_setup(sc, bf) == 0);
|
} while (ath5k_rxbuf_setup(sc, bf) == 0);
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock(&sc->rxbuflock);
|
spin_unlock(&sc->rxbuflock);
|
||||||
|
sc->rx_pending = false;
|
||||||
|
ath5k_set_current_imask(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||||
struct ath5k_txq *txq, struct ath5k_tx_status *ts)
|
struct ath5k_txq *txq, struct ath5k_tx_status *ts)
|
||||||
{
|
{
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
|
u8 tries[3];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sc->stats.tx_all_count++;
|
sc->stats.tx_all_count++;
|
||||||
sc->stats.tx_bytes_count += skb->len;
|
sc->stats.tx_bytes_count += skb->len;
|
||||||
info = IEEE80211_SKB_CB(skb);
|
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);
|
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 =
|
struct ieee80211_tx_rate *r =
|
||||||
&info->status.rates[i];
|
&info->status.rates[i];
|
||||||
|
|
||||||
if (ts->ts_rate[i]) {
|
r->count = tries[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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count the successful attempt as well */
|
info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
|
||||||
info->status.rates[ts->ts_final_idx].count++;
|
info->status.rates[ts->ts_final_idx + 1].idx = -1;
|
||||||
|
|
||||||
if (unlikely(ts->ts_status)) {
|
if (unlikely(ts->ts_status)) {
|
||||||
sc->stats.ack_fail++;
|
sc->stats.ack_fail++;
|
||||||
|
@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||||
} else {
|
} else {
|
||||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||||
info->status.ack_signal = ts->ts_rssi;
|
info->status.ack_signal = ts->ts_rssi;
|
||||||
|
|
||||||
|
/* count the successful attempt as well */
|
||||||
|
info->status.rates[ts->ts_final_idx].count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
|
||||||
for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
|
for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
|
||||||
if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
|
if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
|
||||||
ath5k_tx_processq(sc, &sc->txqs[i]);
|
ath5k_tx_processq(sc, &sc->txqs[i]);
|
||||||
|
|
||||||
|
sc->tx_pending = false;
|
||||||
|
ath5k_set_current_imask(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
|
||||||
* AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
|
* 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
|
irqreturn_t
|
||||||
ath5k_intr(int irq, void *dev_id)
|
ath5k_intr(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
|
@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
|
||||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tasklet_schedule(&sc->rxtq);
|
ath5k_schedule_rx(sc);
|
||||||
} else {
|
} else {
|
||||||
if (status & AR5K_INT_SWBA) {
|
if (status & AR5K_INT_SWBA) {
|
||||||
tasklet_hi_schedule(&sc->beacontq);
|
tasklet_hi_schedule(&sc->beacontq);
|
||||||
|
@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
|
||||||
ath5k_hw_update_tx_triglevel(ah, true);
|
ath5k_hw_update_tx_triglevel(ah, true);
|
||||||
}
|
}
|
||||||
if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
|
if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
|
||||||
tasklet_schedule(&sc->rxtq);
|
ath5k_schedule_rx(sc);
|
||||||
if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
|
if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
|
||||||
| AR5K_INT_TXERR | AR5K_INT_TXEOL))
|
| AR5K_INT_TXERR | AR5K_INT_TXEOL))
|
||||||
tasklet_schedule(&sc->txtq);
|
ath5k_schedule_tx(sc);
|
||||||
if (status & AR5K_INT_BMISS) {
|
if (status & AR5K_INT_BMISS) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
}
|
}
|
||||||
|
@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
|
||||||
|
|
||||||
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
|
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
|
||||||
|
|
||||||
|
if (sc->rx_pending || sc->tx_pending)
|
||||||
|
ath5k_set_current_imask(sc);
|
||||||
|
|
||||||
if (unlikely(!counter))
|
if (unlikely(!counter))
|
||||||
ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
|
ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
|
||||||
|
|
||||||
|
@ -2572,6 +2612,8 @@ done:
|
||||||
|
|
||||||
static void stop_tasklets(struct ath5k_softc *sc)
|
static void stop_tasklets(struct ath5k_softc *sc)
|
||||||
{
|
{
|
||||||
|
sc->rx_pending = false;
|
||||||
|
sc->tx_pending = false;
|
||||||
tasklet_kill(&sc->rxtq);
|
tasklet_kill(&sc->rxtq);
|
||||||
tasklet_kill(&sc->txtq);
|
tasklet_kill(&sc->txtq);
|
||||||
tasklet_kill(&sc->calib);
|
tasklet_kill(&sc->calib);
|
||||||
|
@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
|
||||||
INIT_WORK(&sc->reset_work, ath5k_reset_work);
|
INIT_WORK(&sc->reset_work, ath5k_reset_work);
|
||||||
INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_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) {
|
if (ret) {
|
||||||
ATH5K_ERR(sc, "unable to read address from EEPROM\n");
|
ATH5K_ERR(sc, "unable to read address from EEPROM\n");
|
||||||
goto err_queues;
|
goto err_queues;
|
||||||
|
@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
|
||||||
* XXX: ??? detach ath5k_hw ???
|
* XXX: ??? detach ath5k_hw ???
|
||||||
* Other than that, it's straightforward...
|
* Other than that, it's straightforward...
|
||||||
*/
|
*/
|
||||||
ath5k_debug_finish_device(sc);
|
|
||||||
ieee80211_unregister_hw(hw);
|
ieee80211_unregister_hw(hw);
|
||||||
ath5k_desc_free(sc);
|
ath5k_desc_free(sc);
|
||||||
ath5k_txq_release(sc);
|
ath5k_txq_release(sc);
|
||||||
|
|
|
@ -193,12 +193,13 @@ struct ath5k_softc {
|
||||||
dma_addr_t desc_daddr; /* DMA (physical) address */
|
dma_addr_t desc_daddr; /* DMA (physical) address */
|
||||||
size_t desc_len; /* size of TX/RX descriptors */
|
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_INVALID 0 /* disable hardware accesses */
|
||||||
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
|
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
|
||||||
#define ATH_STAT_PROMISC 2
|
#define ATH_STAT_PROMISC 2
|
||||||
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
|
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
|
||||||
#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
|
#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_* */
|
unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
|
||||||
struct ieee80211_channel *curchan; /* current h/w channel */
|
struct ieee80211_channel *curchan; /* current h/w channel */
|
||||||
|
@ -207,6 +208,10 @@ struct ath5k_softc {
|
||||||
|
|
||||||
enum ath5k_int imask; /* interrupt mask copy */
|
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 lladdr[ETH_ALEN];
|
||||||
u8 bssidmask[ETH_ALEN];
|
u8 bssidmask[ETH_ALEN];
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
|
||||||
|
__clear_bit(AR5K_MODE_11A, caps->cap_mode);
|
||||||
|
|
||||||
/* Set number of supported TX queues */
|
/* Set number of supported TX queues */
|
||||||
if (ah->ah_version == AR5K_AR5210)
|
if (ah->ah_version == AR5K_AR5210)
|
||||||
caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
|
caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
|
||||||
|
|
|
@ -888,65 +888,38 @@ static const struct file_operations fops_queue = {
|
||||||
void
|
void
|
||||||
ath5k_debug_init_device(struct ath5k_softc *sc)
|
ath5k_debug_init_device(struct ath5k_softc *sc)
|
||||||
{
|
{
|
||||||
|
struct dentry *phydir;
|
||||||
|
|
||||||
sc->debug.level = ath5k_debug;
|
sc->debug.level = ath5k_debug;
|
||||||
|
|
||||||
sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
|
phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
|
||||||
sc->hw->wiphy->debugfsdir);
|
if (!phydir)
|
||||||
|
return;
|
||||||
|
|
||||||
sc->debug.debugfs_debug = debugfs_create_file("debug",
|
debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
|
||||||
S_IWUSR | S_IRUSR,
|
&fops_debug);
|
||||||
sc->debug.debugfs_phydir, sc, &fops_debug);
|
|
||||||
|
|
||||||
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
|
debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
|
||||||
sc->debug.debugfs_phydir, sc, &fops_registers);
|
|
||||||
|
|
||||||
sc->debug.debugfs_beacon = debugfs_create_file("beacon",
|
debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
|
||||||
S_IWUSR | S_IRUSR,
|
&fops_beacon);
|
||||||
sc->debug.debugfs_phydir, sc, &fops_beacon);
|
|
||||||
|
|
||||||
sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
|
debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
|
||||||
sc->debug.debugfs_phydir, sc, &fops_reset);
|
|
||||||
|
|
||||||
sc->debug.debugfs_antenna = debugfs_create_file("antenna",
|
debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
|
||||||
S_IWUSR | S_IRUSR,
|
&fops_antenna);
|
||||||
sc->debug.debugfs_phydir, sc, &fops_antenna);
|
|
||||||
|
|
||||||
sc->debug.debugfs_misc = debugfs_create_file("misc",
|
debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
|
||||||
S_IRUSR,
|
|
||||||
sc->debug.debugfs_phydir, sc, &fops_misc);
|
|
||||||
|
|
||||||
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
|
debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
|
||||||
S_IWUSR | S_IRUSR,
|
|
||||||
sc->debug.debugfs_phydir, sc,
|
|
||||||
&fops_frameerrors);
|
&fops_frameerrors);
|
||||||
|
|
||||||
sc->debug.debugfs_ani = debugfs_create_file("ani",
|
debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
|
||||||
S_IWUSR | S_IRUSR,
|
|
||||||
sc->debug.debugfs_phydir, sc,
|
|
||||||
&fops_ani);
|
|
||||||
|
|
||||||
sc->debug.debugfs_queue = debugfs_create_file("queue",
|
debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
|
||||||
S_IWUSR | S_IRUSR,
|
|
||||||
sc->debug.debugfs_phydir, sc,
|
|
||||||
&fops_queue);
|
&fops_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* functions used in other places */
|
/* functions used in other places */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -68,17 +68,6 @@ struct ath5k_buf;
|
||||||
|
|
||||||
struct ath5k_dbg_info {
|
struct ath5k_dbg_info {
|
||||||
unsigned int level; /* debug level */
|
unsigned int level; /* debug level */
|
||||||
/* debugfs entries */
|
|
||||||
struct dentry *debugfs_phydir;
|
|
||||||
struct dentry *debugfs_debug;
|
|
||||||
struct dentry *debugfs_registers;
|
|
||||||
struct dentry *debugfs_beacon;
|
|
||||||
struct dentry *debugfs_reset;
|
|
||||||
struct dentry *debugfs_antenna;
|
|
||||||
struct dentry *debugfs_misc;
|
|
||||||
struct dentry *debugfs_frameerrors;
|
|
||||||
struct dentry *debugfs_ani;
|
|
||||||
struct dentry *debugfs_queue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,9 +129,6 @@ enum ath5k_debug_level {
|
||||||
void
|
void
|
||||||
ath5k_debug_init_device(struct ath5k_softc *sc);
|
ath5k_debug_init_device(struct ath5k_softc *sc);
|
||||||
|
|
||||||
void
|
|
||||||
ath5k_debug_finish_device(struct ath5k_softc *sc);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
|
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
|
||||||
|
|
||||||
|
@ -166,9 +152,6 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
|
||||||
static inline void
|
static inline void
|
||||||
ath5k_debug_init_device(struct ath5k_softc *sc) {}
|
ath5k_debug_init_device(struct ath5k_softc *sc) {}
|
||||||
|
|
||||||
static inline void
|
|
||||||
ath5k_debug_finish_device(struct ath5k_softc *sc) {}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
|
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||||
unsigned int frame_len;
|
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;
|
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -208,8 +214,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
if (tx_power > AR5K_TUNE_MAX_TXPOWER)
|
if (tx_power > AR5K_TUNE_MAX_TXPOWER)
|
||||||
tx_power = AR5K_TUNE_MAX_TXPOWER;
|
tx_power = AR5K_TUNE_MAX_TXPOWER;
|
||||||
|
|
||||||
/* Clear descriptor */
|
/* Clear descriptor status area */
|
||||||
memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
|
memset(&desc->ud.ds_tx5212.tx_stat, 0,
|
||||||
|
sizeof(desc->ud.ds_tx5212.tx_stat));
|
||||||
|
|
||||||
/* Setup control descriptor */
|
/* Setup control descriptor */
|
||||||
|
|
||||||
|
@ -221,7 +228,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
|
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
|
||||||
return -EINVAL;
|
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 */
|
/* Verify and set buffer length */
|
||||||
|
|
||||||
|
@ -232,21 +239,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
|
if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
|
||||||
return -EINVAL;
|
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 |=
|
txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
|
||||||
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);
|
AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
|
||||||
tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
|
txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
|
||||||
AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
|
txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
|
||||||
tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0,
|
txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
||||||
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
|
|
||||||
tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
|
||||||
|
|
||||||
#define _TX_FLAGS(_c, _flag) \
|
#define _TX_FLAGS(_c, _flag) \
|
||||||
if (flags & AR5K_TXDESC_##_flag) { \
|
if (flags & AR5K_TXDESC_##_flag) { \
|
||||||
tx_ctl->tx_control_##_c |= \
|
txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
|
||||||
AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_TX_FLAGS(0, CLRDMASK);
|
_TX_FLAGS(0, CLRDMASK);
|
||||||
|
@ -262,8 +265,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
* WEP crap
|
* WEP crap
|
||||||
*/
|
*/
|
||||||
if (key_index != AR5K_TXKEYIX_INVALID) {
|
if (key_index != AR5K_TXKEYIX_INVALID) {
|
||||||
tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
||||||
tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
|
txctl1 |= AR5K_REG_SM(key_index,
|
||||||
AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
|
AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,12 +277,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||||
if ((flags & AR5K_TXDESC_RTSENA) &&
|
if ((flags & AR5K_TXDESC_RTSENA) &&
|
||||||
(flags & AR5K_TXDESC_CTSENA))
|
(flags & AR5K_TXDESC_CTSENA))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
tx_ctl->tx_control_2 |= rtscts_duration &
|
txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
|
||||||
AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
|
txctl3 |= AR5K_REG_SM(rtscts_rate,
|
||||||
tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
|
|
||||||
AR5K_4W_TX_DESC_CTL3_RTS_CTS_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +371,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
||||||
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
||||||
ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||||
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
|
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);
|
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
|
||||||
/*TODO: ts->ts_virtcol + test*/
|
/*TODO: ts->ts_virtcol + test*/
|
||||||
ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
||||||
|
@ -373,9 +380,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
||||||
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
||||||
ts->ts_antenna = 1;
|
ts->ts_antenna = 1;
|
||||||
ts->ts_status = 0;
|
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;
|
ts->ts_final_idx = 0;
|
||||||
|
|
||||||
if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
||||||
|
@ -401,81 +405,48 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
|
||||||
{
|
{
|
||||||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||||
struct ath5k_hw_tx_status *tx_status;
|
struct ath5k_hw_tx_status *tx_status;
|
||||||
|
u32 txstat0, txstat1;
|
||||||
|
|
||||||
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||||
tx_status = &desc->ud.ds_tx5212.tx_stat;
|
tx_status = &desc->ud.ds_tx5212.tx_stat;
|
||||||
|
|
||||||
|
txstat1 = ACCESS_ONCE(tx_status->tx_status_1);
|
||||||
|
|
||||||
/* No frame has been send or error */
|
/* 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;
|
return -EINPROGRESS;
|
||||||
|
|
||||||
|
txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get descriptor status
|
* 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);
|
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);
|
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);
|
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);
|
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);
|
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;
|
AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
|
||||||
ts->ts_status = 0;
|
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);
|
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 */
|
/* TX error */
|
||||||
if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
||||||
if (tx_status->tx_status_0 &
|
if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
||||||
AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
|
||||||
ts->ts_status |= AR5K_TXERR_XRETRY;
|
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;
|
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;
|
ts->ts_status |= AR5K_TXERR_FILT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,37 +580,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
|
||||||
struct ath5k_rx_status *rs)
|
struct ath5k_rx_status *rs)
|
||||||
{
|
{
|
||||||
struct ath5k_hw_rx_status *rx_status;
|
struct ath5k_hw_rx_status *rx_status;
|
||||||
|
u32 rxstat0, rxstat1;
|
||||||
|
|
||||||
rx_status = &desc->ud.ds_rx.rx_stat;
|
rx_status = &desc->ud.ds_rx.rx_stat;
|
||||||
|
rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);
|
||||||
|
|
||||||
/* No frame received / not ready */
|
/* No frame received / not ready */
|
||||||
if (unlikely(!(rx_status->rx_status_1 &
|
if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
|
||||||
AR5K_5212_RX_DESC_STATUS1_DONE)))
|
|
||||||
return -EINPROGRESS;
|
return -EINPROGRESS;
|
||||||
|
|
||||||
memset(rs, 0, sizeof(struct ath5k_rx_status));
|
memset(rs, 0, sizeof(struct ath5k_rx_status));
|
||||||
|
rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frame receive status
|
* Frame receive status
|
||||||
*/
|
*/
|
||||||
rs->rs_datalen = rx_status->rx_status_0 &
|
rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
|
||||||
AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
|
rs->rs_rssi = AR5K_REG_MS(rxstat0,
|
||||||
rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
|
|
||||||
AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
|
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);
|
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);
|
AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
|
||||||
rs->rs_more = !!(rx_status->rx_status_0 &
|
rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
|
||||||
AR5K_5212_RX_DESC_STATUS0_MORE);
|
rs->rs_tstamp = AR5K_REG_MS(rxstat1,
|
||||||
rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
|
|
||||||
AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
|
AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key table status
|
* Key table status
|
||||||
*/
|
*/
|
||||||
if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
||||||
rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
|
rs->rs_keyix = AR5K_REG_MS(rxstat1,
|
||||||
AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
|
AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
|
||||||
else
|
else
|
||||||
rs->rs_keyix = AR5K_RXKEYIX_INVALID;
|
rs->rs_keyix = AR5K_RXKEYIX_INVALID;
|
||||||
|
@ -647,27 +618,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
|
||||||
/*
|
/*
|
||||||
* Receive/descriptor errors
|
* Receive/descriptor errors
|
||||||
*/
|
*/
|
||||||
if (!(rx_status->rx_status_1 &
|
if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
|
||||||
AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
|
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
|
||||||
if (rx_status->rx_status_1 &
|
|
||||||
AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
|
|
||||||
rs->rs_status |= AR5K_RXERR_CRC;
|
rs->rs_status |= AR5K_RXERR_CRC;
|
||||||
|
|
||||||
if (rx_status->rx_status_1 &
|
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
|
||||||
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
|
|
||||||
rs->rs_status |= AR5K_RXERR_PHY;
|
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);
|
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
|
||||||
if (!ah->ah_capabilities.cap_has_phyerr_counters)
|
if (!ah->ah_capabilities.cap_has_phyerr_counters)
|
||||||
ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
|
ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_status->rx_status_1 &
|
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
||||||
AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
|
||||||
rs->rs_status |= AR5K_RXERR_DECRYPT;
|
rs->rs_status |= AR5K_RXERR_DECRYPT;
|
||||||
|
|
||||||
if (rx_status->rx_status_1 &
|
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
|
||||||
AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
|
|
||||||
rs->rs_status |= AR5K_RXERR_MIC;
|
rs->rs_status |= AR5K_RXERR_MIC;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
|
||||||
vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
|
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
|
/* Convert RF5111 specific data to generic raw data
|
||||||
* used by interpolation code */
|
* used by interpolation code */
|
||||||
static int
|
static int
|
||||||
|
@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Only one curve for RF5111
|
/* Only one curve for RF5111
|
||||||
* find out which one and place
|
* find out which one and place
|
||||||
|
@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (convert power to 0.25dB units
|
* (convert power to 0.25dB units
|
||||||
|
@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill pd_curves */
|
/* Fill pd_curves */
|
||||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||||
|
@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (all power levels are in 0.25dB units) */
|
* (all power levels are in 0.25dB units) */
|
||||||
|
@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* (all power levels are in 0.25dB units) */
|
* (all power levels are in 0.25dB units) */
|
||||||
|
@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (!chinfo[pier].pd_curves)
|
if (!chinfo[pier].pd_curves)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill pd_curves */
|
/* Fill pd_curves */
|
||||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||||
|
@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
sizeof(u8), GFP_KERNEL);
|
sizeof(u8), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_step)
|
if (!pd->pd_step)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||||
sizeof(s16), GFP_KERNEL);
|
sizeof(s16), GFP_KERNEL);
|
||||||
|
|
||||||
if (!pd->pd_pwr)
|
if (!pd->pd_pwr)
|
||||||
return -ENOMEM;
|
goto err_out;
|
||||||
|
|
||||||
/* Fill raw dataset
|
/* Fill raw dataset
|
||||||
* convert all pwr levels to
|
* convert all pwr levels to
|
||||||
|
@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse EEPROM data */
|
/* Parse EEPROM data */
|
||||||
|
@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
|
||||||
return 0;
|
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 */
|
/* Read conformance test limits used for regulatory control */
|
||||||
static int
|
static int
|
||||||
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
||||||
|
@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
|
||||||
return ret;
|
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 *
|
* Init/Detach functions *
|
||||||
|
|
|
@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
if (changes & BSS_CHANGED_BEACON_INT)
|
if (changes & BSS_CHANGED_BEACON_INT)
|
||||||
sc->bintval = bss_conf->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) {
|
if (changes & BSS_CHANGED_ASSOC) {
|
||||||
avf->assoc = bss_conf->assoc;
|
avf->assoc = bss_conf->assoc;
|
||||||
if (bss_conf->assoc)
|
if (bss_conf->assoc)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/nl80211.h>
|
#include <linux/nl80211.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/pci-aspm.h>
|
#include <linux/pci-aspm.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
#include "../ath.h"
|
#include "../ath.h"
|
||||||
#include "ath5k.h"
|
#include "ath5k.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
|
||||||
return 0;
|
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 */
|
/* Common ath_bus_opts structure */
|
||||||
static const struct ath_bus_ops ath_pci_bus_ops = {
|
static const struct ath_bus_ops ath_pci_bus_ops = {
|
||||||
.ath_bus_type = ATH_PCI,
|
.ath_bus_type = ATH_PCI,
|
||||||
.read_cachesize = ath5k_pci_read_cachesize,
|
.read_cachesize = ath5k_pci_read_cachesize,
|
||||||
.eeprom_read = ath5k_pci_eeprom_read,
|
.eeprom_read = ath5k_pci_eeprom_read,
|
||||||
|
.eeprom_read_mac = ath5k_pci_eeprom_read_mac,
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************\
|
/********************\
|
||||||
|
|
|
@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] =
|
||||||
* bwmodes.
|
* bwmodes.
|
||||||
*/
|
*/
|
||||||
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
|
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;
|
struct ath5k_softc *sc = ah->ah_sc;
|
||||||
int sifs, preamble, plcp_bits, sym_time;
|
int sifs, preamble, plcp_bits, sym_time;
|
||||||
|
@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
|
||||||
|
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
if (!ah->ah_bwmode) {
|
if (!ah->ah_bwmode) {
|
||||||
dur = ieee80211_generic_frame_duration(sc->hw,
|
__le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
|
||||||
NULL, len, rate);
|
NULL, len, rate);
|
||||||
return le16_to_cpu(dur);
|
|
||||||
|
/* subtract difference between long and short preamble */
|
||||||
|
dur = le16_to_cpu(raw_dur);
|
||||||
|
if (shortpre)
|
||||||
|
dur -= 96;
|
||||||
|
|
||||||
|
return dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitrate = rate->bitrate;
|
bitrate = rate->bitrate;
|
||||||
|
@ -145,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
|
||||||
slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
|
slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
|
||||||
break;
|
break;
|
||||||
case AR5K_BWMODE_DEFAULT:
|
case AR5K_BWMODE_DEFAULT:
|
||||||
slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
|
|
||||||
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;
|
slot_time = AR5K_INIT_SLOT_TIME_B;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
|
||||||
* actual rate for this rate. See mac80211 tx.c
|
* actual rate for this rate. See mac80211 tx.c
|
||||||
* ieee80211_duration() for a brief description of
|
* ieee80211_duration() for a brief description of
|
||||||
* what rate we should choose to TX ACKs. */
|
* 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);
|
ath5k_hw_reg_write(ah, tx_time, reg);
|
||||||
|
|
||||||
if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
|
if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
ath5k_hw_reg_write(ah, tx_time,
|
ath5k_hw_reg_write(ah, tx_time,
|
||||||
reg + (AR5K_SET_SHORT_PREAMBLE << 2));
|
reg + (AR5K_SET_SHORT_PREAMBLE << 2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sifs = ath5k_hw_get_default_sifs(ah);
|
sifs = ath5k_hw_get_default_sifs(ah);
|
||||||
sifs_clock = ath5k_hw_htoclock(ah, sifs);
|
sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
|
||||||
|
|
||||||
/* EIFS
|
/* EIFS
|
||||||
* Txtime of ack at lowest rate + SIFS + DIFS
|
* Txtime of ack at lowest rate + SIFS + DIFS
|
||||||
|
@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
|
||||||
else
|
else
|
||||||
rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
|
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 */
|
/* ack_tx_time includes an SIFS already */
|
||||||
eifs = ack_tx_time + sifs + 2 * slot_time;
|
eifs = ack_tx_time + sifs + 2 * slot_time;
|
||||||
|
|
|
@ -5,7 +5,7 @@ config ATH9K_COMMON
|
||||||
|
|
||||||
config ATH9K
|
config ATH9K
|
||||||
tristate "Atheros 802.11n wireless cards support"
|
tristate "Atheros 802.11n wireless cards support"
|
||||||
depends on PCI && MAC80211
|
depends on MAC80211
|
||||||
select ATH9K_HW
|
select ATH9K_HW
|
||||||
select MAC80211_LEDS
|
select MAC80211_LEDS
|
||||||
select LEDS_CLASS
|
select LEDS_CLASS
|
||||||
|
@ -23,6 +23,25 @@ config ATH9K
|
||||||
|
|
||||||
If you choose to build a module, it'll be called ath9k.
|
If you choose to build a module, it'll be called ath9k.
|
||||||
|
|
||||||
|
config ATH9K_PCI
|
||||||
|
bool "Atheros ath9k PCI/PCIe bus support"
|
||||||
|
depends on ATH9K && PCI
|
||||||
|
default PCI
|
||||||
|
---help---
|
||||||
|
This option enables the PCI bus support in ath9k.
|
||||||
|
|
||||||
|
Say Y, if you have a compatible PCI/PCIe wireless card.
|
||||||
|
|
||||||
|
config ATH9K_AHB
|
||||||
|
bool "Atheros ath9k AHB bus support"
|
||||||
|
depends on ATH9K
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
This option enables the AHB bus support in ath9k.
|
||||||
|
|
||||||
|
Say Y, if you have a SoC with a compatible built-in
|
||||||
|
wireless MAC. Say N if unsure.
|
||||||
|
|
||||||
config ATH9K_DEBUGFS
|
config ATH9K_DEBUGFS
|
||||||
bool "Atheros ath9k debugging"
|
bool "Atheros ath9k debugging"
|
||||||
depends on ATH9K && DEBUG_FS
|
depends on ATH9K && DEBUG_FS
|
||||||
|
|
|
@ -6,8 +6,8 @@ ath9k-y += beacon.o \
|
||||||
xmit.o \
|
xmit.o \
|
||||||
|
|
||||||
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
|
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
|
||||||
ath9k-$(CONFIG_PCI) += pci.o
|
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
|
||||||
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
|
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
|
||||||
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
|
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
|
||||||
|
|
||||||
obj-$(CONFIG_ATH9K) += ath9k.o
|
obj-$(CONFIG_ATH9K) += ath9k.o
|
||||||
|
@ -48,4 +48,6 @@ ath9k_htc-y += htc_hst.o \
|
||||||
htc_drv_init.o \
|
htc_drv_init.o \
|
||||||
htc_drv_gpio.o
|
htc_drv_gpio.o
|
||||||
|
|
||||||
|
ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o
|
||||||
|
|
||||||
obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
|
obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
#include <linux/ath9k_platform.h>
|
#include <linux/ath9k_platform.h>
|
||||||
#include "ath9k.h"
|
#include "ath9k.h"
|
||||||
|
|
||||||
|
const struct platform_device_id ath9k_platform_id_table[] = {
|
||||||
|
{
|
||||||
|
.name = "ath9k",
|
||||||
|
.driver_data = AR5416_AR9100_DEVID,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
/* return bus cachesize in 4B word units */
|
/* return bus cachesize in 4B word units */
|
||||||
static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
|
static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||||
struct ath_softc *sc;
|
struct ath_softc *sc;
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
const struct platform_device_id *id = platform_get_device_id(pdev);
|
||||||
int irq;
|
int irq;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct ath_hw *ah;
|
struct ath_hw *ah;
|
||||||
|
@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||||
goto err_free_hw;
|
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) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "failed to initialize device\n");
|
dev_err(&pdev->dev, "failed to initialize device\n");
|
||||||
goto err_irq;
|
goto err_irq;
|
||||||
|
@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = {
|
||||||
.name = "ath9k",
|
.name = "ath9k",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
.id_table = ath9k_platform_id_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
|
||||||
|
|
||||||
int ath_ahb_init(void)
|
int ath_ahb_init(void)
|
||||||
{
|
{
|
||||||
return platform_driver_register(&ath_ahb_driver);
|
return platform_driver_register(&ath_ahb_driver);
|
||||||
|
|
|
@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||||
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
||||||
| SM(txPower, AR_XmitPower)
|
| SM(txPower, AR_XmitPower)
|
||||||
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
||||||
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
|
|
||||||
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
|
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
|
||||||
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
|
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
|
||||||
|
|
||||||
|
@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
|
||||||
|
{
|
||||||
|
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
ads->ds_ctl0 |= AR_ClrDestMask;
|
||||||
|
else
|
||||||
|
ads->ds_ctl0 &= ~AR_ClrDestMask;
|
||||||
|
}
|
||||||
|
|
||||||
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
|
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
|
||||||
void *lastds,
|
void *lastds,
|
||||||
u32 durUpdateEn, u32 rtsctsRate,
|
u32 durUpdateEn, u32 rtsctsRate,
|
||||||
|
@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
|
||||||
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
|
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
|
||||||
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
|
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
|
||||||
ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
|
ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
|
||||||
|
ops->set_clrdmask = ar9002_hw_set_clrdmask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -483,7 +483,11 @@
|
||||||
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
|
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
|
||||||
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
|
#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_PWRCTRL9 0xa27C
|
||||||
|
|
||||||
|
#define AR_PHY_TX_PWRCTRL10 0xa394
|
||||||
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
|
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
|
||||||
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
|
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
|
||||||
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
|
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
|
||||||
|
@ -495,6 +499,8 @@
|
||||||
|
|
||||||
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
|
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
|
||||||
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
|
#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 0x0000FC00
|
||||||
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
|
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
|
||||||
|
|
||||||
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
|
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||||
{0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
|
{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
|
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
|
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||||
|
@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
|
{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
|
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
|
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
|
{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
|
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
|
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||||
{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
|
{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
|
||||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||||
|
@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
|
||||||
|
|
||||||
static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
|
static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
|
||||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||||
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
|
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
|
||||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||||
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
|
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
|
||||||
|
@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
|
||||||
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
||||||
{0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
|
{0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
|
||||||
{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
||||||
|
@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
|
||||||
|
|
||||||
static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
|
static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||||
{0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
|
{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
|
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
|
{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
|
||||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||||
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
|
{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
|
||||||
|
@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||||
{0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
|
{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
|
{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
|
{0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
|
{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
||||||
{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
|
{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
|
||||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||||
|
@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
|
||||||
|
|
||||||
static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
|
static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||||
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||||
|
@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
|
{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
|
||||||
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
|
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
|
||||||
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
|
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
|
||||||
{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
|
{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
|
||||||
{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
|
{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
|
||||||
{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
|
{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
|
||||||
{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
|
{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
|
||||||
{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
|
{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
|
||||||
{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
|
{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
|
||||||
{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
|
{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
|
||||||
{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
|
{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
|
{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||||
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
|
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
|
||||||
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
|
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
|
||||||
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
|
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
|
||||||
|
@ -1361,45 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
|
||||||
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
|
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
|
||||||
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
|
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
|
||||||
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
|
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
|
||||||
{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
|
{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
|
||||||
{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
|
{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
|
||||||
{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
|
{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
|
||||||
{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
|
{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
|
||||||
{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
|
{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
|
||||||
{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
|
{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
|
||||||
{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
|
{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
|
||||||
{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
|
{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
|
||||||
{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
|
{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
|
{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
|
||||||
{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
|
{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
|
||||||
{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
|
{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
|
||||||
{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
|
{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
|
||||||
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
|
{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
|
||||||
{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
|
{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
|
||||||
{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
|
{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
|
{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
|
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
|
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
|
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||||
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
|
{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||||
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
|
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||||
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
|
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||||
{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
|
{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
|
||||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||||
|
|
|
@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||||
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
|
||||||
| SM(txpower, AR_XmitPower)
|
| SM(txpower, AR_XmitPower)
|
||||||
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
|
||||||
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
|
|
||||||
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
|
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
|
||||||
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
|
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
|
||||||
|
|
||||||
|
@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||||
ads->ctl22 = 0;
|
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,
|
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
|
||||||
void *lastds,
|
void *lastds,
|
||||||
u32 durUpdateEn, u32 rtsctsRate,
|
u32 durUpdateEn, u32 rtsctsRate,
|
||||||
|
@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
|
||||||
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
|
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
|
||||||
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
|
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
|
||||||
ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
|
ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
|
||||||
|
ops->set_clrdmask = ar9003_hw_set_clrdmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
|
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
|
||||||
|
|
|
@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||||
freq = centers.synth_center;
|
freq = centers.synth_center;
|
||||||
|
|
||||||
if (freq < 4800) { /* 2 GHz, fractional mode */
|
if (freq < 4800) { /* 2 GHz, fractional mode */
|
||||||
if (AR_SREV_9485(ah))
|
if (AR_SREV_9485(ah)) {
|
||||||
channelSel = CHANSEL_2G_9485(freq);
|
u32 chan_frac;
|
||||||
else
|
|
||||||
|
/*
|
||||||
|
* freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
|
||||||
|
* ndiv = ((chan_mhz * 4) / 3) / freq_ref;
|
||||||
|
* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
|
||||||
|
*/
|
||||||
|
channelSel = (freq * 4) / 120;
|
||||||
|
chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
|
||||||
|
channelSel = (channelSel << 17) | chan_frac;
|
||||||
|
} else
|
||||||
channelSel = CHANSEL_2G(freq);
|
channelSel = CHANSEL_2G(freq);
|
||||||
/* Set to 2G mode */
|
/* Set to 2G mode */
|
||||||
bMode = 1;
|
bMode = 1;
|
||||||
|
@ -401,7 +410,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
|
||||||
|
|
||||||
ar9003_hw_spur_ofdm_clear(ah);
|
ar9003_hw_spur_ofdm_clear(ah);
|
||||||
|
|
||||||
for (i = 0; spurChansPtr[i] && i < 5; i++) {
|
for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
|
||||||
freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
|
freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
|
||||||
if (abs(freq_offset) < range) {
|
if (abs(freq_offset) < range) {
|
||||||
ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
|
ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
|
||||||
|
|
|
@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
|
||||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
|
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
|
@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
|
||||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
|
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
|
@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
|
||||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
|
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
|
@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
|
||||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
|
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
|
@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
|
||||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
|
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||||
|
|
|
@ -200,6 +200,7 @@ struct ath_atx_ac {
|
||||||
int sched;
|
int sched;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct list_head tid_q;
|
struct list_head tid_q;
|
||||||
|
bool clear_ps_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_frame_info {
|
struct ath_frame_info {
|
||||||
|
@ -255,8 +256,12 @@ struct ath_node {
|
||||||
#endif
|
#endif
|
||||||
struct ath_atx_tid tid[WME_NUM_TID];
|
struct ath_atx_tid tid[WME_NUM_TID];
|
||||||
struct ath_atx_ac ac[WME_NUM_AC];
|
struct ath_atx_ac ac[WME_NUM_AC];
|
||||||
|
int ps_key;
|
||||||
|
|
||||||
u16 maxampdu;
|
u16 maxampdu;
|
||||||
u8 mpdudensity;
|
u8 mpdudensity;
|
||||||
|
|
||||||
|
bool sleeping;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AGGR_CLEANUP BIT(1)
|
#define AGGR_CLEANUP BIT(1)
|
||||||
|
@ -338,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
void ath_tx_aggr_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_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 */
|
/* VIFs */
|
||||||
/********/
|
/********/
|
||||||
|
@ -665,7 +673,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
|
||||||
bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
|
bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
|
||||||
bool ath9k_uses_beacons(int type);
|
bool ath9k_uses_beacons(int type);
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_ATH9K_PCI
|
||||||
int ath_pci_init(void);
|
int ath_pci_init(void);
|
||||||
void ath_pci_exit(void);
|
void ath_pci_exit(void);
|
||||||
#else
|
#else
|
||||||
|
@ -673,7 +681,7 @@ static inline int ath_pci_init(void) { return 0; };
|
||||||
static inline void ath_pci_exit(void) {};
|
static inline void ath_pci_exit(void) {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ATHEROS_AR71XX
|
#ifdef CONFIG_ATH9K_AHB
|
||||||
int ath_ahb_init(void);
|
int ath_ahb_init(void);
|
||||||
void ath_ahb_exit(void);
|
void ath_ahb_exit(void);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
|
||||||
if (avp->av_bcbuf != NULL) {
|
if (avp->av_bcbuf != NULL) {
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
|
|
||||||
|
avp->is_bslot_active = false;
|
||||||
if (avp->av_bslot != -1) {
|
if (avp->av_bslot != -1) {
|
||||||
sc->beacon.bslot[avp->av_bslot] = NULL;
|
sc->beacon.bslot[avp->av_bslot] = NULL;
|
||||||
sc->nbcnvifs--;
|
sc->nbcnvifs--;
|
||||||
|
@ -743,37 +744,10 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||||
cur_conf->dtim_period = 1;
|
cur_conf->dtim_period = 1;
|
||||||
|
|
||||||
ath_set_beacon(sc);
|
ath_set_beacon(sc);
|
||||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath_set_beacon(struct ath_softc *sc)
|
static bool ath_has_valid_bslot(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);
|
|
||||||
break;
|
|
||||||
case NL80211_IFTYPE_ADHOC:
|
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
|
||||||
ath_beacon_config_adhoc(sc, cur_conf);
|
|
||||||
break;
|
|
||||||
case NL80211_IFTYPE_STATION:
|
|
||||||
ath_beacon_config_sta(sc, cur_conf);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
|
||||||
"Unsupported beaconing mode\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc->sc_flags |= SC_OP_BEACONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
|
|
||||||
{
|
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
|
||||||
struct ath_vif *avp;
|
struct ath_vif *avp;
|
||||||
int slot;
|
int slot;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -787,7 +761,47 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
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:
|
||||||
|
if (ath_has_valid_bslot(sc))
|
||||||
|
ath_beacon_config_ap(sc, cur_conf);
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_ADHOC:
|
||||||
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
|
ath_beacon_config_adhoc(sc, cur_conf);
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
ath_beacon_config_sta(sc, cur_conf);
|
||||||
|
/*
|
||||||
|
* Request a re-configuration of Beacon related timers
|
||||||
|
* on the receipt of the first Beacon frame (i.e.,
|
||||||
|
* after time sync with the AP).
|
||||||
|
*/
|
||||||
|
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
|
"Unsupported beaconing mode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->sc_flags |= SC_OP_BEACONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
|
||||||
|
{
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
|
||||||
|
if (!ath_has_valid_bslot(sc))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ath9k_ps_wakeup(sc);
|
ath9k_ps_wakeup(sc);
|
||||||
|
|
|
@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||||
|
|
||||||
struct ath_softc *sc = file->private_data;
|
struct ath_softc *sc = file->private_data;
|
||||||
char *buf;
|
char *buf;
|
||||||
unsigned int len = 0, size = 1152;
|
unsigned int len = 0, size = 1400;
|
||||||
ssize_t retval = 0;
|
ssize_t retval = 0;
|
||||||
|
|
||||||
buf = kzalloc(size, GFP_KERNEL);
|
buf = kzalloc(size, GFP_KERNEL);
|
||||||
|
@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||||
"%18s : %10u\n", "DECRYPT BUSY ERR",
|
"%18s : %10u\n", "DECRYPT BUSY ERR",
|
||||||
sc->debug.stats.rxstats.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("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
|
||||||
PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
|
PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
|
||||||
PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
|
PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
|
||||||
|
@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
|
||||||
RX_PHY_ERR_INC(phyerr);
|
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_STAT_INC
|
||||||
#undef RX_PHY_ERR_INC
|
#undef RX_PHY_ERR_INC
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,13 @@ struct ath_rx_stats {
|
||||||
u32 post_delim_crc_err;
|
u32 post_delim_crc_err;
|
||||||
u32 decrypt_busy_err;
|
u32 decrypt_busy_err;
|
||||||
u32 phy_err_stats[ATH9K_PHYERR_MAX];
|
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 {
|
struct ath_stats {
|
||||||
|
|
|
@ -436,7 +436,11 @@ struct modal_eep_4k_header {
|
||||||
u8 db2_2:4, db2_3:4;
|
u8 db2_2:4, db2_3:4;
|
||||||
u8 db2_4:4, reserved:4;
|
u8 db2_4:4, reserved:4;
|
||||||
#endif
|
#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];
|
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
|
|
@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||||
{
|
{
|
||||||
struct modal_eep_4k_header *pModal;
|
struct modal_eep_4k_header *pModal;
|
||||||
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
|
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
|
||||||
|
struct base_eep_header_4k *pBase = &eep->baseEepHeader;
|
||||||
u8 txRxAttenLocal;
|
u8 txRxAttenLocal;
|
||||||
u8 ob[5], db1[5], db2[5];
|
u8 ob[5], db1[5], db2[5];
|
||||||
u8 ant_div_control1, ant_div_control2;
|
u8 ant_div_control1, ant_div_control2;
|
||||||
|
@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||||
AR_PHY_SETTLING_SWITCH,
|
AR_PHY_SETTLING_SWITCH,
|
||||||
pModal->swSettleHt40);
|
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)
|
static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
|
||||||
|
|
|
@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
|
||||||
{
|
{
|
||||||
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
|
||||||
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
|
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
|
||||||
u16 antWrites[AR9287_ANT_16S];
|
|
||||||
u32 regChainOffset, regval;
|
u32 regChainOffset, regval;
|
||||||
u8 txRxAttenLocal;
|
u8 txRxAttenLocal;
|
||||||
int i, j, offset_num;
|
int i;
|
||||||
|
|
||||||
pModal = &eep->modalHeader;
|
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);
|
REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
|
||||||
|
|
||||||
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
|
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
#include "htc.h"
|
#include "htc.h"
|
||||||
|
|
||||||
/* identify firmware images */
|
/* identify firmware images */
|
||||||
#define FIRMWARE_AR7010 "ar7010.fw"
|
#define FIRMWARE_AR7010_1_1 "htc_7010.fw"
|
||||||
#define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw"
|
#define FIRMWARE_AR9271 "htc_9271.fw"
|
||||||
#define FIRMWARE_AR9271 "ar9271.fw"
|
|
||||||
|
|
||||||
MODULE_FIRMWARE(FIRMWARE_AR7010);
|
|
||||||
MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
|
MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
|
||||||
MODULE_FIRMWARE(FIRMWARE_AR9271);
|
MODULE_FIRMWARE(FIRMWARE_AR9271);
|
||||||
|
|
||||||
|
@ -80,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb)
|
||||||
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
|
ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
|
||||||
cmd->skb, 1);
|
cmd->skb, true);
|
||||||
kfree(cmd);
|
kfree(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
|
||||||
return ret;
|
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,
|
static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
|
||||||
struct sk_buff_head *list)
|
struct sk_buff_head *list)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +215,22 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
|
||||||
|
|
||||||
while ((skb = __skb_dequeue(list)) != NULL) {
|
while ((skb = __skb_dequeue(list)) != NULL) {
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
TX_STAT_INC(skb_dropped);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
|
||||||
|
struct sk_buff_head *queue,
|
||||||
|
bool txok)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
while ((skb = __skb_dequeue(queue)) != NULL) {
|
||||||
|
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
||||||
|
skb, txok);
|
||||||
|
if (txok)
|
||||||
|
TX_STAT_INC(skb_success);
|
||||||
|
else
|
||||||
|
TX_STAT_INC(skb_failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +238,7 @@ static void hif_usb_tx_cb(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
|
struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
|
||||||
struct hif_device_usb *hif_dev;
|
struct hif_device_usb *hif_dev;
|
||||||
struct sk_buff *skb;
|
bool txok = true;
|
||||||
|
|
||||||
if (!tx_buf || !tx_buf->hif_dev)
|
if (!tx_buf || !tx_buf->hif_dev)
|
||||||
return;
|
return;
|
||||||
|
@ -155,10 +252,7 @@ static void hif_usb_tx_cb(struct urb *urb)
|
||||||
case -ECONNRESET:
|
case -ECONNRESET:
|
||||||
case -ENODEV:
|
case -ENODEV:
|
||||||
case -ESHUTDOWN:
|
case -ESHUTDOWN:
|
||||||
/*
|
txok = false;
|
||||||
* The URB has been killed, free the SKBs.
|
|
||||||
*/
|
|
||||||
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the URBs are being flushed, no need to add this
|
* If the URBs are being flushed, no need to add this
|
||||||
|
@ -167,41 +261,19 @@ static void hif_usb_tx_cb(struct urb *urb)
|
||||||
spin_lock(&hif_dev->tx.tx_lock);
|
spin_lock(&hif_dev->tx.tx_lock);
|
||||||
if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
|
if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
|
||||||
spin_unlock(&hif_dev->tx.tx_lock);
|
spin_unlock(&hif_dev->tx.tx_lock);
|
||||||
|
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spin_unlock(&hif_dev->tx.tx_lock);
|
spin_unlock(&hif_dev->tx.tx_lock);
|
||||||
|
|
||||||
/*
|
break;
|
||||||
* In the stop() case, this URB has to be added to
|
|
||||||
* the free list.
|
|
||||||
*/
|
|
||||||
goto add_free;
|
|
||||||
default:
|
default:
|
||||||
|
txok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
add_free:
|
|
||||||
/* Re-initialize the SKB queue */
|
/* Re-initialize the SKB queue */
|
||||||
tx_buf->len = tx_buf->offset = 0;
|
tx_buf->len = tx_buf->offset = 0;
|
||||||
__skb_queue_head_init(&tx_buf->skb_queue);
|
__skb_queue_head_init(&tx_buf->skb_queue);
|
||||||
|
@ -274,7 +346,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
||||||
ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
|
ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
tx_buf->len = tx_buf->offset = 0;
|
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);
|
__skb_queue_head_init(&tx_buf->skb_queue);
|
||||||
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
||||||
hif_dev->tx.tx_buf_cnt++;
|
hif_dev->tx.tx_buf_cnt++;
|
||||||
|
@ -286,10 +358,11 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
|
static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||||
|
|
||||||
|
@ -304,26 +377,36 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||||
|
|
||||||
|
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);
|
__skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
|
||||||
hif_dev->tx.tx_skb_cnt++;
|
hif_dev->tx.tx_skb_cnt++;
|
||||||
|
}
|
||||||
/* Send normal frames immediately */
|
|
||||||
if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL)))
|
|
||||||
__hif_usb_tx(hif_dev);
|
|
||||||
|
|
||||||
/* Check if AMPDUs have to be sent immediately */
|
/* Check if AMPDUs have to be sent immediately */
|
||||||
if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) &&
|
if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
|
||||||
(hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
|
|
||||||
(hif_dev->tx.tx_skb_cnt < 2)) {
|
(hif_dev->tx.tx_skb_cnt < 2)) {
|
||||||
__hif_usb_tx(hif_dev);
|
__hif_usb_tx(hif_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
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;
|
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -335,14 +418,14 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id)
|
||||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
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 hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
||||||
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
|
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, 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.tx_skb_cnt = 0;
|
||||||
hif_dev->tx.flags |= HIF_USB_TX_STOP;
|
hif_dev->tx.flags |= HIF_USB_TX_STOP;
|
||||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||||
|
@ -352,17 +435,18 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
|
||||||
&hif_dev->tx.tx_pending, list) {
|
&hif_dev->tx.tx_pending, list) {
|
||||||
usb_kill_urb(tx_buf->urb);
|
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,
|
static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
switch (pipe_id) {
|
switch (pipe_id) {
|
||||||
case USB_WLAN_TX_PIPE:
|
case USB_WLAN_TX_PIPE:
|
||||||
ret = hif_usb_send_tx(hif_dev, skb, tx_ctl);
|
ret = hif_usb_send_tx(hif_dev, skb);
|
||||||
break;
|
break;
|
||||||
case USB_REG_OUT_PIPE:
|
case USB_REG_OUT_PIPE:
|
||||||
ret = hif_usb_send_regout(hif_dev, skb);
|
ret = hif_usb_send_regout(hif_dev, skb);
|
||||||
|
@ -377,6 +461,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
|
||||||
return ret;
|
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 = {
|
static struct ath9k_htc_hif hif_usb = {
|
||||||
.transport = ATH9K_HIF_USB,
|
.transport = ATH9K_HIF_USB,
|
||||||
.name = "ath9k_hif_usb",
|
.name = "ath9k_hif_usb",
|
||||||
|
@ -386,6 +504,7 @@ static struct ath9k_htc_hif hif_usb = {
|
||||||
|
|
||||||
.start = hif_usb_start,
|
.start = hif_usb_start,
|
||||||
.stop = hif_usb_stop,
|
.stop = hif_usb_stop,
|
||||||
|
.sta_drain = hif_usb_sta_drain,
|
||||||
.send = hif_usb_send,
|
.send = hif_usb_send,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -567,6 +686,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||||
case -ESHUTDOWN:
|
case -ESHUTDOWN:
|
||||||
goto free;
|
goto free;
|
||||||
default:
|
default:
|
||||||
|
skb_reset_tail_pointer(skb);
|
||||||
|
skb_trim(skb, 0);
|
||||||
|
|
||||||
goto resubmit;
|
goto resubmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,23 +713,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||||
USB_REG_IN_PIPE),
|
USB_REG_IN_PIPE),
|
||||||
nskb->data, MAX_REG_IN_BUF_SIZE,
|
nskb->data, MAX_REG_IN_BUF_SIZE,
|
||||||
ath9k_hif_usb_reg_in_cb, nskb);
|
ath9k_hif_usb_reg_in_cb, nskb);
|
||||||
|
|
||||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
|
||||||
if (ret) {
|
|
||||||
kfree_skb(nskb);
|
|
||||||
urb->context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resubmit:
|
resubmit:
|
||||||
skb_reset_tail_pointer(skb);
|
usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
|
||||||
skb_trim(skb, 0);
|
|
||||||
|
|
||||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
usb_unanchor_urb(urb);
|
||||||
goto free;
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
free:
|
free:
|
||||||
|
@ -641,6 +755,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||||
kfree(tx_buf->buf);
|
kfree(tx_buf->buf);
|
||||||
kfree(tx_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)
|
static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||||
|
@ -652,6 +768,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||||
INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
|
INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
|
||||||
spin_lock_init(&hif_dev->tx.tx_lock);
|
spin_lock_init(&hif_dev->tx.tx_lock);
|
||||||
__skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
|
__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++) {
|
for (i = 0; i < MAX_TX_URB_NUM; i++) {
|
||||||
tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
|
tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
|
||||||
|
@ -748,43 +865,67 @@ err_urb:
|
||||||
return ret;
|
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_anchored_urbs(&hif_dev->reg_in_submitted);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
init_usb_anchor(&hif_dev->reg_in_submitted);
|
||||||
if (hif_dev->reg_in_urb == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
|
||||||
|
|
||||||
|
/* Allocate URB */
|
||||||
|
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
if (urb == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_urb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
|
skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
|
||||||
if (!skb)
|
if (!skb) {
|
||||||
goto err;
|
ret = -ENOMEM;
|
||||||
|
goto err_skb;
|
||||||
|
}
|
||||||
|
|
||||||
usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev,
|
usb_fill_bulk_urb(urb, hif_dev->udev,
|
||||||
usb_rcvbulkpipe(hif_dev->udev,
|
usb_rcvbulkpipe(hif_dev->udev,
|
||||||
USB_REG_IN_PIPE),
|
USB_REG_IN_PIPE),
|
||||||
skb->data, MAX_REG_IN_BUF_SIZE,
|
skb->data, MAX_REG_IN_BUF_SIZE,
|
||||||
ath9k_hif_usb_reg_in_cb, skb);
|
ath9k_hif_usb_reg_in_cb, skb);
|
||||||
|
|
||||||
if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
|
/* Anchor URB */
|
||||||
goto err;
|
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;
|
return 0;
|
||||||
|
|
||||||
err:
|
err_submit:
|
||||||
ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
|
kfree_skb(skb);
|
||||||
return -ENOMEM;
|
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)
|
static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
|
||||||
|
@ -801,7 +942,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
|
||||||
goto err_rx;
|
goto err_rx;
|
||||||
|
|
||||||
/* Register Read */
|
/* 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;
|
goto err_reg;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -816,7 +957,7 @@ err:
|
||||||
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
|
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
|
||||||
{
|
{
|
||||||
usb_kill_anchored_urbs(&hif_dev->regout_submitted);
|
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_tx_urbs(hif_dev);
|
||||||
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
|
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
|
||||||
}
|
}
|
||||||
|
@ -1026,10 +1167,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
||||||
/* Find out which firmware to load */
|
/* Find out which firmware to load */
|
||||||
|
|
||||||
if (IS_AR7010_DEVICE(id->driver_info))
|
if (IS_AR7010_DEVICE(id->driver_info))
|
||||||
if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
|
|
||||||
hif_dev->fw_name = FIRMWARE_AR7010_1_1;
|
hif_dev->fw_name = FIRMWARE_AR7010_1_1;
|
||||||
else
|
|
||||||
hif_dev->fw_name = FIRMWARE_AR7010;
|
|
||||||
else
|
else
|
||||||
hif_dev->fw_name = FIRMWARE_AR9271;
|
hif_dev->fw_name = FIRMWARE_AR9271;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
/* FIXME: Verify these numbers (with Windows) */
|
/* FIXME: Verify these numbers (with Windows) */
|
||||||
#define MAX_TX_URB_NUM 8
|
#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_BUF_SIZE 32768
|
||||||
#define MAX_TX_AGGR_NUM 20
|
#define MAX_TX_AGGR_NUM 20
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
#define MAX_PKT_NUM_IN_TRANSFER 10
|
#define MAX_PKT_NUM_IN_TRANSFER 10
|
||||||
|
|
||||||
#define MAX_REG_OUT_URB_NUM 1
|
#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
|
#define MAX_REG_IN_BUF_SIZE 64
|
||||||
|
|
||||||
|
@ -90,9 +90,10 @@ struct hif_device_usb {
|
||||||
const struct firmware *firmware;
|
const struct firmware *firmware;
|
||||||
struct htc_target *htc_handle;
|
struct htc_target *htc_handle;
|
||||||
struct hif_usb_tx tx;
|
struct hif_usb_tx tx;
|
||||||
struct urb *reg_in_urb;
|
|
||||||
struct usb_anchor regout_submitted;
|
struct usb_anchor regout_submitted;
|
||||||
struct usb_anchor rx_submitted;
|
struct usb_anchor rx_submitted;
|
||||||
|
struct usb_anchor reg_in_submitted;
|
||||||
|
struct usb_anchor mgmt_submitted;
|
||||||
struct sk_buff *remain_skb;
|
struct sk_buff *remain_skb;
|
||||||
const char *fw_name;
|
const char *fw_name;
|
||||||
int rx_remain_len;
|
int rx_remain_len;
|
||||||
|
|
|
@ -67,8 +67,11 @@ enum htc_opmode {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr)
|
#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_NORMAL 2
|
||||||
|
#define ATH9K_HTC_BEACON 3
|
||||||
|
#define ATH9K_HTC_MGMT 4
|
||||||
|
|
||||||
#define ATH9K_HTC_TX_CTSONLY 0x1
|
#define ATH9K_HTC_TX_CTSONLY 0x1
|
||||||
#define ATH9K_HTC_TX_RTSCTS 0x2
|
#define ATH9K_HTC_TX_RTSCTS 0x2
|
||||||
|
@ -82,7 +85,8 @@ struct tx_frame_hdr {
|
||||||
__be32 flags; /* ATH9K_HTC_TX_* */
|
__be32 flags; /* ATH9K_HTC_TX_* */
|
||||||
u8 key_type;
|
u8 key_type;
|
||||||
u8 keyix;
|
u8 keyix;
|
||||||
u8 reserved[26];
|
u8 cookie;
|
||||||
|
u8 pad;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct tx_mgmt_hdr {
|
struct tx_mgmt_hdr {
|
||||||
|
@ -92,26 +96,16 @@ struct tx_mgmt_hdr {
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 key_type;
|
u8 key_type;
|
||||||
u8 keyix;
|
u8 keyix;
|
||||||
u16 reserved;
|
u8 cookie;
|
||||||
|
u8 pad;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct tx_beacon_header {
|
struct tx_beacon_header {
|
||||||
u8 len_changed;
|
|
||||||
u8 vif_index;
|
u8 vif_index;
|
||||||
|
u8 len_changed;
|
||||||
u16 rev;
|
u16 rev;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct ath9k_htc_target_hw {
|
|
||||||
u32 flags;
|
|
||||||
u32 flags_ext;
|
|
||||||
u32 ampdu_limit;
|
|
||||||
u8 ampdu_subframes;
|
|
||||||
u8 tx_chainmask;
|
|
||||||
u8 tx_chainmask_legacy;
|
|
||||||
u8 rtscts_ratecode;
|
|
||||||
u8 protmode;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct ath9k_htc_cap_target {
|
struct ath9k_htc_cap_target {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u32 flags_ext;
|
u32 flags_ext;
|
||||||
|
@ -121,21 +115,16 @@ struct ath9k_htc_cap_target {
|
||||||
u8 tx_chainmask_legacy;
|
u8 tx_chainmask_legacy;
|
||||||
u8 rtscts_ratecode;
|
u8 rtscts_ratecode;
|
||||||
u8 protmode;
|
u8 protmode;
|
||||||
|
u8 pad;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct ath9k_htc_target_vif {
|
struct ath9k_htc_target_vif {
|
||||||
u8 index;
|
u8 index;
|
||||||
u8 des_bssid[ETH_ALEN];
|
u8 opmode;
|
||||||
__be32 opmode;
|
|
||||||
u8 myaddr[ETH_ALEN];
|
u8 myaddr[ETH_ALEN];
|
||||||
u8 bssid[ETH_ALEN];
|
|
||||||
u32 flags;
|
|
||||||
u32 flags_ext;
|
|
||||||
u16 ps_sta;
|
|
||||||
__be16 rtsthreshold;
|
|
||||||
u8 ath_cap;
|
u8 ath_cap;
|
||||||
u8 node;
|
__be16 rtsthreshold;
|
||||||
s8 mcast_rate;
|
u8 pad;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define ATH_HTC_STA_AUTH 0x0001
|
#define ATH_HTC_STA_AUTH 0x0001
|
||||||
|
@ -143,27 +132,16 @@ struct ath9k_htc_target_vif {
|
||||||
#define ATH_HTC_STA_ERP 0x0004
|
#define ATH_HTC_STA_ERP 0x0004
|
||||||
#define ATH_HTC_STA_HT 0x0008
|
#define ATH_HTC_STA_HT 0x0008
|
||||||
|
|
||||||
/* FIXME: UAPSD variables */
|
|
||||||
struct ath9k_htc_target_sta {
|
struct ath9k_htc_target_sta {
|
||||||
u16 associd;
|
|
||||||
u16 txpower;
|
|
||||||
u32 ucastkey;
|
|
||||||
u8 macaddr[ETH_ALEN];
|
u8 macaddr[ETH_ALEN];
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
u8 sta_index;
|
u8 sta_index;
|
||||||
u8 vif_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;
|
u8 is_vif_sta;
|
||||||
u16 maxampdu;
|
__be16 flags; /* ATH_HTC_STA_* */
|
||||||
u16 iv16;
|
__be16 htcap;
|
||||||
u32 iv32;
|
__be16 maxampdu;
|
||||||
|
u8 pad;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct ath9k_htc_target_aggr {
|
struct ath9k_htc_target_aggr {
|
||||||
|
@ -197,12 +175,31 @@ struct ath9k_htc_target_rate {
|
||||||
struct ath9k_htc_rate rates;
|
struct ath9k_htc_rate rates;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath9k_htc_target_stats {
|
struct ath9k_htc_target_int_stats {
|
||||||
__be32 tx_shortretry;
|
__be32 rx;
|
||||||
__be32 tx_longretry;
|
__be32 rxorn;
|
||||||
__be32 tx_xretries;
|
__be32 rxeol;
|
||||||
__be32 ht_txunaggr_xretry;
|
__be32 txurn;
|
||||||
__be32 ht_tx_xretries;
|
__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;
|
} __packed;
|
||||||
|
|
||||||
#define ATH9K_HTC_MAX_VIF 2
|
#define ATH9K_HTC_MAX_VIF 2
|
||||||
|
@ -244,6 +241,8 @@ struct ath9k_htc_vif {
|
||||||
u8 index;
|
u8 index;
|
||||||
u16 seq_no;
|
u16 seq_no;
|
||||||
bool beacon_configured;
|
bool beacon_configured;
|
||||||
|
int bslot;
|
||||||
|
__le64 tsfadjust;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath9k_vif_iter_data {
|
struct ath9k_vif_iter_data {
|
||||||
|
@ -282,23 +281,65 @@ struct ath9k_htc_rx {
|
||||||
spinlock_t rxbuflock;
|
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 {
|
struct ath9k_htc_tx_ctl {
|
||||||
u8 type; /* ATH9K_HTC_* */
|
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
|
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
||||||
|
|
||||||
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
|
#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 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]++)
|
#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 {
|
struct ath_tx_stats {
|
||||||
u32 buf_queued;
|
u32 buf_queued;
|
||||||
u32 buf_completed;
|
u32 buf_completed;
|
||||||
u32 skb_queued;
|
u32 skb_queued;
|
||||||
u32 skb_completed;
|
u32 skb_success;
|
||||||
u32 skb_dropped;
|
u32 skb_failed;
|
||||||
|
u32 cab_queued;
|
||||||
u32 queue_stats[WME_NUM_AC];
|
u32 queue_stats[WME_NUM_AC];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -306,25 +347,35 @@ struct ath_rx_stats {
|
||||||
u32 skb_allocated;
|
u32 skb_allocated;
|
||||||
u32 skb_completed;
|
u32 skb_completed;
|
||||||
u32 skb_dropped;
|
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 ath9k_debug {
|
||||||
struct dentry *debugfs_phy;
|
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_tx_stats tx_stats;
|
||||||
struct ath_rx_stats rx_stats;
|
struct ath_rx_stats rx_stats;
|
||||||
u32 txrate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define TX_STAT_INC(c) do { } while (0)
|
#define TX_STAT_INC(c) do { } while (0)
|
||||||
#define RX_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)
|
#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 */
|
#endif /* CONFIG_ATH9K_HTC_DEBUGFS */
|
||||||
|
|
||||||
#define ATH_LED_PIN_DEF 1
|
#define ATH_LED_PIN_DEF 1
|
||||||
|
@ -351,10 +402,21 @@ struct ath_led {
|
||||||
int brightness;
|
int brightness;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BSTUCK_THRESHOLD 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust these when the max. no of beaconing interfaces is
|
||||||
|
* increased.
|
||||||
|
*/
|
||||||
|
#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */
|
||||||
|
#define MIN_SWBA_RESPONSE 10 /* in TUs */
|
||||||
|
|
||||||
struct htc_beacon_config {
|
struct htc_beacon_config {
|
||||||
|
struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF];
|
||||||
u16 beacon_interval;
|
u16 beacon_interval;
|
||||||
u16 dtim_period;
|
u16 dtim_period;
|
||||||
u16 bmiss_timeout;
|
u16 bmiss_timeout;
|
||||||
|
u32 bmiss_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_btcoex {
|
struct ath_btcoex {
|
||||||
|
@ -388,6 +450,9 @@ struct ath9k_htc_priv {
|
||||||
struct htc_target *htc;
|
struct htc_target *htc;
|
||||||
struct wmi *wmi;
|
struct wmi *wmi;
|
||||||
|
|
||||||
|
u16 fw_version_major;
|
||||||
|
u16 fw_version_minor;
|
||||||
|
|
||||||
enum htc_endpoint_id wmi_cmd_ep;
|
enum htc_endpoint_id wmi_cmd_ep;
|
||||||
enum htc_endpoint_id beacon_ep;
|
enum htc_endpoint_id beacon_ep;
|
||||||
enum htc_endpoint_id cab_ep;
|
enum htc_endpoint_id cab_ep;
|
||||||
|
@ -411,27 +476,23 @@ struct ath9k_htc_priv {
|
||||||
u16 txpowlimit;
|
u16 txpowlimit;
|
||||||
u16 nvifs;
|
u16 nvifs;
|
||||||
u16 nstations;
|
u16 nstations;
|
||||||
u32 bmiss_cnt;
|
|
||||||
bool rearm_ani;
|
bool rearm_ani;
|
||||||
bool reconfig_beacon;
|
bool reconfig_beacon;
|
||||||
|
unsigned int rxfilter;
|
||||||
|
|
||||||
struct ath9k_hw_cal_data caldata;
|
struct ath9k_hw_cal_data caldata;
|
||||||
|
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||||
|
|
||||||
spinlock_t beacon_lock;
|
spinlock_t beacon_lock;
|
||||||
|
|
||||||
bool tx_queues_stop;
|
|
||||||
spinlock_t tx_lock;
|
|
||||||
|
|
||||||
struct ieee80211_vif *vif;
|
|
||||||
struct htc_beacon_config cur_beacon_conf;
|
struct htc_beacon_config cur_beacon_conf;
|
||||||
unsigned int rxfilter;
|
|
||||||
|
struct ath9k_htc_rx rx;
|
||||||
|
struct ath9k_htc_tx tx;
|
||||||
|
|
||||||
struct tasklet_struct swba_tasklet;
|
struct tasklet_struct swba_tasklet;
|
||||||
struct tasklet_struct rx_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 delayed_work ani_work;
|
||||||
|
struct tasklet_struct tx_failed_tasklet;
|
||||||
struct work_struct ps_work;
|
struct work_struct ps_work;
|
||||||
struct work_struct fatal_work;
|
struct work_struct fatal_work;
|
||||||
|
|
||||||
|
@ -470,11 +531,18 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||||
|
|
||||||
void ath9k_htc_reset(struct ath9k_htc_priv *priv);
|
void ath9k_htc_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_beaconq_config(struct ath9k_htc_priv *priv);
|
||||||
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
|
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
|
||||||
struct ieee80211_vif *vif);
|
struct ieee80211_vif *vif);
|
||||||
void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
|
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,
|
void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
|
||||||
enum htc_endpoint_id ep_id);
|
enum htc_endpoint_id ep_id);
|
||||||
|
@ -491,14 +559,23 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
|
||||||
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
|
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
|
||||||
|
|
||||||
int ath9k_tx_init(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,
|
||||||
int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb);
|
struct sk_buff *skb, u8 slot, bool is_cab);
|
||||||
void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
|
void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
|
||||||
bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype);
|
bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype);
|
||||||
int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);
|
int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);
|
||||||
int get_hw_qnum(u16 queue, int *hwq_map);
|
int get_hw_qnum(u16 queue, int *hwq_map);
|
||||||
int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
||||||
struct ath9k_tx_queue_info *qinfo);
|
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);
|
int ath9k_rx_init(struct ath9k_htc_priv *priv);
|
||||||
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
|
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
|
||||||
|
@ -528,15 +605,9 @@ void ath9k_htc_suspend(struct htc_target *htc_handle);
|
||||||
int ath9k_htc_resume(struct htc_target *htc_handle);
|
int ath9k_htc_resume(struct htc_target *htc_handle);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
#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);
|
int ath9k_htc_init_debug(struct ath_hw *ah);
|
||||||
void ath9k_htc_exit_debug(struct ath_hw *ah);
|
|
||||||
#else
|
#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 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 /* CONFIG_ATH9K_HTC_DEBUGFS */
|
||||||
|
|
||||||
#endif /* HTC_H */
|
#endif /* HTC_H */
|
||||||
|
|
|
@ -18,6 +18,50 @@
|
||||||
|
|
||||||
#define FUDGE 2
|
#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,
|
static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
|
||||||
struct htc_beacon_config *bss_conf)
|
struct htc_beacon_config *bss_conf)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
|
||||||
intval /= ATH9K_HTC_MAX_BCN_VIF;
|
intval /= ATH9K_HTC_MAX_BCN_VIF;
|
||||||
nexttbtt = intval;
|
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) {
|
if (priv->op_flags & OP_TSF_RESET) {
|
||||||
ath9k_hw_reset_tsf(priv->ah);
|
ath9k_hw_reset_tsf(priv->ah);
|
||||||
priv->op_flags &= ~OP_TSF_RESET;
|
priv->op_flags &= ~OP_TSF_RESET;
|
||||||
|
@ -172,12 +225,16 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
|
||||||
imask |= ATH9K_INT_SWBA;
|
imask |= ATH9K_INT_SWBA;
|
||||||
|
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
|
"AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d "
|
||||||
bss_conf->beacon_interval, nexttbtt, imask);
|
"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);
|
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||||
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
||||||
priv->bmiss_cnt = 0;
|
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||||
htc_imask = cpu_to_be32(imask);
|
htc_imask = cpu_to_be32(imask);
|
||||||
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
||||||
}
|
}
|
||||||
|
@ -205,16 +262,26 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
|
||||||
nexttbtt += intval;
|
nexttbtt += intval;
|
||||||
} while (nexttbtt < tsftu);
|
} while (nexttbtt < tsftu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only one IBSS interfce is allowed.
|
||||||
|
*/
|
||||||
|
if (intval > DEFAULT_SWBA_RESPONSE)
|
||||||
|
priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE;
|
||||||
|
else
|
||||||
|
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
|
||||||
|
|
||||||
if (priv->op_flags & OP_ENABLE_BEACON)
|
if (priv->op_flags & OP_ENABLE_BEACON)
|
||||||
imask |= ATH9K_INT_SWBA;
|
imask |= ATH9K_INT_SWBA;
|
||||||
|
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n",
|
"IBSS Beacon config, intval: %d, nexttbtt: %u, "
|
||||||
bss_conf->beacon_interval, nexttbtt, imask);
|
"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);
|
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||||
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval));
|
||||||
priv->bmiss_cnt = 0;
|
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||||
htc_imask = cpu_to_be32(imask);
|
htc_imask = cpu_to_be32(imask);
|
||||||
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
|
||||||
}
|
}
|
||||||
|
@ -225,38 +292,101 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
|
||||||
dev_kfree_skb_any(skb);
|
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 ath9k_htc_vif *avp = (void *)priv->vif->drv_priv;
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
struct tx_beacon_header beacon_hdr;
|
struct ieee80211_vif *vif;
|
||||||
struct ath9k_htc_tx_ctl tx_ctl;
|
struct sk_buff *skb;
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_hdr *hdr;
|
||||||
struct sk_buff *beacon;
|
int padpos, padsize, ret, tx_slot;
|
||||||
u8 *tx_fhdr;
|
|
||||||
|
|
||||||
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);
|
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 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 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));
|
||||||
|
|
||||||
|
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)) {
|
if (unlikely(priv->op_flags & OP_SCANNING)) {
|
||||||
spin_unlock_bh(&priv->beacon_lock);
|
spin_unlock_bh(&priv->beacon_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a new beacon */
|
/* Get a new beacon */
|
||||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
beacon = ieee80211_beacon_get(priv->hw, vif);
|
||||||
if (!beacon) {
|
if (!beacon) {
|
||||||
spin_unlock_bh(&priv->beacon_lock);
|
spin_unlock_bh(&priv->beacon_lock);
|
||||||
return;
|
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);
|
info = IEEE80211_SKB_CB(beacon);
|
||||||
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||||
struct ieee80211_hdr *hdr =
|
struct ieee80211_hdr *hdr =
|
||||||
|
@ -266,45 +396,149 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
|
||||||
hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
|
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;
|
beacon_hdr.vif_index = avp->index;
|
||||||
tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
|
tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
|
||||||
memcpy(tx_fhdr, (u8 *) &beacon_hdr, 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);
|
spin_unlock_bh(&priv->beacon_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently, only for IBSS */
|
static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
|
||||||
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
struct wmi_event_swba *swba)
|
||||||
{
|
{
|
||||||
struct ath_hw *ah = priv->ah;
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
struct ath9k_tx_queue_info qi, qi_be;
|
u64 tsf;
|
||||||
int qnum = priv->hwq_map[WME_AC_BE];
|
u32 tsftu;
|
||||||
|
u16 intval;
|
||||||
|
int slot;
|
||||||
|
|
||||||
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
|
intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD;
|
||||||
memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info));
|
|
||||||
|
|
||||||
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
|
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;
|
||||||
|
|
||||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
ath_dbg(common, ATH_DBG_BEACON,
|
||||||
/* For WIFI Beacon Distribution
|
"Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n",
|
||||||
* Long slot time : 2x cwmin
|
slot, tsf, tsftu, intval);
|
||||||
* 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)) {
|
return slot;
|
||||||
ath_err(ath9k_hw_common(ah),
|
}
|
||||||
"Unable to update beacon queue %u!\n", qnum);
|
|
||||||
} else {
|
void ath9k_htc_swba(struct ath9k_htc_priv *priv,
|
||||||
ath9k_hw_resettxqueue(ah, priv->beaconq);
|
struct wmi_event_swba *swba)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if (swba->beacon_pending != 0) {
|
||||||
|
priv->cur_beacon_conf.bmiss_cnt++;
|
||||||
|
if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) {
|
||||||
|
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||||
|
"Beacon stuck, HW reset\n");
|
||||||
|
ieee80211_queue_work(priv->hw,
|
||||||
|
&priv->fatal_work);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->cur_beacon_conf.bmiss_cnt) {
|
||||||
|
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||||
|
"Resuming beacon xmit after %u misses\n",
|
||||||
|
priv->cur_beacon_conf.bmiss_cnt);
|
||||||
|
priv->cur_beacon_conf.bmiss_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = ath9k_htc_choose_bslot(priv, swba);
|
||||||
|
spin_lock_bh(&priv->beacon_lock);
|
||||||
|
if (priv->cur_beacon_conf.bslot[slot] == NULL) {
|
||||||
|
spin_unlock_bh(&priv->beacon_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&priv->beacon_lock);
|
||||||
|
|
||||||
|
ath9k_htc_send_buffered(priv, slot);
|
||||||
|
ath9k_htc_send_beacon(priv, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||||
|
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2011 Atheros Communications Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "htc.h"
|
||||||
|
|
||||||
|
static int ath9k_debugfs_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
file->private_data = inode->i_private;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
struct ath9k_htc_target_int_stats cmd_rsp;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
memset(&cmd_rsp, 0, sizeof(cmd_rsp));
|
||||||
|
|
||||||
|
WMI_CMD(WMI_INT_STATS_CMDID);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "RX",
|
||||||
|
be32_to_cpu(cmd_rsp.rx));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "RXORN",
|
||||||
|
be32_to_cpu(cmd_rsp.rxorn));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "RXEOL",
|
||||||
|
be32_to_cpu(cmd_rsp.rxeol));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "TXURN",
|
||||||
|
be32_to_cpu(cmd_rsp.txurn));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "TXTO",
|
||||||
|
be32_to_cpu(cmd_rsp.txto));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "CST",
|
||||||
|
be32_to_cpu(cmd_rsp.cst));
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_tgt_int_stats = {
|
||||||
|
.read = read_file_tgt_int_stats,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
struct ath9k_htc_target_tx_stats cmd_rsp;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
memset(&cmd_rsp, 0, sizeof(cmd_rsp));
|
||||||
|
|
||||||
|
WMI_CMD(WMI_TX_STATS_CMDID);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "Xretries",
|
||||||
|
be32_to_cpu(cmd_rsp.xretries));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "FifoErr",
|
||||||
|
be32_to_cpu(cmd_rsp.fifoerr));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "Filtered",
|
||||||
|
be32_to_cpu(cmd_rsp.filtered));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "TimerExp",
|
||||||
|
be32_to_cpu(cmd_rsp.timer_exp));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "ShortRetries",
|
||||||
|
be32_to_cpu(cmd_rsp.shortretries));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "LongRetries",
|
||||||
|
be32_to_cpu(cmd_rsp.longretries));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "QueueNull",
|
||||||
|
be32_to_cpu(cmd_rsp.qnull));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "EncapFail",
|
||||||
|
be32_to_cpu(cmd_rsp.encap_fail));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "NoBuf",
|
||||||
|
be32_to_cpu(cmd_rsp.nobuf));
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_tgt_tx_stats = {
|
||||||
|
.read = read_file_tgt_tx_stats,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
struct ath9k_htc_target_rx_stats cmd_rsp;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
memset(&cmd_rsp, 0, sizeof(cmd_rsp));
|
||||||
|
|
||||||
|
WMI_CMD(WMI_RX_STATS_CMDID);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "NoBuf",
|
||||||
|
be32_to_cpu(cmd_rsp.nobuf));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "HostSend",
|
||||||
|
be32_to_cpu(cmd_rsp.host_send));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "HostDone",
|
||||||
|
be32_to_cpu(cmd_rsp.host_done));
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_tgt_rx_stats = {
|
||||||
|
.read = read_file_tgt_rx_stats,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "Buffers queued",
|
||||||
|
priv->debug.tx_stats.buf_queued);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "Buffers completed",
|
||||||
|
priv->debug.tx_stats.buf_completed);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "SKBs queued",
|
||||||
|
priv->debug.tx_stats.skb_queued);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "SKBs success",
|
||||||
|
priv->debug.tx_stats.skb_success);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "SKBs failed",
|
||||||
|
priv->debug.tx_stats.skb_failed);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "CAB queued",
|
||||||
|
priv->debug.tx_stats.cab_queued);
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "BE queued",
|
||||||
|
priv->debug.tx_stats.queue_stats[WME_AC_BE]);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "BK queued",
|
||||||
|
priv->debug.tx_stats.queue_stats[WME_AC_BK]);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "VI queued",
|
||||||
|
priv->debug.tx_stats.queue_stats[WME_AC_VI]);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"%20s : %10u\n", "VO queued",
|
||||||
|
priv->debug.tx_stats.queue_stats[WME_AC_VO]);
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_xmit = {
|
||||||
|
.read = read_file_xmit,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
|
||||||
|
struct ath_htc_rx_status *rxs)
|
||||||
|
{
|
||||||
|
#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++
|
||||||
|
|
||||||
|
if (rxs->rs_status & ATH9K_RXERR_CRC)
|
||||||
|
priv->debug.rx_stats.err_crc++;
|
||||||
|
if (rxs->rs_status & ATH9K_RXERR_DECRYPT)
|
||||||
|
priv->debug.rx_stats.err_decrypt_crc++;
|
||||||
|
if (rxs->rs_status & ATH9K_RXERR_MIC)
|
||||||
|
priv->debug.rx_stats.err_mic++;
|
||||||
|
if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
|
||||||
|
priv->debug.rx_stats.err_pre_delim++;
|
||||||
|
if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST)
|
||||||
|
priv->debug.rx_stats.err_post_delim++;
|
||||||
|
if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY)
|
||||||
|
priv->debug.rx_stats.err_decrypt_busy++;
|
||||||
|
|
||||||
|
if (rxs->rs_status & ATH9K_RXERR_PHY) {
|
||||||
|
priv->debug.rx_stats.err_phy++;
|
||||||
|
if (rxs->rs_phyerr < ATH9K_PHYERR_MAX)
|
||||||
|
RX_PHY_ERR_INC(rxs->rs_phyerr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RX_PHY_ERR_INC
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
#define PHY_ERR(s, p) \
|
||||||
|
len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \
|
||||||
|
priv->debug.rx_stats.err_phy_stats[p]);
|
||||||
|
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
char *buf;
|
||||||
|
unsigned int len = 0, size = 1500;
|
||||||
|
ssize_t retval = 0;
|
||||||
|
|
||||||
|
buf = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "SKBs allocated",
|
||||||
|
priv->debug.rx_stats.skb_allocated);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "SKBs completed",
|
||||||
|
priv->debug.rx_stats.skb_completed);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "SKBs Dropped",
|
||||||
|
priv->debug.rx_stats.skb_dropped);
|
||||||
|
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "CRC ERR",
|
||||||
|
priv->debug.rx_stats.err_crc);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "DECRYPT CRC ERR",
|
||||||
|
priv->debug.rx_stats.err_decrypt_crc);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "MIC ERR",
|
||||||
|
priv->debug.rx_stats.err_mic);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "PRE-DELIM CRC ERR",
|
||||||
|
priv->debug.rx_stats.err_pre_delim);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "POST-DELIM CRC ERR",
|
||||||
|
priv->debug.rx_stats.err_post_delim);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "DECRYPT BUSY ERR",
|
||||||
|
priv->debug.rx_stats.err_decrypt_busy);
|
||||||
|
len += snprintf(buf + len, size - len,
|
||||||
|
"%20s : %10u\n", "TOTAL PHY ERR",
|
||||||
|
priv->debug.rx_stats.err_phy);
|
||||||
|
|
||||||
|
|
||||||
|
PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
|
||||||
|
PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
|
||||||
|
PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
|
||||||
|
PHY_ERR("RATE", ATH9K_PHYERR_RATE);
|
||||||
|
PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
|
||||||
|
PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
|
||||||
|
PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
|
||||||
|
PHY_ERR("TOR", ATH9K_PHYERR_TOR);
|
||||||
|
PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
|
||||||
|
PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
|
||||||
|
PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
|
||||||
|
PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
|
||||||
|
PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
|
||||||
|
PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
|
||||||
|
PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
|
||||||
|
PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
|
||||||
|
PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
|
||||||
|
PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
|
||||||
|
PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
|
||||||
|
PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
|
||||||
|
PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
|
||||||
|
PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
|
||||||
|
PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
|
||||||
|
PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
|
||||||
|
PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
|
||||||
|
PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
|
||||||
|
|
||||||
|
if (len > size)
|
||||||
|
len = size;
|
||||||
|
|
||||||
|
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
#undef PHY_ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_recv = {
|
||||||
|
.read = read_file_recv,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_slot(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : ");
|
||||||
|
|
||||||
|
len += bitmap_scnprintf(buf + len, sizeof(buf) - len,
|
||||||
|
priv->tx.tx_slot, MAX_TX_BUF_NUM);
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "\n");
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len,
|
||||||
|
"Used slots : %d\n",
|
||||||
|
bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
|
||||||
|
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_slot = {
|
||||||
|
.read = read_file_slot,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_queue(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
char buf[512];
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
|
||||||
|
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Failed queue", skb_queue_len(&priv->tx.tx_failed));
|
||||||
|
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
|
||||||
|
"Queued count", priv->tx.queued_cnt);
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_queue = {
|
||||||
|
.read = read_file_queue,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t read_file_debug(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
char buf[32];
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
len = sprintf(buf, "0x%08x\n", common->debug_mask);
|
||||||
|
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = file->private_data;
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
unsigned long mask;
|
||||||
|
char buf[32];
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
if (strict_strtoul(buf, 0, &mask))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
common->debug_mask = mask;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_debug = {
|
||||||
|
.read = read_file_debug,
|
||||||
|
.write = write_file_debug,
|
||||||
|
.open = ath9k_debugfs_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ath9k_htc_init_debug(struct ath_hw *ah)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
|
||||||
|
|
||||||
|
priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
|
||||||
|
priv->hw->wiphy->debugfsdir);
|
||||||
|
if (!priv->debug.debugfs_phy)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_tgt_int_stats);
|
||||||
|
debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_tgt_tx_stats);
|
||||||
|
debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_tgt_rx_stats);
|
||||||
|
debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_xmit);
|
||||||
|
debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_recv);
|
||||||
|
debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_slot);
|
||||||
|
debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_queue);
|
||||||
|
debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
|
||||||
|
priv, &fops_debug);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
|
||||||
|
|
||||||
/* Start TX */
|
/* Start TX */
|
||||||
htc_start(priv->htc);
|
htc_start(priv->htc);
|
||||||
spin_lock_bh(&priv->tx_lock);
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
priv->tx_queues_stop = false;
|
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
|
||||||
spin_unlock_bh(&priv->tx_lock);
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
ieee80211_wake_queues(hw);
|
ieee80211_wake_queues(hw);
|
||||||
|
|
||||||
WMI_CMD(WMI_ENABLE_INTR_CMDID);
|
WMI_CMD(WMI_ENABLE_INTR_CMDID);
|
||||||
|
@ -429,13 +429,15 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
|
||||||
|
|
||||||
/* Stop TX */
|
/* Stop TX */
|
||||||
ieee80211_stop_queues(hw);
|
ieee80211_stop_queues(hw);
|
||||||
htc_stop(priv->htc);
|
ath9k_htc_tx_drain(priv);
|
||||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||||
skb_queue_purge(&priv->tx_queue);
|
|
||||||
|
|
||||||
/* Stop RX */
|
/* Stop RX */
|
||||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||||
|
|
||||||
|
/* Clear the WMI event queue */
|
||||||
|
ath9k_wmi_event_drain(priv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The MIB counters have to be disabled here,
|
* The MIB counters have to be disabled here,
|
||||||
* since the target doesn't do it.
|
* since the target doesn't do it.
|
||||||
|
|
|
@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
|
||||||
|
|
||||||
static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
|
static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
|
||||||
{
|
{
|
||||||
ath9k_htc_exit_debug(priv->ah);
|
|
||||||
ath9k_hw_deinit(priv->ah);
|
ath9k_hw_deinit(priv->ah);
|
||||||
kfree(priv->ah);
|
kfree(priv->ah);
|
||||||
priv->ah = NULL;
|
priv->ah = NULL;
|
||||||
|
@ -643,7 +642,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||||
{
|
{
|
||||||
struct ath_hw *ah = NULL;
|
struct ath_hw *ah = NULL;
|
||||||
struct ath_common *common;
|
struct ath_common *common;
|
||||||
int ret = 0, csz = 0;
|
int i, ret = 0, csz = 0;
|
||||||
|
|
||||||
priv->op_flags |= OP_INVALID;
|
priv->op_flags |= OP_INVALID;
|
||||||
|
|
||||||
|
@ -671,20 +670,19 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||||
common->priv = priv;
|
common->priv = priv;
|
||||||
common->debug_mask = ath9k_debug;
|
common->debug_mask = ath9k_debug;
|
||||||
|
|
||||||
spin_lock_init(&priv->wmi->wmi_lock);
|
|
||||||
spin_lock_init(&priv->beacon_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->mutex);
|
||||||
mutex_init(&priv->htc_pm_lock);
|
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,
|
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
|
||||||
(unsigned long)priv);
|
(unsigned long)priv);
|
||||||
tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
|
tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
|
||||||
(unsigned long)priv);
|
(unsigned long)priv);
|
||||||
INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
|
INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
|
||||||
INIT_WORK(&priv->ps_work, ath9k_ps_work);
|
INIT_WORK(&priv->ps_work, ath9k_ps_work);
|
||||||
INIT_WORK(&priv->fatal_work, ath9k_fatal_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
|
* Cache line size is used to size and align various
|
||||||
|
@ -701,16 +699,13 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||||
goto err_hw;
|
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);
|
ret = ath9k_init_queues(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_queues;
|
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_crypto(priv);
|
||||||
ath9k_init_channels_rates(priv);
|
ath9k_init_channels_rates(priv);
|
||||||
ath9k_init_misc(priv);
|
ath9k_init_misc(priv);
|
||||||
|
@ -723,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_queues:
|
err_queues:
|
||||||
ath9k_htc_exit_debug(ah);
|
|
||||||
err_debug:
|
|
||||||
ath9k_hw_deinit(ah);
|
ath9k_hw_deinit(ah);
|
||||||
err_hw:
|
err_hw:
|
||||||
|
|
||||||
|
@ -745,11 +738,15 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
||||||
IEEE80211_HW_HAS_RATE_CONTROL |
|
IEEE80211_HW_HAS_RATE_CONTROL |
|
||||||
IEEE80211_HW_RX_INCLUDES_FCS |
|
IEEE80211_HW_RX_INCLUDES_FCS |
|
||||||
IEEE80211_HW_SUPPORTS_PS |
|
IEEE80211_HW_SUPPORTS_PS |
|
||||||
IEEE80211_HW_PS_NULLFUNC_STACK;
|
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||||
|
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
|
||||||
|
|
||||||
hw->wiphy->interface_modes =
|
hw->wiphy->interface_modes =
|
||||||
BIT(NL80211_IFTYPE_STATION) |
|
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->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||||
|
|
||||||
|
@ -782,6 +779,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
||||||
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
|
||||||
|
{
|
||||||
|
struct ieee80211_hw *hw = priv->hw;
|
||||||
|
struct wmi_fw_version cmd_rsp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&cmd_rsp, 0, sizeof(cmd_rsp));
|
||||||
|
|
||||||
|
WMI_CMD(WMI_GET_FW_VERSION);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
|
||||||
|
priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
|
||||||
|
|
||||||
|
snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
|
||||||
|
priv->fw_version_major,
|
||||||
|
priv->fw_version_minor);
|
||||||
|
|
||||||
|
dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
|
||||||
|
priv->fw_version_major,
|
||||||
|
priv->fw_version_minor);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ath9k_init_device(struct ath9k_htc_priv *priv,
|
static int ath9k_init_device(struct ath9k_htc_priv *priv,
|
||||||
u16 devid, char *product, u32 drv_info)
|
u16 devid, char *product, u32 drv_info)
|
||||||
{
|
{
|
||||||
|
@ -801,6 +824,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
|
||||||
common = ath9k_hw_common(ah);
|
common = ath9k_hw_common(ah);
|
||||||
ath9k_set_hw_capab(priv, hw);
|
ath9k_set_hw_capab(priv, hw);
|
||||||
|
|
||||||
|
error = ath9k_init_firmware_version(priv);
|
||||||
|
if (error != 0)
|
||||||
|
goto err_fw;
|
||||||
|
|
||||||
/* Initialize regulatory */
|
/* Initialize regulatory */
|
||||||
error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
|
error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
|
||||||
ath9k_reg_notifier);
|
ath9k_reg_notifier);
|
||||||
|
@ -831,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
|
||||||
goto err_world;
|
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,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
|
"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
|
||||||
"BE:%d, BK:%d, VI:%d, VO:%d\n",
|
"BE:%d, BK:%d, VI:%d, VO:%d\n",
|
||||||
|
@ -861,6 +894,8 @@ err_rx:
|
||||||
err_tx:
|
err_tx:
|
||||||
/* Nothing */
|
/* Nothing */
|
||||||
err_regd:
|
err_regd:
|
||||||
|
/* Nothing */
|
||||||
|
err_fw:
|
||||||
ath9k_deinit_priv(priv);
|
ath9k_deinit_priv(priv);
|
||||||
err_init:
|
err_init:
|
||||||
return error;
|
return error;
|
||||||
|
@ -949,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
|
||||||
|
|
||||||
static int __init ath9k_htc_init(void)
|
static int __init ath9k_htc_init(void)
|
||||||
{
|
{
|
||||||
int error;
|
if (ath9k_hif_usb_init() < 0) {
|
||||||
|
|
||||||
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) {
|
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"ath9k_htc: No USB devices found,"
|
"ath9k_htc: No USB devices found,"
|
||||||
" driver not installed.\n");
|
" driver not installed.\n");
|
||||||
error = -ENODEV;
|
return -ENODEV;
|
||||||
goto err_usb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_usb:
|
|
||||||
ath9k_htc_debug_remove_root();
|
|
||||||
err_dbg:
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
module_init(ath9k_htc_init);
|
module_init(ath9k_htc_init);
|
||||||
|
|
||||||
static void __exit ath9k_htc_exit(void)
|
static void __exit ath9k_htc_exit(void)
|
||||||
{
|
{
|
||||||
ath9k_hif_usb_exit();
|
ath9k_hif_usb_exit();
|
||||||
ath9k_htc_debug_remove_root();
|
|
||||||
printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
|
printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
|
||||||
}
|
}
|
||||||
module_exit(ath9k_htc_exit);
|
module_exit(ath9k_htc_exit);
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
#include "htc.h"
|
#include "htc.h"
|
||||||
|
|
||||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
|
||||||
static struct dentry *ath9k_debugfs_root;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*************/
|
/*************/
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
/*************/
|
/*************/
|
||||||
|
@ -197,11 +193,16 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
|
||||||
|
|
||||||
ath9k_htc_stop_ani(priv);
|
ath9k_htc_stop_ani(priv);
|
||||||
ieee80211_stop_queues(priv->hw);
|
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_DISABLE_INTR_CMDID);
|
||||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||||
|
|
||||||
|
ath9k_wmi_event_drain(priv);
|
||||||
|
|
||||||
caldata = &priv->caldata;
|
caldata = &priv->caldata;
|
||||||
ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
|
ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
|
||||||
ath9k_htc_vif_reconfig(priv);
|
ath9k_htc_vif_reconfig(priv);
|
||||||
ieee80211_wake_queues(priv->hw);
|
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);
|
ath9k_htc_ps_restore(priv);
|
||||||
mutex_unlock(&priv->mutex);
|
mutex_unlock(&priv->mutex);
|
||||||
}
|
}
|
||||||
|
@ -250,11 +254,16 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||||
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
|
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
|
||||||
|
|
||||||
ath9k_htc_ps_wakeup(priv);
|
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_DISABLE_INTR_CMDID);
|
||||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||||
|
|
||||||
|
ath9k_wmi_event_drain(priv);
|
||||||
|
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
|
"(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
|
||||||
priv->ah->curchan->channel,
|
priv->ah->curchan->channel,
|
||||||
|
@ -263,6 +272,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||||
|
|
||||||
if (!fastcc)
|
if (!fastcc)
|
||||||
caldata = &priv->caldata;
|
caldata = &priv->caldata;
|
||||||
|
|
||||||
ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ath_err(common,
|
ath_err(common,
|
||||||
|
@ -296,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||||
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
|
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
|
||||||
ath9k_htc_vif_reconfig(priv);
|
ath9k_htc_vif_reconfig(priv);
|
||||||
|
|
||||||
|
mod_timer(&priv->tx.cleanup_timer,
|
||||||
|
jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
|
||||||
|
|
||||||
err:
|
err:
|
||||||
ath9k_htc_ps_restore(priv);
|
ath9k_htc_ps_restore(priv);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -349,7 +362,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
|
||||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||||
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
|
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);
|
hvif.index = ffz(priv->vif_slot);
|
||||||
|
|
||||||
WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
|
WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
|
||||||
|
@ -382,7 +395,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
|
||||||
tsta.is_vif_sta = 1;
|
tsta.is_vif_sta = 1;
|
||||||
tsta.sta_index = sta_idx;
|
tsta.sta_index = sta_idx;
|
||||||
tsta.vif_index = hvif.index;
|
tsta.vif_index = hvif.index;
|
||||||
tsta.maxampdu = 0xffff;
|
tsta.maxampdu = cpu_to_be16(0xffff);
|
||||||
|
|
||||||
WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
|
WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -463,9 +476,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
|
||||||
ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||||
memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
|
memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
|
||||||
memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
|
memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
|
||||||
tsta.associd = common->curaid;
|
|
||||||
tsta.is_vif_sta = 0;
|
tsta.is_vif_sta = 0;
|
||||||
tsta.valid = true;
|
|
||||||
ista->index = sta_idx;
|
ista->index = sta_idx;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
|
memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
|
||||||
|
@ -474,7 +485,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
|
||||||
|
|
||||||
tsta.sta_index = sta_idx;
|
tsta.sta_index = sta_idx;
|
||||||
tsta.vif_index = avp->index;
|
tsta.vif_index = avp->index;
|
||||||
tsta.maxampdu = 0xffff;
|
tsta.maxampdu = cpu_to_be16(0xffff);
|
||||||
if (sta && sta->ht_cap.ht_supported)
|
if (sta && sta->ht_cap.ht_supported)
|
||||||
tsta.flags = cpu_to_be16(ATH_HTC_STA_HT);
|
tsta.flags = cpu_to_be16(ATH_HTC_STA_HT);
|
||||||
|
|
||||||
|
@ -709,218 +720,13 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
|
||||||
(aggr.aggr_enable) ? "Starting" : "Stopping",
|
(aggr.aggr_enable) ? "Starting" : "Stopping",
|
||||||
sta->addr, tid);
|
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;
|
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;
|
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 */
|
/* ANI */
|
||||||
/*******/
|
/*******/
|
||||||
|
@ -1040,7 +846,8 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_hdr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
struct ath9k_htc_priv *priv = hw->priv;
|
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;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
|
|
||||||
|
@ -1048,30 +855,32 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||||
padsize = padpos & 3;
|
padsize = padpos & 3;
|
||||||
if (padsize && skb->len > padpos) {
|
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;
|
goto fail_tx;
|
||||||
|
}
|
||||||
skb_push(skb, padsize);
|
skb_push(skb, padsize);
|
||||||
memmove(skb->data, skb->data + padsize, padpos);
|
memmove(skb->data, skb->data + padsize, padpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath9k_htc_tx_start(priv, skb);
|
slot = ath9k_htc_tx_get_slot(priv);
|
||||||
if (ret != 0) {
|
if (slot < 0) {
|
||||||
if (ret == -ENOMEM) {
|
ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n");
|
||||||
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");
|
|
||||||
}
|
|
||||||
goto fail_tx;
|
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;
|
return;
|
||||||
|
|
||||||
|
clear_slot:
|
||||||
|
ath9k_htc_tx_clear_slot(priv, slot);
|
||||||
fail_tx:
|
fail_tx:
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
|
@ -1130,12 +939,15 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||||
priv->op_flags &= ~OP_INVALID;
|
priv->op_flags &= ~OP_INVALID;
|
||||||
htc_start(priv->htc);
|
htc_start(priv->htc);
|
||||||
|
|
||||||
spin_lock_bh(&priv->tx_lock);
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
priv->tx_queues_stop = false;
|
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
|
||||||
spin_unlock_bh(&priv->tx_lock);
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
ieee80211_wake_queues(hw);
|
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) {
|
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
|
||||||
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
|
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
|
||||||
AR_STOMP_LOW_WLAN_WGHT);
|
AR_STOMP_LOW_WLAN_WGHT);
|
||||||
|
@ -1164,16 +976,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||||
}
|
}
|
||||||
|
|
||||||
ath9k_htc_ps_wakeup(priv);
|
ath9k_htc_ps_wakeup(priv);
|
||||||
htc_stop(priv->htc);
|
|
||||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||||
|
|
||||||
tasklet_kill(&priv->swba_tasklet);
|
|
||||||
tasklet_kill(&priv->rx_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);
|
mutex_unlock(&priv->mutex);
|
||||||
|
|
||||||
|
@ -1245,13 +1057,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
switch (vif->type) {
|
switch (vif->type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
hvif.opmode = cpu_to_be32(HTC_M_STA);
|
hvif.opmode = HTC_M_STA;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
hvif.opmode = cpu_to_be32(HTC_M_IBSS);
|
hvif.opmode = HTC_M_IBSS;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
hvif.opmode = cpu_to_be32(HTC_M_HOSTAP);
|
hvif.opmode = HTC_M_HOSTAP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath_err(common,
|
ath_err(common,
|
||||||
|
@ -1281,14 +1093,20 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
priv->vif_slot |= (1 << avp->index);
|
priv->vif_slot |= (1 << avp->index);
|
||||||
priv->nvifs++;
|
priv->nvifs++;
|
||||||
priv->vif = vif;
|
|
||||||
|
|
||||||
INC_VIF(priv, vif->type);
|
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);
|
ath9k_htc_set_opmode(priv);
|
||||||
|
|
||||||
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
|
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);
|
ath9k_htc_start_ani(priv);
|
||||||
|
}
|
||||||
|
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
|
"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
|
||||||
|
@ -1321,9 +1139,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
||||||
priv->vif_slot &= ~(1 << avp->index);
|
priv->vif_slot &= ~(1 << avp->index);
|
||||||
|
|
||||||
ath9k_htc_remove_station(priv, vif, NULL);
|
ath9k_htc_remove_station(priv, vif, NULL);
|
||||||
priv->vif = NULL;
|
|
||||||
|
|
||||||
DEC_VIF(priv, vif->type);
|
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);
|
ath9k_htc_set_opmode(priv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1493,10 +1315,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
struct ath9k_htc_priv *priv = hw->priv;
|
struct ath9k_htc_priv *priv = hw->priv;
|
||||||
|
struct ath9k_htc_sta *ista;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
ath9k_htc_ps_wakeup(priv);
|
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);
|
ret = ath9k_htc_remove_station(priv, vif, sta);
|
||||||
ath9k_htc_ps_restore(priv);
|
ath9k_htc_ps_restore(priv);
|
||||||
mutex_unlock(&priv->mutex);
|
mutex_unlock(&priv->mutex);
|
||||||
|
@ -1644,6 +1469,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
|
if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"Beacon enabled for BSS: %pM\n", bss_conf->bssid);
|
"Beacon enabled for BSS: %pM\n", bss_conf->bssid);
|
||||||
|
ath9k_htc_set_tsfadjust(priv, vif);
|
||||||
priv->op_flags |= OP_ENABLE_BEACON;
|
priv->op_flags |= OP_ENABLE_BEACON;
|
||||||
ath9k_htc_beacon_config(priv, vif);
|
ath9k_htc_beacon_config(priv, vif);
|
||||||
}
|
}
|
||||||
|
@ -1758,9 +1584,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
|
||||||
break;
|
break;
|
||||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||||
ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
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;
|
ista->tid_state[tid] = AGGR_OPERATIONAL;
|
||||||
spin_unlock_bh(&priv->tx_lock);
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
|
ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
|
||||||
|
|
|
@ -53,6 +53,138 @@ int get_hw_qnum(u16 queue, int *hwq_map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv)
|
||||||
|
{
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
priv->tx.queued_cnt++;
|
||||||
|
if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) &&
|
||||||
|
!(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) {
|
||||||
|
priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP;
|
||||||
|
ieee80211_stop_queues(priv->hw);
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv)
|
||||||
|
{
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) &&
|
||||||
|
(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) {
|
||||||
|
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
|
||||||
|
ieee80211_wake_queues(priv->hw);
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv)
|
||||||
|
{
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM);
|
||||||
|
if (slot >= MAX_TX_BUF_NUM) {
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
__set_bit(slot, priv->tx.tx_slot);
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot)
|
||||||
|
{
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
__clear_bit(slot, priv->tx.tx_slot);
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
|
||||||
|
u16 qnum)
|
||||||
|
{
|
||||||
|
enum htc_endpoint_id epid;
|
||||||
|
|
||||||
|
switch (qnum) {
|
||||||
|
case 0:
|
||||||
|
TX_QSTAT_INC(WME_AC_VO);
|
||||||
|
epid = priv->data_vo_ep;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
TX_QSTAT_INC(WME_AC_VI);
|
||||||
|
epid = priv->data_vi_ep;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
TX_QSTAT_INC(WME_AC_BE);
|
||||||
|
epid = priv->data_be_ep;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
TX_QSTAT_INC(WME_AC_BK);
|
||||||
|
epid = priv->data_bk_ep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return epid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct sk_buff_head*
|
||||||
|
get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
struct sk_buff_head *epid_queue = NULL;
|
||||||
|
|
||||||
|
if (epid == priv->mgmt_ep)
|
||||||
|
epid_queue = &priv->tx.mgmt_ep_queue;
|
||||||
|
else if (epid == priv->cab_ep)
|
||||||
|
epid_queue = &priv->tx.cab_ep_queue;
|
||||||
|
else if (epid == priv->data_be_ep)
|
||||||
|
epid_queue = &priv->tx.data_be_queue;
|
||||||
|
else if (epid == priv->data_bk_ep)
|
||||||
|
epid_queue = &priv->tx.data_bk_queue;
|
||||||
|
else if (epid == priv->data_vi_ep)
|
||||||
|
epid_queue = &priv->tx.data_vi_queue;
|
||||||
|
else if (epid == priv->data_vo_ep)
|
||||||
|
epid_queue = &priv->tx.data_vo_queue;
|
||||||
|
else
|
||||||
|
ath_err(common, "Invalid EPID: %d\n", epid);
|
||||||
|
|
||||||
|
return epid_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes the driver header and returns the TX slot number
|
||||||
|
*/
|
||||||
|
static inline int strip_drv_header(struct ath9k_htc_priv *priv,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
tx_ctl = HTC_SKB_CB(skb);
|
||||||
|
|
||||||
|
if (tx_ctl->epid == priv->mgmt_ep) {
|
||||||
|
struct tx_mgmt_hdr *tx_mhdr =
|
||||||
|
(struct tx_mgmt_hdr *)skb->data;
|
||||||
|
slot = tx_mhdr->cookie;
|
||||||
|
skb_pull(skb, sizeof(struct tx_mgmt_hdr));
|
||||||
|
} else if ((tx_ctl->epid == priv->data_bk_ep) ||
|
||||||
|
(tx_ctl->epid == priv->data_be_ep) ||
|
||||||
|
(tx_ctl->epid == priv->data_vi_ep) ||
|
||||||
|
(tx_ctl->epid == priv->data_vo_ep) ||
|
||||||
|
(tx_ctl->epid == priv->cab_ep)) {
|
||||||
|
struct tx_frame_hdr *tx_fhdr =
|
||||||
|
(struct tx_frame_hdr *)skb->data;
|
||||||
|
slot = tx_fhdr->cookie;
|
||||||
|
skb_pull(skb, sizeof(struct tx_frame_hdr));
|
||||||
|
} else {
|
||||||
|
ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid);
|
||||||
|
slot = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
||||||
struct ath9k_tx_queue_info *qinfo)
|
struct ath9k_tx_queue_info *qinfo)
|
||||||
{
|
{
|
||||||
|
@ -79,23 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
||||||
return error;
|
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_hdr *hdr;
|
||||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||||
struct ieee80211_sta *sta = tx_info->control.sta;
|
struct ieee80211_sta *sta = tx_info->control.sta;
|
||||||
struct ieee80211_vif *vif = tx_info->control.vif;
|
struct ieee80211_vif *vif = tx_info->control.vif;
|
||||||
struct ath9k_htc_sta *ista;
|
struct ath9k_htc_sta *ista;
|
||||||
struct ath9k_htc_vif *avp;
|
struct ath9k_htc_vif *avp = NULL;
|
||||||
struct ath9k_htc_tx_ctl tx_ctl;
|
|
||||||
enum htc_endpoint_id epid;
|
|
||||||
u16 qnum;
|
|
||||||
__le16 fc;
|
|
||||||
u8 *tx_fhdr;
|
|
||||||
u8 sta_idx, vif_idx;
|
u8 sta_idx, vif_idx;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
fc = hdr->frame_control;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out on which interface this packet has to be
|
* Find out on which interface this packet has to be
|
||||||
|
@ -124,144 +373,49 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
|
||||||
sta_idx = priv->vif_sta_pos[vif_idx];
|
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,
|
||||||
if (ieee80211_is_data(fc)) {
|
sta_idx, vif_idx, slot, is_cab);
|
||||||
struct tx_frame_hdr tx_hdr;
|
|
||||||
u32 flags = 0;
|
|
||||||
u8 *qc;
|
|
||||||
|
|
||||||
memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));
|
|
||||||
|
|
||||||
tx_hdr.node_idx = sta_idx;
|
|
||||||
tx_hdr.vif_idx = vif_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(fc)) {
|
|
||||||
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
|
else
|
||||||
tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx;
|
ath9k_htc_tx_mgmt(priv, avp, skb,
|
||||||
|
sta_idx, vif_idx, slot);
|
||||||
|
|
||||||
tx_fhdr = skb_push(skb, sizeof(tx_hdr));
|
|
||||||
memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
|
|
||||||
|
|
||||||
qnum = skb_get_queue_mapping(skb);
|
return htc_send(priv->htc, 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;
|
|
||||||
|
|
||||||
memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));
|
|
||||||
|
|
||||||
tx_ctl.type = ATH9K_HTC_NORMAL;
|
|
||||||
|
|
||||||
mgmt_hdr.node_idx = sta_idx;
|
|
||||||
mgmt_hdr.vif_idx = vif_idx;
|
|
||||||
mgmt_hdr.tidno = 0;
|
|
||||||
mgmt_hdr.flags = 0;
|
|
||||||
|
|
||||||
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));
|
|
||||||
epid = priv->mgmt_ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
return htc_send(priv->htc, skb, epid, &tx_ctl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
|
static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
|
||||||
struct ath9k_htc_sta *ista, u8 tid)
|
struct ath9k_htc_sta *ista, u8 tid)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
spin_lock_bh(&priv->tx_lock);
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP))
|
if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP))
|
||||||
ret = true;
|
ret = true;
|
||||||
spin_unlock_bh(&priv->tx_lock);
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_tx_tasklet(unsigned long data)
|
static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
|
||||||
struct ieee80211_vif *vif;
|
|
||||||
struct ieee80211_sta *sta;
|
struct ieee80211_sta *sta;
|
||||||
struct ieee80211_hdr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
struct ieee80211_tx_info *tx_info;
|
|
||||||
struct sk_buff *skb = NULL;
|
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
|
|
||||||
while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) {
|
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) skb->data;
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
fc = hdr->frame_control;
|
fc = hdr->frame_control;
|
||||||
tx_info = IEEE80211_SKB_CB(skb);
|
|
||||||
vif = tx_info->control.vif;
|
|
||||||
|
|
||||||
memset(&tx_info->status, 0, sizeof(tx_info->status));
|
|
||||||
|
|
||||||
if (!vif)
|
|
||||||
goto send_mac80211;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
sta = ieee80211_find_sta(vif, hdr->addr1);
|
sta = ieee80211_find_sta(vif, hdr->addr1);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
ieee80211_tx_status(priv->hw, skb);
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we need to start aggregation */
|
|
||||||
|
|
||||||
if (sta && conf_is_ht(&priv->hw->conf) &&
|
if (sta && conf_is_ht(&priv->hw->conf) &&
|
||||||
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
|
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
|
||||||
if (ieee80211_is_data_qos(fc)) {
|
if (ieee80211_is_data_qos(fc)) {
|
||||||
|
@ -271,71 +425,380 @@ void ath9k_tx_tasklet(unsigned long data)
|
||||||
qc = ieee80211_get_qos_ctl(hdr);
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
tid = qc[0] & 0xf;
|
tid = qc[0] & 0xf;
|
||||||
ista = (struct ath9k_htc_sta *)sta->drv_priv;
|
ista = (struct ath9k_htc_sta *)sta->drv_priv;
|
||||||
|
if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) {
|
||||||
if (ath9k_htc_check_tx_aggr(priv, ista, tid)) {
|
|
||||||
ieee80211_start_tx_ba_session(sta, tid, 0);
|
ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||||
spin_lock_bh(&priv->tx_lock);
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
ista->tid_state[tid] = AGGR_PROGRESS;
|
ista->tid_state[tid] = AGGR_PROGRESS;
|
||||||
spin_unlock_bh(&priv->tx_lock);
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
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;
|
||||||
|
struct ieee80211_supported_band *sband;
|
||||||
|
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];
|
||||||
|
sband = priv->hw->wiphy->bands[cur_conf->channel->band];
|
||||||
|
|
||||||
|
memset(&tx_info->status, 0, sizeof(tx_info->status));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT)
|
||||||
|
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||||
|
|
||||||
|
if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS)
|
||||||
|
rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
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_mac80211:
|
|
||||||
/* Send status to mac80211 */
|
/* Send status to mac80211 */
|
||||||
ieee80211_tx_status(priv->hw, skb);
|
ieee80211_tx_status(priv->hw, skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv,
|
||||||
|
struct sk_buff_head *queue)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
while ((skb = skb_dequeue(queue)) != NULL) {
|
||||||
|
ath9k_htc_tx_process(priv, skb, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_failed_tasklet(unsigned long data)
|
||||||
|
{
|
||||||
|
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool check_cookie(struct ath9k_htc_priv *priv,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
u8 cookie, u8 epid)
|
||||||
|
{
|
||||||
|
u8 fcookie = 0;
|
||||||
|
|
||||||
|
if (epid == priv->mgmt_ep) {
|
||||||
|
struct tx_mgmt_hdr *hdr;
|
||||||
|
hdr = (struct tx_mgmt_hdr *) skb->data;
|
||||||
|
fcookie = hdr->cookie;
|
||||||
|
} else if ((epid == priv->data_bk_ep) ||
|
||||||
|
(epid == priv->data_be_ep) ||
|
||||||
|
(epid == priv->data_vi_ep) ||
|
||||||
|
(epid == priv->data_vo_ep) ||
|
||||||
|
(epid == priv->cab_ep)) {
|
||||||
|
struct tx_frame_hdr *hdr;
|
||||||
|
hdr = (struct tx_frame_hdr *) skb->data;
|
||||||
|
fcookie = hdr->cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcookie == cookie)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv,
|
||||||
|
struct __wmi_event_txstatus *txs)
|
||||||
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
struct sk_buff_head *epid_queue;
|
||||||
|
struct sk_buff *skb, *tmp;
|
||||||
|
unsigned long flags;
|
||||||
|
u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID);
|
||||||
|
|
||||||
|
epid_queue = get_htc_epid_queue(priv, epid);
|
||||||
|
if (!epid_queue)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&epid_queue->lock, flags);
|
||||||
|
skb_queue_walk_safe(epid_queue, skb, tmp) {
|
||||||
|
if (check_cookie(priv, skb, txs->cookie, epid)) {
|
||||||
|
__skb_unlink(skb, epid_queue);
|
||||||
|
spin_unlock_irqrestore(&epid_queue->lock, flags);
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&epid_queue->lock, flags);
|
||||||
|
|
||||||
|
ath_dbg(common, ATH_DBG_XMIT,
|
||||||
|
"No matching packet for cookie: %d, epid: %d\n",
|
||||||
|
txs->cookie, epid);
|
||||||
|
|
||||||
|
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 */
|
/* Wake TX queues if needed */
|
||||||
spin_lock_bh(&priv->tx_lock);
|
ath9k_htc_check_wake_queues(priv);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
|
void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
|
||||||
enum htc_endpoint_id ep_id, bool txok)
|
enum htc_endpoint_id ep_id, bool txok)
|
||||||
{
|
{
|
||||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
|
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
|
||||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
struct ieee80211_tx_info *tx_info;
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ep_id == priv->mgmt_ep) {
|
epid_queue = get_htc_epid_queue(priv, ep_id);
|
||||||
skb_pull(skb, sizeof(struct tx_mgmt_hdr));
|
if (!epid_queue) {
|
||||||
} 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);
|
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_info = IEEE80211_SKB_CB(skb);
|
skb_queue_tail(epid_queue, skb);
|
||||||
|
}
|
||||||
|
|
||||||
if (txok)
|
static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb)
|
||||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
{
|
||||||
|
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||||
|
struct ath9k_htc_tx_ctl *tx_ctl;
|
||||||
|
|
||||||
skb_queue_tail(&priv->tx_queue, skb);
|
tx_ctl = HTC_SKB_CB(skb);
|
||||||
tasklet_schedule(&priv->tx_tasklet);
|
|
||||||
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,8 +970,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
|
|
||||||
if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) {
|
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
|
||||||
ath_err(common, "Corrupted RX frame, dropping\n");
|
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
|
||||||
|
skb->len);
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,6 +986,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ath9k_htc_err_stat_rx(priv, rxstatus);
|
||||||
|
|
||||||
/* Get the RX status information */
|
/* Get the RX status information */
|
||||||
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
|
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
|
||||||
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "htc.h"
|
#include "htc.h"
|
||||||
|
|
||||||
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
||||||
u16 len, u8 flags, u8 epid,
|
u16 len, u8 flags, u8 epid)
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
struct htc_frame_hdr *hdr;
|
struct htc_frame_hdr *hdr;
|
||||||
struct htc_endpoint *endpoint = &target->endpoint[epid];
|
struct htc_endpoint *endpoint = &target->endpoint[epid];
|
||||||
|
@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
|
||||||
hdr->flags = flags;
|
hdr->flags = flags;
|
||||||
hdr->payload_len = cpu_to_be16(len);
|
hdr->payload_len = cpu_to_be16(len);
|
||||||
|
|
||||||
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
|
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
|
||||||
tx_ctl);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
|
||||||
|
|
||||||
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
|
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)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target)
|
||||||
|
|
||||||
target->htc_flags |= HTC_OP_START_WAIT;
|
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)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target,
|
||||||
conn_msg->dl_pipeid = endpoint->dl_pipeid;
|
conn_msg->dl_pipeid = endpoint->dl_pipeid;
|
||||||
conn_msg->ul_pipeid = endpoint->ul_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)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -286,35 +286,33 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
int htc_send(struct htc_target *target, struct sk_buff *skb)
|
||||||
enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
|
||||||
|
enum htc_endpoint_id epid)
|
||||||
|
{
|
||||||
|
return htc_issue_send(target, skb, skb->len, 0, epid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void htc_stop(struct htc_target *target)
|
void htc_stop(struct htc_target *target)
|
||||||
{
|
{
|
||||||
enum htc_endpoint_id epid;
|
target->hif->stop(target->hif_dev);
|
||||||
struct htc_endpoint *endpoint;
|
|
||||||
|
|
||||||
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_start(struct htc_target *target)
|
void htc_start(struct htc_target *target)
|
||||||
{
|
{
|
||||||
enum htc_endpoint_id epid;
|
target->hif->start(target->hif_dev);
|
||||||
struct htc_endpoint *endpoint;
|
}
|
||||||
|
|
||||||
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
|
void htc_sta_drain(struct htc_target *target, u8 idx)
|
||||||
endpoint = &target->endpoint[epid];
|
{
|
||||||
if (endpoint->service_id != 0)
|
target->hif->sta_drain(target->hif_dev, idx);
|
||||||
target->hif->start(target->hif_dev,
|
|
||||||
endpoint->ul_pipeid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
||||||
|
|
|
@ -33,10 +33,10 @@ struct ath9k_htc_hif {
|
||||||
u8 control_dl_pipe;
|
u8 control_dl_pipe;
|
||||||
u8 control_ul_pipe;
|
u8 control_ul_pipe;
|
||||||
|
|
||||||
void (*start) (void *hif_handle, u8 pipe);
|
void (*start) (void *hif_handle);
|
||||||
void (*stop) (void *hif_handle, u8 pipe);
|
void (*stop) (void *hif_handle);
|
||||||
int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf,
|
void (*sta_drain) (void *hif_handle, u8 idx);
|
||||||
struct ath9k_htc_tx_ctl *tx_ctl);
|
int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum htc_endpoint_id {
|
enum htc_endpoint_id {
|
||||||
|
@ -205,10 +205,12 @@ int htc_init(struct htc_target *target);
|
||||||
int htc_connect_service(struct htc_target *target,
|
int htc_connect_service(struct htc_target *target,
|
||||||
struct htc_service_connreq *service_connreq,
|
struct htc_service_connreq *service_connreq,
|
||||||
enum htc_endpoint_id *conn_rsp_eid);
|
enum htc_endpoint_id *conn_rsp_eid);
|
||||||
int htc_send(struct htc_target *target, struct sk_buff *skb,
|
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_epid(struct htc_target *target, struct sk_buff *skb,
|
||||||
|
enum htc_endpoint_id epid);
|
||||||
void htc_stop(struct htc_target *target);
|
void htc_stop(struct htc_target *target);
|
||||||
void htc_start(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,
|
void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
||||||
struct sk_buff *skb, u32 len, u8 pipe_id);
|
struct sk_buff *skb, u32 len, u8 pipe_id);
|
||||||
|
|
|
@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
|
||||||
ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
|
ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
|
||||||
|
{
|
||||||
|
ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* Private hardware call ops */
|
/* Private hardware call ops */
|
||||||
|
|
||||||
/* PHY ops */
|
/* PHY ops */
|
||||||
|
|
|
@ -676,42 +676,55 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
|
EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
|
||||||
|
|
||||||
#define DPLL2_KD_VAL 0x3D
|
|
||||||
#define DPLL2_KI_VAL 0x06
|
|
||||||
#define DPLL3_PHASE_SHIFT_VAL 0x1
|
#define DPLL3_PHASE_SHIFT_VAL 0x1
|
||||||
|
|
||||||
static void ath9k_hw_init_pll(struct ath_hw *ah,
|
static void ath9k_hw_init_pll(struct ath_hw *ah,
|
||||||
struct ath9k_channel *chan)
|
struct ath9k_channel *chan)
|
||||||
{
|
{
|
||||||
u32 pll;
|
u32 pll;
|
||||||
|
|
||||||
if (AR_SREV_9485(ah)) {
|
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,
|
/* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
|
||||||
AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
|
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_CONTROL, 0x1142c);
|
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_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_BB_DPLL2_EN_NEGTRIG, 0x1);
|
||||||
|
|
||||||
|
/* program BB PLL phase_shift to 0x6 */
|
||||||
|
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
|
||||||
|
AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6);
|
||||||
|
|
||||||
|
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
|
||||||
|
AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
|
|
||||||
REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
|
|
||||||
|
|
||||||
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
|
|
||||||
AR_CH0_DPLL2_KD, DPLL2_KD_VAL);
|
|
||||||
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
|
|
||||||
AR_CH0_DPLL2_KI, DPLL2_KI_VAL);
|
|
||||||
|
|
||||||
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
|
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
|
||||||
AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
|
AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
|
||||||
REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
|
|
||||||
udelay(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pll = ath9k_hw_compute_pll_control(ah, chan);
|
pll = ath9k_hw_compute_pll_control(ah, chan);
|
||||||
|
|
||||||
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
|
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
|
||||||
|
|
||||||
|
if (AR_SREV_9485(ah))
|
||||||
|
udelay(1000);
|
||||||
|
|
||||||
/* Switch the core clock for ar9271 to 117Mhz */
|
/* Switch the core clock for ar9271 to 117Mhz */
|
||||||
if (AR_SREV_9271(ah)) {
|
if (AR_SREV_9271(ah)) {
|
||||||
udelay(500);
|
udelay(500);
|
||||||
|
|
|
@ -626,6 +626,7 @@ struct ath_hw_ops {
|
||||||
void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
|
void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
|
||||||
void (*set11n_burstduration)(struct ath_hw *ah, void *ds,
|
void (*set11n_burstduration)(struct ath_hw *ah, void *ds,
|
||||||
u32 burstDuration);
|
u32 burstDuration);
|
||||||
|
void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_nf_limits {
|
struct ath_nf_limits {
|
||||||
|
@ -846,6 +847,14 @@ struct ath_hw {
|
||||||
u32 ent_mode;
|
u32 ent_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ath_bus_ops {
|
||||||
|
enum ath_bus_type ath_bus_type;
|
||||||
|
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||||
|
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||||
|
void (*bt_coex_prep)(struct ath_common *common);
|
||||||
|
void (*extn_synch_en)(struct ath_common *common);
|
||||||
|
};
|
||||||
|
|
||||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
return &ah->common;
|
return &ah->common;
|
||||||
|
|
|
@ -239,7 +239,6 @@ struct ath_desc {
|
||||||
void *ds_vdata;
|
void *ds_vdata;
|
||||||
} __packed __aligned(4);
|
} __packed __aligned(4);
|
||||||
|
|
||||||
#define ATH9K_TXDESC_CLRDMASK 0x0001
|
|
||||||
#define ATH9K_TXDESC_NOACK 0x0002
|
#define ATH9K_TXDESC_NOACK 0x0002
|
||||||
#define ATH9K_TXDESC_RTSENA 0x0004
|
#define ATH9K_TXDESC_RTSENA 0x0004
|
||||||
#define ATH9K_TXDESC_CTSENA 0x0008
|
#define ATH9K_TXDESC_CTSENA 0x0008
|
||||||
|
|
|
@ -1373,6 +1373,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
|
||||||
if ((iter_data.naps + iter_data.nadhocs) > 0) {
|
if ((iter_data.naps + iter_data.nadhocs) > 0) {
|
||||||
sc->sc_flags |= SC_OP_ANI_RUN;
|
sc->sc_flags |= SC_OP_ANI_RUN;
|
||||||
ath_start_ani(common);
|
ath_start_ani(common);
|
||||||
|
} else {
|
||||||
|
sc->sc_flags &= ~SC_OP_ANI_RUN;
|
||||||
|
del_timer_sync(&common->ani.timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1733,23 +1736,63 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = hw->priv;
|
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);
|
ath_node_attach(sc, sta);
|
||||||
|
an->ps_key = ath_key_config(common, vif, sta, &ps_key);
|
||||||
|
|
||||||
return 0;
|
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,
|
static int ath9k_sta_remove(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = hw->priv;
|
struct ath_softc *sc = hw->priv;
|
||||||
|
|
||||||
|
ath9k_del_ps_key(sc, vif, sta);
|
||||||
ath_node_detach(sc, sta);
|
ath_node_detach(sc, sta);
|
||||||
|
|
||||||
return 0;
|
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,
|
static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||||
const struct ieee80211_tx_queue_params *params)
|
const struct ieee80211_tx_queue_params *params)
|
||||||
{
|
{
|
||||||
|
@ -1826,6 +1869,9 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SET_KEY:
|
case SET_KEY:
|
||||||
|
if (sta)
|
||||||
|
ath9k_del_ps_key(sc, vif, sta);
|
||||||
|
|
||||||
ret = ath_key_config(common, vif, sta, key);
|
ret = ath_key_config(common, vif, sta, key);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
key->hw_key_idx = ret;
|
key->hw_key_idx = ret;
|
||||||
|
@ -2209,6 +2255,21 @@ out:
|
||||||
ath9k_ps_restore(sc);
|
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 = {
|
struct ieee80211_ops ath9k_ops = {
|
||||||
.tx = ath9k_tx,
|
.tx = ath9k_tx,
|
||||||
.start = ath9k_start,
|
.start = ath9k_start,
|
||||||
|
@ -2220,6 +2281,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||||
.configure_filter = ath9k_configure_filter,
|
.configure_filter = ath9k_configure_filter,
|
||||||
.sta_add = ath9k_sta_add,
|
.sta_add = ath9k_sta_add,
|
||||||
.sta_remove = ath9k_sta_remove,
|
.sta_remove = ath9k_sta_remove,
|
||||||
|
.sta_notify = ath9k_sta_notify,
|
||||||
.conf_tx = ath9k_conf_tx,
|
.conf_tx = ath9k_conf_tx,
|
||||||
.bss_info_changed = ath9k_bss_info_changed,
|
.bss_info_changed = ath9k_bss_info_changed,
|
||||||
.set_key = ath9k_set_key,
|
.set_key = ath9k_set_key,
|
||||||
|
@ -2231,4 +2293,5 @@ struct ieee80211_ops ath9k_ops = {
|
||||||
.rfkill_poll = ath9k_rfkill_poll_state,
|
.rfkill_poll = ath9k_rfkill_poll_state,
|
||||||
.set_coverage_class = ath9k_set_coverage_class,
|
.set_coverage_class = ath9k_set_coverage_class,
|
||||||
.flush = ath9k_flush,
|
.flush = ath9k_flush,
|
||||||
|
.tx_frames_pending = ath9k_tx_frames_pending,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#define CHANSEL_DIV 15
|
#define CHANSEL_DIV 15
|
||||||
#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
|
#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 CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)
|
||||||
|
|
||||||
#define AR_PHY_BASE 0x9800
|
#define AR_PHY_BASE 0x9800
|
||||||
|
|
|
@ -1092,8 +1092,7 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
|
||||||
if (!(rate->flags & IEEE80211_TX_RC_MCS))
|
if (!(rate->flags & IEEE80211_TX_RC_MCS))
|
||||||
return rate->idx;
|
return rate->idx;
|
||||||
|
|
||||||
while (rate->idx > mcs_rix_off[i] &&
|
while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {
|
||||||
i < ARRAY_SIZE(mcs_rix_off)) {
|
|
||||||
rix++; i++;
|
rix++; i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
*sc->rx.rxlink = bf->bf_daddr;
|
*sc->rx.rxlink = bf->bf_daddr;
|
||||||
|
|
||||||
sc->rx.rxlink = &ds->ds_link;
|
sc->rx.rxlink = &ds->ds_link;
|
||||||
ath9k_hw_rxena(ah);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
|
static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
|
||||||
|
@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||||
else
|
else
|
||||||
rfilt |= ATH9K_RX_FILTER_BEACON;
|
rfilt |= ATH9K_RX_FILTER_BEACON;
|
||||||
|
|
||||||
if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
|
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
|
||||||
AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
|
|
||||||
(sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
|
|
||||||
(sc->rx.rxfilter & FIF_PSPOLL))
|
(sc->rx.rxfilter & FIF_PSPOLL))
|
||||||
rfilt |= ATH9K_RX_FILTER_PSPOLL;
|
rfilt |= ATH9K_RX_FILTER_PSPOLL;
|
||||||
|
|
||||||
|
@ -1767,6 +1764,7 @@ requeue:
|
||||||
} else {
|
} else {
|
||||||
list_move_tail(&bf->list, &sc->rx.rxbuf);
|
list_move_tail(&bf->list, &sc->rx.rxbuf);
|
||||||
ath_rx_buf_link(sc, bf);
|
ath_rx_buf_link(sc, bf);
|
||||||
|
ath9k_hw_rxena(ah);
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
|
|
|
@ -858,9 +858,7 @@
|
||||||
#define AR_SREV_9300(_ah) \
|
#define AR_SREV_9300(_ah) \
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
|
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
|
||||||
#define AR_SREV_9300_20_OR_LATER(_ah) \
|
#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.macVersion == AR_SREV_VERSION_9300) && \
|
|
||||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20)))
|
|
||||||
|
|
||||||
#define AR_SREV_9485(_ah) \
|
#define AR_SREV_9485(_ah) \
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
|
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
|
||||||
|
@ -1088,14 +1086,35 @@ enum {
|
||||||
#define AR_ENT_OTP 0x40d8
|
#define AR_ENT_OTP 0x40d8
|
||||||
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
|
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
|
||||||
#define AR_ENT_OTP_MPSD 0x00800000
|
#define AR_ENT_OTP_MPSD 0x00800000
|
||||||
|
|
||||||
|
#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 0x16184
|
||||||
#define AR_CH0_BB_DPLL3 0x16188
|
#define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000
|
||||||
#define AR_CH0_DDR_DPLL2 0x16244
|
#define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30
|
||||||
#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 0x3C000000
|
||||||
#define AR_CH0_DPLL2_KI_S 26
|
#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_DPLL3_PHASE_SHIFT 0x3F800000
|
#define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000
|
||||||
#define AR_CH0_DPLL3_PHASE_SHIFT_S 23
|
#define AR_CH0_DPLL3_PHASE_SHIFT_S 23
|
||||||
#define AR_PHY_CCA_NOM_VAL_2GHZ -118
|
#define AR_PHY_CCA_NOM_VAL_2GHZ -118
|
||||||
|
|
|
@ -23,20 +23,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
|
||||||
return "WMI_ECHO_CMDID";
|
return "WMI_ECHO_CMDID";
|
||||||
case WMI_ACCESS_MEMORY_CMDID:
|
case WMI_ACCESS_MEMORY_CMDID:
|
||||||
return "WMI_ACCESS_MEMORY_CMDID";
|
return "WMI_ACCESS_MEMORY_CMDID";
|
||||||
|
case WMI_GET_FW_VERSION:
|
||||||
|
return "WMI_GET_FW_VERSION";
|
||||||
case WMI_DISABLE_INTR_CMDID:
|
case WMI_DISABLE_INTR_CMDID:
|
||||||
return "WMI_DISABLE_INTR_CMDID";
|
return "WMI_DISABLE_INTR_CMDID";
|
||||||
case WMI_ENABLE_INTR_CMDID:
|
case WMI_ENABLE_INTR_CMDID:
|
||||||
return "WMI_ENABLE_INTR_CMDID";
|
return "WMI_ENABLE_INTR_CMDID";
|
||||||
case WMI_RX_LINK_CMDID:
|
|
||||||
return "WMI_RX_LINK_CMDID";
|
|
||||||
case WMI_ATH_INIT_CMDID:
|
case WMI_ATH_INIT_CMDID:
|
||||||
return "WMI_ATH_INIT_CMDID";
|
return "WMI_ATH_INIT_CMDID";
|
||||||
case WMI_ABORT_TXQ_CMDID:
|
case WMI_ABORT_TXQ_CMDID:
|
||||||
return "WMI_ABORT_TXQ_CMDID";
|
return "WMI_ABORT_TXQ_CMDID";
|
||||||
case WMI_STOP_TX_DMA_CMDID:
|
case WMI_STOP_TX_DMA_CMDID:
|
||||||
return "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:
|
case WMI_ABORT_TX_DMA_CMDID:
|
||||||
return "WMI_ABORT_TX_DMA_CMDID";
|
return "WMI_ABORT_TX_DMA_CMDID";
|
||||||
case WMI_DRAIN_TXQ_CMDID:
|
case WMI_DRAIN_TXQ_CMDID:
|
||||||
|
@ -51,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
|
||||||
return "WMI_FLUSH_RECV_CMDID";
|
return "WMI_FLUSH_RECV_CMDID";
|
||||||
case WMI_SET_MODE_CMDID:
|
case WMI_SET_MODE_CMDID:
|
||||||
return "WMI_SET_MODE_CMDID";
|
return "WMI_SET_MODE_CMDID";
|
||||||
case WMI_RESET_CMDID:
|
|
||||||
return "WMI_RESET_CMDID";
|
|
||||||
case WMI_NODE_CREATE_CMDID:
|
case WMI_NODE_CREATE_CMDID:
|
||||||
return "WMI_NODE_CREATE_CMDID";
|
return "WMI_NODE_CREATE_CMDID";
|
||||||
case WMI_NODE_REMOVE_CMDID:
|
case WMI_NODE_REMOVE_CMDID:
|
||||||
|
@ -61,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
|
||||||
return "WMI_VAP_REMOVE_CMDID";
|
return "WMI_VAP_REMOVE_CMDID";
|
||||||
case WMI_VAP_CREATE_CMDID:
|
case WMI_VAP_CREATE_CMDID:
|
||||||
return "WMI_VAP_CREATE_CMDID";
|
return "WMI_VAP_CREATE_CMDID";
|
||||||
case WMI_BEACON_UPDATE_CMDID:
|
|
||||||
return "WMI_BEACON_UPDATE_CMDID";
|
|
||||||
case WMI_REG_READ_CMDID:
|
case WMI_REG_READ_CMDID:
|
||||||
return "WMI_REG_READ_CMDID";
|
return "WMI_REG_READ_CMDID";
|
||||||
case WMI_REG_WRITE_CMDID:
|
case WMI_REG_WRITE_CMDID:
|
||||||
|
@ -71,20 +65,20 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
|
||||||
return "WMI_RC_STATE_CHANGE_CMDID";
|
return "WMI_RC_STATE_CHANGE_CMDID";
|
||||||
case WMI_RC_RATE_UPDATE_CMDID:
|
case WMI_RC_RATE_UPDATE_CMDID:
|
||||||
return "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:
|
case WMI_TARGET_IC_UPDATE_CMDID:
|
||||||
return "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:
|
case WMI_TX_AGGR_ENABLE_CMDID:
|
||||||
return "WMI_TX_AGGR_ENABLE_CMDID";
|
return "WMI_TX_AGGR_ENABLE_CMDID";
|
||||||
case WMI_TGT_DETACH_CMDID:
|
case WMI_TGT_DETACH_CMDID:
|
||||||
return "WMI_TGT_DETACH_CMDID";
|
return "WMI_TGT_DETACH_CMDID";
|
||||||
case WMI_TGT_TXQ_ENABLE_CMDID:
|
case WMI_NODE_UPDATE_CMDID:
|
||||||
return "WMI_TGT_TXQ_ENABLE_CMDID";
|
return "WMI_NODE_UPDATE_CMDID";
|
||||||
|
case WMI_INT_STATS_CMDID:
|
||||||
|
return "WMI_INT_STATS_CMDID";
|
||||||
|
case WMI_TX_STATS_CMDID:
|
||||||
|
return "WMI_TX_STATS_CMDID";
|
||||||
|
case WMI_RX_STATS_CMDID:
|
||||||
|
return "WMI_RX_STATS_CMDID";
|
||||||
case WMI_AGGR_LIMIT_CMD:
|
case WMI_AGGR_LIMIT_CMD:
|
||||||
return "WMI_AGGR_LIMIT_CMD";
|
return "WMI_AGGR_LIMIT_CMD";
|
||||||
}
|
}
|
||||||
|
@ -102,9 +96,15 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
|
||||||
|
|
||||||
wmi->drv_priv = priv;
|
wmi->drv_priv = priv;
|
||||||
wmi->stopped = false;
|
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->op_mutex);
|
||||||
mutex_init(&wmi->multi_write_mutex);
|
mutex_init(&wmi->multi_write_mutex);
|
||||||
init_completion(&wmi->cmd_wait);
|
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;
|
return wmi;
|
||||||
}
|
}
|
||||||
|
@ -120,11 +120,65 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
|
||||||
kfree(priv->wmi);
|
kfree(priv->wmi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_swba_tasklet(unsigned long data)
|
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
|
||||||
{
|
{
|
||||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
unsigned long flags;
|
||||||
|
|
||||||
ath9k_htc_swba(priv, priv->wmi->beacon_pending);
|
tasklet_kill(&priv->wmi->wmi_event_tasklet);
|
||||||
|
spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
|
||||||
|
__skb_queue_purge(&priv->wmi->wmi_event_queue);
|
||||||
|
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_wmi_event_tasklet(unsigned long data)
|
||||||
|
{
|
||||||
|
struct wmi *wmi = (struct wmi *)data;
|
||||||
|
struct ath9k_htc_priv *priv = wmi->drv_priv;
|
||||||
|
struct wmi_cmd_hdr *hdr;
|
||||||
|
void *wmi_event;
|
||||||
|
struct wmi_event_swba *swba;
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
unsigned long flags;
|
||||||
|
u16 cmd_id;
|
||||||
|
|
||||||
|
do {
|
||||||
|
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||||
|
skb = __skb_dequeue(&wmi->wmi_event_queue);
|
||||||
|
if (!skb) {
|
||||||
|
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||||
|
|
||||||
|
hdr = (struct wmi_cmd_hdr *) skb->data;
|
||||||
|
cmd_id = be16_to_cpu(hdr->command_id);
|
||||||
|
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
|
||||||
|
|
||||||
|
switch (cmd_id) {
|
||||||
|
case WMI_SWBA_EVENTID:
|
||||||
|
swba = (struct wmi_event_swba *) wmi_event;
|
||||||
|
ath9k_htc_swba(priv, swba);
|
||||||
|
break;
|
||||||
|
case WMI_FATAL_EVENTID:
|
||||||
|
ieee80211_queue_work(wmi->drv_priv->hw,
|
||||||
|
&wmi->drv_priv->fatal_work);
|
||||||
|
break;
|
||||||
|
case WMI_TXSTATUS_EVENTID:
|
||||||
|
spin_lock_bh(&priv->tx.tx_lock);
|
||||||
|
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&priv->tx.tx_lock);
|
||||||
|
|
||||||
|
ath9k_htc_txstatus(priv, wmi_event);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree_skb(skb);
|
||||||
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_fatal_work(struct work_struct *work)
|
void ath9k_fatal_work(struct work_struct *work)
|
||||||
|
@ -153,10 +207,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
||||||
struct wmi *wmi = (struct wmi *) priv;
|
struct wmi *wmi = (struct wmi *) priv;
|
||||||
struct wmi_cmd_hdr *hdr;
|
struct wmi_cmd_hdr *hdr;
|
||||||
u16 cmd_id;
|
u16 cmd_id;
|
||||||
void *wmi_event;
|
|
||||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
|
||||||
__be32 txrate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (unlikely(wmi->stopped))
|
if (unlikely(wmi->stopped))
|
||||||
goto free_skb;
|
goto free_skb;
|
||||||
|
@ -165,26 +215,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
||||||
cmd_id = be16_to_cpu(hdr->command_id);
|
cmd_id = be16_to_cpu(hdr->command_id);
|
||||||
|
|
||||||
if (cmd_id & 0x1000) {
|
if (cmd_id & 0x1000) {
|
||||||
wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
|
spin_lock(&wmi->wmi_lock);
|
||||||
switch (cmd_id) {
|
__skb_queue_tail(&wmi->wmi_event_queue, skb);
|
||||||
case WMI_SWBA_EVENTID:
|
spin_unlock(&wmi->wmi_lock);
|
||||||
wmi->beacon_pending = *(u8 *)wmi_event;
|
tasklet_schedule(&wmi->wmi_event_tasklet);
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
|
||||||
hdr->command_id = cpu_to_be16(cmd);
|
hdr->command_id = cpu_to_be16(cmd);
|
||||||
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
|
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,
|
int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#ifndef WMI_H
|
#ifndef WMI_H
|
||||||
#define WMI_H
|
#define WMI_H
|
||||||
|
|
||||||
|
|
||||||
struct wmi_event_txrate {
|
struct wmi_event_txrate {
|
||||||
__be32 txrate;
|
__be32 txrate;
|
||||||
struct {
|
struct {
|
||||||
|
@ -31,18 +30,65 @@ struct wmi_cmd_hdr {
|
||||||
__be16 seq_no;
|
__be16 seq_no;
|
||||||
} __packed;
|
} __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 {
|
enum wmi_cmd_id {
|
||||||
WMI_ECHO_CMDID = 0x0001,
|
WMI_ECHO_CMDID = 0x0001,
|
||||||
WMI_ACCESS_MEMORY_CMDID,
|
WMI_ACCESS_MEMORY_CMDID,
|
||||||
|
|
||||||
/* Commands to Target */
|
/* Commands to Target */
|
||||||
|
WMI_GET_FW_VERSION,
|
||||||
WMI_DISABLE_INTR_CMDID,
|
WMI_DISABLE_INTR_CMDID,
|
||||||
WMI_ENABLE_INTR_CMDID,
|
WMI_ENABLE_INTR_CMDID,
|
||||||
WMI_RX_LINK_CMDID,
|
|
||||||
WMI_ATH_INIT_CMDID,
|
WMI_ATH_INIT_CMDID,
|
||||||
WMI_ABORT_TXQ_CMDID,
|
WMI_ABORT_TXQ_CMDID,
|
||||||
WMI_STOP_TX_DMA_CMDID,
|
WMI_STOP_TX_DMA_CMDID,
|
||||||
WMI_STOP_DMA_RECV_CMDID,
|
|
||||||
WMI_ABORT_TX_DMA_CMDID,
|
WMI_ABORT_TX_DMA_CMDID,
|
||||||
WMI_DRAIN_TXQ_CMDID,
|
WMI_DRAIN_TXQ_CMDID,
|
||||||
WMI_DRAIN_TXQ_ALL_CMDID,
|
WMI_DRAIN_TXQ_ALL_CMDID,
|
||||||
|
@ -50,23 +96,21 @@ enum wmi_cmd_id {
|
||||||
WMI_STOP_RECV_CMDID,
|
WMI_STOP_RECV_CMDID,
|
||||||
WMI_FLUSH_RECV_CMDID,
|
WMI_FLUSH_RECV_CMDID,
|
||||||
WMI_SET_MODE_CMDID,
|
WMI_SET_MODE_CMDID,
|
||||||
WMI_RESET_CMDID,
|
|
||||||
WMI_NODE_CREATE_CMDID,
|
WMI_NODE_CREATE_CMDID,
|
||||||
WMI_NODE_REMOVE_CMDID,
|
WMI_NODE_REMOVE_CMDID,
|
||||||
WMI_VAP_REMOVE_CMDID,
|
WMI_VAP_REMOVE_CMDID,
|
||||||
WMI_VAP_CREATE_CMDID,
|
WMI_VAP_CREATE_CMDID,
|
||||||
WMI_BEACON_UPDATE_CMDID,
|
|
||||||
WMI_REG_READ_CMDID,
|
WMI_REG_READ_CMDID,
|
||||||
WMI_REG_WRITE_CMDID,
|
WMI_REG_WRITE_CMDID,
|
||||||
WMI_RC_STATE_CHANGE_CMDID,
|
WMI_RC_STATE_CHANGE_CMDID,
|
||||||
WMI_RC_RATE_UPDATE_CMDID,
|
WMI_RC_RATE_UPDATE_CMDID,
|
||||||
WMI_DEBUG_INFO_CMDID,
|
|
||||||
WMI_HOST_ATTACH,
|
|
||||||
WMI_TARGET_IC_UPDATE_CMDID,
|
WMI_TARGET_IC_UPDATE_CMDID,
|
||||||
WMI_TGT_STATS_CMDID,
|
|
||||||
WMI_TX_AGGR_ENABLE_CMDID,
|
WMI_TX_AGGR_ENABLE_CMDID,
|
||||||
WMI_TGT_DETACH_CMDID,
|
WMI_TGT_DETACH_CMDID,
|
||||||
WMI_TGT_TXQ_ENABLE_CMDID,
|
WMI_NODE_UPDATE_CMDID,
|
||||||
|
WMI_INT_STATS_CMDID,
|
||||||
|
WMI_TX_STATS_CMDID,
|
||||||
|
WMI_RX_STATS_CMDID,
|
||||||
WMI_AGGR_LIMIT_CMD = 0x0026,
|
WMI_AGGR_LIMIT_CMD = 0x0026,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,9 +120,8 @@ enum wmi_event_id {
|
||||||
WMI_FATAL_EVENTID,
|
WMI_FATAL_EVENTID,
|
||||||
WMI_TXTO_EVENTID,
|
WMI_TXTO_EVENTID,
|
||||||
WMI_BMISS_EVENTID,
|
WMI_BMISS_EVENTID,
|
||||||
WMI_WLAN_TXCOMP_EVENTID,
|
|
||||||
WMI_DELBA_EVENTID,
|
WMI_DELBA_EVENTID,
|
||||||
WMI_TXRATE_EVENTID,
|
WMI_TXSTATUS_EVENTID,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_CMD_NUMBER 62
|
#define MAX_CMD_NUMBER 62
|
||||||
|
@ -88,6 +131,12 @@ struct register_write {
|
||||||
__be32 val;
|
__be32 val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ath9k_htc_tx_event {
|
||||||
|
int count;
|
||||||
|
struct __wmi_event_txstatus txs;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
struct wmi {
|
struct wmi {
|
||||||
struct ath9k_htc_priv *drv_priv;
|
struct ath9k_htc_priv *drv_priv;
|
||||||
struct htc_target *htc;
|
struct htc_target *htc;
|
||||||
|
@ -95,12 +144,16 @@ struct wmi {
|
||||||
struct mutex op_mutex;
|
struct mutex op_mutex;
|
||||||
struct completion cmd_wait;
|
struct completion cmd_wait;
|
||||||
enum wmi_cmd_id last_cmd_id;
|
enum wmi_cmd_id last_cmd_id;
|
||||||
|
struct sk_buff_head wmi_event_queue;
|
||||||
|
struct tasklet_struct wmi_event_tasklet;
|
||||||
u16 tx_seq_id;
|
u16 tx_seq_id;
|
||||||
u8 *cmd_rsp_buf;
|
u8 *cmd_rsp_buf;
|
||||||
u32 cmd_rsp_len;
|
u32 cmd_rsp_len;
|
||||||
bool stopped;
|
bool stopped;
|
||||||
|
|
||||||
u8 beacon_pending;
|
struct list_head pending_tx_events;
|
||||||
|
spinlock_t event_lock;
|
||||||
|
|
||||||
spinlock_t wmi_lock;
|
spinlock_t wmi_lock;
|
||||||
|
|
||||||
atomic_t mwrite_cnt;
|
atomic_t mwrite_cnt;
|
||||||
|
@ -117,8 +170,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||||
u8 *cmd_buf, u32 cmd_len,
|
u8 *cmd_buf, u32 cmd_len,
|
||||||
u8 *rsp_buf, u32 rsp_len,
|
u8 *rsp_buf, u32 rsp_len,
|
||||||
u32 timeout);
|
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_fatal_work(struct work_struct *work);
|
||||||
|
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
|
||||||
|
|
||||||
#define WMI_CMD(_wmi_cmd) \
|
#define WMI_CMD(_wmi_cmd) \
|
||||||
do { \
|
do { \
|
||||||
|
|
|
@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
struct ath_frame_info *fi;
|
struct ath_frame_info *fi;
|
||||||
int nframes;
|
int nframes;
|
||||||
u8 tidno;
|
u8 tidno;
|
||||||
|
bool clear_filter;
|
||||||
|
|
||||||
skb = bf->bf_mpdu;
|
skb = bf->bf_mpdu;
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
@ -441,9 +442,18 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
/* transmit completion */
|
/* transmit completion */
|
||||||
acked_cnt++;
|
acked_cnt++;
|
||||||
} else {
|
} else {
|
||||||
if (!(tid->state & AGGR_CLEANUP) && retry) {
|
if ((tid->state & AGGR_CLEANUP) || !retry) {
|
||||||
if (fi->retries < ATH_MAX_SW_RETRIES) {
|
/*
|
||||||
|
* 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);
|
ath_tx_set_retry(sc, txq, bf->bf_mpdu);
|
||||||
|
|
||||||
|
clear_filter = true;
|
||||||
txpending = 1;
|
txpending = 1;
|
||||||
} else {
|
} else {
|
||||||
bf->bf_state.bf_type |= BUF_XRETRY;
|
bf->bf_state.bf_type |= BUF_XRETRY;
|
||||||
|
@ -451,13 +461,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
sendbar = 1;
|
sendbar = 1;
|
||||||
txfail_cnt++;
|
txfail_cnt++;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* cleanup in progress, just fail
|
|
||||||
* the un-acked sub-frames
|
|
||||||
*/
|
|
||||||
txfail = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
||||||
|
@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
!txfail, sendbar);
|
!txfail, sendbar);
|
||||||
} else {
|
} else {
|
||||||
/* retry the un-acked ones */
|
/* 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 (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
|
||||||
if (bf->bf_next == NULL && bf_last->bf_stale) {
|
if (bf->bf_next == NULL && bf_last->bf_stale) {
|
||||||
struct ath_buf *tbf;
|
struct ath_buf *tbf;
|
||||||
|
@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
|
|
||||||
/* prepend un-acked frames to the beginning of the pending frame queue */
|
/* prepend un-acked frames to the beginning of the pending frame queue */
|
||||||
if (!list_empty(&bf_pending)) {
|
if (!list_empty(&bf_pending)) {
|
||||||
|
if (an->sleeping)
|
||||||
|
ieee80211_sta_set_tim(sta);
|
||||||
|
|
||||||
spin_lock_bh(&txq->axq_lock);
|
spin_lock_bh(&txq->axq_lock);
|
||||||
|
if (clear_filter)
|
||||||
|
tid->ac->clear_ps_filter = true;
|
||||||
list_splice(&bf_pending, &tid->buf_q);
|
list_splice(&bf_pending, &tid->buf_q);
|
||||||
ath_tx_queue_tid(txq, tid);
|
ath_tx_queue_tid(txq, tid);
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
spin_unlock_bh(&txq->axq_lock);
|
||||||
|
@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
bf = list_first_entry(&bf_q, struct ath_buf, list);
|
bf = list_first_entry(&bf_q, struct ath_buf, list);
|
||||||
bf->bf_lastbf = list_entry(bf_q.prev, 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 only one frame, send as non-aggregate */
|
||||||
if (bf == bf->bf_lastbf) {
|
if (bf == bf->bf_lastbf) {
|
||||||
fi = get_frame_info(bf->bf_mpdu);
|
fi = get_frame_info(bf->bf_mpdu);
|
||||||
|
@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||||
ath_tx_flush_tid(sc, txtid);
|
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)
|
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||||
{
|
{
|
||||||
struct ath_atx_tid *txtid;
|
struct ath_atx_tid *txtid;
|
||||||
|
@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||||
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
|
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
|
||||||
struct ieee80211_hdr *hdr;
|
struct ieee80211_hdr *hdr;
|
||||||
struct ath_frame_info *fi = get_frame_info(skb);
|
struct ath_frame_info *fi = get_frame_info(skb);
|
||||||
struct ath_node *an;
|
struct ath_node *an = NULL;
|
||||||
struct ath_atx_tid *tid;
|
struct ath_atx_tid *tid;
|
||||||
enum ath9k_key_type keytype;
|
enum ath9k_key_type keytype;
|
||||||
u16 seqno = 0;
|
u16 seqno = 0;
|
||||||
|
@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||||
|
|
||||||
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
|
keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
|
||||||
|
|
||||||
|
if (sta)
|
||||||
|
an = (struct ath_node *) sta->drv_priv;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
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)) {
|
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;
|
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||||
memset(fi, 0, sizeof(*fi));
|
memset(fi, 0, sizeof(*fi));
|
||||||
if (hw_key)
|
if (hw_key)
|
||||||
fi->keyix = hw_key->hw_key_idx;
|
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
|
else
|
||||||
fi->keyix = ATH9K_TXKEYIX_INVALID;
|
fi->keyix = ATH9K_TXKEYIX_INVALID;
|
||||||
fi->keytype = keytype;
|
fi->keytype = keytype;
|
||||||
|
@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb)
|
||||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
|
|
||||||
flags |= ATH9K_TXDESC_INTREQ;
|
flags |= ATH9K_TXDESC_INTREQ;
|
||||||
|
|
||||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
|
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||||
|
@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
||||||
if (txctl->paprd)
|
if (txctl->paprd)
|
||||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
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);
|
ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *common,
|
||||||
memset(&hk, 0, sizeof(hk));
|
memset(&hk, 0, sizeof(hk));
|
||||||
|
|
||||||
switch (key->cipher) {
|
switch (key->cipher) {
|
||||||
|
case 0:
|
||||||
|
hk.kv_type = ATH_CIPHER_CLR;
|
||||||
|
break;
|
||||||
case WLAN_CIPHER_SUITE_WEP40:
|
case WLAN_CIPHER_SUITE_WEP40:
|
||||||
case WLAN_CIPHER_SUITE_WEP104:
|
case WLAN_CIPHER_SUITE_WEP104:
|
||||||
hk.kv_type = ATH_CIPHER_WEP;
|
hk.kv_type = ATH_CIPHER_WEP;
|
||||||
|
@ -498,6 +501,7 @@ int ath_key_config(struct ath_common *common,
|
||||||
}
|
}
|
||||||
|
|
||||||
hk.kv_len = key->keylen;
|
hk.kv_len = key->keylen;
|
||||||
|
if (key->keylen)
|
||||||
memcpy(hk.kv_val, key->key, key->keylen);
|
memcpy(hk.kv_val, key->key, key->keylen);
|
||||||
|
|
||||||
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||||
|
|
|
@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Can be used by 0x67, 0x6A and 0x68 */
|
/* Can be used by 0x67, 0x68, 0x6A and 0x6C */
|
||||||
static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
|
static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
|
||||||
.n_reg_rules = 4,
|
.n_reg_rules = 4,
|
||||||
.alpha2 = "99",
|
.alpha2 = "99",
|
||||||
.reg_rules = {
|
.reg_rules = {
|
||||||
|
@ -151,7 +151,8 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
|
||||||
case 0x67:
|
case 0x67:
|
||||||
case 0x68:
|
case 0x68:
|
||||||
case 0x6A:
|
case 0x6A:
|
||||||
return &ath_world_regdom_67_68_6A;
|
case 0x6C:
|
||||||
|
return &ath_world_regdom_67_68_6A_6C;
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return ath_default_world_regdomain();
|
return ath_default_world_regdomain();
|
||||||
|
@ -333,6 +334,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
|
||||||
case 0x63:
|
case 0x63:
|
||||||
case 0x66:
|
case 0x66:
|
||||||
case 0x67:
|
case 0x67:
|
||||||
|
case 0x6C:
|
||||||
ath_reg_apply_beaconing_flags(wiphy, initiator);
|
ath_reg_apply_beaconing_flags(wiphy, initiator);
|
||||||
break;
|
break;
|
||||||
case 0x68:
|
case 0x68:
|
||||||
|
|
|
@ -86,6 +86,7 @@ enum EnumRd {
|
||||||
WOR9_WORLD = 0x69,
|
WOR9_WORLD = 0x69,
|
||||||
WORA_WORLD = 0x6A,
|
WORA_WORLD = 0x6A,
|
||||||
WORB_WORLD = 0x6B,
|
WORB_WORLD = 0x6B,
|
||||||
|
WORC_WORLD = 0x6C,
|
||||||
|
|
||||||
MKK3_MKKB = 0x80,
|
MKK3_MKKB = 0x80,
|
||||||
MKK3_MKKA2 = 0x81,
|
MKK3_MKKA2 = 0x81,
|
||||||
|
@ -282,6 +283,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
||||||
{WOR9_WORLD, NO_CTL, NO_CTL},
|
{WOR9_WORLD, NO_CTL, NO_CTL},
|
||||||
{WORA_WORLD, NO_CTL, NO_CTL},
|
{WORA_WORLD, NO_CTL, NO_CTL},
|
||||||
{WORB_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[] = {
|
static struct country_code_to_enum_rd allCountries[] = {
|
||||||
|
|
|
@ -2860,7 +2860,6 @@ static struct rate_control_ops rs_4965_ops = {
|
||||||
|
|
||||||
int iwl4965_rate_control_register(void)
|
int iwl4965_rate_control_register(void)
|
||||||
{
|
{
|
||||||
pr_err("Registering 4965 rate control operations\n");
|
|
||||||
return ieee80211_rate_control_register(&rs_4965_ops);
|
return ieee80211_rate_control_register(&rs_4965_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3173,7 +3173,7 @@ static void iwl4965_hw_detect(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
|
priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
|
||||||
priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG);
|
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);
|
IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# AGN
|
# AGN
|
||||||
obj-$(CONFIG_IWLAGN) += iwlagn.o
|
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-ucode.o iwl-agn-tx.o
|
||||||
iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
|
iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
|
||||||
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
|
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "iwl-agn.h"
|
#include "iwl-agn.h"
|
||||||
#include "iwl-helpers.h"
|
#include "iwl-helpers.h"
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
#include "iwl-agn-debugfs.h"
|
#include "iwl-agn-debugfs.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
|
@ -57,12 +56,10 @@
|
||||||
#define IWL100_UCODE_API_MIN 5
|
#define IWL100_UCODE_API_MIN 5
|
||||||
|
|
||||||
#define IWL1000_FW_PRE "iwlwifi-1000-"
|
#define IWL1000_FW_PRE "iwlwifi-1000-"
|
||||||
#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
|
#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
|
||||||
#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL100_FW_PRE "iwlwifi-100-"
|
#define IWL100_FW_PRE "iwlwifi-100-"
|
||||||
#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
|
#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
|
||||||
#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -184,10 +181,6 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||||
.rx_handler_setup = iwlagn_rx_handler_setup,
|
.rx_handler_setup = iwlagn_rx_handler_setup,
|
||||||
.setup_deferred_work = iwlagn_setup_deferred_work,
|
.setup_deferred_work = iwlagn_setup_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.dump_fh = iwl_dump_fh,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.apm_ops = {
|
.apm_ops = {
|
||||||
|
@ -202,7 +195,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||||
EEPROM_REG_BAND_4_CHANNELS,
|
EEPROM_REG_BAND_4_CHANNELS,
|
||||||
EEPROM_REG_BAND_5_CHANNELS,
|
EEPROM_REG_BAND_5_CHANNELS,
|
||||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||||
},
|
},
|
||||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||||
|
@ -221,19 +214,12 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static const struct iwl_ops iwl1000_ops = {
|
||||||
.lib = &iwl1000_lib,
|
.lib = &iwl1000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_base_params iwl1000_base_params = {
|
static struct iwl_base_params iwl1000_base_params = {
|
||||||
|
@ -241,7 +227,6 @@ static struct iwl_base_params iwl1000_base_params = {
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||||
.shadow_ram_support = false,
|
.shadow_ram_support = false,
|
||||||
.led_compensation = 51,
|
.led_compensation = 51,
|
||||||
|
@ -251,9 +236,6 @@ static struct iwl_base_params iwl1000_base_params = {
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||||
.max_event_log_size = 128,
|
.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 = {
|
static struct iwl_ht_params iwl1000_ht_params = {
|
||||||
.ht_greenfield_support = true,
|
.ht_greenfield_support = true,
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "iwl-helpers.h"
|
#include "iwl-helpers.h"
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
#include "iwl-6000-hw.h"
|
#include "iwl-6000-hw.h"
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
#include "iwl-agn-debugfs.h"
|
#include "iwl-agn-debugfs.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
|
@ -60,16 +59,13 @@
|
||||||
#define IWL200_UCODE_API_MIN 5
|
#define IWL200_UCODE_API_MIN 5
|
||||||
|
|
||||||
#define IWL2030_FW_PRE "iwlwifi-2030-"
|
#define IWL2030_FW_PRE "iwlwifi-2030-"
|
||||||
#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"
|
#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"
|
||||||
#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL2000_FW_PRE "iwlwifi-2000-"
|
#define IWL2000_FW_PRE "iwlwifi-2000-"
|
||||||
#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"
|
#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"
|
||||||
#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL200_FW_PRE "iwlwifi-200-"
|
#define IWL200_FW_PRE "iwlwifi-200-"
|
||||||
#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"
|
#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"
|
||||||
#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
|
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +97,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
|
||||||
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
|
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
|
||||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
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 = {
|
static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
||||||
|
@ -265,10 +263,6 @@ static struct iwl_lib_ops iwl2000_lib = {
|
||||||
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
||||||
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.dump_fh = iwl_dump_fh,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.set_channel_switch = iwl2030_hw_channel_switch,
|
.set_channel_switch = iwl2030_hw_channel_switch,
|
||||||
|
@ -284,7 +278,7 @@ static struct iwl_lib_ops iwl2000_lib = {
|
||||||
EEPROM_REG_BAND_4_CHANNELS,
|
EEPROM_REG_BAND_4_CHANNELS,
|
||||||
EEPROM_REG_BAND_5_CHANNELS,
|
EEPROM_REG_BAND_5_CHANNELS,
|
||||||
EEPROM_6000_REG_BAND_24_HT40_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,
|
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||||
|
@ -304,43 +298,30 @@ static struct iwl_lib_ops iwl2000_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static const struct iwl_ops iwl2000_ops = {
|
||||||
.lib = &iwl2000_lib,
|
.lib = &iwl2000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iwl_ops iwl2030_ops = {
|
static const struct iwl_ops iwl2030_ops = {
|
||||||
.lib = &iwl2000_lib,
|
.lib = &iwl2000_lib,
|
||||||
.hcmd = &iwlagn_bt_hcmd,
|
.hcmd = &iwlagn_bt_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.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 iwl200_ops = {
|
||||||
.lib = &iwl2000_lib,
|
.lib = &iwl2000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.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 iwl230_ops = {
|
||||||
.lib = &iwl2000_lib,
|
.lib = &iwl2000_lib,
|
||||||
.hcmd = &iwlagn_bt_hcmd,
|
.hcmd = &iwlagn_bt_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_base_params iwl2000_base_params = {
|
static struct iwl_base_params iwl2000_base_params = {
|
||||||
|
@ -348,7 +329,6 @@ static struct iwl_base_params iwl2000_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = 0,
|
.pll_cfg_val = 0,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||||
.shadow_ram_support = true,
|
.shadow_ram_support = true,
|
||||||
.led_compensation = 51,
|
.led_compensation = 51,
|
||||||
|
@ -359,9 +339,6 @@ static struct iwl_base_params iwl2000_base_params = {
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||||
.max_event_log_size = 512,
|
.max_event_log_size = 512,
|
||||||
.ucode_tracing = true,
|
|
||||||
.sensitivity_calib_by_driver = true,
|
|
||||||
.chain_noise_calib_by_driver = true,
|
|
||||||
.shadow_reg_enable = true,
|
.shadow_reg_enable = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -371,7 +348,6 @@ static struct iwl_base_params iwl2030_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = 0,
|
.pll_cfg_val = 0,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||||
.shadow_ram_support = true,
|
.shadow_ram_support = true,
|
||||||
.led_compensation = 57,
|
.led_compensation = 57,
|
||||||
|
@ -382,9 +358,6 @@ static struct iwl_base_params iwl2030_base_params = {
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||||
.max_event_log_size = 512,
|
.max_event_log_size = 512,
|
||||||
.ucode_tracing = true,
|
|
||||||
.sensitivity_calib_by_driver = true,
|
|
||||||
.chain_noise_calib_by_driver = true,
|
|
||||||
.shadow_reg_enable = true,
|
.shadow_reg_enable = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -394,7 +367,6 @@ static struct iwl_ht_params iwl2000_ht_params = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_bt_params iwl2030_bt_params = {
|
static struct iwl_bt_params iwl2030_bt_params = {
|
||||||
.bt_statistics = true,
|
|
||||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||||
.advanced_bt_coexist = true,
|
.advanced_bt_coexist = true,
|
||||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||||
|
@ -416,7 +388,8 @@ static struct iwl_bt_params iwl2030_bt_params = {
|
||||||
.need_dc_calib = true, \
|
.need_dc_calib = true, \
|
||||||
.need_temp_offset_calib = true, \
|
.need_temp_offset_calib = true, \
|
||||||
.led_mode = IWL_LED_RF_STATE, \
|
.led_mode = IWL_LED_RF_STATE, \
|
||||||
.iq_invert = true \
|
.iq_invert = true, \
|
||||||
|
.disable_otp_refresh = true \
|
||||||
|
|
||||||
struct iwl_cfg iwl2000_2bgn_cfg = {
|
struct iwl_cfg iwl2000_2bgn_cfg = {
|
||||||
.name = "2000 Series 2x2 BGN",
|
.name = "2000 Series 2x2 BGN",
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "iwl-sta.h"
|
#include "iwl-sta.h"
|
||||||
#include "iwl-helpers.h"
|
#include "iwl-helpers.h"
|
||||||
#include "iwl-agn.h"
|
#include "iwl-agn.h"
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
#include "iwl-5000-hw.h"
|
#include "iwl-5000-hw.h"
|
||||||
#include "iwl-agn-debugfs.h"
|
#include "iwl-agn-debugfs.h"
|
||||||
|
@ -59,12 +58,10 @@
|
||||||
#define IWL5150_UCODE_API_MIN 1
|
#define IWL5150_UCODE_API_MIN 1
|
||||||
|
|
||||||
#define IWL5000_FW_PRE "iwlwifi-5000-"
|
#define IWL5000_FW_PRE "iwlwifi-5000-"
|
||||||
#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
|
#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
|
||||||
#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL5150_FW_PRE "iwlwifi-5150-"
|
#define IWL5150_FW_PRE "iwlwifi-5150-"
|
||||||
#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
|
#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
|
||||||
#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
/* NIC configuration for 5000 series */
|
/* NIC configuration for 5000 series */
|
||||||
static void iwl5000_nic_config(struct iwl_priv *priv)
|
static void iwl5000_nic_config(struct iwl_priv *priv)
|
||||||
|
@ -261,7 +258,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
|
||||||
u32 vt = 0;
|
u32 vt = 0;
|
||||||
s32 offset = iwl_temp_calib_to_offset(priv);
|
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;
|
vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
|
||||||
/* now vt hold the temperature in Kelvin */
|
/* now vt hold the temperature in Kelvin */
|
||||||
priv->temperature = KELVIN_TO_CELSIUS(vt);
|
priv->temperature = KELVIN_TO_CELSIUS(vt);
|
||||||
|
@ -352,10 +349,6 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||||
.rx_handler_setup = iwlagn_rx_handler_setup,
|
.rx_handler_setup = iwlagn_rx_handler_setup,
|
||||||
.setup_deferred_work = iwlagn_setup_deferred_work,
|
.setup_deferred_work = iwlagn_setup_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.dump_fh = iwl_dump_fh,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||||
|
@ -390,11 +383,6 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static struct iwl_lib_ops iwl5150_lib = {
|
||||||
|
@ -408,9 +396,6 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||||
.rx_handler_setup = iwlagn_rx_handler_setup,
|
.rx_handler_setup = iwlagn_rx_handler_setup,
|
||||||
.setup_deferred_work = iwlagn_setup_deferred_work,
|
.setup_deferred_work = iwlagn_setup_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||||
|
@ -445,27 +430,18 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static const struct iwl_ops iwl5000_ops = {
|
||||||
.lib = &iwl5000_lib,
|
.lib = &iwl5000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iwl_ops iwl5150_ops = {
|
static const struct iwl_ops iwl5150_ops = {
|
||||||
.lib = &iwl5150_lib,
|
.lib = &iwl5150_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_base_params iwl5000_base_params = {
|
static struct iwl_base_params iwl5000_base_params = {
|
||||||
|
@ -473,16 +449,12 @@ static struct iwl_base_params iwl5000_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||||
.set_l0s = true,
|
|
||||||
.led_compensation = 51,
|
.led_compensation = 51,
|
||||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||||
.max_event_log_size = 512,
|
.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 = {
|
static struct iwl_ht_params iwl5000_ht_params = {
|
||||||
.ht_greenfield_support = true,
|
.ht_greenfield_support = true,
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "iwl-helpers.h"
|
#include "iwl-helpers.h"
|
||||||
#include "iwl-agn-hw.h"
|
#include "iwl-agn-hw.h"
|
||||||
#include "iwl-6000-hw.h"
|
#include "iwl-6000-hw.h"
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
#include "iwl-agn-debugfs.h"
|
#include "iwl-agn-debugfs.h"
|
||||||
|
|
||||||
/* Highest firmware API version supported */
|
/* Highest firmware API version supported */
|
||||||
|
@ -60,20 +59,16 @@
|
||||||
#define IWL6000G2_UCODE_API_MIN 4
|
#define IWL6000G2_UCODE_API_MIN 4
|
||||||
|
|
||||||
#define IWL6000_FW_PRE "iwlwifi-6000-"
|
#define IWL6000_FW_PRE "iwlwifi-6000-"
|
||||||
#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
|
#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
|
||||||
#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL6050_FW_PRE "iwlwifi-6050-"
|
#define IWL6050_FW_PRE "iwlwifi-6050-"
|
||||||
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
|
#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
|
||||||
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
|
#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
|
||||||
#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
|
#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
|
||||||
#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
|
#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
|
||||||
#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
|
#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
|
||||||
#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api)
|
|
||||||
|
|
||||||
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
|
@ -293,10 +288,6 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||||
.rx_handler_setup = iwlagn_rx_handler_setup,
|
.rx_handler_setup = iwlagn_rx_handler_setup,
|
||||||
.setup_deferred_work = iwlagn_setup_deferred_work,
|
.setup_deferred_work = iwlagn_setup_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.dump_fh = iwl_dump_fh,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||||
|
@ -332,11 +323,6 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static struct iwl_lib_ops iwl6030_lib = {
|
||||||
|
@ -351,10 +337,6 @@ static struct iwl_lib_ops iwl6030_lib = {
|
||||||
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
.setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
||||||
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
||||||
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
|
||||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
|
||||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
|
||||||
.dump_csr = iwl_dump_csr,
|
|
||||||
.dump_fh = iwl_dump_fh,
|
|
||||||
.send_tx_power = iwlagn_send_tx_power,
|
.send_tx_power = iwlagn_send_tx_power,
|
||||||
.update_chain_flags = iwl_update_chain_flags,
|
.update_chain_flags = iwl_update_chain_flags,
|
||||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||||
|
@ -390,11 +372,6 @@ static struct iwl_lib_ops iwl6030_lib = {
|
||||||
},
|
},
|
||||||
.txfifo_flush = iwlagn_txfifo_flush,
|
.txfifo_flush = iwlagn_txfifo_flush,
|
||||||
.dev_txfifo_flush = iwlagn_dev_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 = {
|
static struct iwl_nic_ops iwl6050_nic_ops = {
|
||||||
|
@ -409,34 +386,26 @@ static const struct iwl_ops iwl6000_ops = {
|
||||||
.lib = &iwl6000_lib,
|
.lib = &iwl6000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iwl_ops iwl6050_ops = {
|
static const struct iwl_ops iwl6050_ops = {
|
||||||
.lib = &iwl6000_lib,
|
.lib = &iwl6000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.nic = &iwl6050_nic_ops,
|
.nic = &iwl6050_nic_ops,
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iwl_ops iwl6150_ops = {
|
static const struct iwl_ops iwl6150_ops = {
|
||||||
.lib = &iwl6000_lib,
|
.lib = &iwl6000_lib,
|
||||||
.hcmd = &iwlagn_hcmd,
|
.hcmd = &iwlagn_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.nic = &iwl6150_nic_ops,
|
.nic = &iwl6150_nic_ops,
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iwl_ops iwl6030_ops = {
|
static const struct iwl_ops iwl6030_ops = {
|
||||||
.lib = &iwl6030_lib,
|
.lib = &iwl6030_lib,
|
||||||
.hcmd = &iwlagn_bt_hcmd,
|
.hcmd = &iwlagn_bt_hcmd,
|
||||||
.utils = &iwlagn_hcmd_utils,
|
.utils = &iwlagn_hcmd_utils,
|
||||||
.led = &iwlagn_led_ops,
|
|
||||||
.ieee80211_ops = &iwlagn_hw_ops,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_base_params iwl6000_base_params = {
|
static struct iwl_base_params iwl6000_base_params = {
|
||||||
|
@ -444,7 +413,6 @@ static struct iwl_base_params iwl6000_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = 0,
|
.pll_cfg_val = 0,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||||
.shadow_ram_support = true,
|
.shadow_ram_support = true,
|
||||||
.led_compensation = 51,
|
.led_compensation = 51,
|
||||||
|
@ -455,9 +423,6 @@ static struct iwl_base_params iwl6000_base_params = {
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||||
.max_event_log_size = 512,
|
.max_event_log_size = 512,
|
||||||
.ucode_tracing = true,
|
|
||||||
.sensitivity_calib_by_driver = true,
|
|
||||||
.chain_noise_calib_by_driver = true,
|
|
||||||
.shadow_reg_enable = true,
|
.shadow_reg_enable = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -466,7 +431,6 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = 0,
|
.pll_cfg_val = 0,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||||
.shadow_ram_support = true,
|
.shadow_ram_support = true,
|
||||||
.led_compensation = 51,
|
.led_compensation = 51,
|
||||||
|
@ -477,9 +441,6 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||||
.chain_noise_scale = 1500,
|
.chain_noise_scale = 1500,
|
||||||
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
.wd_timeout = IWL_DEF_WD_TIMEOUT,
|
||||||
.max_event_log_size = 1024,
|
.max_event_log_size = 1024,
|
||||||
.ucode_tracing = true,
|
|
||||||
.sensitivity_calib_by_driver = true,
|
|
||||||
.chain_noise_calib_by_driver = true,
|
|
||||||
.shadow_reg_enable = true,
|
.shadow_reg_enable = true,
|
||||||
};
|
};
|
||||||
static struct iwl_base_params iwl6000_g2_base_params = {
|
static struct iwl_base_params iwl6000_g2_base_params = {
|
||||||
|
@ -487,7 +448,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
|
||||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||||
.pll_cfg_val = 0,
|
.pll_cfg_val = 0,
|
||||||
.set_l0s = true,
|
|
||||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||||
.shadow_ram_support = true,
|
.shadow_ram_support = true,
|
||||||
.led_compensation = 57,
|
.led_compensation = 57,
|
||||||
|
@ -498,9 +458,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
|
||||||
.chain_noise_scale = 1000,
|
.chain_noise_scale = 1000,
|
||||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||||
.max_event_log_size = 512,
|
.max_event_log_size = 512,
|
||||||
.ucode_tracing = true,
|
|
||||||
.sensitivity_calib_by_driver = true,
|
|
||||||
.chain_noise_calib_by_driver = true,
|
|
||||||
.shadow_reg_enable = true,
|
.shadow_reg_enable = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -510,7 +467,6 @@ static struct iwl_ht_params iwl6000_ht_params = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct iwl_bt_params iwl6000_bt_params = {
|
static struct iwl_bt_params iwl6000_bt_params = {
|
||||||
.bt_statistics = true,
|
|
||||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||||
.advanced_bt_coexist = true,
|
.advanced_bt_coexist = true,
|
||||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||||
|
|
|
@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
|
||||||
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
|
IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
|
void iwl_sensitivity_calibration(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
u32 rx_enable_time;
|
u32 rx_enable_time;
|
||||||
u32 fa_cck;
|
u32 fa_cck;
|
||||||
|
@ -631,16 +631,9 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
if (iwl_bt_statistics(priv)) {
|
rx_info = &priv->statistics.rx_non_phy;
|
||||||
rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
|
ofdm = &priv->statistics.rx_ofdm;
|
||||||
rx.general.common);
|
cck = &priv->statistics.rx_cck;
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||||
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
|
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
@ -851,7 +844,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
||||||
* 1) Which antennas are connected.
|
* 1) Which antennas are connected.
|
||||||
* 2) Differential rx gain settings to balance the 3 receivers.
|
* 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;
|
struct iwl_chain_noise_data *data = NULL;
|
||||||
|
|
||||||
|
@ -896,13 +889,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
if (iwl_bt_statistics(priv)) {
|
|
||||||
rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
|
rx_info = &priv->statistics.rx_non_phy;
|
||||||
rx.general.common);
|
|
||||||
} else {
|
|
||||||
rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
|
|
||||||
rx.general);
|
|
||||||
}
|
|
||||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||||
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
|
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
@ -911,19 +900,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
||||||
|
|
||||||
rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
|
rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
|
||||||
rxon_chnum = le16_to_cpu(ctx->staging.channel);
|
rxon_chnum = le16_to_cpu(ctx->staging.channel);
|
||||||
if (iwl_bt_statistics(priv)) {
|
stat_band24 =
|
||||||
stat_band24 = !!(((struct iwl_bt_notif_statistics *)
|
!!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
|
||||||
stat_resp)->flag &
|
stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure we accumulate data for just the associated channel
|
/* Make sure we accumulate data for just the associated channel
|
||||||
* (even if scanning). */
|
* (even if scanning). */
|
||||||
|
|
|
@ -66,8 +66,8 @@
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-commands.h"
|
#include "iwl-commands.h"
|
||||||
|
|
||||||
void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
|
void iwl_chain_noise_calibration(struct iwl_priv *priv);
|
||||||
void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp);
|
void iwl_sensitivity_calibration(struct iwl_priv *priv);
|
||||||
|
|
||||||
void iwl_init_sensitivity(struct iwl_priv *priv);
|
void iwl_init_sensitivity(struct iwl_priv *priv);
|
||||||
void iwl_reset_run_time_calib(struct iwl_priv *priv);
|
void iwl_reset_run_time_calib(struct iwl_priv *priv);
|
||||||
|
|
|
@ -39,10 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
|
||||||
int p = 0;
|
int p = 0;
|
||||||
u32 flag;
|
u32 flag;
|
||||||
|
|
||||||
if (iwl_bt_statistics(priv))
|
flag = le32_to_cpu(priv->statistics.flag);
|
||||||
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);
|
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
|
||||||
if (flag & UCODE_STATISTICS_CLEAR_MSK)
|
if (flag & UCODE_STATISTICS_CLEAR_MSK)
|
||||||
|
@ -88,43 +85,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
||||||
* the last statistics notification from uCode
|
* the last statistics notification from uCode
|
||||||
* might not reflect the current uCode activity
|
* might not reflect the current uCode activity
|
||||||
*/
|
*/
|
||||||
if (iwl_bt_statistics(priv)) {
|
ofdm = &priv->statistics.rx_ofdm;
|
||||||
ofdm = &priv->_agn.statistics_bt.rx.ofdm;
|
cck = &priv->statistics.rx_cck;
|
||||||
cck = &priv->_agn.statistics_bt.rx.cck;
|
general = &priv->statistics.rx_non_phy;
|
||||||
general = &priv->_agn.statistics_bt.rx.general.common;
|
ht = &priv->statistics.rx_ofdm_ht;
|
||||||
ht = &priv->_agn.statistics_bt.rx.ofdm_ht;
|
accum_ofdm = &priv->accum_stats.rx_ofdm;
|
||||||
accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm;
|
accum_cck = &priv->accum_stats.rx_cck;
|
||||||
accum_cck = &priv->_agn.accum_statistics_bt.rx.cck;
|
accum_general = &priv->accum_stats.rx_non_phy;
|
||||||
accum_general =
|
accum_ht = &priv->accum_stats.rx_ofdm_ht;
|
||||||
&priv->_agn.accum_statistics_bt.rx.general.common;
|
delta_ofdm = &priv->delta_stats.rx_ofdm;
|
||||||
accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht;
|
delta_cck = &priv->delta_stats.rx_cck;
|
||||||
delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm;
|
delta_general = &priv->delta_stats.rx_non_phy;
|
||||||
delta_cck = &priv->_agn.delta_statistics_bt.rx.cck;
|
delta_ht = &priv->delta_stats.rx_ofdm_ht;
|
||||||
delta_general =
|
max_ofdm = &priv->max_delta_stats.rx_ofdm;
|
||||||
&priv->_agn.delta_statistics_bt.rx.general.common;
|
max_cck = &priv->max_delta_stats.rx_cck;
|
||||||
delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht;
|
max_general = &priv->max_delta_stats.rx_non_phy;
|
||||||
max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm;
|
max_ht = &priv->max_delta_stats.rx_ofdm_ht;
|
||||||
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 += iwl_statistics_flag(priv, buf, bufsz);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
@ -534,17 +510,10 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
|
||||||
* the last statistics notification from uCode
|
* the last statistics notification from uCode
|
||||||
* might not reflect the current uCode activity
|
* might not reflect the current uCode activity
|
||||||
*/
|
*/
|
||||||
if (iwl_bt_statistics(priv)) {
|
tx = &priv->statistics.tx;
|
||||||
tx = &priv->_agn.statistics_bt.tx;
|
accum_tx = &priv->accum_stats.tx;
|
||||||
accum_tx = &priv->_agn.accum_statistics_bt.tx;
|
delta_tx = &priv->delta_stats.tx;
|
||||||
delta_tx = &priv->_agn.delta_statistics_bt.tx;
|
max_tx = &priv->max_delta_stats.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 += iwl_statistics_flag(priv, buf, bufsz);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
@ -734,33 +703,18 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
|
||||||
* the last statistics notification from uCode
|
* the last statistics notification from uCode
|
||||||
* might not reflect the current uCode activity
|
* might not reflect the current uCode activity
|
||||||
*/
|
*/
|
||||||
if (iwl_bt_statistics(priv)) {
|
general = &priv->statistics.common;
|
||||||
general = &priv->_agn.statistics_bt.general.common;
|
dbg = &priv->statistics.common.dbg;
|
||||||
dbg = &priv->_agn.statistics_bt.general.common.dbg;
|
div = &priv->statistics.common.div;
|
||||||
div = &priv->_agn.statistics_bt.general.common.div;
|
accum_general = &priv->accum_stats.common;
|
||||||
accum_general = &priv->_agn.accum_statistics_bt.general.common;
|
accum_dbg = &priv->accum_stats.common.dbg;
|
||||||
accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg;
|
accum_div = &priv->accum_stats.common.div;
|
||||||
accum_div = &priv->_agn.accum_statistics_bt.general.common.div;
|
delta_general = &priv->delta_stats.common;
|
||||||
delta_general = &priv->_agn.delta_statistics_bt.general.common;
|
max_general = &priv->max_delta_stats.common;
|
||||||
max_general = &priv->_agn.max_delta_bt.general.common;
|
delta_dbg = &priv->delta_stats.common.dbg;
|
||||||
delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg;
|
max_dbg = &priv->max_delta_stats.common.dbg;
|
||||||
max_dbg = &priv->_agn.max_delta_bt.general.common.dbg;
|
delta_div = &priv->delta_stats.common.div;
|
||||||
delta_div = &priv->_agn.delta_statistics_bt.general.common.div;
|
max_div = &priv->max_delta_stats.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 += iwl_statistics_flag(priv, buf, bufsz);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
|
@ -876,8 +830,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
|
||||||
* the last statistics notification from uCode
|
* the last statistics notification from uCode
|
||||||
* might not reflect the current uCode activity
|
* might not reflect the current uCode activity
|
||||||
*/
|
*/
|
||||||
bt = &priv->_agn.statistics_bt.general.activity;
|
bt = &priv->statistics.bt_activity;
|
||||||
accum_bt = &priv->_agn.accum_statistics_bt.general.activity;
|
accum_bt = &priv->accum_stats.bt_activity;
|
||||||
|
|
||||||
pos += iwl_statistics_flag(priv, buf, bufsz);
|
pos += iwl_statistics_flag(priv, buf, bufsz);
|
||||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
|
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");
|
||||||
|
@ -918,10 +872,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
|
||||||
|
|
||||||
pos += scnprintf(buf + pos, bufsz - pos,
|
pos += scnprintf(buf + pos, bufsz - pos,
|
||||||
"(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
|
"(rx)num_bt_kills:\t\t%u\t\t\t%u\n",
|
||||||
le32_to_cpu(priv->_agn.statistics_bt.rx.
|
le32_to_cpu(priv->statistics.num_bt_kills),
|
||||||
general.num_bt_kills),
|
priv->statistics.accum_num_bt_kills);
|
||||||
priv->_agn.accum_statistics_bt.rx.
|
|
||||||
general.num_bt_kills);
|
|
||||||
|
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of version 2 of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
|
||||||
*
|
|
||||||
* The full GNU General Public License is included in this distribution in the
|
|
||||||
* file called LICENSE.
|
|
||||||
*
|
|
||||||
* Contact Information:
|
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/pci.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/skbuff.h>
|
|
||||||
#include <linux/netdevice.h>
|
|
||||||
#include <linux/wireless.h>
|
|
||||||
#include <net/mac80211.h>
|
|
||||||
#include <linux/etherdevice.h>
|
|
||||||
#include <asm/unaligned.h>
|
|
||||||
|
|
||||||
#include "iwl-commands.h"
|
|
||||||
#include "iwl-dev.h"
|
|
||||||
#include "iwl-core.h"
|
|
||||||
#include "iwl-io.h"
|
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
|
|
||||||
/* Send led command */
|
|
||||||
static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
|
||||||
{
|
|
||||||
struct iwl_host_cmd cmd = {
|
|
||||||
.id = REPLY_LEDS_CMD,
|
|
||||||
.len = sizeof(struct iwl_led_cmd),
|
|
||||||
.data = led_cmd,
|
|
||||||
.flags = CMD_ASYNC,
|
|
||||||
.callback = NULL,
|
|
||||||
};
|
|
||||||
u32 reg;
|
|
||||||
|
|
||||||
reg = iwl_read32(priv, CSR_LED_REG);
|
|
||||||
if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
|
|
||||||
iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
|
|
||||||
|
|
||||||
return iwl_send_cmd(priv, &cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set led register off */
|
|
||||||
void iwlagn_led_enable(struct iwl_priv *priv)
|
|
||||||
{
|
|
||||||
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct iwl_led_ops iwlagn_led_ops = {
|
|
||||||
.cmd = iwl_send_led_cmd,
|
|
||||||
};
|
|
|
@ -1,33 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of version 2 of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
|
||||||
*
|
|
||||||
* The full GNU General Public License is included in this distribution in the
|
|
||||||
* file called LICENSE.
|
|
||||||
*
|
|
||||||
* Contact Information:
|
|
||||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
|
||||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
|
||||||
*
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __iwl_agn_led_h__
|
|
||||||
#define __iwl_agn_led_h__
|
|
||||||
|
|
||||||
extern const struct iwl_led_ops iwlagn_led_ops;
|
|
||||||
void iwlagn_led_enable(struct iwl_priv *priv);
|
|
||||||
|
|
||||||
#endif /* __iwl_agn_led_h__ */
|
|
|
@ -172,6 +172,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
|
||||||
|
|
||||||
static void iwlagn_set_tx_status(struct iwl_priv *priv,
|
static void iwlagn_set_tx_status(struct iwl_priv *priv,
|
||||||
struct ieee80211_tx_info *info,
|
struct ieee80211_tx_info *info,
|
||||||
|
struct iwl_rxon_context *ctx,
|
||||||
struct iwlagn_tx_resp *tx_resp,
|
struct iwlagn_tx_resp *tx_resp,
|
||||||
int txq_id, bool is_agg)
|
int txq_id, bool is_agg)
|
||||||
{
|
{
|
||||||
|
@ -186,6 +187,13 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv,
|
||||||
if (!iwl_is_tx_success(status))
|
if (!iwl_is_tx_success(status))
|
||||||
iwlagn_count_tx_err_status(priv, 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 "
|
IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
|
||||||
"0x%x retries %d\n",
|
"0x%x retries %d\n",
|
||||||
txq_id,
|
txq_id,
|
||||||
|
@ -242,15 +250,16 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
|
||||||
|
|
||||||
/* # frames attempted by Tx command */
|
/* # frames attempted by Tx command */
|
||||||
if (agg->frame_count == 1) {
|
if (agg->frame_count == 1) {
|
||||||
|
struct iwl_tx_info *txb;
|
||||||
|
|
||||||
/* Only one frame was attempted; no block-ack will arrive */
|
/* Only one frame was attempted; no block-ack will arrive */
|
||||||
idx = start_idx;
|
idx = start_idx;
|
||||||
|
|
||||||
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
|
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
|
||||||
agg->frame_count, agg->start_idx, idx);
|
agg->frame_count, agg->start_idx, idx);
|
||||||
iwlagn_set_tx_status(priv,
|
txb = &priv->txq[txq_id].txb[idx];
|
||||||
IEEE80211_SKB_CB(
|
iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb),
|
||||||
priv->txq[txq_id].txb[idx].skb),
|
txb->ctx, tx_resp, txq_id, true);
|
||||||
tx_resp, txq_id, true);
|
|
||||||
agg->wait_for_ba = 0;
|
agg->wait_for_ba = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Two or more frames were attempted; expect block-ack */
|
/* Two or more frames were attempted; expect block-ack */
|
||||||
|
@ -391,6 +400,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
||||||
struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
||||||
|
struct iwl_tx_info *txb;
|
||||||
u32 status = le16_to_cpu(tx_resp->status.status);
|
u32 status = le16_to_cpu(tx_resp->status.status);
|
||||||
int tid;
|
int tid;
|
||||||
int sta_id;
|
int sta_id;
|
||||||
|
@ -406,7 +416,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
txq->time_stamp = jiffies;
|
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));
|
memset(&info->status, 0, sizeof(info->status));
|
||||||
|
|
||||||
tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
|
tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
|
||||||
|
@ -450,12 +461,14 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
||||||
iwl_wake_queue(priv, txq);
|
iwl_wake_queue(priv, txq);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
|
||||||
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
|
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
|
||||||
|
|
||||||
if (priv->mac80211_registered &&
|
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);
|
iwl_wake_queue(priv, txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,8 +495,10 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
|
||||||
|
|
||||||
void iwlagn_setup_deferred_work(struct iwl_priv *priv)
|
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)
|
int iwlagn_hw_valid_rtc_data_addr(u32 addr)
|
||||||
|
@ -534,9 +549,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
||||||
void iwlagn_temperature(struct iwl_priv *priv)
|
void iwlagn_temperature(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
/* store temperature from correct statistics (in Celsius) */
|
/* store temperature from correct statistics (in Celsius) */
|
||||||
priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ?
|
priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
|
||||||
priv->_agn.statistics_bt.general.common.temperature :
|
|
||||||
priv->_agn.statistics.general.common.temperature);
|
|
||||||
iwl_tt_handler(priv);
|
iwl_tt_handler(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ enum {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
|
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_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
|
||||||
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
|
IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
|
||||||
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
|
IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "iwl-sta.h"
|
#include "iwl-sta.h"
|
||||||
#include "iwl-core.h"
|
#include "iwl-core.h"
|
||||||
#include "iwl-agn-calib.h"
|
#include "iwl-agn-calib.h"
|
||||||
|
#include "iwl-helpers.h"
|
||||||
|
|
||||||
static int iwlagn_disable_bss(struct iwl_priv *priv,
|
static int iwlagn_disable_bss(struct iwl_priv *priv,
|
||||||
struct iwl_rxon_context *ctx,
|
struct iwl_rxon_context *ctx,
|
||||||
|
@ -600,6 +601,18 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
priv->timestamp = bss_conf->timestamp;
|
priv->timestamp = bss_conf->timestamp;
|
||||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||||
} else {
|
} 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;
|
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,6 +428,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
|
||||||
int iwlagn_alive_notify(struct iwl_priv *priv)
|
int iwlagn_alive_notify(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
const struct queue_to_fifo_ac *queue_to_fifo;
|
const struct queue_to_fifo_ac *queue_to_fifo;
|
||||||
|
struct iwl_rxon_context *ctx;
|
||||||
u32 a;
|
u32 a;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i, chan;
|
int i, chan;
|
||||||
|
@ -501,6 +502,8 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
||||||
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
atomic_set(&priv->queue_stop_count[i], 0);
|
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 */
|
/* reset to 0 to enable all the queue first */
|
||||||
priv->txq_ctx_active_msk = 0;
|
priv->txq_ctx_active_msk = 0;
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
#include "iwl-sta.h"
|
#include "iwl-sta.h"
|
||||||
#include "iwl-agn-calib.h"
|
#include "iwl-agn-calib.h"
|
||||||
#include "iwl-agn.h"
|
#include "iwl-agn.h"
|
||||||
#include "iwl-agn-led.h"
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -254,6 +253,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
||||||
struct iwl_frame *frame;
|
struct iwl_frame *frame;
|
||||||
unsigned int frame_size;
|
unsigned int frame_size;
|
||||||
int rc;
|
int rc;
|
||||||
|
struct iwl_host_cmd cmd = {
|
||||||
|
.id = REPLY_TX_BEACON,
|
||||||
|
.flags = CMD_SIZE_HUGE,
|
||||||
|
};
|
||||||
|
|
||||||
frame = iwl_get_free_frame(priv);
|
frame = iwl_get_free_frame(priv);
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
|
@ -269,8 +272,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
|
cmd.len = frame_size;
|
||||||
&frame->u.cmd[0]);
|
cmd.data = &frame->u.cmd[0];
|
||||||
|
|
||||||
|
rc = iwl_send_cmd_sync(priv, &cmd);
|
||||||
|
|
||||||
iwl_free_frame(priv, frame);
|
iwl_free_frame(priv, frame);
|
||||||
|
|
||||||
|
@ -395,7 +400,9 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
|
||||||
return -EINVAL;
|
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))
|
if (unlikely(addr & ~IWL_TX_DMA_MASK))
|
||||||
IWL_ERR(priv, "Unaligned address = %llx\n",
|
IWL_ERR(priv, "Unaligned address = %llx\n",
|
||||||
(unsigned long long)addr);
|
(unsigned long long)addr);
|
||||||
|
@ -719,7 +726,10 @@ static void iwl_rx_handle(struct iwl_priv *priv)
|
||||||
/* If an RXB doesn't have a Rx queue slot associated with it,
|
/* If an RXB doesn't have a Rx queue slot associated with it,
|
||||||
* then a bug has been introduced in the queue refilling
|
* then a bug has been introduced in the queue refilling
|
||||||
* routines -- catch it here */
|
* routines -- catch it here */
|
||||||
BUG_ON(rxb == NULL);
|
if (WARN_ON(rxb == NULL)) {
|
||||||
|
i = (i + 1) & RX_QUEUE_MASK;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
rxq->queue[i] = NULL;
|
rxq->queue[i] = NULL;
|
||||||
|
|
||||||
|
@ -1481,7 +1491,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||||
le32_to_cpup((__le32 *)tlv_data);
|
le32_to_cpup((__le32 *)tlv_data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
IWL_WARN(priv, "unknown TLV: %d\n", tlv_type);
|
IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1705,10 +1715,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||||
else
|
else
|
||||||
priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||||
|
|
||||||
if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS ||
|
|
||||||
(priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics))
|
|
||||||
priv->bt_statistics = true;
|
|
||||||
|
|
||||||
/* Copy images into buffers for card's bus-master reads ... */
|
/* Copy images into buffers for card's bus-master reads ... */
|
||||||
|
|
||||||
/* Runtime instructions (first block of data in file) */
|
/* Runtime instructions (first block of data in file) */
|
||||||
|
@ -2626,17 +2632,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->start_calib) {
|
if (priv->start_calib) {
|
||||||
if (iwl_bt_statistics(priv)) {
|
iwl_chain_noise_calibration(priv);
|
||||||
iwl_chain_noise_calibration(priv,
|
iwl_sensitivity_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&priv->mutex);
|
mutex_unlock(&priv->mutex);
|
||||||
|
@ -2828,7 +2825,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
|
||||||
|
|
||||||
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
||||||
|
|
||||||
if (!priv->cfg->base_params->broken_powersave)
|
|
||||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
||||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||||
|
|
||||||
|
@ -3732,6 +3728,28 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
|
||||||
7, 6, 5, 4,
|
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)
|
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
int err = 0, i;
|
int err = 0, i;
|
||||||
|
|
|
@ -173,8 +173,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv);
|
||||||
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
|
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
|
||||||
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
|
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
|
||||||
void iwlagn_dev_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 */
|
/* rx */
|
||||||
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
|
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
|
||||||
|
@ -222,6 +220,7 @@ static inline u32 iwl_tx_status_to_mac80211(u32 status)
|
||||||
case TX_STATUS_DIRECT_DONE:
|
case TX_STATUS_DIRECT_DONE:
|
||||||
return IEEE80211_TX_STAT_ACK;
|
return IEEE80211_TX_STAT_ACK;
|
||||||
case TX_STATUS_FAIL_DEST_PS:
|
case TX_STATUS_FAIL_DEST_PS:
|
||||||
|
case TX_STATUS_FAIL_PASSIVE_NO_RX:
|
||||||
return IEEE80211_TX_STAT_TX_FILTERED;
|
return IEEE80211_TX_STAT_TX_FILTERED;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2535,53 +2535,6 @@ struct rate_histogram {
|
||||||
|
|
||||||
/* statistics command response */
|
/* 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 {
|
struct statistics_dbg {
|
||||||
__le32 burst_check;
|
__le32 burst_check;
|
||||||
__le32 burst_count;
|
__le32 burst_count;
|
||||||
|
@ -2589,23 +2542,6 @@ struct statistics_dbg {
|
||||||
__le32 reserved[3];
|
__le32 reserved[3];
|
||||||
} __packed;
|
} __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 {
|
struct statistics_rx_phy {
|
||||||
__le32 ina_cnt;
|
__le32 ina_cnt;
|
||||||
__le32 fina_cnt;
|
__le32 fina_cnt;
|
||||||
|
|
|
@ -67,30 +67,6 @@ u32 iwl_debug_level;
|
||||||
|
|
||||||
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
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_40_MHZ 150 /* Mbps */
|
||||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||||
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
|
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
|
||||||
|
@ -965,12 +941,10 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
|
||||||
IWL_ERR(priv, "Loaded firmware version: %s\n",
|
IWL_ERR(priv, "Loaded firmware version: %s\n",
|
||||||
priv->hw->wiphy->fw_version);
|
priv->hw->wiphy->fw_version);
|
||||||
|
|
||||||
priv->cfg->ops->lib->dump_nic_error_log(priv);
|
iwl_dump_nic_error_log(priv);
|
||||||
if (priv->cfg->ops->lib->dump_csr)
|
iwl_dump_csr(priv);
|
||||||
priv->cfg->ops->lib->dump_csr(priv);
|
iwl_dump_fh(priv, NULL, false);
|
||||||
if (priv->cfg->ops->lib->dump_fh)
|
iwl_dump_nic_event_log(priv, false, NULL, false);
|
||||||
priv->cfg->ops->lib->dump_fh(priv, NULL, false);
|
|
||||||
priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
|
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||||
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
|
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
|
||||||
iwl_print_rx_config_cmd(priv,
|
iwl_print_rx_config_cmd(priv,
|
||||||
|
@ -1051,7 +1025,6 @@ int iwl_apm_init(struct iwl_priv *priv)
|
||||||
/*
|
/*
|
||||||
* Enable HAP INTA (interrupt from management bus) to
|
* Enable HAP INTA (interrupt from management bus) to
|
||||||
* wake device's PCI Express link L1a -> L0s
|
* 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,
|
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||||
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
|
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
|
||||||
|
@ -1064,7 +1037,6 @@ int iwl_apm_init(struct iwl_priv *priv)
|
||||||
* If not (unlikely), enable L0S, so there is at least some
|
* If not (unlikely), enable L0S, so there is at least some
|
||||||
* power savings, even without L1.
|
* power savings, even without L1.
|
||||||
*/
|
*/
|
||||||
if (priv->cfg->base_params->set_l0s) {
|
|
||||||
lctl = iwl_pcie_link_ctl(priv);
|
lctl = iwl_pcie_link_ctl(priv);
|
||||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
|
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
|
||||||
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
|
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
|
||||||
|
@ -1078,7 +1050,6 @@ int iwl_apm_init(struct iwl_priv *priv)
|
||||||
CSR_GIO_REG_VAL_L0S_ENABLED);
|
CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||||
IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
|
IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure analog phase-lock-loop before activating to D0A */
|
/* Configure analog phase-lock-loop before activating to D0A */
|
||||||
if (priv->cfg->base_params->pll_cfg_val)
|
if (priv->cfg->base_params->pll_cfg_val)
|
||||||
|
@ -1777,6 +1748,15 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
|
||||||
mutex_lock(&priv->mutex);
|
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;
|
interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
|
||||||
|
|
||||||
if (!(interface_modes & BIT(newtype))) {
|
if (!(interface_modes & BIT(newtype))) {
|
||||||
|
@ -1804,6 +1784,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
/* success */
|
/* success */
|
||||||
iwl_teardown_interface(priv, vif, true);
|
iwl_teardown_interface(priv, vif, true);
|
||||||
vif->type = newtype;
|
vif->type = newtype;
|
||||||
|
vif->p2p = newp2p;
|
||||||
err = iwl_setup_interface(priv, ctx);
|
err = iwl_setup_interface(priv, ctx);
|
||||||
WARN_ON(err);
|
WARN_ON(err);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -139,12 +139,6 @@ struct iwl_temp_ops {
|
||||||
void (*temperature)(struct iwl_priv *priv);
|
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 {
|
struct iwl_lib_ops {
|
||||||
/* set hw dependent parameters */
|
/* set hw dependent parameters */
|
||||||
int (*set_hw_params)(struct iwl_priv *priv);
|
int (*set_hw_params)(struct iwl_priv *priv);
|
||||||
|
@ -171,12 +165,6 @@ struct iwl_lib_ops {
|
||||||
void (*cancel_deferred_work)(struct iwl_priv *priv);
|
void (*cancel_deferred_work)(struct iwl_priv *priv);
|
||||||
/* check validity of rtc data address */
|
/* check validity of rtc data address */
|
||||||
int (*is_valid_rtc_data_addr)(u32 addr);
|
int (*is_valid_rtc_data_addr)(u32 addr);
|
||||||
|
|
||||||
int (*dump_nic_event_log)(struct iwl_priv *priv,
|
|
||||||
bool full_log, char **buf, bool display);
|
|
||||||
void (*dump_nic_error_log)(struct iwl_priv *priv);
|
|
||||||
void (*dump_csr)(struct iwl_priv *priv);
|
|
||||||
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
|
|
||||||
int (*set_channel_switch)(struct iwl_priv *priv,
|
int (*set_channel_switch)(struct iwl_priv *priv,
|
||||||
struct ieee80211_channel_switch *ch_switch);
|
struct ieee80211_channel_switch *ch_switch);
|
||||||
/* power management */
|
/* power management */
|
||||||
|
@ -196,13 +184,6 @@ struct iwl_lib_ops {
|
||||||
void (*dev_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;
|
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 */
|
/* NIC specific ops */
|
||||||
|
@ -210,23 +191,11 @@ struct iwl_nic_ops {
|
||||||
void (*additional_nic_config)(struct iwl_priv *priv);
|
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 {
|
struct iwl_ops {
|
||||||
const struct iwl_lib_ops *lib;
|
const struct iwl_lib_ops *lib;
|
||||||
const struct iwl_hcmd_ops *hcmd;
|
const struct iwl_hcmd_ops *hcmd;
|
||||||
const struct iwl_hcmd_utils_ops *utils;
|
const struct iwl_hcmd_utils_ops *utils;
|
||||||
const struct iwl_led_ops *led;
|
|
||||||
const struct iwl_nic_ops *nic;
|
const struct iwl_nic_ops *nic;
|
||||||
const struct iwl_legacy_ops *legacy;
|
|
||||||
const struct ieee80211_ops *ieee80211_ops;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iwl_mod_params {
|
struct iwl_mod_params {
|
||||||
|
@ -256,13 +225,6 @@ struct iwl_mod_params {
|
||||||
* @wd_timeout: TX queues watchdog timeout
|
* @wd_timeout: TX queues watchdog timeout
|
||||||
* @temperature_kelvin: temperature report by uCode in kelvin
|
* @temperature_kelvin: temperature report by uCode in kelvin
|
||||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
* @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
|
* @shadow_reg_enable: HW shadhow register bit
|
||||||
*/
|
*/
|
||||||
struct iwl_base_params {
|
struct iwl_base_params {
|
||||||
|
@ -271,12 +233,10 @@ struct iwl_base_params {
|
||||||
int num_of_ampdu_queues;/* def: HW dependent */
|
int num_of_ampdu_queues;/* def: HW dependent */
|
||||||
/* for iwl_apm_init() */
|
/* for iwl_apm_init() */
|
||||||
u32 pll_cfg_val;
|
u32 pll_cfg_val;
|
||||||
bool set_l0s;
|
|
||||||
|
|
||||||
const u16 max_ll_items;
|
const u16 max_ll_items;
|
||||||
const bool shadow_ram_support;
|
const bool shadow_ram_support;
|
||||||
u16 led_compensation;
|
u16 led_compensation;
|
||||||
const bool broken_powersave;
|
|
||||||
int chain_noise_num_beacons;
|
int chain_noise_num_beacons;
|
||||||
bool adv_thermal_throttle;
|
bool adv_thermal_throttle;
|
||||||
bool support_ct_kill_exit;
|
bool support_ct_kill_exit;
|
||||||
|
@ -286,17 +246,12 @@ struct iwl_base_params {
|
||||||
unsigned int wd_timeout;
|
unsigned int wd_timeout;
|
||||||
bool temperature_kelvin;
|
bool temperature_kelvin;
|
||||||
u32 max_event_log_size;
|
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 shadow_reg_enable;
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* @advanced_bt_coexist: support advanced bt coexist
|
* @advanced_bt_coexist: support advanced bt coexist
|
||||||
* @bt_init_traffic_load: specify initial bt traffic load
|
* @bt_init_traffic_load: specify initial bt traffic load
|
||||||
* @bt_prio_boost: default bt priority boost value
|
* @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
|
* @agg_time_limit: maximum number of uSec in aggregation
|
||||||
* @ampdu_factor: Maximum A-MPDU length factor
|
* @ampdu_factor: Maximum A-MPDU length factor
|
||||||
* @ampdu_density: Minimum A-MPDU spacing
|
* @ampdu_density: Minimum A-MPDU spacing
|
||||||
|
@ -306,7 +261,6 @@ struct iwl_bt_params {
|
||||||
bool advanced_bt_coexist;
|
bool advanced_bt_coexist;
|
||||||
u8 bt_init_traffic_load;
|
u8 bt_init_traffic_load;
|
||||||
u8 bt_prio_boost;
|
u8 bt_prio_boost;
|
||||||
const bool bt_statistics;
|
|
||||||
u16 agg_time_limit;
|
u16 agg_time_limit;
|
||||||
u8 ampdu_factor;
|
u8 ampdu_factor;
|
||||||
u8 ampdu_density;
|
u8 ampdu_density;
|
||||||
|
@ -337,6 +291,7 @@ struct iwl_ht_params {
|
||||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||||
* @iq_invert: I/Q inversion
|
* @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
|
* We enable the driver to be backward compatible wrt API version. The
|
||||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||||
|
@ -387,13 +342,13 @@ struct iwl_cfg {
|
||||||
const bool rx_with_siso_diversity;
|
const bool rx_with_siso_diversity;
|
||||||
const bool internal_wimax_coex;
|
const bool internal_wimax_coex;
|
||||||
const bool iq_invert;
|
const bool iq_invert;
|
||||||
|
const bool disable_otp_refresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
* L i b *
|
* L i b *
|
||||||
***************************/
|
***************************/
|
||||||
|
|
||||||
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);
|
|
||||||
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||||
const struct ieee80211_tx_queue_params *params);
|
const struct ieee80211_tx_queue_params *params);
|
||||||
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
||||||
|
@ -598,6 +553,8 @@ extern const struct dev_pm_ops iwl_pm_ops;
|
||||||
void iwl_dump_nic_error_log(struct iwl_priv *priv);
|
void iwl_dump_nic_error_log(struct iwl_priv *priv);
|
||||||
int iwl_dump_nic_event_log(struct iwl_priv *priv,
|
int iwl_dump_nic_event_log(struct iwl_priv *priv,
|
||||||
bool full_log, char **buf, bool display);
|
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
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||||
struct iwl_rxon_context *ctx);
|
struct iwl_rxon_context *ctx);
|
||||||
|
@ -709,11 +666,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
|
||||||
priv->cfg->bt_params->advanced_bt_coexist;
|
priv->cfg->bt_params->advanced_bt_coexist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool iwl_bt_statistics(struct iwl_priv *priv)
|
|
||||||
{
|
|
||||||
return priv->bt_statistics;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern bool bt_coex_active;
|
extern bool bt_coex_active;
|
||||||
extern bool bt_siso_mode;
|
extern bool bt_siso_mode;
|
||||||
|
|
||||||
|
|
|
@ -437,8 +437,7 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file,
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
ssize_t ret = -ENOMEM;
|
ssize_t ret = -ENOMEM;
|
||||||
|
|
||||||
ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
|
ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
|
||||||
priv, true, &buf, true);
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
@ -462,8 +461,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
|
||||||
if (sscanf(buf, "%d", &event_log_flag) != 1)
|
if (sscanf(buf, "%d", &event_log_flag) != 1)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (event_log_flag == 1)
|
if (event_log_flag == 1)
|
||||||
priv->cfg->ops->lib->dump_nic_event_log(priv, true,
|
iwl_dump_nic_event_log(priv, true, NULL, false);
|
||||||
NULL, false);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -1268,8 +1266,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,
|
||||||
if (sscanf(buf, "%d", &csr) != 1)
|
if (sscanf(buf, "%d", &csr) != 1)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (priv->cfg->ops->lib->dump_csr)
|
iwl_dump_csr(priv);
|
||||||
priv->cfg->ops->lib->dump_csr(priv);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -1359,14 +1356,12 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
ssize_t ret = -EFAULT;
|
ssize_t ret = -EFAULT;
|
||||||
|
|
||||||
if (priv->cfg->ops->lib->dump_fh) {
|
ret = pos = iwl_dump_fh(priv, &buf, true);
|
||||||
ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
ret = simple_read_from_buffer(user_buf,
|
ret = simple_read_from_buffer(user_buf,
|
||||||
count, ppos, buf, pos);
|
count, ppos, buf, pos);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1728,11 +1723,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||||
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
|
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
|
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(qos, dir_data, 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(sleep_level_override, dir_data,
|
|
||||||
S_IWUSR | S_IRUSR);
|
|
||||||
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
|
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
|
||||||
}
|
|
||||||
DEBUGFS_ADD_FILE(thermal_throttling, 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(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
|
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
|
||||||
|
@ -1755,13 +1747,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||||
DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
|
DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
|
||||||
DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
|
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);
|
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);
|
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);
|
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(ucode_bt_stats, dir_debug, S_IRUSR);
|
||||||
DEBUGFS_ADD_FILE(reply_tx_error, 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_flags, dir_debug, S_IWUSR);
|
||||||
|
@ -1769,15 +1757,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||||
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
|
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
|
||||||
if (iwl_advanced_bt_coexist(priv))
|
if (iwl_advanced_bt_coexist(priv))
|
||||||
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
|
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,
|
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
|
||||||
&priv->disable_sens_cal);
|
&priv->disable_sens_cal);
|
||||||
if (priv->cfg->base_params->chain_noise_calib_by_driver)
|
|
||||||
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
||||||
&priv->disable_chain_noise_cal);
|
&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);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -543,13 +543,12 @@ enum iwl_ucode_tlv_type {
|
||||||
* enum iwl_ucode_tlv_flag - ucode API flags
|
* enum iwl_ucode_tlv_flag - ucode API flags
|
||||||
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
|
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
|
||||||
* was a separate TLV but moved here to save space.
|
* was a separate TLV but moved here to save space.
|
||||||
* @IWL_UCODE_TLV_FLAGS_BTSTATS: This uCode image uses BT statistics, which
|
* @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved
|
||||||
* may be true even if the device doesn't have BT.
|
|
||||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||||
*/
|
*/
|
||||||
enum iwl_ucode_tlv_flag {
|
enum iwl_ucode_tlv_flag {
|
||||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||||
IWL_UCODE_TLV_FLAGS_BTSTATS = BIT(1),
|
IWL_UCODE_TLV_FLAGS_RESERVED_1 = BIT(1),
|
||||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1170,6 +1169,8 @@ struct iwl_rxon_context {
|
||||||
bool enabled, is_40mhz;
|
bool enabled, is_40mhz;
|
||||||
u8 extension_chan_offset;
|
u8 extension_chan_offset;
|
||||||
} ht;
|
} ht;
|
||||||
|
|
||||||
|
bool last_tx_rejected;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum iwl_scan_type {
|
enum iwl_scan_type {
|
||||||
|
@ -1354,6 +1355,31 @@ struct iwl_priv {
|
||||||
/* Last Rx'd beacon timestamp */
|
/* Last Rx'd beacon timestamp */
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
__le32 flag;
|
||||||
|
struct statistics_general_common common;
|
||||||
|
struct statistics_rx_non_phy rx_non_phy;
|
||||||
|
struct statistics_rx_phy rx_ofdm;
|
||||||
|
struct statistics_rx_ht_phy rx_ofdm_ht;
|
||||||
|
struct statistics_rx_phy rx_cck;
|
||||||
|
struct statistics_tx tx;
|
||||||
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
|
struct statistics_bt_activity bt_activity;
|
||||||
|
__le32 num_bt_kills, accum_num_bt_kills;
|
||||||
|
#endif
|
||||||
|
} statistics;
|
||||||
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
|
struct {
|
||||||
|
struct statistics_general_common common;
|
||||||
|
struct statistics_rx_non_phy rx_non_phy;
|
||||||
|
struct statistics_rx_phy rx_ofdm;
|
||||||
|
struct statistics_rx_ht_phy rx_ofdm_ht;
|
||||||
|
struct statistics_rx_phy rx_cck;
|
||||||
|
struct statistics_tx tx;
|
||||||
|
struct statistics_bt_activity bt_activity;
|
||||||
|
} accum_stats, delta_stats, max_delta_stats;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* INT ICT Table */
|
/* INT ICT Table */
|
||||||
__le32 *ict_tbl;
|
__le32 *ict_tbl;
|
||||||
|
@ -1385,19 +1411,9 @@ struct iwl_priv {
|
||||||
u8 phy_calib_chain_noise_reset_cmd;
|
u8 phy_calib_chain_noise_reset_cmd;
|
||||||
u8 phy_calib_chain_noise_gain_cmd;
|
u8 phy_calib_chain_noise_gain_cmd;
|
||||||
|
|
||||||
struct iwl_notif_statistics statistics;
|
|
||||||
struct iwl_bt_notif_statistics statistics_bt;
|
|
||||||
/* counts reply_tx error */
|
/* counts reply_tx error */
|
||||||
struct reply_tx_error_statistics reply_tx_stats;
|
struct reply_tx_error_statistics reply_tx_stats;
|
||||||
struct reply_agg_tx_error_statistics reply_agg_tx_stats;
|
struct reply_agg_tx_error_statistics reply_agg_tx_stats;
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
|
||||||
struct iwl_notif_statistics accum_statistics;
|
|
||||||
struct iwl_notif_statistics delta_statistics;
|
|
||||||
struct iwl_notif_statistics max_delta;
|
|
||||||
struct iwl_bt_notif_statistics accum_statistics_bt;
|
|
||||||
struct iwl_bt_notif_statistics delta_statistics_bt;
|
|
||||||
struct iwl_bt_notif_statistics max_delta_bt;
|
|
||||||
#endif
|
|
||||||
/* notification wait support */
|
/* notification wait support */
|
||||||
struct list_head notif_waits;
|
struct list_head notif_waits;
|
||||||
spinlock_t notif_wait_lock;
|
spinlock_t notif_wait_lock;
|
||||||
|
@ -1422,7 +1438,6 @@ struct iwl_priv {
|
||||||
bool bt_ch_announce;
|
bool bt_ch_announce;
|
||||||
bool bt_full_concurrent;
|
bool bt_full_concurrent;
|
||||||
bool bt_ant_couple_ok;
|
bool bt_ant_couple_ok;
|
||||||
bool bt_statistics;
|
|
||||||
__le32 kill_ack_mask;
|
__le32 kill_ack_mask;
|
||||||
__le32 kill_cts_mask;
|
__le32 kill_cts_mask;
|
||||||
__le16 bt_valid;
|
__le16 bt_valid;
|
||||||
|
@ -1487,7 +1502,6 @@ struct iwl_priv {
|
||||||
struct work_struct txpower_work;
|
struct work_struct txpower_work;
|
||||||
u32 disable_sens_cal;
|
u32 disable_sens_cal;
|
||||||
u32 disable_chain_noise_cal;
|
u32 disable_chain_noise_cal;
|
||||||
u32 disable_tx_power_cal;
|
|
||||||
struct work_struct run_time_calib_work;
|
struct work_struct run_time_calib_work;
|
||||||
struct timer_list statistics_periodic;
|
struct timer_list statistics_periodic;
|
||||||
struct timer_list ucode_trace;
|
struct timer_list ucode_trace;
|
||||||
|
|
|
@ -215,12 +215,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
|
||||||
return nvm_type;
|
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)
|
static int iwl_init_otp_access(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -309,7 +309,6 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv);
|
||||||
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
|
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
|
||||||
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
|
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
|
||||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
|
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);
|
int iwl_init_channel_map(struct iwl_priv *priv);
|
||||||
void iwl_free_channel_map(struct iwl_priv *priv);
|
void iwl_free_channel_map(struct iwl_priv *priv);
|
||||||
const struct iwl_channel_info *iwl_get_channel_info(
|
const struct iwl_channel_info *iwl_get_channel_info(
|
||||||
|
|
|
@ -77,14 +77,14 @@
|
||||||
/**
|
/**
|
||||||
* Keep-Warm (KW) buffer base address.
|
* 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
|
* 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,
|
* 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.
|
* 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)
|
* 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
|
* automatically invokes keep-warm accesses when normal accesses might not
|
||||||
* be sufficient to maintain fast DRAM response.
|
* be sufficient to maintain fast DRAM response.
|
||||||
*
|
*
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
/**
|
/**
|
||||||
* TFD Circular Buffers Base (CBBC) addresses
|
* 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)
|
* circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
|
||||||
* (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04
|
* (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
|
* 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)
|
* 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.
|
* (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
|
* 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
|
* 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
|
* Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
|
||||||
* mapping between RBDs and RBs.
|
* mapping between RBDs and RBs.
|
||||||
*
|
*
|
||||||
* Driver must allocate host DRAM memory for the following, and set the
|
* 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
|
* 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
|
||||||
* entries (although any power of 2, up to 4096, is selectable by driver).
|
* 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
|
* Driver sets physical address [35:8] of base of RBD circular buffer
|
||||||
* into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
|
* 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
|
* (RBs) have been filled, via a "write pointer", actually the index of
|
||||||
* the RB's corresponding RBD within the circular buffer. Driver sets
|
* the RB's corresponding RBD within the circular buffer. Driver sets
|
||||||
* physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
|
* 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
|
* 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
|
* 31-12: Not used by driver
|
||||||
* 11- 0: Index of last filled Rx buffer descriptor
|
* 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,
|
* 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.
|
* FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
|
||||||
*
|
*
|
||||||
* This "write" index corresponds to the *next* RBD that the driver will make
|
* 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
|
* 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
|
* wrap back to 0 at the end of the circular buffer (but don't wrap before
|
||||||
* "read" index has advanced past 1! See below).
|
* "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,
|
* 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
|
* 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
|
* 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
|
* 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
|
* driver may process the RB pointed to by RBD 0. Depending on volume of
|
||||||
* traffic, there may be many RBs to process.
|
* 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
|
* 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"
|
* 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
|
* 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)
|
* 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,
|
* 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.
|
* 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)
|
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
|
||||||
|
|
||||||
/* Find Control/Status reg for given Tx DMA/FIFO channel */
|
/* Find Control/Status reg for given Tx DMA/FIFO channel */
|
||||||
#define FH49_TCSR_CHNL_NUM (7)
|
|
||||||
#define FH50_TCSR_CHNL_NUM (8)
|
#define FH50_TCSR_CHNL_NUM (8)
|
||||||
|
|
||||||
/* TCSR: tx_config register values */
|
/* TCSR: tx_config register values */
|
||||||
|
@ -424,7 +423,6 @@
|
||||||
#define RX_LOW_WATERMARK 8
|
#define RX_LOW_WATERMARK 8
|
||||||
|
|
||||||
/* Size of one Rx buffer in host DRAM */
|
/* 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_4K (4 * 1024)
|
||||||
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
|
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
|
||||||
|
|
||||||
|
@ -443,7 +441,7 @@ struct iwl_rb_status {
|
||||||
__le16 closed_fr_num;
|
__le16 closed_fr_num;
|
||||||
__le16 finished_rb_num;
|
__le16 finished_rb_num;
|
||||||
__le16 finished_fr_nam;
|
__le16 finished_fr_nam;
|
||||||
__le32 __unused; /* 3945 only */
|
__le32 __unused;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -143,10 +143,12 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||||
{
|
{
|
||||||
int ret;
|
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. */
|
/* 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 */
|
/* Assign a generic callback if one is not provided */
|
||||||
if (!cmd->callback)
|
if (!cmd->callback)
|
||||||
|
@ -169,10 +171,12 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||||
int cmd_idx;
|
int cmd_idx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lockdep_assert_held(&priv->mutex);
|
if (WARN_ON(cmd->flags & CMD_ASYNC))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* A synchronous command can not have a callback set. */
|
/* A synchronous command can not have a callback set. */
|
||||||
BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback);
|
if (WARN_ON(cmd->callback))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
|
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
|
||||||
get_cmd_string(cmd->id));
|
get_cmd_string(cmd->id));
|
||||||
|
|
|
@ -131,6 +131,19 @@ static inline void iwl_stop_queue(struct iwl_priv *priv,
|
||||||
ieee80211_stop_queue(priv->hw, ac);
|
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_stop_queue DO_NOT_USE_ieee80211_stop_queue
|
||||||
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
|
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,16 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
|
||||||
{ .throughput = 300 * 1024 - 1, .blink_time = 50 },
|
{ .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
|
* 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,
|
* Led blink rate analysis showed an average deviation of 20% on 5000 series
|
||||||
* 5% on 4965 HW and 20% on 5000 series and up.
|
* and up.
|
||||||
* Need to compensate on the led on/off time per HW according to the deviation
|
* Need to compensate on the led on/off time per HW according to the deviation
|
||||||
* to achieve the desired led frequency
|
* to achieve the desired led frequency
|
||||||
* The calculation is: (100-averageDeviation)/100 * blinkTime
|
* The calculation is: (100-averageDeviation)/100 * blinkTime
|
||||||
|
@ -84,6 +90,24 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv,
|
||||||
return (u8)((time * compensation) >> 6);
|
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 */
|
/* Set led pattern command */
|
||||||
static int iwl_led_cmd(struct iwl_priv *priv,
|
static int iwl_led_cmd(struct iwl_priv *priv,
|
||||||
unsigned long on,
|
unsigned long on,
|
||||||
|
@ -108,7 +132,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
|
||||||
led_cmd.off = iwl_blink_compensation(priv, off,
|
led_cmd.off = iwl_blink_compensation(priv, off,
|
||||||
priv->cfg->base_params->led_compensation);
|
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) {
|
if (!ret) {
|
||||||
priv->blink_on = on;
|
priv->blink_on = on;
|
||||||
priv->blink_off = off;
|
priv->blink_off = off;
|
||||||
|
|
|
@ -50,6 +50,7 @@ enum iwl_led_mode {
|
||||||
IWL_LED_BLINK,
|
IWL_LED_BLINK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void iwlagn_led_enable(struct iwl_priv *priv);
|
||||||
void iwl_leds_init(struct iwl_priv *priv);
|
void iwl_leds_init(struct iwl_priv *priv);
|
||||||
void iwl_leds_exit(struct iwl_priv *priv);
|
void iwl_leds_exit(struct iwl_priv *priv);
|
||||||
|
|
||||||
|
|
|
@ -188,8 +188,9 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
||||||
table = range_0;
|
table = range_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
|
if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM))
|
||||||
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
|
else
|
||||||
*cmd = table[lvl].cmd;
|
*cmd = table[lvl].cmd;
|
||||||
|
|
||||||
if (period == 0) {
|
if (period == 0) {
|
||||||
|
@ -354,16 +355,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
||||||
|
|
||||||
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
||||||
|
|
||||||
if (priv->cfg->base_params->broken_powersave)
|
if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||||
iwl_power_sleep_cam_cmd(priv, cmd);
|
|
||||||
else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
|
||||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
||||||
else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
|
else if (iwl_tt_is_low_power_state(priv)) {
|
||||||
priv->cfg->ops->lib->tt_ops.tt_power_mode &&
|
|
||||||
priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
|
|
||||||
/* in thermal throttling low power state */
|
/* in thermal throttling low power state */
|
||||||
iwl_static_sleep_cmd(priv, cmd,
|
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)
|
} else if (!enabled)
|
||||||
iwl_power_sleep_cam_cmd(priv, cmd);
|
iwl_power_sleep_cam_cmd(priv, cmd);
|
||||||
else if (priv->power_data.debug_sleep_level_override >= 0)
|
else if (priv->power_data.debug_sleep_level_override >= 0)
|
||||||
|
|
|
@ -107,17 +107,7 @@
|
||||||
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
|
* device. A queue maps to only one (selectable by driver) Tx DMA channel,
|
||||||
* but one DMA channel may take input from several queues.
|
* but one DMA channel may take input from several queues.
|
||||||
*
|
*
|
||||||
* Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows
|
* Tx DMA FIFOs have dedicated purposes.
|
||||||
* (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)
|
|
||||||
*
|
*
|
||||||
* For 5000 series and up, they are used differently
|
* For 5000 series and up, they are used differently
|
||||||
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
|
* (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
|
||||||
|
@ -151,7 +141,7 @@
|
||||||
* Tx completion may end up being out-of-order).
|
* Tx completion may end up being out-of-order).
|
||||||
*
|
*
|
||||||
* The driver must maintain the queue's Byte Count table in host DRAM
|
* 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.
|
* This mode does not support fragmentation.
|
||||||
*
|
*
|
||||||
* 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
|
* 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
|
||||||
|
@ -164,7 +154,7 @@
|
||||||
*
|
*
|
||||||
* Driver controls scheduler operation via 3 means:
|
* Driver controls scheduler operation via 3 means:
|
||||||
* 1) Scheduler registers
|
* 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
|
* 3) Shared data in host DRAM
|
||||||
*
|
*
|
||||||
* Initialization:
|
* Initialization:
|
||||||
|
|
|
@ -390,21 +390,16 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
||||||
* the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
|
* the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
|
||||||
* operation state.
|
* 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;
|
int actual_delta, expected_delta, ba_timeout_delta;
|
||||||
struct statistics_tx *cur, *old;
|
struct statistics_tx *old;
|
||||||
|
|
||||||
if (priv->_agn.agg_tids_count)
|
if (priv->_agn.agg_tids_count)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (iwl_bt_statistics(priv)) {
|
old = &priv->statistics.tx;
|
||||||
cur = &pkt->u.stats_bt.tx;
|
|
||||||
old = &priv->_agn.statistics_bt.tx;
|
|
||||||
} else {
|
|
||||||
cur = &pkt->u.stats.tx;
|
|
||||||
old = &priv->_agn.statistics.tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
|
actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
|
||||||
le32_to_cpu(old->actual_ack_cnt);
|
le32_to_cpu(old->actual_ack_cnt);
|
||||||
|
@ -430,10 +425,10 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt
|
||||||
* DEBUG is not, these will just compile out.
|
* DEBUG is not, these will just compile out.
|
||||||
*/
|
*/
|
||||||
IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
|
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,
|
IWL_DEBUG_RADIO(priv,
|
||||||
"ack_or_ba_timeout_collision delta %d\n",
|
"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
|
#endif
|
||||||
|
|
||||||
if (ba_timeout_delta >= BA_TIMEOUT_MAX)
|
if (ba_timeout_delta >= BA_TIMEOUT_MAX)
|
||||||
|
@ -450,7 +445,9 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt
|
||||||
* to improve the throughput.
|
* to improve the throughput.
|
||||||
*/
|
*/
|
||||||
static bool iwl_good_plcp_health(struct iwl_priv *priv,
|
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 delta;
|
||||||
int threshold = priv->cfg->base_params->plcp_delta_threshold;
|
int threshold = priv->cfg->base_params->plcp_delta_threshold;
|
||||||
|
@ -460,29 +457,12 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iwl_bt_statistics(priv)) {
|
delta = le32_to_cpu(cur_ofdm->plcp_err) -
|
||||||
struct statistics_rx_bt *cur, *old;
|
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;
|
/* Can be negative if firmware reset statistics */
|
||||||
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 */
|
|
||||||
if (delta <= 0)
|
if (delta <= 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -497,44 +477,36 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_recover_from_statistics(struct iwl_priv *priv,
|
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;
|
const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
|
||||||
unsigned int msecs;
|
unsigned int msecs;
|
||||||
unsigned long stamp;
|
|
||||||
|
|
||||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stamp = jiffies;
|
|
||||||
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
|
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
|
||||||
|
|
||||||
/* Only gather statistics and update time stamp when not associated */
|
/* Only gather statistics and update time stamp when not associated */
|
||||||
if (!iwl_is_any_associated(priv))
|
if (!iwl_is_any_associated(priv))
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
/* Do not check/recover when do not have enough statistics data */
|
/* Do not check/recover when do not have enough statistics data */
|
||||||
if (msecs < 99)
|
if (msecs < 99)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) {
|
if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) {
|
||||||
IWL_ERR(priv, "low ack count detected, restart firmware\n");
|
IWL_ERR(priv, "low ack count detected, restart firmware\n");
|
||||||
if (!iwl_force_reset(priv, IWL_FW_RESET, false))
|
if (!iwl_force_reset(priv, IWL_FW_RESET, false))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs))
|
if (mod_params->plcp_check &&
|
||||||
|
!iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
|
||||||
iwl_force_reset(priv, IWL_RF_RESET, false);
|
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
|
/* Calculate noise level, based on measurements during network silence just
|
||||||
|
@ -548,10 +520,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
|
||||||
int bcn_silence_a, bcn_silence_b, bcn_silence_c;
|
int bcn_silence_a, bcn_silence_b, bcn_silence_c;
|
||||||
int last_rx_noise;
|
int last_rx_noise;
|
||||||
|
|
||||||
if (iwl_bt_statistics(priv))
|
rx_info = &priv->statistics.rx_non_phy;
|
||||||
rx_info = &(priv->_agn.statistics_bt.rx.general.common);
|
|
||||||
else
|
|
||||||
rx_info = &(priv->_agn.statistics.rx.general);
|
|
||||||
bcn_silence_a =
|
bcn_silence_a =
|
||||||
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
|
le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
|
||||||
bcn_silence_b =
|
bcn_silence_b =
|
||||||
|
@ -583,105 +553,153 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
|
||||||
last_rx_noise);
|
last_rx_noise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
/*
|
/*
|
||||||
* based on the assumption of all statistics counter are in DWORD
|
* based on the assumption of all statistics counter are in DWORD
|
||||||
* FIXME: This function is for debugging, do not deal with
|
* FIXME: This function is for debugging, do not deal with
|
||||||
* the case of counters roll-over.
|
* the case of counters roll-over.
|
||||||
*/
|
*/
|
||||||
static void iwl_accumulative_statistics(struct iwl_priv *priv,
|
static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta,
|
||||||
__le32 *stats)
|
__le32 *max_delta, __le32 *accum, int size)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
int i;
|
||||||
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)) {
|
for (i = 0;
|
||||||
prev_stats = (__le32 *)&priv->_agn.statistics_bt;
|
i < size / sizeof(__le32);
|
||||||
accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
|
i++, prev++, cur++, delta++, max_delta++, accum++) {
|
||||||
size = sizeof(struct iwl_bt_notif_statistics);
|
if (le32_to_cpu(*cur) > le32_to_cpu(*prev)) {
|
||||||
general = &priv->_agn.statistics_bt.general.common;
|
*delta = cpu_to_le32(
|
||||||
accum_general = &priv->_agn.accum_statistics_bt.general.common;
|
le32_to_cpu(*cur) - le32_to_cpu(*prev));
|
||||||
tx = &priv->_agn.statistics_bt.tx;
|
le32_add_cpu(accum, le32_to_cpu(*delta));
|
||||||
accum_tx = &priv->_agn.accum_statistics_bt.tx;
|
if (le32_to_cpu(*delta) > le32_to_cpu(*max_delta))
|
||||||
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)
|
|
||||||
*max_delta = *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,
|
static void iwl_rx_statistics(struct iwl_priv *priv,
|
||||||
struct iwl_rx_mem_buffer *rxb)
|
struct iwl_rx_mem_buffer *rxb)
|
||||||
{
|
{
|
||||||
|
unsigned long stamp = jiffies;
|
||||||
const int reg_recalib_period = 60;
|
const int reg_recalib_period = 60;
|
||||||
int change;
|
int change;
|
||||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
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;
|
||||||
|
|
||||||
if (iwl_bt_statistics(priv)) {
|
len -= sizeof(struct iwl_cmd_header); /* skip header */
|
||||||
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 !=
|
IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
|
||||||
pkt->u.stats_bt.general.common.temperature) ||
|
len);
|
||||||
((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);
|
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;
|
||||||
|
|
||||||
|
#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 {
|
} else {
|
||||||
IWL_DEBUG_RX(priv,
|
WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
|
||||||
"Statistics notification received (%d vs %d).\n",
|
len, sizeof(struct iwl_bt_notif_statistics),
|
||||||
(int)sizeof(struct iwl_notif_statistics),
|
sizeof(struct iwl_notif_statistics));
|
||||||
le32_to_cpu(pkt->len_n_flags) &
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
set_bit(STATUS_STATISTICS, &priv->status);
|
||||||
|
|
||||||
|
@ -708,18 +726,12 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,
|
||||||
|
|
||||||
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
memset(&priv->_agn.accum_statistics, 0,
|
memset(&priv->accum_stats, 0,
|
||||||
sizeof(struct iwl_notif_statistics));
|
sizeof(priv->accum_stats));
|
||||||
memset(&priv->_agn.delta_statistics, 0,
|
memset(&priv->delta_stats, 0,
|
||||||
sizeof(struct iwl_notif_statistics));
|
sizeof(priv->delta_stats));
|
||||||
memset(&priv->_agn.max_delta, 0,
|
memset(&priv->max_delta_stats, 0,
|
||||||
sizeof(struct iwl_notif_statistics));
|
sizeof(priv->max_delta_stats));
|
||||||
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));
|
|
||||||
#endif
|
#endif
|
||||||
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
|
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
|
||||||
}
|
}
|
||||||
|
@ -873,6 +885,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
__le16 fc = hdr->frame_control;
|
__le16 fc = hdr->frame_control;
|
||||||
|
struct iwl_rxon_context *ctx;
|
||||||
|
|
||||||
/* We only process data packets if the interface is open */
|
/* We only process data packets if the interface is open */
|
||||||
if (unlikely(!priv->is_open)) {
|
if (unlikely(!priv->is_open)) {
|
||||||
|
@ -895,6 +908,26 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||||
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
|
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
|
||||||
|
|
||||||
iwl_update_stats(priv, false, fc, 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));
|
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||||
|
|
||||||
ieee80211_rx(priv->hw, skb);
|
ieee80211_rx(priv->hw, skb);
|
||||||
|
|
|
@ -494,7 +494,8 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||||
|
|
||||||
priv->num_stations--;
|
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);
|
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||||
|
|
||||||
|
@ -679,7 +680,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||||
|
|
||||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||||
priv->num_stations--;
|
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);
|
kfree(priv->stations[i].lq);
|
||||||
priv->stations[i].lq = NULL;
|
priv->stations[i].lq = NULL;
|
||||||
}
|
}
|
||||||
|
@ -775,7 +777,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||||
|
|
||||||
iwl_dump_lq_cmd(priv, lq);
|
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))
|
if (is_lq_table_valid(priv, ctx, lq))
|
||||||
ret = iwl_send_cmd(priv, &cmd);
|
ret = iwl_send_cmd(priv, &cmd);
|
||||||
|
|
|
@ -232,7 +232,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
|
||||||
* reclaiming packets (on 'tx done IRQ), if free space become > high mark,
|
* reclaiming packets (on 'tx done IRQ), if free space become > high mark,
|
||||||
* Tx queue resumed.
|
* Tx queue resumed.
|
||||||
*
|
*
|
||||||
* See more detailed info in iwl-4965-hw.h.
|
|
||||||
***************************************************/
|
***************************************************/
|
||||||
|
|
||||||
int iwl_queue_space(const struct iwl_queue *q)
|
int iwl_queue_space(const struct iwl_queue *q)
|
||||||
|
@ -264,11 +263,13 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
|
||||||
|
|
||||||
/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
|
/* count must be power-of-two size, otherwise iwl_queue_inc_wrap
|
||||||
* and iwl_queue_dec_wrap are broken. */
|
* 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
|
/* slots_num must be power-of-two size, otherwise
|
||||||
* get_cmd_index is broken. */
|
* 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;
|
q->low_mark = q->n_window / 4;
|
||||||
if (q->low_mark < 4)
|
if (q->low_mark < 4)
|
||||||
|
@ -385,7 +386,9 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
||||||
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
|
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
|
||||||
|
|
||||||
/* Initialize queue's high/low-water marks, and head/tail indexes */
|
/* 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 */
|
/* Tell device where to find queue */
|
||||||
priv->cfg->ops->lib->txq_init(priv, txq);
|
priv->cfg->ops->lib->txq_init(priv, txq);
|
||||||
|
@ -447,14 +450,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||||
cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
|
cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
|
||||||
fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
|
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
|
* the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
|
||||||
* we will need to increase the size of the TFD entries
|
* we will need to increase the size of the TFD entries
|
||||||
* Also, check to see if command buffer should not exceed the size
|
* Also, check to see if command buffer should not exceed the size
|
||||||
* of device_cmd and max_cmd_size. */
|
* of device_cmd and max_cmd_size.
|
||||||
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
|
*/
|
||||||
!(cmd->flags & CMD_SIZE_HUGE));
|
if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
|
||||||
BUG_ON(fix_size > IWL_MAX_CMD_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)) {
|
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
|
||||||
IWL_WARN(priv, "Not sending command - %s KILL\n",
|
IWL_WARN(priv, "Not sending command - %s KILL\n",
|
||||||
|
@ -462,16 +470,21 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||||
return -EIO;
|
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);
|
spin_lock_irqsave(&priv->hcmd_lock, flags);
|
||||||
|
|
||||||
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
|
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
|
||||||
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
|
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
|
||||||
|
|
||||||
IWL_ERR(priv, "No space in command queue\n");
|
IWL_ERR(priv, "No space in command queue\n");
|
||||||
if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
|
is_ct_kill = iwl_check_for_ct_kill(priv);
|
||||||
is_ct_kill =
|
|
||||||
priv->cfg->ops->lib->tt_ops.ct_kill_check(priv);
|
|
||||||
}
|
|
||||||
if (!is_ct_kill) {
|
if (!is_ct_kill) {
|
||||||
IWL_ERR(priv, "Restarting adapter due to queue full\n");
|
IWL_ERR(priv, "Restarting adapter due to queue full\n");
|
||||||
iwlagn_fw_error(priv, false);
|
iwlagn_fw_error(priv, false);
|
||||||
|
|
|
@ -115,7 +115,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv,
|
||||||
SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);
|
SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);
|
||||||
|
|
||||||
/* Clear RD responder bit */
|
/* Clear RD responder bit */
|
||||||
RESETHT_EXTCAP_RDG(ht_ext_cap);
|
ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;
|
||||||
|
|
||||||
ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info);
|
ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info);
|
||||||
ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
|
ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap);
|
||||||
|
@ -242,9 +242,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
|
||||||
*
|
*
|
||||||
* Handling includes changing the header fields into CPU format.
|
* Handling includes changing the header fields into CPU format.
|
||||||
*/
|
*/
|
||||||
int mwifiex_ret_11n_cfg(struct mwifiex_private *priv,
|
int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
|
||||||
struct host_cmd_ds_command *resp,
|
|
||||||
void *data_buf)
|
|
||||||
{
|
{
|
||||||
struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL;
|
struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL;
|
||||||
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
|
struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
|
||||||
|
@ -298,8 +296,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
|
||||||
* - Setting AMSDU control parameters (for SET only)
|
* - Setting AMSDU control parameters (for SET only)
|
||||||
* - Ensuring correct endian-ness
|
* - Ensuring correct endian-ness
|
||||||
*/
|
*/
|
||||||
int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,
|
int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
|
||||||
struct host_cmd_ds_command *cmd,
|
|
||||||
int cmd_action, void *data_buf)
|
int cmd_action, void *data_buf)
|
||||||
{
|
{
|
||||||
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
|
struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
|
||||||
|
@ -331,8 +328,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,
|
||||||
*
|
*
|
||||||
* Handling includes changing the header fields into CPU format.
|
* Handling includes changing the header fields into CPU format.
|
||||||
*/
|
*/
|
||||||
int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,
|
int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
|
||||||
struct host_cmd_ds_command *resp,
|
|
||||||
void *data_buf)
|
void *data_buf)
|
||||||
{
|
{
|
||||||
struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL;
|
struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL;
|
||||||
|
@ -357,8 +353,7 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,
|
||||||
* - Setting HT Tx capability and HT Tx information fields
|
* - Setting HT Tx capability and HT Tx information fields
|
||||||
* - Ensuring correct endian-ness
|
* - Ensuring correct endian-ness
|
||||||
*/
|
*/
|
||||||
int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
|
int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
|
||||||
struct host_cmd_ds_command *cmd,
|
|
||||||
u16 cmd_action, void *data_buf)
|
u16 cmd_action, void *data_buf)
|
||||||
{
|
{
|
||||||
struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
|
struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
|
||||||
|
@ -541,11 +536,8 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv,
|
||||||
else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K)
|
else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K)
|
||||||
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)
|
if (curr_tx_buf_size != tx_buf)
|
||||||
mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
|
mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
|
||||||
HostCmd_ACT_GEN_SET, 0,
|
HostCmd_ACT_GEN_SET, 0, &tx_buf);
|
||||||
NULL, &tx_buf);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -583,8 +575,6 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
|
||||||
list_del(&tx_ba_tsr_tbl->list);
|
list_del(&tx_ba_tsr_tbl->list);
|
||||||
|
|
||||||
kfree(tx_ba_tsr_tbl);
|
kfree(tx_ba_tsr_tbl);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -663,8 +653,6 @@ void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv,
|
||||||
list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
|
list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);
|
||||||
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -694,8 +682,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
|
||||||
memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);
|
memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);
|
||||||
|
|
||||||
/* We don't wait for the response of this command */
|
/* We don't wait for the response of this command */
|
||||||
ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ,
|
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ,
|
||||||
0, 0, NULL, &add_ba_req);
|
0, 0, &add_ba_req);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -722,8 +710,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
|
||||||
memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
|
memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
|
||||||
|
|
||||||
/* We don't wait for the response of this command */
|
/* We don't wait for the response of this command */
|
||||||
ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA,
|
ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA,
|
||||||
HostCmd_ACT_GEN_SET, 0, NULL, &delba);
|
HostCmd_ACT_GEN_SET, 0, &delba);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue