mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
@@ -188,7 +188,7 @@ config BT_MRVL
|
||||
The core driver to support Marvell Bluetooth devices.
|
||||
|
||||
This driver is required if you want to support
|
||||
Marvell Bluetooth devices, such as 8688.
|
||||
Marvell Bluetooth devices, such as 8688/8787.
|
||||
|
||||
Say Y here to compile Marvell Bluetooth driver
|
||||
into the kernel or say M to compile it as module.
|
||||
@@ -201,7 +201,7 @@ config BT_MRVL_SDIO
|
||||
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
||||
|
||||
This driver is required if you want to use Marvell Bluetooth
|
||||
devices with SDIO interface. Currently only SD8688 chipset is
|
||||
devices with SDIO interface. Currently SD8688/SD8787 chipsets are
|
||||
supported.
|
||||
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
|
||||
@@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
||||
count -= size;
|
||||
}
|
||||
|
||||
kfree(send_buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(send_buf);
|
||||
return err;
|
||||
|
||||
@@ -49,15 +49,59 @@
|
||||
static u8 user_rmmod;
|
||||
static u8 sdio_ireg;
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
|
||||
.cfg = 0x03,
|
||||
.host_int_mask = 0x04,
|
||||
.host_intstatus = 0x05,
|
||||
.card_status = 0x20,
|
||||
.sq_read_base_addr_a0 = 0x10,
|
||||
.sq_read_base_addr_a1 = 0x11,
|
||||
.card_fw_status0 = 0x40,
|
||||
.card_fw_status1 = 0x41,
|
||||
.card_rx_len = 0x42,
|
||||
.card_rx_unit = 0x43,
|
||||
.io_port_0 = 0x00,
|
||||
.io_port_1 = 0x01,
|
||||
.io_port_2 = 0x02,
|
||||
};
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x02,
|
||||
.host_intstatus = 0x03,
|
||||
.card_status = 0x30,
|
||||
.sq_read_base_addr_a0 = 0x40,
|
||||
.sq_read_base_addr_a1 = 0x41,
|
||||
.card_revision = 0x5c,
|
||||
.card_fw_status0 = 0x60,
|
||||
.card_fw_status1 = 0x61,
|
||||
.card_rx_len = 0x62,
|
||||
.card_rx_unit = 0x63,
|
||||
.io_port_0 = 0x78,
|
||||
.io_port_1 = 0x79,
|
||||
.io_port_2 = 0x7a,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
|
||||
.helper = "sd8688_helper.bin",
|
||||
.firmware = "sd8688.bin",
|
||||
.reg = &btmrvl_reg_8688,
|
||||
.sd_blksz_fw_dl = 64,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sd8787_uapsta.bin",
|
||||
.reg = &btmrvl_reg_8787,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
};
|
||||
|
||||
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
||||
/* Marvell SD8688 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
|
||||
/* Marvell SD8787 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
@@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret);
|
||||
reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
|
||||
if (!ret)
|
||||
card->rx_unit = reg;
|
||||
|
||||
@@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
|
||||
|
||||
*dat = 0;
|
||||
|
||||
fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
|
||||
fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
|
||||
fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
@@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret);
|
||||
reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
|
||||
if (!ret)
|
||||
*dat = (u16) reg << card->rx_unit;
|
||||
|
||||
@@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
|
||||
{
|
||||
int ret;
|
||||
|
||||
sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret);
|
||||
sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("Unable to enable the host interrupt!");
|
||||
ret = -EIO;
|
||||
@@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
|
||||
u8 host_int_mask;
|
||||
int ret;
|
||||
|
||||
host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret);
|
||||
host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
host_int_mask &= ~mask;
|
||||
|
||||
sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret);
|
||||
sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Unable to disable the host interrupt!");
|
||||
return -EIO;
|
||||
@@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
|
||||
int ret;
|
||||
|
||||
for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
|
||||
status = sdio_readb(card->func, CARD_STATUS_REG, &ret);
|
||||
status = sdio_readb(card->func, card->reg->card_status, &ret);
|
||||
if (ret)
|
||||
goto failed;
|
||||
if ((status & bits) == bits)
|
||||
@@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
u8 base0, base1;
|
||||
void *tmpfwbuf = NULL;
|
||||
u8 *fwbuf;
|
||||
u16 len;
|
||||
u16 len, blksz_dl = card->sd_blksz_fw_dl;
|
||||
int txlen = 0, tx_blocks = 0, count = 0;
|
||||
|
||||
ret = request_firmware(&fw_firmware, card->firmware,
|
||||
@@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
|
||||
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
|
||||
base0 = sdio_readb(card->func,
|
||||
SQ_READ_BASE_ADDRESS_A0_REG, &ret);
|
||||
card->reg->sq_read_base_addr_a0, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("BASE0 register read failed:"
|
||||
" base0 = 0x%04X(%d)."
|
||||
@@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
goto done;
|
||||
}
|
||||
base1 = sdio_readb(card->func,
|
||||
SQ_READ_BASE_ADDRESS_A1_REG, &ret);
|
||||
card->reg->sq_read_base_addr_a1, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("BASE1 register read failed:"
|
||||
" base1 = 0x%04X(%d)."
|
||||
@@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
if (firmwarelen - offset < txlen)
|
||||
txlen = firmwarelen - offset;
|
||||
|
||||
tx_blocks =
|
||||
(txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
|
||||
tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
|
||||
|
||||
memcpy(fwbuf, &firmware[offset], txlen);
|
||||
}
|
||||
|
||||
ret = sdio_writesb(card->func, card->ioport, fwbuf,
|
||||
tx_blocks * SDIO_BLOCK_SIZE);
|
||||
tx_blocks * blksz_dl);
|
||||
|
||||
if (ret < 0) {
|
||||
BT_ERR("FW download, writesb(%d) failed @%d",
|
||||
count, offset);
|
||||
sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
|
||||
&ret);
|
||||
sdio_writeb(card->func, HOST_CMD53_FIN,
|
||||
card->reg->cfg, &ret);
|
||||
if (ret)
|
||||
BT_ERR("writeb failed (CFG)");
|
||||
}
|
||||
@@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||
|
||||
priv = card->priv;
|
||||
|
||||
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
|
||||
ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_readb: read int status register failed");
|
||||
return;
|
||||
@@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||
|
||||
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
|
||||
UP_LD_HOST_INT_STATUS),
|
||||
HOST_INTSTATUS_REG, &ret);
|
||||
card->reg->host_intstatus, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_writeb: clear int status register failed");
|
||||
return;
|
||||
@@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||
goto release_irq;
|
||||
}
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_0_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_0, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
@@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||
|
||||
card->ioport = reg;
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_1_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_1, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
@@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||
|
||||
card->ioport |= (reg << 8);
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_2_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_2, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
@@ -815,6 +858,8 @@ exit:
|
||||
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 fws0;
|
||||
int pollnum = MAX_POLL_TRIES;
|
||||
|
||||
if (!card || !card->func) {
|
||||
BT_ERR("card or function is NULL!");
|
||||
@@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = btmrvl_sdio_download_helper(card);
|
||||
/* Check if other function driver is downloading the firmware */
|
||||
fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("Failed to download helper!");
|
||||
BT_ERR("Failed to read FW downloading status!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
if (fws0) {
|
||||
BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
|
||||
|
||||
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
||||
BT_ERR("Failed to download firmware!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
/* Give other function more time to download the firmware */
|
||||
pollnum *= 10;
|
||||
} else {
|
||||
if (card->helper) {
|
||||
ret = btmrvl_sdio_download_helper(card);
|
||||
if (ret) {
|
||||
BT_ERR("Failed to download helper!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
||||
BT_ERR("Failed to download firmware!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) {
|
||||
if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
|
||||
BT_ERR("FW failed to be active in time!");
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
@@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
|
||||
|
||||
sdio_claim_host(card->func);
|
||||
|
||||
sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret);
|
||||
sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
|
||||
|
||||
sdio_release_host(card->func);
|
||||
|
||||
@@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
|
||||
if (id->driver_data) {
|
||||
struct btmrvl_sdio_device *data = (void *) id->driver_data;
|
||||
card->helper = data->helper;
|
||||
card->helper = data->helper;
|
||||
card->firmware = data->firmware;
|
||||
card->reg = data->reg;
|
||||
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||
@@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||
|
||||
@@ -47,44 +47,46 @@
|
||||
/* Max retry number of CMD53 write */
|
||||
#define MAX_WRITE_IOMEM_RETRY 2
|
||||
|
||||
/* Host Control Registers */
|
||||
#define IO_PORT_0_REG 0x00
|
||||
#define IO_PORT_1_REG 0x01
|
||||
#define IO_PORT_2_REG 0x02
|
||||
/* register bitmasks */
|
||||
#define HOST_POWER_UP BIT(1)
|
||||
#define HOST_CMD53_FIN BIT(2)
|
||||
|
||||
#define CONFIG_REG 0x03
|
||||
#define HOST_POWER_UP BIT(1)
|
||||
#define HOST_CMD53_FIN BIT(2)
|
||||
#define HIM_DISABLE 0xff
|
||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||
|
||||
#define HOST_INT_MASK_REG 0x04
|
||||
#define HIM_DISABLE 0xff
|
||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
||||
|
||||
#define HOST_INTSTATUS_REG 0x05
|
||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
||||
#define DN_LD_CARD_RDY BIT(0)
|
||||
#define CARD_IO_READY BIT(3)
|
||||
|
||||
/* Card Control Registers */
|
||||
#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
|
||||
#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
|
||||
#define FIRMWARE_READY 0xfedc
|
||||
|
||||
#define CARD_STATUS_REG 0x20
|
||||
#define DN_LD_CARD_RDY BIT(0)
|
||||
#define CARD_IO_READY BIT(3)
|
||||
|
||||
#define CARD_FW_STATUS0_REG 0x40
|
||||
#define CARD_FW_STATUS1_REG 0x41
|
||||
#define FIRMWARE_READY 0xfedc
|
||||
|
||||
#define CARD_RX_LEN_REG 0x42
|
||||
#define CARD_RX_UNIT_REG 0x43
|
||||
|
||||
struct btmrvl_sdio_card_reg {
|
||||
u8 cfg;
|
||||
u8 host_int_mask;
|
||||
u8 host_intstatus;
|
||||
u8 card_status;
|
||||
u8 sq_read_base_addr_a0;
|
||||
u8 sq_read_base_addr_a1;
|
||||
u8 card_revision;
|
||||
u8 card_fw_status0;
|
||||
u8 card_fw_status1;
|
||||
u8 card_rx_len;
|
||||
u8 card_rx_unit;
|
||||
u8 io_port_0;
|
||||
u8 io_port_1;
|
||||
u8 io_port_2;
|
||||
};
|
||||
|
||||
struct btmrvl_sdio_card {
|
||||
struct sdio_func *func;
|
||||
u32 ioport;
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
u16 sd_blksz_fw_dl;
|
||||
u8 rx_unit;
|
||||
struct btmrvl_private *priv;
|
||||
};
|
||||
@@ -92,6 +94,8 @@ struct btmrvl_sdio_card {
|
||||
struct btmrvl_sdio_device {
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
u16 sd_blksz_fw_dl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
|
||||
/* Recv data */
|
||||
static int ath_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
|
||||
int ret;
|
||||
|
||||
ret = hci_recv_stream_fragment(hu->hdev, data, count);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Frame Reassembly Failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
|
||||
/* Recv data */
|
||||
static int h4_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
|
||||
int ret;
|
||||
|
||||
ret = hci_recv_stream_fragment(hu->hdev, data, count);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Frame Reassembly Failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
||||
*/
|
||||
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
||||
{
|
||||
int ret;
|
||||
struct hci_uart *hu = (void *)tty->disc_data;
|
||||
|
||||
if (!hu || tty != hu->tty)
|
||||
@@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
|
||||
return;
|
||||
|
||||
spin_lock(&hu->rx_lock);
|
||||
hu->proto->recv(hu, (void *) data, count);
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
ret = hu->proto->recv(hu, (void *) data, count);
|
||||
if (ret > 0)
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
spin_unlock(&hu->rx_lock);
|
||||
|
||||
tty_unthrottle(tty);
|
||||
|
||||
@@ -123,14 +123,7 @@ struct ath_ops {
|
||||
};
|
||||
|
||||
struct ath_common;
|
||||
|
||||
struct ath_bus_ops {
|
||||
enum ath_bus_type ath_bus_type;
|
||||
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||
void (*bt_coex_prep)(struct ath_common *common);
|
||||
void (*extn_synch_en)(struct ath_common *common);
|
||||
};
|
||||
struct ath_bus_ops;
|
||||
|
||||
struct ath_common {
|
||||
void *ah;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <ar231x_platform.h>
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
@@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
||||
{
|
||||
struct ath5k_softc *sc = ah->ah_sc;
|
||||
struct platform_device *pdev = to_platform_device(sc->dev);
|
||||
struct ar231x_board_config *bcfg = pdev->dev.platform_data;
|
||||
u8 *cfg_mac;
|
||||
|
||||
if (to_platform_device(sc->dev)->id == 0)
|
||||
cfg_mac = bcfg->config->wlan0_mac;
|
||||
else
|
||||
cfg_mac = bcfg->config->wlan1_mac;
|
||||
|
||||
memcpy(mac, cfg_mac, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ath_bus_ops ath_ahb_bus_ops = {
|
||||
.ath_bus_type = ATH_AHB,
|
||||
.read_cachesize = ath5k_ahb_read_cachesize,
|
||||
.eeprom_read = ath5k_ahb_eeprom_read,
|
||||
.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
|
||||
};
|
||||
|
||||
/*Initialization*/
|
||||
@@ -142,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
else
|
||||
reg |= AR5K_AR5312_ENABLE_WLAN1;
|
||||
__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
|
||||
|
||||
/*
|
||||
* On a dual-band AR5312, the multiband radio is only
|
||||
* used as pass-through. Disable 2 GHz support in the
|
||||
* driver for it
|
||||
*/
|
||||
if (to_platform_device(sc->dev)->id == 0 &&
|
||||
(bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
|
||||
(BD_WLAN1|BD_WLAN0))
|
||||
__set_bit(ATH_STAT_2G_DISABLED, sc->status);
|
||||
}
|
||||
|
||||
ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
|
||||
|
||||
@@ -224,8 +224,7 @@
|
||||
|
||||
/* SIFS */
|
||||
#define AR5K_INIT_SIFS_TURBO 6
|
||||
/* XXX: 8 from initvals 10 from standard */
|
||||
#define AR5K_INIT_SIFS_DEFAULT_BG 8
|
||||
#define AR5K_INIT_SIFS_DEFAULT_BG 10
|
||||
#define AR5K_INIT_SIFS_DEFAULT_A 16
|
||||
#define AR5K_INIT_SIFS_HALF_RATE 32
|
||||
#define AR5K_INIT_SIFS_QUARTER_RATE 64
|
||||
@@ -453,12 +452,10 @@ struct ath5k_tx_status {
|
||||
u16 ts_seqnum;
|
||||
u16 ts_tstamp;
|
||||
u8 ts_status;
|
||||
u8 ts_rate[4];
|
||||
u8 ts_retry[4];
|
||||
u8 ts_final_idx;
|
||||
u8 ts_final_retry;
|
||||
s8 ts_rssi;
|
||||
u8 ts_shortretry;
|
||||
u8 ts_longretry;
|
||||
u8 ts_virtcol;
|
||||
u8 ts_antenna;
|
||||
};
|
||||
@@ -875,6 +872,19 @@ enum ath5k_int {
|
||||
AR5K_INT_QTRIG = 0x40000000, /* Non common */
|
||||
AR5K_INT_GLOBAL = 0x80000000,
|
||||
|
||||
AR5K_INT_TX_ALL = AR5K_INT_TXOK
|
||||
| AR5K_INT_TXDESC
|
||||
| AR5K_INT_TXERR
|
||||
| AR5K_INT_TXEOL
|
||||
| AR5K_INT_TXURN,
|
||||
|
||||
AR5K_INT_RX_ALL = AR5K_INT_RXOK
|
||||
| AR5K_INT_RXDESC
|
||||
| AR5K_INT_RXERR
|
||||
| AR5K_INT_RXNOFRM
|
||||
| AR5K_INT_RXEOL
|
||||
| AR5K_INT_RXORN,
|
||||
|
||||
AR5K_INT_COMMON = AR5K_INT_RXOK
|
||||
| AR5K_INT_RXDESC
|
||||
| AR5K_INT_RXERR
|
||||
@@ -1058,6 +1068,7 @@ struct ath5k_hw {
|
||||
u8 ah_coverage_class;
|
||||
bool ah_ack_bitrate_high;
|
||||
u8 ah_bwmode;
|
||||
bool ah_short_slot;
|
||||
|
||||
/* Antenna Control */
|
||||
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
|
||||
@@ -1144,6 +1155,13 @@ struct ath5k_hw {
|
||||
struct ath5k_rx_status *);
|
||||
};
|
||||
|
||||
struct ath_bus_ops {
|
||||
enum ath_bus_type ath_bus_type;
|
||||
void (*read_cachesize)(struct ath_common *common, int *csz);
|
||||
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
||||
int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac);
|
||||
};
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
@@ -1227,13 +1245,12 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
|
||||
/* EEPROM access functions */
|
||||
int ath5k_eeprom_init(struct ath5k_hw *ah);
|
||||
void ath5k_eeprom_detach(struct ath5k_hw *ah);
|
||||
int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
|
||||
|
||||
|
||||
/* Protocol Control Unit Functions */
|
||||
/* Helpers */
|
||||
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
|
||||
int len, struct ieee80211_rate *rate);
|
||||
int len, struct ieee80211_rate *rate, bool shortpre);
|
||||
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
|
||||
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
|
||||
|
||||
@@ -313,12 +313,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
|
||||
__clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
|
||||
__clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
|
||||
}
|
||||
|
||||
/* Crypto settings */
|
||||
common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
|
||||
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
|
||||
|
||||
if (srev >= AR5K_SREV_AR5212_V4 &&
|
||||
(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
|
||||
(ee->ee_version < AR5K_EEPROM_VERSION_5_0 ||
|
||||
!AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
|
||||
common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
|
||||
|
||||
|
||||
@@ -1443,6 +1443,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_set_current_imask(struct ath5k_softc *sc)
|
||||
{
|
||||
enum ath5k_int imask = sc->imask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sc->irqlock, flags);
|
||||
if (sc->rx_pending)
|
||||
imask &= ~AR5K_INT_RX_ALL;
|
||||
if (sc->tx_pending)
|
||||
imask &= ~AR5K_INT_TX_ALL;
|
||||
ath5k_hw_set_imr(sc->ah, imask);
|
||||
spin_unlock_irqrestore(&sc->irqlock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
@@ -1506,6 +1521,8 @@ next:
|
||||
} while (ath5k_rxbuf_setup(sc, bf) == 0);
|
||||
unlock:
|
||||
spin_unlock(&sc->rxbuflock);
|
||||
sc->rx_pending = false;
|
||||
ath5k_set_current_imask(sc);
|
||||
}
|
||||
|
||||
|
||||
@@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||
struct ath5k_txq *txq, struct ath5k_tx_status *ts)
|
||||
{
|
||||
struct ieee80211_tx_info *info;
|
||||
u8 tries[3];
|
||||
int i;
|
||||
|
||||
sc->stats.tx_all_count++;
|
||||
sc->stats.tx_bytes_count += skb->len;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
tries[0] = info->status.rates[0].count;
|
||||
tries[1] = info->status.rates[1].count;
|
||||
tries[2] = info->status.rates[2].count;
|
||||
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
for (i = 0; i < ts->ts_final_idx; i++) {
|
||||
struct ieee80211_tx_rate *r =
|
||||
&info->status.rates[i];
|
||||
|
||||
if (ts->ts_rate[i]) {
|
||||
r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
|
||||
r->count = ts->ts_retry[i];
|
||||
} else {
|
||||
r->idx = -1;
|
||||
r->count = 0;
|
||||
}
|
||||
r->count = tries[i];
|
||||
}
|
||||
|
||||
/* count the successful attempt as well */
|
||||
info->status.rates[ts->ts_final_idx].count++;
|
||||
info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
|
||||
info->status.rates[ts->ts_final_idx + 1].idx = -1;
|
||||
|
||||
if (unlikely(ts->ts_status)) {
|
||||
sc->stats.ack_fail++;
|
||||
@@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ts->ts_rssi;
|
||||
|
||||
/* count the successful attempt as well */
|
||||
info->status.rates[ts->ts_final_idx].count++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
|
||||
for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
|
||||
if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
|
||||
ath5k_tx_processq(sc, &sc->txqs[i]);
|
||||
|
||||
sc->tx_pending = false;
|
||||
ath5k_set_current_imask(sc);
|
||||
}
|
||||
|
||||
|
||||
@@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
|
||||
* AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_schedule_rx(struct ath5k_softc *sc)
|
||||
{
|
||||
sc->rx_pending = true;
|
||||
tasklet_schedule(&sc->rxtq);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_schedule_tx(struct ath5k_softc *sc)
|
||||
{
|
||||
sc->tx_pending = true;
|
||||
tasklet_schedule(&sc->txtq);
|
||||
}
|
||||
|
||||
irqreturn_t
|
||||
ath5k_intr(int irq, void *dev_id)
|
||||
{
|
||||
@@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
}
|
||||
else
|
||||
tasklet_schedule(&sc->rxtq);
|
||||
ath5k_schedule_rx(sc);
|
||||
} else {
|
||||
if (status & AR5K_INT_SWBA) {
|
||||
tasklet_hi_schedule(&sc->beacontq);
|
||||
@@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
|
||||
ath5k_hw_update_tx_triglevel(ah, true);
|
||||
}
|
||||
if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
|
||||
tasklet_schedule(&sc->rxtq);
|
||||
ath5k_schedule_rx(sc);
|
||||
if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
|
||||
| AR5K_INT_TXERR | AR5K_INT_TXEOL))
|
||||
tasklet_schedule(&sc->txtq);
|
||||
ath5k_schedule_tx(sc);
|
||||
if (status & AR5K_INT_BMISS) {
|
||||
/* TODO */
|
||||
}
|
||||
@@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
|
||||
|
||||
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
|
||||
|
||||
if (sc->rx_pending || sc->tx_pending)
|
||||
ath5k_set_current_imask(sc);
|
||||
|
||||
if (unlikely(!counter))
|
||||
ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
|
||||
|
||||
@@ -2572,6 +2612,8 @@ done:
|
||||
|
||||
static void stop_tasklets(struct ath5k_softc *sc)
|
||||
{
|
||||
sc->rx_pending = false;
|
||||
sc->tx_pending = false;
|
||||
tasklet_kill(&sc->rxtq);
|
||||
tasklet_kill(&sc->txtq);
|
||||
tasklet_kill(&sc->calib);
|
||||
@@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
|
||||
INIT_WORK(&sc->reset_work, ath5k_reset_work);
|
||||
INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
|
||||
|
||||
ret = ath5k_eeprom_read_mac(ah, mac);
|
||||
ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "unable to read address from EEPROM\n");
|
||||
goto err_queues;
|
||||
@@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
|
||||
* XXX: ??? detach ath5k_hw ???
|
||||
* Other than that, it's straightforward...
|
||||
*/
|
||||
ath5k_debug_finish_device(sc);
|
||||
ieee80211_unregister_hw(hw);
|
||||
ath5k_desc_free(sc);
|
||||
ath5k_txq_release(sc);
|
||||
|
||||
@@ -193,12 +193,13 @@ struct ath5k_softc {
|
||||
dma_addr_t desc_daddr; /* DMA (physical) address */
|
||||
size_t desc_len; /* size of TX/RX descriptors */
|
||||
|
||||
DECLARE_BITMAP(status, 5);
|
||||
DECLARE_BITMAP(status, 6);
|
||||
#define ATH_STAT_INVALID 0 /* disable hardware accesses */
|
||||
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
|
||||
#define ATH_STAT_PROMISC 2
|
||||
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
|
||||
#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
|
||||
#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */
|
||||
|
||||
unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
|
||||
struct ieee80211_channel *curchan; /* current h/w channel */
|
||||
@@ -207,6 +208,10 @@ struct ath5k_softc {
|
||||
|
||||
enum ath5k_int imask; /* interrupt mask copy */
|
||||
|
||||
spinlock_t irqlock;
|
||||
bool rx_pending; /* rx tasklet pending */
|
||||
bool tx_pending; /* tx tasklet pending */
|
||||
|
||||
u8 lladdr[ETH_ALEN];
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
|
||||
__clear_bit(AR5K_MODE_11A, caps->cap_mode);
|
||||
|
||||
/* Set number of supported TX queues */
|
||||
if (ah->ah_version == AR5K_AR5210)
|
||||
caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
|
||||
|
||||
@@ -888,65 +888,38 @@ static const struct file_operations fops_queue = {
|
||||
void
|
||||
ath5k_debug_init_device(struct ath5k_softc *sc)
|
||||
{
|
||||
struct dentry *phydir;
|
||||
|
||||
sc->debug.level = ath5k_debug;
|
||||
|
||||
sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
|
||||
sc->hw->wiphy->debugfsdir);
|
||||
phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
|
||||
if (!phydir)
|
||||
return;
|
||||
|
||||
sc->debug.debugfs_debug = debugfs_create_file("debug",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_debug);
|
||||
debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
|
||||
&fops_debug);
|
||||
|
||||
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_registers);
|
||||
debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
|
||||
|
||||
sc->debug.debugfs_beacon = debugfs_create_file("beacon",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_beacon);
|
||||
debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
|
||||
&fops_beacon);
|
||||
|
||||
sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_reset);
|
||||
debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
|
||||
|
||||
sc->debug.debugfs_antenna = debugfs_create_file("antenna",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_antenna);
|
||||
debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
|
||||
&fops_antenna);
|
||||
|
||||
sc->debug.debugfs_misc = debugfs_create_file("misc",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc, &fops_misc);
|
||||
debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
|
||||
|
||||
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_frameerrors);
|
||||
debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
|
||||
&fops_frameerrors);
|
||||
|
||||
sc->debug.debugfs_ani = debugfs_create_file("ani",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_ani);
|
||||
debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
|
||||
|
||||
sc->debug.debugfs_queue = debugfs_create_file("queue",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_queue);
|
||||
debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
|
||||
&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 */
|
||||
|
||||
void
|
||||
|
||||
@@ -68,17 +68,6 @@ struct ath5k_buf;
|
||||
|
||||
struct ath5k_dbg_info {
|
||||
unsigned int level; /* debug level */
|
||||
/* debugfs entries */
|
||||
struct dentry *debugfs_phydir;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_registers;
|
||||
struct dentry *debugfs_beacon;
|
||||
struct dentry *debugfs_reset;
|
||||
struct dentry *debugfs_antenna;
|
||||
struct dentry *debugfs_misc;
|
||||
struct dentry *debugfs_frameerrors;
|
||||
struct dentry *debugfs_ani;
|
||||
struct dentry *debugfs_queue;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,9 +129,6 @@ enum ath5k_debug_level {
|
||||
void
|
||||
ath5k_debug_init_device(struct ath5k_softc *sc);
|
||||
|
||||
void
|
||||
ath5k_debug_finish_device(struct ath5k_softc *sc);
|
||||
|
||||
void
|
||||
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
|
||||
|
||||
@@ -166,9 +152,6 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
|
||||
static inline void
|
||||
ath5k_debug_init_device(struct ath5k_softc *sc) {}
|
||||
|
||||
static inline void
|
||||
ath5k_debug_finish_device(struct ath5k_softc *sc) {}
|
||||
|
||||
static inline void
|
||||
ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
|
||||
|
||||
|
||||
@@ -185,6 +185,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||
unsigned int frame_len;
|
||||
|
||||
/*
|
||||
* Use local variables for these to reduce load/store access on
|
||||
* uncached memory
|
||||
*/
|
||||
u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0;
|
||||
|
||||
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||
|
||||
/*
|
||||
@@ -208,8 +214,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
if (tx_power > AR5K_TUNE_MAX_TXPOWER)
|
||||
tx_power = AR5K_TUNE_MAX_TXPOWER;
|
||||
|
||||
/* Clear descriptor */
|
||||
memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
|
||||
/* Clear descriptor status area */
|
||||
memset(&desc->ud.ds_tx5212.tx_stat, 0,
|
||||
sizeof(desc->ud.ds_tx5212.tx_stat));
|
||||
|
||||
/* Setup control descriptor */
|
||||
|
||||
@@ -221,7 +228,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
|
||||
txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
|
||||
|
||||
/* Verify and set buffer length */
|
||||
|
||||
@@ -232,21 +239,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
|
||||
txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
|
||||
|
||||
tx_ctl->tx_control_0 |=
|
||||
AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
|
||||
AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
|
||||
tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
|
||||
AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
|
||||
tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0,
|
||||
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
|
||||
tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
||||
txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
|
||||
AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
|
||||
txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
|
||||
txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
|
||||
txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
||||
|
||||
#define _TX_FLAGS(_c, _flag) \
|
||||
if (flags & AR5K_TXDESC_##_flag) { \
|
||||
tx_ctl->tx_control_##_c |= \
|
||||
AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
|
||||
txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
|
||||
}
|
||||
|
||||
_TX_FLAGS(0, CLRDMASK);
|
||||
@@ -262,8 +265,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
* WEP crap
|
||||
*/
|
||||
if (key_index != AR5K_TXKEYIX_INVALID) {
|
||||
tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
||||
tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
|
||||
txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
|
||||
txctl1 |= AR5K_REG_SM(key_index,
|
||||
AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
|
||||
}
|
||||
|
||||
@@ -274,12 +277,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
||||
if ((flags & AR5K_TXDESC_RTSENA) &&
|
||||
(flags & AR5K_TXDESC_CTSENA))
|
||||
return -EINVAL;
|
||||
tx_ctl->tx_control_2 |= rtscts_duration &
|
||||
AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
|
||||
tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
|
||||
txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
|
||||
txctl3 |= AR5K_REG_SM(rtscts_rate,
|
||||
AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
|
||||
}
|
||||
|
||||
tx_ctl->tx_control_0 = txctl0;
|
||||
tx_ctl->tx_control_1 = txctl1;
|
||||
tx_ctl->tx_control_2 = txctl2;
|
||||
tx_ctl->tx_control_3 = txctl3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -364,7 +371,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
||||
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
||||
ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
|
||||
ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
|
||||
/*TODO: ts->ts_virtcol + test*/
|
||||
ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
||||
@@ -373,9 +380,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
||||
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
||||
ts->ts_antenna = 1;
|
||||
ts->ts_status = 0;
|
||||
ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
|
||||
AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
|
||||
ts->ts_retry[0] = ts->ts_longretry;
|
||||
ts->ts_final_idx = 0;
|
||||
|
||||
if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
||||
@@ -401,81 +405,48 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
|
||||
{
|
||||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||
struct ath5k_hw_tx_status *tx_status;
|
||||
u32 txstat0, txstat1;
|
||||
|
||||
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||
tx_status = &desc->ud.ds_tx5212.tx_stat;
|
||||
|
||||
txstat1 = ACCESS_ONCE(tx_status->tx_status_1);
|
||||
|
||||
/* No frame has been send or error */
|
||||
if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
|
||||
if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))
|
||||
return -EINPROGRESS;
|
||||
|
||||
txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
|
||||
|
||||
/*
|
||||
* Get descriptor status
|
||||
*/
|
||||
ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
ts->ts_tstamp = AR5K_REG_MS(txstat0,
|
||||
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
|
||||
ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
ts->ts_shortretry = AR5K_REG_MS(txstat0,
|
||||
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
|
||||
ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
|
||||
ts->ts_final_retry = AR5K_REG_MS(txstat0,
|
||||
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
|
||||
ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
|
||||
ts->ts_seqnum = AR5K_REG_MS(txstat1,
|
||||
AR5K_DESC_TX_STATUS1_SEQ_NUM);
|
||||
ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
|
||||
ts->ts_rssi = AR5K_REG_MS(txstat1,
|
||||
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
|
||||
ts->ts_antenna = (tx_status->tx_status_1 &
|
||||
ts->ts_antenna = (txstat1 &
|
||||
AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
|
||||
ts->ts_status = 0;
|
||||
|
||||
ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
|
||||
ts->ts_final_idx = AR5K_REG_MS(txstat1,
|
||||
AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
|
||||
|
||||
/* The longretry counter has the number of un-acked retries
|
||||
* for the final rate. To get the total number of retries
|
||||
* we have to add the retry counters for the other rates
|
||||
* as well
|
||||
*/
|
||||
ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
|
||||
switch (ts->ts_final_idx) {
|
||||
case 3:
|
||||
ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
|
||||
AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
|
||||
|
||||
ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
|
||||
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
|
||||
ts->ts_longretry += ts->ts_retry[2];
|
||||
/* fall through */
|
||||
case 2:
|
||||
ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
|
||||
AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
|
||||
|
||||
ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
|
||||
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
|
||||
ts->ts_longretry += ts->ts_retry[1];
|
||||
/* fall through */
|
||||
case 1:
|
||||
ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
|
||||
AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
|
||||
|
||||
ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
|
||||
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
|
||||
ts->ts_longretry += ts->ts_retry[0];
|
||||
/* fall through */
|
||||
case 0:
|
||||
ts->ts_rate[0] = tx_ctl->tx_control_3 &
|
||||
AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TX error */
|
||||
if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
||||
if (tx_status->tx_status_0 &
|
||||
AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
||||
if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
|
||||
if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
|
||||
ts->ts_status |= AR5K_TXERR_XRETRY;
|
||||
|
||||
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
|
||||
if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
|
||||
ts->ts_status |= AR5K_TXERR_FIFO;
|
||||
|
||||
if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
|
||||
if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)
|
||||
ts->ts_status |= AR5K_TXERR_FILT;
|
||||
}
|
||||
|
||||
@@ -609,37 +580,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
|
||||
struct ath5k_rx_status *rs)
|
||||
{
|
||||
struct ath5k_hw_rx_status *rx_status;
|
||||
u32 rxstat0, rxstat1;
|
||||
|
||||
rx_status = &desc->ud.ds_rx.rx_stat;
|
||||
rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);
|
||||
|
||||
/* No frame received / not ready */
|
||||
if (unlikely(!(rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_DONE)))
|
||||
if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
|
||||
return -EINPROGRESS;
|
||||
|
||||
memset(rs, 0, sizeof(struct ath5k_rx_status));
|
||||
rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);
|
||||
|
||||
/*
|
||||
* Frame receive status
|
||||
*/
|
||||
rs->rs_datalen = rx_status->rx_status_0 &
|
||||
AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
|
||||
rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
|
||||
rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
|
||||
rs->rs_rssi = AR5K_REG_MS(rxstat0,
|
||||
AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
|
||||
rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
|
||||
rs->rs_rate = AR5K_REG_MS(rxstat0,
|
||||
AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
|
||||
rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
|
||||
rs->rs_antenna = AR5K_REG_MS(rxstat0,
|
||||
AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
|
||||
rs->rs_more = !!(rx_status->rx_status_0 &
|
||||
AR5K_5212_RX_DESC_STATUS0_MORE);
|
||||
rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
|
||||
rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
|
||||
rs->rs_tstamp = AR5K_REG_MS(rxstat1,
|
||||
AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
|
||||
|
||||
/*
|
||||
* Key table status
|
||||
*/
|
||||
if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
||||
rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
|
||||
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
|
||||
rs->rs_keyix = AR5K_REG_MS(rxstat1,
|
||||
AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
|
||||
else
|
||||
rs->rs_keyix = AR5K_RXKEYIX_INVALID;
|
||||
@@ -647,27 +618,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
|
||||
/*
|
||||
* Receive/descriptor errors
|
||||
*/
|
||||
if (!(rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
|
||||
if (rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
|
||||
if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
|
||||
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
|
||||
rs->rs_status |= AR5K_RXERR_CRC;
|
||||
|
||||
if (rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
|
||||
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
|
||||
rs->rs_status |= AR5K_RXERR_PHY;
|
||||
rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
|
||||
rs->rs_phyerr = AR5K_REG_MS(rxstat1,
|
||||
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
|
||||
if (!ah->ah_capabilities.cap_has_phyerr_counters)
|
||||
ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
|
||||
}
|
||||
|
||||
if (rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
||||
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
|
||||
rs->rs_status |= AR5K_RXERR_DECRYPT;
|
||||
|
||||
if (rx_status->rx_status_1 &
|
||||
AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
|
||||
if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
|
||||
rs->rs_status |= AR5K_RXERR_MIC;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
|
||||
vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
struct ath5k_chan_pcal_info *chinfo;
|
||||
u8 pier, pdg;
|
||||
|
||||
switch (mode) {
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_a;
|
||||
break;
|
||||
case AR5K_EEPROM_MODE_11B:
|
||||
if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_b;
|
||||
break;
|
||||
case AR5K_EEPROM_MODE_11G:
|
||||
if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_g;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
|
||||
if (!chinfo[pier].pd_curves)
|
||||
continue;
|
||||
|
||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||
struct ath5k_pdgain_info *pd =
|
||||
&chinfo[pier].pd_curves[pdg];
|
||||
|
||||
if (pd != NULL) {
|
||||
kfree(pd->pd_step);
|
||||
kfree(pd->pd_pwr);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(chinfo[pier].pd_curves);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert RF5111 specific data to generic raw data
|
||||
* used by interpolation code */
|
||||
static int
|
||||
@@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!chinfo[pier].pd_curves)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Only one curve for RF5111
|
||||
* find out which one and place
|
||||
@@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||
pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||
sizeof(u8), GFP_KERNEL);
|
||||
if (!pd->pd_step)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
|
||||
sizeof(s16), GFP_KERNEL);
|
||||
if (!pd->pd_pwr)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Fill raw dataset
|
||||
* (convert power to 0.25dB units
|
||||
@@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Parse EEPROM data */
|
||||
@@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!chinfo[pier].pd_curves)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Fill pd_curves */
|
||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||
@@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||
sizeof(u8), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_step)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||
sizeof(s16), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_pwr)
|
||||
return -ENOMEM;
|
||||
|
||||
goto err_out;
|
||||
|
||||
/* Fill raw dataset
|
||||
* (all power levels are in 0.25dB units) */
|
||||
@@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||
sizeof(u8), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_step)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||
sizeof(s16), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_pwr)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Fill raw dataset
|
||||
* (all power levels are in 0.25dB units) */
|
||||
@@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Parse EEPROM data */
|
||||
@@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!chinfo[pier].pd_curves)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Fill pd_curves */
|
||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||
@@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||
sizeof(u8), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_step)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
pd->pd_pwr = kcalloc(pd->pd_points,
|
||||
sizeof(s16), GFP_KERNEL);
|
||||
|
||||
if (!pd->pd_pwr)
|
||||
return -ENOMEM;
|
||||
goto err_out;
|
||||
|
||||
/* Fill raw dataset
|
||||
* convert all pwr levels to
|
||||
@@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ath5k_eeprom_free_pcal_info(ah, mode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Parse EEPROM data */
|
||||
@@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
struct ath5k_chan_pcal_info *chinfo;
|
||||
u8 pier, pdg;
|
||||
|
||||
switch (mode) {
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_a;
|
||||
break;
|
||||
case AR5K_EEPROM_MODE_11B:
|
||||
if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_b;
|
||||
break;
|
||||
case AR5K_EEPROM_MODE_11G:
|
||||
if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
|
||||
return 0;
|
||||
chinfo = ee->ee_pwr_cal_g;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
|
||||
if (!chinfo[pier].pd_curves)
|
||||
continue;
|
||||
|
||||
for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
|
||||
struct ath5k_pdgain_info *pd =
|
||||
&chinfo[pier].pd_curves[pdg];
|
||||
|
||||
if (pd != NULL) {
|
||||
kfree(pd->pd_step);
|
||||
kfree(pd->pd_pwr);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(chinfo[pier].pd_curves);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read conformance test limits used for regulatory control */
|
||||
static int
|
||||
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
||||
@@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the MAC address from eeprom
|
||||
*/
|
||||
int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
||||
{
|
||||
u8 mac_d[ETH_ALEN] = {};
|
||||
u32 total, offset;
|
||||
u16 data;
|
||||
int octet;
|
||||
|
||||
AR5K_EEPROM_READ(0x20, data);
|
||||
|
||||
for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
|
||||
AR5K_EEPROM_READ(offset, data);
|
||||
|
||||
total += data;
|
||||
mac_d[octet + 1] = data & 0xff;
|
||||
mac_d[octet] = data >> 8;
|
||||
octet += 2;
|
||||
}
|
||||
|
||||
if (!total || total == 3 * 0xffff)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(mac, mac_d, ETH_ALEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************\
|
||||
* Init/Detach functions *
|
||||
|
||||
@@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (changes & BSS_CHANGED_BEACON_INT)
|
||||
sc->bintval = bss_conf->beacon_int;
|
||||
|
||||
if (changes & BSS_CHANGED_ERP_SLOT) {
|
||||
int slot_time;
|
||||
|
||||
ah->ah_short_slot = bss_conf->use_short_slot;
|
||||
slot_time = ath5k_hw_get_default_slottime(ah) +
|
||||
3 * ah->ah_coverage_class;
|
||||
ath5k_hw_set_ifs_intervals(ah, slot_time);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_ASSOC) {
|
||||
avf->assoc = bss_conf->assoc;
|
||||
if (bss_conf->assoc)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include "../ath.h"
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
@@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the MAC address from eeprom or platform_data
|
||||
*/
|
||||
static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
||||
{
|
||||
u8 mac_d[ETH_ALEN] = {};
|
||||
u32 total, offset;
|
||||
u16 data;
|
||||
int octet;
|
||||
|
||||
AR5K_EEPROM_READ(0x20, data);
|
||||
|
||||
for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
|
||||
AR5K_EEPROM_READ(offset, data);
|
||||
|
||||
total += data;
|
||||
mac_d[octet + 1] = data & 0xff;
|
||||
mac_d[octet] = data >> 8;
|
||||
octet += 2;
|
||||
}
|
||||
|
||||
if (!total || total == 3 * 0xffff)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(mac, mac_d, ETH_ALEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Common ath_bus_opts structure */
|
||||
static const struct ath_bus_ops ath_pci_bus_ops = {
|
||||
.ath_bus_type = ATH_PCI,
|
||||
.read_cachesize = ath5k_pci_read_cachesize,
|
||||
.eeprom_read = ath5k_pci_eeprom_read,
|
||||
.eeprom_read_mac = ath5k_pci_eeprom_read_mac,
|
||||
};
|
||||
|
||||
/********************\
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user