Commit 345578d9 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of...

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
parents fe2a70ee cfef6047
......@@ -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 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
{
int ret = 0;
u8 fws0;
int pollnum = MAX_POLL_TRIES;
if (!card || !card->func) {
BT_ERR("card or function is NULL!");
......@@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
goto done;
}
ret = btmrvl_sdio_download_helper(card);
/* Check if other function driver is downloading the firmware */
fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
if (ret) {
BT_ERR("Failed to download helper!");
BT_ERR("Failed to read FW downloading status!");
ret = -EIO;
goto done;
}
if (fws0) {
BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
/* Give other function more time to download the firmware */
pollnum *= 10;
} else {
if (card->helper) {
ret = btmrvl_sdio_download_helper(card);
if (ret) {
BT_ERR("Failed to download helper!");
ret = -EIO;
goto done;
}
}
if (btmrvl_sdio_download_fw_w_helper(card)) {
BT_ERR("Failed to download firmware!");
ret = -EIO;
goto done;
if (btmrvl_sdio_download_fw_w_helper(card)) {
BT_ERR("Failed to download firmware!");
ret = -EIO;
goto done;
}
}
if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) {
if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
BT_ERR("FW failed to be active in time!");
ret = -ETIMEDOUT;
goto done;
......@@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
sdio_claim_host(card->func);
sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret);
sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
sdio_release_host(card->func);
......@@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
if (id->driver_data) {
struct btmrvl_sdio_device *data = (void *) id->driver_data;
card->helper = data->helper;
card->helper = data->helper;
card->firmware = data->firmware;
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
}
if (btmrvl_sdio_register_dev(card) < 0) {
......@@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE("sd8688_helper.bin");
MODULE_FIRMWARE("sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
......@@ -47,44 +47,46 @@
/* Max retry number of CMD53 write */
#define MAX_WRITE_IOMEM_RETRY 2
/* Host Control Registers */
#define IO_PORT_0_REG 0x00
#define IO_PORT_1_REG 0x01
#define IO_PORT_2_REG 0x02
#define CONFIG_REG 0x03
#define HOST_POWER_UP BIT(1)
#define HOST_CMD53_FIN BIT(2)
#define HOST_INT_MASK_REG 0x04
#define HIM_DISABLE 0xff
#define HIM_ENABLE (BIT(0) | BIT(1))
#define HOST_INTSTATUS_REG 0x05
#define UP_LD_HOST_INT_STATUS BIT(0)
#define DN_LD_HOST_INT_STATUS BIT(1)
/* Card Control Registers */
#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
#define CARD_STATUS_REG 0x20
#define DN_LD_CARD_RDY BIT(0)
#define CARD_IO_READY BIT(3)
#define CARD_FW_STATUS0_REG 0x40
#define CARD_FW_STATUS1_REG 0x41
#define FIRMWARE_READY 0xfedc
#define CARD_RX_LEN_REG 0x42
#define CARD_RX_UNIT_REG 0x43
/* register bitmasks */
#define HOST_POWER_UP BIT(1)
#define HOST_CMD53_FIN BIT(2)
#define HIM_DISABLE 0xff
#define HIM_ENABLE (BIT(0) | BIT(1))
#define UP_LD_HOST_INT_STATUS BIT(0)
#define DN_LD_HOST_INT_STATUS BIT(1)
#define DN_LD_CARD_RDY BIT(0)
#define CARD_IO_READY BIT(3)
#define FIRMWARE_READY 0xfedc
struct btmrvl_sdio_card_reg {
u8 cfg;
u8 host_int_mask;
u8 host_intstatus;
u8 card_status;
u8 sq_read_base_addr_a0;
u8 sq_read_base_addr_a1;
u8 card_revision;
u8 card_fw_status0;
u8 card_fw_status1;
u8 card_rx_len;
u8 card_rx_unit;
u8 io_port_0;
u8 io_port_1;
u8 io_port_2;
};
struct btmrvl_sdio_card {
struct sdio_func *func;
u32 ioport;
const char *helper;
const char *firmware;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
u8 rx_unit;
struct btmrvl_private *priv;
};
......@@ -92,6 +94,8 @@ struct btmrvl_sdio_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 @@ ath5k_tasklet_rx(unsigned long data)
} 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 @@ ath5k_init_hw(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->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)
{
sc->debug.level = ath5k_debug;
struct dentry *phydir;
sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
sc->hw->wiphy->debugfsdir);
sc->debug.level = ath5k_debug;
sc->debug.debugfs_debug = debugfs_create_file("debug",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_debug);
phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
if (!phydir)
return;
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_registers);
debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
&fops_debug);
sc->debug.debugfs_beacon = debugfs_create_file("beacon",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_beacon);
debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
sc->debug.debugfs_phydir, sc, &fops_reset);
debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
&fops_beacon);
sc->debug.debugfs_antenna = debugfs_create_file("antenna",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_antenna);
debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
sc->debug.debugfs_misc = debugfs_create_file("misc",
S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_misc);
debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
&fops_antenna);
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
&fops_frameerrors);
debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
sc->debug.debugfs_ani = debugfs_create_file("ani",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
&fops_ani);
debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
&fops_frameerrors);
sc->debug.debugfs_queue = debugfs_create_file("queue",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
&fops_queue);
}
debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
void
ath5k_debug_finish_device(struct ath5k_softc *sc)
{
debugfs_remove(sc->debug.debugfs_debug);
debugfs_remove(sc->debug.debugfs_registers);
debugfs_remove(sc->debug.debugfs_beacon);
debugfs_remove(sc->debug.debugfs_reset);
debugfs_remove(sc->debug.debugfs_antenna);
debugfs_remove(sc->debug.debugfs_misc);
debugfs_remove(sc->debug.debugfs_frameerrors);
debugfs_remove(sc->debug.debugfs_ani);
debugfs_remove(sc->debug.debugfs_queue);
debugfs_remove(sc->debug.debugfs_phydir);
debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
&fops_queue);
}
/* functions used in other places */
void
......
......@@ -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) {}
......
This diff is collapsed.
......@@ -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,
};
/********************\
......
......@@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] =
* bwmodes.
*/
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate)
int len, struct ieee80211_rate *rate, bool shortpre)
{
struct ath5k_softc *sc = ah->ah_sc;
int sifs, preamble, plcp_bits, sym_time;
......@@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
/* Fallback */
if (!ah->ah_bwmode) {
dur = ieee80211_generic_frame_duration(sc->hw,
NULL, len, rate);
return le16_to_cpu(dur);
__le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
NULL, len, rate);
/* subtract difference between long and short preamble */
dur = le16_to_cpu(raw_dur);
if (shortpre)
dur -= 96;
return dur;
}
bitrate = rate->bitrate;
......@@ -145,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
break;
case AR5K_BWMODE_DEFAULT:
slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
default:
if (channel->hw_value & CHANNEL_CCK)
slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
slot_time = AR5K_INIT_SLOT_TIME_B;
break;
}
......@@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
* actual rate for this rate. See mac80211 tx.c
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
ath5k_hw_reg_write(ah, tx_time, reg);
if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
continue;
/*
* We're not distinguishing short preamble here,
* This is true, all we'll get is a longer value here
* which is not necessarilly bad. We could use
* export ieee80211_frame_duration() but that needs to be
* fixed first to be properly used by mac802111 drivers:
*
* - remove erp stuff and let the routine figure ofdm
* erp rates
* - remove passing argument ieee80211_local as
* drivers don't have access to it
* - move drivers using ieee80211_generic_frame_duration()
* to this
*/
tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);
ath5k_hw_reg_write(ah, tx_time,
reg + (AR5K_SET_SHORT_PREAMBLE << 2));
}
......
......@@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
return -EINVAL;
sifs = ath5k_hw_get_default_sifs(ah);
sifs_clock = ath5k_hw_htoclock(ah, sifs);
sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
/* EIFS
* Txtime of ack at lowest rate + SIFS + DIFS
......@@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
else
rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
/* ack_tx_time includes an SIFS already */
eifs = ack_tx_time + sifs + 2 * slot_time;
......
......@@ -5,7 +5,7 @@ config ATH9K_COMMON
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211
depends on MAC80211
select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
......@@ -23,6 +23,25 @@ config ATH9K
If you choose to build a module, it'll be called ath9k.
config ATH9K_PCI
bool "Atheros ath9k PCI/PCIe bus support"
depends on ATH9K && PCI
default PCI
---help---
This option enables the PCI bus support in ath9k.
Say Y, if you have a compatible PCI/PCIe wireless card.
config ATH9K_AHB
bool "Atheros ath9k AHB bus support"
depends on ATH9K
default n
---help---
This option enables the AHB bus support in ath9k.
Say Y, if you have a SoC with a compatible built-in
wireless MAC. Say N if unsure.
config ATH9K_DEBUGFS
bool "Atheros ath9k debugging"
depends on ATH9K && DEBUG_FS
......
......@@ -6,8 +6,8 @@ ath9k-y += beacon.o \
xmit.o \
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_PCI) += pci.o
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
obj-$(CONFIG_ATH9K) += ath9k.o
......@@ -48,4 +48,6 @@ ath9k_htc-y += htc_hst.o \
htc_drv_init.o \
htc_drv_gpio.o
ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o
obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
......@@ -21,6 +21,14 @@
#include <linux/ath9k_platform.h>
#include "ath9k.h"
const struct platform_device_id ath9k_platform_id_table[] = {
{
.name = "ath9k",
.driver_data = AR5416_AR9100_DEVID,
},
{},
};
/* return bus cachesize in 4B word units */
static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
{
......@@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
struct ath_softc *sc;
struct ieee80211_hw *hw;
struct resource *res;
const struct platform_device_id *id = platform_get_device_id(pdev);
int irq;
int ret = 0;
struct ath_hw *ah;
......@@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
goto err_free_hw;
}
ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops);
ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops);
if (ret) {
dev_err(&pdev->dev, "failed to initialize device\n");
goto err_irq;
......@@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = {
.name = "ath9k",
.owner = THIS_MODULE,
},
.id_table = ath9k_platform_id_table,
};
MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
int ath_ahb_init(void)
{
return platform_driver_register(&ath_ahb_driver);
......
......@@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txPower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
......@@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
}
}
static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (val)
ads->ds_ctl0 |= AR_ClrDestMask;
else
ads->ds_ctl0 &= ~AR_ClrDestMask;
}
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
......@@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
ops->set_clrdmask = ar9002_hw_set_clrdmask;
}
......@@ -483,7 +483,11 @@
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
#define AR_PHY_TX_PWRCTRL8 0xa278
#define AR_PHY_TX_PWRCTRL9 0xa27C
#define AR_PHY_TX_PWRCTRL10 0xa394
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
......@@ -495,6 +499,8 @@
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
#define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc
#define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
......
......@@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txpower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
......@@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
ads->ctl22 = 0;
}
static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
if (val)
ads->ctl11 |= AR_ClrDestMask;
else
ads->ctl11 &= ~AR_ClrDestMask;
}
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
......@@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
ops->set_clrdmask = ar9003_hw_set_clrdmask;
}
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
......
......@@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
freq = centers.synth_center;
if (freq < 4800) { /* 2 GHz, fractional mode */
if (AR_SREV_9485(ah))
channelSel = CHANSEL_2G_9485(freq);
else
if (AR_SREV_9485(ah)) {
u32 chan_frac;
/*
* freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
* ndiv = ((chan_mhz * 4) / 3) / freq_ref;
* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
*/
channelSel = (freq * 4) / 120;
chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
channelSel = (channelSel << 17) | chan_frac;
} else
channelSel = CHANSEL_2G(freq);
/* Set to 2G mode */
bMode = 1;
......@@ -401,7 +410,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
ar9003_hw_spur_ofdm_clear(ah);
for (i = 0; spurChansPtr[i] && i < 5; i++) {
for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
if (abs(freq_offset) < range) {
ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
......
......@@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
......@@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
......@@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
......@@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
......@@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
......
......@@ -200,6 +200,7 @@ struct ath_atx_ac {
int sched;
struct list_head list;
struct list_head tid_q;
bool clear_ps_filter;
};
struct ath_frame_info {
......@@ -255,8 +256,12 @@ struct ath_node {
#endif
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
int ps_key;
u16 maxampdu;
u8 mpdudensity;
bool sleeping;
};
#define AGGR_CLEANUP BIT(1)
......@@ -338,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
/********/
/* VIFs */
/********/
......@@ -665,7 +673,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
bool ath9k_uses_beacons(int type);
#ifdef CONFIG_PCI
#ifdef CONFIG_ATH9K_PCI
int ath_pci_init(void);
void ath_pci_exit(void);
#else
......@@ -673,7 +681,7 @@ static inline int ath_pci_init(void) { return 0; };
static inline void ath_pci_exit(void) {};
#endif
#ifdef CONFIG_ATHEROS_AR71XX
#ifdef CONFIG_ATH9K_AHB
int ath_ahb_init(void);
void ath_ahb_exit(void);
#else
......
......@@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
if (avp->av_bcbuf != NULL) {
struct ath_buf *bf;
avp->is_bslot_active = false;
if (avp->av_bslot != -1) {
sc->beacon.bslot[avp->av_bslot] = NULL;
sc->nbcnvifs--;
......@@ -743,9 +744,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
cur_conf->dtim_period = 1;
ath_set_beacon(sc);
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
}
static bool ath_has_valid_bslot(struct ath_softc *sc)
{
struct ath_vif *avp;
int slot;
bool found = false;
for (slot = 0; slot < ATH_BCBUF; slot++) {
if (sc->beacon.bslot[slot]) {
avp = (void *)sc->beacon.bslot[slot]->drv_priv;
if (avp->is_bslot_active) {
found = true;
break;
}
}
}
return found;
}
void ath_set_beacon(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
......@@ -753,7 +772,8 @@ void ath_set_beacon(struct ath_softc *sc)
switch (sc->sc_ah->opmode) {
case NL80211_IFTYPE_AP:
ath_beacon_config_ap(sc, cur_conf);
if (ath_has_valid_bslot(sc))
ath_beacon_config_ap(sc, cur_conf);
break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
......@@ -761,6 +781,12 @@ void ath_set_beacon(struct ath_softc *sc)
break;
case NL80211_IFTYPE_STATION:
ath_beacon_config_sta(sc, cur_conf);
/*
* Request a re-configuration of Beacon related timers
* on the receipt of the first Beacon frame (i.e.,
* after time sync with the AP).
*/
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
break;
default:
ath_dbg(common, ATH_DBG_CONFIG,
......@@ -774,20 +800,8 @@ void ath_set_beacon(struct ath_softc *sc)
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_vif *avp;
int slot;
bool found = false;
for (slot = 0; slot < ATH_BCBUF; slot++) {
if (sc->beacon.bslot[slot]) {
avp = (void *)sc->beacon.bslot[slot]->drv_priv;
if (avp->is_bslot_active) {
found = true;
break;
}
}
}
if (!found)
if (!ath_has_valid_bslot(sc))
return;
ath9k_ps_wakeup(sc);
......
......@@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
struct ath_softc *sc = file->private_data;
char *buf;
unsigned int len = 0, size = 1152;
unsigned int len = 0, size = 1400;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
......@@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
"%18s : %10u\n", "DECRYPT BUSY ERR",
sc->debug.stats.rxstats.decrypt_busy_err);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-CTL0",
sc->debug.stats.rxstats.rs_rssi_ctl0);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-CTL1",
sc->debug.stats.rxstats.rs_rssi_ctl1);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-CTL2",
sc->debug.stats.rxstats.rs_rssi_ctl2);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-EXT0",
sc->debug.stats.rxstats.rs_rssi_ext0);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-EXT1",
sc->debug.stats.rxstats.rs_rssi_ext1);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "RSSI-EXT2",
sc->debug.stats.rxstats.rs_rssi_ext2);
len += snprintf(buf + len, size - len,
"%18s : %10d\n", "Rx Antenna",
sc->debug.stats.rxstats.rs_antenna);
PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
......@@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
RX_PHY_ERR_INC(phyerr);
}
sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
#undef RX_STAT_INC
#undef RX_PHY_ERR_INC
}
......
......@@ -157,6 +157,13 @@ struct ath_rx_stats {
u32 post_delim_crc_err;
u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX];
int8_t rs_rssi_ctl0;
int8_t rs_rssi_ctl1;
int8_t rs_rssi_ctl2;
int8_t rs_rssi_ext0;
int8_t rs_rssi_ext1;
int8_t rs_rssi_ext2;
u8 rs_antenna;
};
struct ath_stats {
......
......@@ -436,7 +436,11 @@ struct modal_eep_4k_header {
u8 db2_2:4, db2_3:4;
u8 db2_4:4, reserved:4;
#endif
u8 futureModal[4];
u8 tx_diversity;
u8 flc_pwr_thresh;
u8 bb_scale_smrt_antenna;
#define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f
u8 futureModal[1];
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
} __packed;
......
......@@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
{
struct modal_eep_4k_header *pModal;
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct base_eep_header_4k *pBase = &eep->baseEepHeader;
u8 txRxAttenLocal;
u8 ob[5], db1[5], db2[5];
u8 ant_div_control1, ant_div_control2;
......@@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
AR_PHY_SETTLING_SWITCH,
pModal->swSettleHt40);
}
if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
EEP_4K_BB_DESIRED_SCALE_MASK);
if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
u32 pwrctrl, mask, clr;
mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
pwrctrl = mask * bb_desired_scale;
clr = mask * 0x1f;
REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
mask = BIT(0)|BIT(5)|BIT(15);
pwrctrl = mask * bb_desired_scale;
clr = mask * 0x1f;
REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
mask = BIT(0)|BIT(5);
pwrctrl = mask * bb_desired_scale;
clr = mask * 0x1f;
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
}
}
}
static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
......
......@@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
{
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
u16 antWrites[AR9287_ANT_16S];
u32 regChainOffset, regval;
u8 txRxAttenLocal;
int i, j, offset_num;
int i;
pModal = &eep->modalHeader;
antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF);
antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
offset_num = 8;
for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
antWrites[j++] = 0;
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
}
REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
......
This diff is collapsed.
......@@ -31,7 +31,7 @@
/* FIXME: Verify these numbers (with Windows) */
#define MAX_TX_URB_NUM 8
#define MAX_TX_BUF_NUM 1024
#define MAX_TX_BUF_NUM 256
#define MAX_TX_BUF_SIZE 32768
#define MAX_TX_AGGR_NUM 20
......@@ -40,7 +40,7 @@
#define MAX_PKT_NUM_IN_TRANSFER 10
#define MAX_REG_OUT_URB_NUM 1
#define MAX_REG_OUT_BUF_NUM 8
#define MAX_REG_IN_URB_NUM 64
#define MAX_REG_IN_BUF_SIZE 64
......@@ -90,9 +90,10 @@ struct hif_device_usb {
const struct firmware *firmware;
struct htc_target *htc_handle;
struct hif_usb_tx tx;
struct urb *reg_in_urb;
struct usb_anchor regout_submitted;
struct usb_anchor rx_submitted;
struct usb_anchor reg_in_submitted;
struct usb_anchor mgmt_submitted;
struct sk_buff *remain_skb;
const char *fw_name;
int rx_remain_len;
......
This diff is collapsed.
This diff is collapsed.
......@@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
/* Start TX */
htc_start(priv->htc);
spin_lock_bh(&priv->tx_lock);
priv->tx_queues_stop = false;
spin_unlock_bh(&priv->tx_lock);
spin_lock_bh(&priv->tx.tx_lock);
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
spin_unlock_bh(&priv->tx.tx_lock);
ieee80211_wake_queues(hw);
WMI_CMD(WMI_ENABLE_INTR_CMDID);
......@@ -429,13 +429,15 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
/* Stop TX */
ieee80211_stop_queues(hw);
htc_stop(priv->htc);
ath9k_htc_tx_drain(priv);
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
skb_queue_purge(&priv->tx_queue);
/* Stop RX */
WMI_CMD(WMI_STOP_RECV_CMDID);
/* Clear the WMI event queue */
ath9k_wmi_event_drain(priv);
/*
* The MIB counters have to be disabled here,
* since the target doesn't do it.
......
......@@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
{
ath9k_htc_exit_debug(priv->ah);
ath9k_hw_deinit(priv->ah);
kfree(priv->ah);
priv->ah = NULL;
......@@ -643,7 +642,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
{
struct ath_hw *ah = NULL;
struct ath_common *common;
int ret = 0, csz = 0;
int i, ret = 0, csz = 0;
priv->op_flags |= OP_INVALID;
......@@ -671,20 +670,19 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
common->priv = priv;
common->debug_mask = ath9k_debug;
spin_lock_init(&priv->wmi->wmi_lock);
spin_lock_init(&priv->beacon_lock);
spin_lock_init(&priv->tx_lock);
spin_lock_init(&priv->tx.tx_lock);
mutex_init(&priv->mutex);
mutex_init(&priv->htc_pm_lock);
tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
(unsigned long)priv);
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
(unsigned long)priv);
tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
(unsigned long)priv);
INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
INIT_WORK(&priv->ps_work, ath9k_ps_work);
INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
(unsigned long)priv);
/*
* Cache line size is used to size and align various
......@@ -701,16 +699,13 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
goto err_hw;
}
ret = ath9k_htc_init_debug(ah);
if (ret) {
ath_err(common, "Unable to create debugfs files\n");
goto err_debug;
}
ret = ath9k_init_queues(priv);
if (ret)
goto err_queues;
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
priv->cur_beacon_conf.bslot[i] = NULL;
ath9k_init_crypto(priv);
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);
......@@ -723,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
return 0;
err_queues:
ath9k_htc_exit_debug(ah);
err_debug:
ath9k_hw_deinit(ah);
err_hw:
......@@ -745,11 +738,15 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
IEEE80211_HW_HAS_RATE_CONTROL |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK;
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
......@@ -782,6 +779,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
{
struct ieee80211_hw *hw = priv->hw;
struct wmi_fw_version cmd_rsp;
int ret;
memset(&cmd_rsp, 0, sizeof(cmd_rsp));
WMI_CMD(WMI_GET_FW_VERSION);
if (ret)
return -EINVAL;
priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
priv->fw_version_major,
priv->fw_version_minor);
dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
priv->fw_version_major,
priv->fw_version_minor);
return 0;
}
static int ath9k_init_device(struct ath9k_htc_priv *priv,
u16 devid, char *product, u32 drv_info)
{
......@@ -801,6 +824,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(priv, hw);
error = ath9k_init_firmware_version(priv);
if (error != 0)
goto err_fw;
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
ath9k_reg_notifier);
......@@ -831,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
goto err_world;
}
error = ath9k_htc_init_debug(priv->ah);
if (error) {
ath_err(common, "Unable to create debugfs files\n");
goto err_world;
}
ath_dbg(common, ATH_DBG_CONFIG,
"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
"BE:%d, BK:%d, VI:%d, VO:%d\n",
......@@ -861,6 +894,8 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
err_tx:
/* Nothing */
err_regd:
/* Nothing */
err_fw:
ath9k_deinit_priv(priv);
err_init:
return error;
......@@ -949,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
static int __init ath9k_htc_init(void)
{
int error;
error = ath9k_htc_debug_create_root();
if (error < 0) {
printk(KERN_ERR
"ath9k_htc: Unable to create debugfs root: %d\n",
error);
goto err_dbg;
}
error = ath9k_hif_usb_init();
if (error < 0) {
if (ath9k_hif_usb_init() < 0) {
printk(KERN_ERR
"ath9k_htc: No USB devices found,"
" driver not installed.\n");
error = -ENODEV;
goto err_usb;
return -ENODEV;
}
return 0;
err_usb:
ath9k_htc_debug_remove_root();
err_dbg:
return error;
}
module_init(ath9k_htc_init);
static void __exit ath9k_htc_exit(void)
{
ath9k_hif_usb_exit();
ath9k_htc_debug_remove_root();
printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
}
module_exit(ath9k_htc_exit);
......@@ -17,8 +17,8 @@
#include "htc.h"
static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
u16 len, u8 flags, u8 epid,
struct ath9k_htc_tx_ctl *tx_ctl)
u16 len, u8 flags, u8 epid)
{
struct htc_frame_hdr *hdr;
struct htc_endpoint *endpoint = &target->endpoint[epid];
......@@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,
hdr->flags = flags;
hdr->payload_len = cpu_to_be16(len);
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb,
tx_ctl);
status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
return status;
}
......@@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
if (ret)
goto err;
......@@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target)
target->htc_flags |= HTC_OP_START_WAIT;
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
if (ret)
goto err;
......@@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target,
conn_msg->dl_pipeid = endpoint->dl_pipeid;
conn_msg->ul_pipeid = endpoint->ul_pipeid;
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL);
ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
if (ret)
goto err;
......@@ -286,35 +286,33 @@ int htc_connect_service(struct htc_target *target,
return ret;
}
int htc_send(struct htc_target *target, struct sk_buff *skb,
enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl)
int htc_send(struct htc_target *target, struct sk_buff *skb)
{
return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl);
struct ath9k_htc_tx_ctl *tx_ctl;
tx_ctl = HTC_SKB_CB(skb);
return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid);
}
void htc_stop(struct htc_target *target)
int htc_send_epid(struct htc_target *target, struct sk_buff *skb,
enum htc_endpoint_id epid)
{
enum htc_endpoint_id epid;
struct htc_endpoint *endpoint;
return htc_issue_send(target, skb, skb->len, 0, epid);
}
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
endpoint = &target->endpoint[epid];
if (endpoint->service_id != 0)
target->hif->stop(target->hif_dev, endpoint->ul_pipeid);
}
void htc_stop(struct htc_target *target)
{
target->hif->stop(target->hif_dev);
}
void htc_start(struct htc_target *target)
{
enum htc_endpoint_id epid;
struct htc_endpoint *endpoint;
target->hif->start(target->hif_dev);
}
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
endpoint = &target->endpoint[epid];
if (endpoint->service_id != 0)
target->hif->start(target->hif_dev,
endpoint->ul_pipeid);
}
void htc_sta_drain(struct htc_target *target, u8 idx)
{
target->hif->sta_drain(target->hif_dev, idx);
}
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
......
This diff is collapsed.
......@@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
}
static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
{
ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
}
/* Private hardware call ops */
/* PHY ops */
......
This diff is collapsed.
This diff is collapsed.
......@@ -239,7 +239,6 @@ struct ath_desc {
void *ds_vdata;
} __packed __aligned(4);
#define ATH9K_TXDESC_CLRDMASK 0x0001
#define ATH9K_TXDESC_NOACK 0x0002
#define ATH9K_TXDESC_RTSENA 0x0004
#define ATH9K_TXDESC_CTSENA 0x0008
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment